diff --git a/third/Blackbone/.gitattributes b/third/Blackbone/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..1ff0c423042b46cb1d617b81efb715defbe8054d --- /dev/null +++ b/third/Blackbone/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/third/Blackbone/.gitignore b/third/Blackbone/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d0bbc704c9009b75f82471c741178a5f08c34d76 --- /dev/null +++ b/third/Blackbone/.gitignore @@ -0,0 +1,87 @@ +#OS junk files +[Tt]humbs.db +*.DS_Store + +#Visual Studio files +*.[Oo]bj +*.user +*.aps +*.pch +*.vspscc +*.vssscc +*_i.c +*_p.c +*.ncb +*.suo +*.tlb +*.tlh +*.bak +*.[Cc]ache +*.ilk +*.log +*.tlog +*.pdb +*.cer +*.lib +*.sbr +*.sdf +*.opensdf +*.unsuccessfulbuild +*.lastbuildstate +ipch/ +obj/ +cmake/ +[Bb]in +[Dd]ebug*/ +[Rr]elease*/ +Ankh.NoLoad + +#MonoDevelop +*.pidb +*.userprefs + +#Tooling +_ReSharper*/ +*.resharper +[Tt]est[Rr]esult* +*.sass-cache + +#Project files +[Bb]uild/ +obj/ + +#Subversion files +.svn + +# Office Temp Files +~$* + +#NuGet +packages/ + +#ncrunch +*ncrunch* +*crunch*.local.xml + +# visual studio database projects +*.dbmdl + +#Test files +*.testsettings + +#Generated libraries +*.dll +*.bin +*.sys +#and files +GeneratedFiles*/ + +*.ggpk +*.idb +*.opendb +*.db +*.sqlite +/.vs +*.db-shm +*.db-wal +*.json diff --git a/third/Blackbone/BlackBone.sln b/third/Blackbone/BlackBone.sln new file mode 100644 index 0000000000000000000000000000000000000000..1e8f4cf0d26f675ac8b5433edfa374e3f0da5f83 --- /dev/null +++ b/third/Blackbone/BlackBone.sln @@ -0,0 +1,114 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.15 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackBone", "src\BlackBone\BlackBone.vcxproj", "{A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Samples", "src\Samples\Samples.vcxproj", "{D31B07B5-C75F-4382-B07F-D95922764BD7}" + ProjectSection(ProjectDependencies) = postProject + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB} = {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackBoneTest", "src\BlackBoneTest\BlackBoneTest.vcxproj", "{15F6F215-4A5E-4B57-B0A0-90B067111285}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug(DLL)|Win32 = Debug(DLL)|Win32 + Debug(DLL)|x64 = Debug(DLL)|x64 + Debug(XP)|Win32 = Debug(XP)|Win32 + Debug(XP)|x64 = Debug(XP)|x64 + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release(DLL)|Win32 = Release(DLL)|Win32 + Release(DLL)|x64 = Release(DLL)|x64 + Release(XP)|Win32 = Release(XP)|Win32 + Release(XP)|x64 = Release(XP)|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Debug(DLL)|Win32.ActiveCfg = Debug(DLL)|Win32 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Debug(DLL)|Win32.Build.0 = Debug(DLL)|Win32 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Debug(DLL)|x64.ActiveCfg = Debug(DLL)|x64 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Debug(DLL)|x64.Build.0 = Debug(DLL)|x64 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Debug(XP)|Win32.ActiveCfg = Debug(XP)|Win32 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Debug(XP)|Win32.Build.0 = Debug(XP)|Win32 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Debug(XP)|x64.ActiveCfg = Debug(XP)|x64 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Debug(XP)|x64.Build.0 = Debug(XP)|x64 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Debug|Win32.ActiveCfg = Debug|Win32 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Debug|Win32.Build.0 = Debug|Win32 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Debug|x64.ActiveCfg = Debug|x64 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Debug|x64.Build.0 = Debug|x64 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Release(DLL)|Win32.ActiveCfg = Release(DLL)|Win32 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Release(DLL)|Win32.Build.0 = Release(DLL)|Win32 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Release(DLL)|x64.ActiveCfg = Release(DLL)|x64 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Release(DLL)|x64.Build.0 = Release(DLL)|x64 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Release(XP)|Win32.ActiveCfg = Release(XP)|Win32 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Release(XP)|Win32.Build.0 = Release(XP)|Win32 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Release(XP)|x64.ActiveCfg = Release(XP)|x64 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Release(XP)|x64.Build.0 = Release(XP)|x64 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Release|Win32.ActiveCfg = Release|Win32 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Release|Win32.Build.0 = Release|Win32 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Release|x64.ActiveCfg = Release|x64 + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB}.Release|x64.Build.0 = Release|x64 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Debug(DLL)|Win32.ActiveCfg = Debug(DLL)|Win32 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Debug(DLL)|Win32.Build.0 = Debug(DLL)|Win32 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Debug(DLL)|x64.ActiveCfg = Debug(DLL)|x64 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Debug(DLL)|x64.Build.0 = Debug(DLL)|x64 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Debug(XP)|Win32.ActiveCfg = Debug(XP)|Win32 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Debug(XP)|Win32.Build.0 = Debug(XP)|Win32 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Debug(XP)|x64.ActiveCfg = Debug(XP)|x64 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Debug(XP)|x64.Build.0 = Debug(XP)|x64 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Debug|Win32.ActiveCfg = Debug|Win32 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Debug|Win32.Build.0 = Debug|Win32 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Debug|Win32.Deploy.0 = Debug|Win32 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Debug|x64.ActiveCfg = Debug|x64 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Debug|x64.Build.0 = Debug|x64 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Debug|x64.Deploy.0 = Debug|x64 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Release(DLL)|Win32.ActiveCfg = Release(DLL)|Win32 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Release(DLL)|Win32.Build.0 = Release(DLL)|Win32 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Release(DLL)|Win32.Deploy.0 = Release(DLL)|Win32 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Release(DLL)|x64.ActiveCfg = Release(DLL)|x64 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Release(DLL)|x64.Build.0 = Release(DLL)|x64 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Release(XP)|Win32.ActiveCfg = Release(XP)|Win32 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Release(XP)|Win32.Build.0 = Release(XP)|Win32 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Release(XP)|x64.ActiveCfg = Release(XP)|x64 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Release(XP)|x64.Build.0 = Release(XP)|x64 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Release|Win32.ActiveCfg = Release|Win32 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Release|Win32.Build.0 = Release|Win32 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Release|Win32.Deploy.0 = Release|Win32 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Release|x64.ActiveCfg = Release|x64 + {D31B07B5-C75F-4382-B07F-D95922764BD7}.Release|x64.Build.0 = Release|x64 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Debug(DLL)|Win32.ActiveCfg = Debug(DLL)|Win32 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Debug(DLL)|Win32.Build.0 = Debug(DLL)|Win32 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Debug(DLL)|x64.ActiveCfg = Debug(DLL)|x64 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Debug(DLL)|x64.Build.0 = Debug(DLL)|x64 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Debug(XP)|Win32.ActiveCfg = Debug|Win32 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Debug(XP)|Win32.Build.0 = Debug|Win32 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Debug(XP)|x64.ActiveCfg = Debug|x64 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Debug(XP)|x64.Build.0 = Debug|x64 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Debug|Win32.ActiveCfg = Debug|Win32 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Debug|Win32.Build.0 = Debug|Win32 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Debug|x64.ActiveCfg = Debug|x64 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Debug|x64.Build.0 = Debug|x64 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Release(DLL)|Win32.ActiveCfg = Release(DLL)|Win32 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Release(DLL)|Win32.Build.0 = Release(DLL)|Win32 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Release(DLL)|x64.ActiveCfg = Release(DLL)|x64 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Release(DLL)|x64.Build.0 = Release(DLL)|x64 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Release(XP)|Win32.ActiveCfg = Release|Win32 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Release(XP)|Win32.Build.0 = Release|Win32 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Release(XP)|x64.ActiveCfg = Release|x64 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Release(XP)|x64.Build.0 = Release|x64 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Release|Win32.ActiveCfg = Release|Win32 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Release|Win32.Build.0 = Release|Win32 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Release|x64.ActiveCfg = Release|x64 + {15F6F215-4A5E-4B57-B0A0-90B067111285}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FA23DB8B-7FAB-4586-936D-4ADB4CD8B90E} + EndGlobalSection +EndGlobal diff --git a/third/Blackbone/LICENSE b/third/Blackbone/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..6576d540905d764a60e5a2231ad9b89af4d56ec9 --- /dev/null +++ b/third/Blackbone/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2015 DarthTon + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/third/Blackbone/README.md b/third/Blackbone/README.md new file mode 100644 index 0000000000000000000000000000000000000000..3fbc93e1088eabfa68ed585ab7c1f7e303913226 --- /dev/null +++ b/third/Blackbone/README.md @@ -0,0 +1,99 @@ +# Blackbone + +### Windows memory hacking library + +## Features + +- **x86 and x64 support** + +**Process interaction** + - Manage PEB32/PEB64 + - Manage process through WOW64 barrier + +**Process Memory** + - Allocate and free virtual memory + - Change memory protection + - Read/Write virtual memory + +**Process modules** + - Enumerate all (32/64 bit) modules loaded. Enumerate modules using Loader list/Section objects/PE headers methods. + - Get exported function address + - Get the main module + - Unlink module from loader lists + - Inject and eject modules (including pure IL images) + - Inject 64bit modules into WOW64 processes + - Manually map native PE images + +**Threads** + - Enumerate threads + - Create and terminate threads. Support for cross-session thread creation. + - Get thread exit code + - Get main thread + - Manage TEB32/TEB64 + - Join threads + - Suspend and resume threads + - Set/Remove hardware breakpoints + +**Pattern search** + - Search for arbitrary pattern in local or remote process + +**Remote code execution** + - Execute functions in remote process + - Assemble own code and execute it remotely + - Support for cdecl/stdcall/thiscall/fastcall conventions + - Support for arguments passed by value, pointer or reference, including structures + - FPU types are supported + - Execute code in new thread or any existing one + +**Remote hooking** + - Hook functions in remote process using int3 or hardware breakpoints + - Hook functions upon return + +**Manual map features** + - x86 and x64 image support + - Mapping into any arbitrary unprotected process + - Section mapping with proper memory protection flags + - Image relocations (only 2 types supported. I haven't seen a single PE image with some other relocation types) + - Imports and Delayed imports are resolved + - Bound import is resolved as a side effect, I think + - Module exports + - Loading of forwarded export images + - Api schema name redirection + - SxS redirection and isolation + - Activation context support + - Dll path resolving similar to native load order + - TLS callbacks. Only for one thread and only with PROCESS_ATTACH/PROCESS_DETACH reasons. + - Static TLS + - Exception handling support (SEH and C++) + - Adding module to some native loader structures(for basic module api support: GetModuleHandle, GetProcAdress, etc.) + - Security cookie initialization + - C++/CLI images are supported + - Image unloading + - Increase reference counter for import libraries in case of manual import mapping + - Cyclic dependencies are handled properly + +**Driver features** +- Allocate/free/protect user memory +- Read/write user and kernel memory +- Disable permanent DEP for WOW64 processes +- Change process protection flag +- Change handle access rights +- Remap process memory +- Hiding allocated user-mode memory +- User-mode dll injection and manual mapping +- Manual mapping of drivers + +## Requirements + +- Visual Studio 2017 15.7 or higher +- Windows SDK 10.0.17134 or higher +- WDK 10.0.17134 or higher (driver only) +- VC++ 2017 Libs for Spectre (x86 and x64) +- Visual C++ ATL (x86/x64) with Spectre Mitigations + +## License +Blackbone is licensed under the MIT License. Dependencies are under their respective licenses. + +[![Build status](https://ci.appveyor.com/api/projects/status/h3tr97727ngr7jko?svg=true)](https://ci.appveyor.com/project/DarthTon/blackbone) + +[![Build status](https://ci.appveyor.com/api/projects/status/5lu9aw84t00ibkdo?svg=true)](https://ci.appveyor.com/project/DarthTon/blackbone-q21rd) \ No newline at end of file diff --git a/third/Blackbone/appveyor.yml b/third/Blackbone/appveyor.yml new file mode 100644 index 0000000000000000000000000000000000000000..a9101586b3428f141441b25adb16e289e35b322f --- /dev/null +++ b/third/Blackbone/appveyor.yml @@ -0,0 +1,32 @@ +version: 1.0.{build} + +branches: + only: + - master + - testing + +image: Visual Studio 2017 +clone_folder: c:\projects\blackbone + +platform: + - Win32 + - x64 + +configuration: + - Debug + - Debug(DLL) + - Release + - Release(DLL) + +build: + parallel: true + project: BlackBone.sln + +build_script: + MSBuild.exe BlackBone.sln /p:CI=true /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" + +test_script: + - ps: vstest.console /logger:Appveyor "build/$env:PLATFORM/$env:CONFIGURATION/BlackboneTest.dll" + +skip_commits: + message: /Driver/ \ No newline at end of file diff --git a/third/Blackbone/appveyor_drv.yml b/third/Blackbone/appveyor_drv.yml new file mode 100644 index 0000000000000000000000000000000000000000..73ddc33f17765e31686df296b98dad31dc3dbd4d --- /dev/null +++ b/third/Blackbone/appveyor_drv.yml @@ -0,0 +1,28 @@ +version: 1.0.{build} + +branches: + only: + - master + +image: Visual Studio 2015 +clone_folder: c:\projects\blackboneDrv + +platform: + - x64 + +configuration: + - Win10Debug + - Win10Release + - Win8.1 Debug + - Win8.1 Release + - Win8 Debug + - Win8 Release + - Win7 Debug + - Win7 Release + +build: + parallel: true + project: src/BlackBoneDrv/BlackBoneDrv.sln + +only_commits: + message: /Driver/ \ No newline at end of file diff --git a/third/Blackbone/src/3rd_party/AsmJit/ApiBegin.h b/third/Blackbone/src/3rd_party/AsmJit/ApiBegin.h new file mode 100644 index 0000000000000000000000000000000000000000..b025e2e96f7db693914cb0b98c169c76c170f347 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/ApiBegin.h @@ -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__ diff --git a/third/Blackbone/src/3rd_party/AsmJit/ApiEnd.h b/third/Blackbone/src/3rd_party/AsmJit/ApiEnd.h new file mode 100644 index 0000000000000000000000000000000000000000..4ec7834cbbeefd2bc7e01183244475339fc9b41f --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/ApiEnd.h @@ -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__ diff --git a/third/Blackbone/src/3rd_party/AsmJit/AsmJit.h b/third/Blackbone/src/3rd_party/AsmJit/AsmJit.h new file mode 100644 index 0000000000000000000000000000000000000000..9b143d44dde956349fdb3ee6650f7b429eb15f07 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/AsmJit.h @@ -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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/Build.h b/third/Blackbone/src/3rd_party/AsmJit/Build.h new file mode 100644 index 0000000000000000000000000000000000000000..b97a456537a4b6e0088a4172a4de5660708b296d --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/Build.h @@ -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 +#include +#include + +// [Dependencies - C++] +#include + +// ============================================================================ +// [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((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 +#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 +# include +#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 + +# 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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/Config.h b/third/Blackbone/src/3rd_party/AsmJit/Config.h new file mode 100644 index 0000000000000000000000000000000000000000..4041c112f3e8166d44f9115335a13b048bc5faa5 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/Config.h @@ -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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/LICENSE.md b/third/Blackbone/src/3rd_party/AsmJit/LICENSE.md new file mode 100644 index 0000000000000000000000000000000000000000..7742e92fff72593b8f75d72b2a896114f9ffa493 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/LICENSE.md @@ -0,0 +1,18 @@ +AsmJit - Complete x86/x64 JIT and Remote Assembler for C++ +Copyright (c) 2008-2014, Petr Kobalicek + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. diff --git a/third/Blackbone/src/3rd_party/AsmJit/README.md b/third/Blackbone/src/3rd_party/AsmJit/README.md new file mode 100644 index 0000000000000000000000000000000000000000..f7cd03e36f2bb0245ec6b5e4bf1db8b36541db45 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/README.md @@ -0,0 +1,538 @@ +AsmJit +------ + +Complete x86/x64 JIT and Remote Assembler for C++. + + * [Official Repository (kobalicek/asmjit)](https://github.com/kobalicek/asmjit) + * [Zlib Licensed] (http://www.opensource.org/licenses/zlib-license.php) + +Introduction +------------ + +AsmJit is a complete JIT and remote assembler for C++ language. It can generate native code for x86 and x64 architectures and supports the whole x86/x64 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 nor tries to be. It's a tool that can be used to encode instructions into their machine code representations and tries to make such process easy and fun. AsmJit has been used so far in software encryption, image/sound processing, emulators and as a JIT backend in virtual machines. + +Features +-------- + + * Complete x86/x64 instruction set - MMX, SSE, AVX, BMI, XOP, FMA..., + * Low-level and high-level code generation, + * Built-in CPU detection, + * Virtual Memory management, + * Pretty logging and error handling, + * Small and embeddable, around 150-200kB compiled, + * Zero dependencies, not even STL or RTTI. + +Supported Environments +---------------------- + +### Operating Systems + + * BSDs + * Linux + * Mac + * Windows + +### C++ Compilers + + * BorlandC++ + * Clang (Travis-CI) + * Gcc (Travis-CI) + * MinGW + * MSVC + * Other compilers require testing and support in `asmjit/build.h` header + +### Backends + + * X86 + * X64 + +Project Organization +-------------------- + + * `/` - Project root + * `src` - Source code + * `asmjit` - Public header files (always include from here) + * `base` - Base files, used by the AsmJit and all backends + * `contrib` - Contributions that extend the base functionality + * `test` - Unit testing support (don't include in your project) + * `x86` - X86/X64 specific files, used only by X86/X64 backend + * `tools` - Tools used for configuring, documenting and generating files + +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 optionally code-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 a 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 easier and more portable. However, Compiler does sometimes relatively bad job when it comes to register allocation, so for projects where there is already an analysis performed, pure Assembler code generator is the preferred way. + +Configuring & Building +---------------------- + +AsmJit is designed to be easy embeddable in any kind project. However, it has some compile-time flags that can be used to build a specific version of AsmJit including or omitting certain features. A typical way to build AsmJit is to use [cmake](http://www.cmake.org), but it's also possible to just include AsmJit source code in our project and build it with it optionally editing its `asmjit/config.h` file to turn on/off some specific features. The most easies way to include AsmJit in your project is to just copy AsmJit source somewhere into it and to define globally `ASMJIT_STATIC` macro. This way AsmJit can be just updated from time to time without any changes to it. Please do not include / compile AsmJit test files (`asmjit/test` directory) when embedding. + +### Build Type + + * `ASMJIT_EMBED` - Parameter that can be set to cmake to turn off building library, useful if you want to include asmjit in your project without building the library. `ASMJIT_EMBED` behaves identically as `ASMJIT_STATIC`. + * `ASMJIT_STATIC` - Define when building AsmJit as a static library. No symbols will be exported by AsmJit by default. + + * By default AsmJit build is configured as a shared library so none of `ASMJIT_EMBED` and `ASMJIT_STATIC` have to be defined explicitly. + +### Build Mode + + * `ASMJIT_DEBUG` - Define to always turn debugging on (regardless of build-mode). + * `ASMJIT_RELEASE` - Define to always turn debugging off (regardless of build-mode). + * `ASMJIT_TRACE` - Define to enable AsmJit tracing. Tracing is used to catch bugs in AsmJit and it has to be enabled explicitly. When AsmJit is compiled with `ASMJIT_TRACE` it uses `stdout` to log information related to AsmJit execution. This log can be helpful when examining liveness analysis, register allocation or any other part of AsmJit. + + * By default none of these is defined, AsmJit detects mode based on compile-time macros (useful when using IDE that has switches for Debug/Release/etc...). + +### Architectures + + * `ASMJIT_BUILD_X86` - Always build x86 backend regardless of host architecture. + * `ASMJIT_BUILD_X64` - Always build x64 backend regardless of host architecture. + * `ASMJIT_BUILD_HOST` - Always build host backend, if only `ASMJIT_BUILD_HOST` is used only the host architecture detected at compile-time will be included. + + * By default only `ASMJIT_BUILD_HOST` is defined. + +### Features + + * `ASMJIT_DISABLE_COMPILER` - Disable `Compiler` completely. Use this flag if you don't use Compiler and want slimmer binary. + + * `ASMJIT_DISABLE_LOGGER` - Disable `Logger` completely. Use this flag if you don't need `Logger` functionality and want slimmer binary. AsmJit compiled with or without `Logger` support is binary compatible (all classes that use Logger pointer will simply use `void*`), but the Logger interface and in general instruction dumps are not available. + + * `ASMJIT_DISABLE_NAMES` - Disable everything that uses strings and that causes certain strings to be stored in the resulting binary. For example when this flag is enabled instruction or error names (and related APIs) will not be available. This flag has to be disabled together with `ASMJIT_DISABLE_LOGGER`. + +Using AsmJit +------------ + +AsmJit library uses one global namespace called `asmjit`, which contains the basics. Architecture specific code is prefixed by the architecture and architecture registers and operand builders are in its own namespace. For example classes for both x86 and x64 code generation are prefixed by `X86`, enums by `kX86`, registers and operand builders are accessible through `x86` namespace. This design is very different from the initial version of AsmJit and it seems now as the most convenient one. + +### Runtime & Code-Generators + +AsmJit contains two classes that are required to generate a machine code. `Runtime` specifies where the code is generated and acts as a storage, while `CodeGen` specifies how the code is generated and acts as a machine code stream. All the examples here use `Compiler` code-generator to generate the code and `JitRuntime` to store and run it. + +### Instruction Operands + +Operand is a part of CPU instruction which specifies the data the instruction will operate on. There are five types of operands in AsmJit: + + * `Reg` - Physical register, used only by `Assembler` + * `Var` - Virtual register, used only by `Compiler` + * `Mem` - Used to reference memory location + * `Label` - Used to reference a location in code + * `Imm` - Immediate value that is encoded with the instruction itself + +Base class for all operands is `Operand`. It contains interface that can be used by all types of operands only and it is typically passed by value, not as a pointer. The classes `Reg`, `Var`, `BaseMem`, `Label` and `Imm` all inherit `Operand` and provide an operand specific functionality. Architecture specific operands are prefixed by the architecture like `X86Reg` or `X86Mem`. Most of the architectures provide several types of registers, for example x86/x64 architecture has `X86GpReg`, `X86MmReg`, `X86FpReg`, `X86XmmReg` and `X86YmmReg` registers plus some extras including segment registers and `rip` (relative instruction pointer). + +When using a code-generator some operands have to be created explicitly by using its interface. For example labels are created by using `newLabel()` method of the code-generator and variables are created by using architecture specific methods like `newGpVar()`, `newMmVar()` or `newXmmVar()`. + +### Function Prototypes + +AsmJit needs to know the prototype of the function it will generate or call. AsmJit contains a mapping between a type and the register that will be used to represent it. To make life easier there is a function builder that does the mapping on the fly. Function builder is a template class that helps with creating a function prototype by using native C/C++ types that describe function arguments and return value. It translates C/C++ native types into AsmJit specific IDs and makes these IDs accessible to Compiler. + +### Putting It All Together + +Let's put all together and generate a first function that sums its two arguments and returns the result. At the end the generated function is called from a C++ code. + +```C++ +#include + +using namespace asmjit; + +int main(int argc, char* argv[]) { + // Create JitRuntime and X86 Compiler. + JitRuntime runtime; + X86Compiler c(&runtime); + + // Build function having two arguments and a return value of type 'int'. + // First type in function builder describes the return value. kFuncConvHost + // tells compiler to use a host calling convention. + c.addFunc(kFuncConvHost, FuncBuilder2()); + + // Create 32-bit variables (virtual registers) and assign some names to + // them. Using names is purely optional and only greatly helps while + // debugging. + X86GpVar a(c, kVarTypeInt32, "a"); + X86GpVar b(c, kVarTypeInt32, "b"); + + // Tell asmjit to use these variables as function arguments. + c.setArg(0, a); + c.setArg(1, b); + + // a = a + b; + c.add(a, b); + + // Tell asmjit to return 'a'. + c.ret(a); + + // Finalize the current function. + c.endFunc(); + + // Now the Compiler contains the whole function, but the code is not yet + // generated. To tell compiler to generate the function make() has to be + // called. + + // Make uses the JitRuntime passed to Compiler constructor to allocate a + // buffer for the function and make it executable. + void* funcPtr = c.make(); + + // In order to run 'funcPtr' it has to be casted to the desired type. + // Typedef is a recommended and safe way to create a function-type. + typedef int (*FuncType)(int, int); + + // Using asmjit_cast is purely optional, it's basically a C-style cast + // that tries to make it visible that a function-type is returned. + FuncType func = asmjit_cast(funcPtr); + + // Finally, run it and do something with the result... + int x = func(1, 2); + printf("x=%d\n", x); // Outputs "x=3". + + // The function will remain in memory after Compiler is destroyed, but + // will be destroyed together with Runtime. This is just simple example + // where we can just destroy both at the end of the scope and that's it. + // However, it's a good practice to clean-up resources after they are + // not needed and using runtime.release() is the preferred way to free + // a function added to JitRuntime. + runtime.release((void*)func); + + // Runtime and Compiler will be destroyed at the end of the scope. + return 0; +} +``` + +The code should be self explanatory, however there are some details to be clarified. + +The code above generates and calls a function of `kFuncConvHost` calling convention. 32-bit architecture contains a wide range of function calling conventions that can be all used by a single program, so it's important to know which calling convention is used by your C/C++ compiler so you can call the function. However, most compilers should generate CDecl by default. In 64-bit mode there are only two calling conventions, one is specific for Windows (Win64 calling convention) and the other for Unix (AMD64 calling convention). The `kFuncConvHost` is defined to be one of CDecl, Win64 or AMD64 depending on your architecture and operating system. + +Default integer size is platform specific, virtual types `kVarTypeIntPtr` and `kVarTypeUIntPtr` can be used to make the code more portable and they should be always used when a pointer type is needed. When no type is specified AsmJit always defaults to `kVarTypeIntPtr`. The code above works with integers where the default behavior has been overidden to 32-bits. Note it's always a good practice to specify the type of the variable used. Alternative form of creating a variable is `c.newGpVar(...)`, `c.newMmVar(...)`, `c.newXmmVar` and so on... + +The function starts with `c.addFunc()` and ends with `c.endFunc()`. It's not allowed to put code outside of the function; however, embedding data outside of the function body is allowed. + +### Using Labels + +Labels are essential for making jumps, function calls or to refer to a data that is embedded in the code section. Label has to be explicitly created by using `newLabel()` method of your code generator in order to be used. The following example executes a code that depends on the condition by using a `Label` and conditional jump instruction. If the first parameter is zero it returns `a + b`, otherwise `a - b`. + +```C++ +#include + +using namespace asmjit; + +int main(int argc, char* argv[]) { + JitRuntime runtime; + X86Compiler c(&runtime); + + // This function uses 3 arguments. + c.addFunc(kFuncConvHost, FuncBuilder3()); + + // New variable 'op' added. + X86GpVar op(c, kVarTypeInt32, "op"); + X86GpVar a(c, kVarTypeInt32, "a"); + X86GpVar b(c, kVarTypeInt32, "b"); + + c.setArg(0, op); + c.setArg(1, a); + c.setArg(2, b); + + // Create labels. + Label L_Subtract(c); + Label L_Skip(c); + + // If (op != 0) + // goto L_Subtract; + c.test(op, op); + c.jne(L_Subtract); + + // a = a + b; + // goto L_Skip; + c.add(a, b); + c.jmp(L_Skip); + + // L_Subtract: + // a = a - b; + c.bind(L_Subtract); + c.sub(a, b); + + // L_Skip: + c.bind(L_Skip); + + c.ret(a); + c.endFunc(); + + // The prototype of the generated function changed also here. + typedef int (*FuncType)(int, int, int); + FuncType func = asmjit_cast(c.make()); + + int x = func(0, 1, 2); + int y = func(1, 1, 2); + + printf("x=%d\n", x); // Outputs "x=3". + printf("y=%d\n", y); // Outputs "y=-1". + + runtime.release((void*)func); + return 0; +} +``` + +In this example conditional and unconditional jumps were used with labels together. Labels are created explicitly by the `Compiler` by passing a `Compiler` instance to a `Label` constructor or by using a `Label l = c.newLabel()` form. Each label as an unique ID that identifies it, however it's not a string and there is no way to query for a `Label` instance that already exists. Label is like any other operand moved by value, so the copy of the label will still reference the same label and changing a copied label will not change the original label. + +Each label has to be bound to the location in the code by using `c.bind()`; however, it can be only bound once! Trying to bind the same label multiple times has undefined behavior - it will trigger an assertion failure in the best case. + +### Memory Addressing + +X86/X64 architectures have several memory addressing modes which can be used to combine base register, index register and a displacement. In addition, index register can be shifted by a constant from 1 to 3 that can help with addressing elements up to 8-byte long in an array. AsmJit supports all forms of memory addressing. Memory operand can be created by using `asmjit::X86Mem` or by using related non-member functions like `asmjit::x86::ptr` or `asmjit::x86::ptr_abs`. Use `ptr` to create a memory operand having a base register with optional index register and a displacement; use and `ptr_abs` to create a memory operand referring to an absolute address in memory (32-bit) and optionally having an index register. + +In the following example various memory addressing modes are used to demonstrate how to construct and use them. It creates a function that accepts an array and two indexes which specify which elements to sum and return. + +```C++ +#include + +using namespace asmjit; + +int main(int argc, char* argv[]) { + JitRuntime runtime; + X86Compiler c(&runtime); + + // Function returning 'int' accepting pointer and two indexes. + c.addFunc(kFuncConvHost, FuncBuilder3()); + + X86GpVar p(c, kVarTypeIntPtr, "p"); + X86GpVar aIndex(c, kVarTypeIntPtr, "aIndex"); + X86GpVar bIndex(c, kVarTypeIntPtr, "bIndex"); + + c.setArg(0, p); + c.setArg(1, aIndex); + c.setArg(2, bIndex); + + X86GpVar a(c, kVarTypeInt32, "a"); + X86GpVar b(c, kVarTypeInt32, "b"); + + // Read 'a' by using a memory operand having base register, index register + // and scale. Translates to 'mov a, dword ptr [p + aIndex << 2]'. + c.mov(a, ptr(p, aIndex, 2)); + + // Read 'b' by using a memory operand having base register only. Variables + // 'p' and 'bIndex' are both modified. + + // Shift bIndex by 2 (exactly the same as multiplying by 4). + // And add scaled 'bIndex' to 'p' resulting in 'p = p + bIndex * 4'. + c.shl(bIndex, 2); + c.add(p, bIndex); + + // Read 'b'. + c.mov(b, ptr(p)); + + // a = a + b; + c.add(a, b); + + c.ret(a); + c.endFunc(); + + // The prototype of the generated function changed also here. + typedef int (*FuncType)(const int*, intptr_t, intptr_t); + FuncType func = asmjit_cast(c.make()); + + // Array passed to 'func' + const int array[] = { 1, 2, 3, 5, 8, 13 }; + + int x = func(array, 1, 2); + int y = func(array, 3, 5); + + printf("x=%d\n", x); // Outputs "x=5". + printf("y=%d\n", y); // Outputs "y=18". + + runtime.release((void*)func); + return 0; +} +``` + +### Using Stack + +AsmJit uses stack automatically to spill variables if there is not enough registers to keep them all allocated. The stack frame is managed by `Compiler` that provides also an interface to allocate chunks of memory of user specified size and alignment. + +In the following example a stack of 256 bytes size is allocated, filled by bytes starting from 0 to 255 and then iterated again to sum all the values. + +```C++ +#include + +using namespace asmjit; + +int main(int argc, char* argv[]) { + JitRuntime runtime; + X86Compiler c(&runtime); + + // Function returning 'int' without any arguments. + c.addFunc(kFuncConvHost, FuncBuilder0()); + + // Allocate a function stack of size 256 aligned to 4 bytes. + X86Mem stack = c.newStack(256, 4); + + X86GpVar p(c, kVarTypeIntPtr, "p"); + X86GpVar i(c, kVarTypeIntPtr, "i"); + + // Load a stack address to 'p'. This step is purely optional and shows + // that 'lea' is useful to load a memory operands address (even absolute) + // to a general purpose register. + c.lea(p, stack); + + // Clear 'i'. Notice that xor_() is used instead of xor(), because xor is + // unfortunately a keyword in C++. + c.xor_(i, i); + + // First loop, fill the stack allocated by a sequence of bytes from 0 to 255. + Label L1(c); + c.bind(L1); + + // Mov [p + i], i. + // + // Any operand can be cloned and modified. By cloning 'stack' and calling + // 'setIndex' we created a new memory operand based on stack having an + // index register set. + c.mov(stack.clone().setIndex(i), i.r8()); + + // if (++i < 256) + // goto L1; + c.inc(i); + c.cmp(i, 256); + c.jb(L1); + + // Second loop, sum all bytes stored in 'stack'. + X86GpVar a(c, kVarTypeInt32, "a"); + X86GpVar t(c, kVarTypeInt32, "t"); + + c.xor_(i, i); + c.xor_(a, a); + + Label L2(c); + c.bind(L2); + + // Movzx t, byte ptr [stack + i] + c.movzx(t, stack.clone().setIndex(i).setSize(1)); + // a += t; + c.add(a, t); + + // if (++i < 256) + // goto L2; + c.inc(i); + c.cmp(i, 256); + c.jb(L2); + + c.ret(a); + c.endFunc(); + + typedef int (*FuncType)(void); + + FuncType func = asmjit_cast(c.make()); + printf("a=%d\n", func()); // Outputs "a=32640". + + runtime.release((void*)func); + return 0; +} +``` + +### Using Constant Pool + +To be documented. + +Advanced Features +----------------- + +AsmJit offers much more, but not everything can fit into the introduction. The following sections don't have complete examples, but contain hints that can be useful and can change a bit the way AsmJit is used. + +### Logging and Error Handling + +Failures are common when working at machine level. AsmJit does already a good job with function overloading to prevent from emitting semantically incorrect instructions; however, AsmJit can't prevent from emitting code that is semantically correct, but contains bug(s). Logging has always been an important part of AsmJit's infrastructure and the output can be very valuable after something went wrong. + +AsmJit contains extensible logging interface defined by `Logger` class and implemented by `FileLogger` and `StringLogger`. `FileLogger` can log into a standard C-based `FILE*` stream while `StringLogger` logs to an internal buffer that can be used after the code generation is done. + +Loggers can be assigned to any code generator and there is no restriction of assigning a single logger to multiple code generators, but this is not practical when running these in multiple threads. `FileLogger` is thread-safe since it uses plain C `FILE*` stream, but `StringLogger` is not! + +The following snippet describes how to log into `FILE*`: + +```C++ +// Create logger logging to `stdout`. Logger life-time should always be +// greater than lifetime of the code generator. +FileLogger logger(stdout); + +// Create a code generator and assign our logger into it. +X86Compiler c(...); +c.setLogger(&logger); + +// ... Generate the code ... +``` + +The following snippet describes how to log into a string: + +```C++ +StringLogger logger; + +// Create a code generator and assign our logger into it. +X86Compiler c(...); +c.setLogger(&logger); + +// ... Generate the code ... + +printf("Logger Content:\n%s", logger.getString()); + +// You can also use `logger.clearString()` if the logger +// instance will be reused. +``` + +Logger can be configured to show more information by using `logger.setOption()` method. The following options are available: + + * `kLoggerOptionBinaryForm` - Log also binary sequence for each instruction generated. + * `kLoggerOptionHexImmediate` - Format immediate values to base16 (hex) form. + * `kLoggerOptionHexDisplacement` - Format memory displacements to base16 (hex) form. + +TODO: Liveness analysis and instruction scheduling options. + +### Code Injection + +Code injection was one of key concepts of Compiler from the beginning. Compiler records all emitted instructions in a double-linked list which can be manipulated before `make()` is called. Any call to Compiler that adds instruction, function or anything else in fact manipulates this list by inserting nodes into it. + +To manipulate the current cursor use Compiler's `getCursor()` and `setCursor()` methods. The following snippet demonstrates the proper way of code injection. + +```C++ +X86Compiler c(...); + +X86GpVar a(c, kVarTypeInt32, "a"); +X86GpVar b(c, kVarTypeInt32, "b"); + +Node* here = c.getCursor(); +c.mov(b, 2); + +// Now, 'here' can be used to inject something before 'mov b, 2'. To inject +// anything it's good to remember the current cursor so it can be set back +// after the injecting is done. When setCursor() is called it returns the old +// cursor. +Node* oldCursor = c.setCursor(here); +c.mov(a, 1); +c.setCursor(oldCursor); +``` + +The resulting code would look like: + +``` +c.mov(a, 1); +c.mov(b, 2); +``` + +Support +------- + +Please consider a donation if you use the project and would like to keep it active in the future. + + * [Donate by PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=QDRM6SRNG7378&lc=EN;&item_name=asmjit¤cy_code=EUR) + +Received From: + + * [PeLock - Software copy protection and license key system](http://www.pelock.com) + +Authors & Maintainers +--------------------- + + * Petr Kobalicek diff --git a/third/Blackbone/src/3rd_party/AsmJit/base.h b/third/Blackbone/src/3rd_party/AsmJit/base.h new file mode 100644 index 0000000000000000000000000000000000000000..47e1bfef363d3942753c9e05430c698b58f80a95 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base.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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/assembler.cpp b/third/Blackbone/src/3rd_party/AsmJit/base/assembler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3718bafee5d91e2fb1d97395541251e8e17a0ba3 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/assembler.cpp @@ -0,0 +1,387 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Dependencies - AsmJit] +#include "../base/assembler.h" +#include "../base/intutil.h" +#include "../base/vmem.h" + +// [Dependenceis - C] +#include + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [asmjit::Assembler - Construction / Destruction] +// ============================================================================ + +Assembler::Assembler(Runtime* runtime) : + CodeGen(runtime), + _buffer(NULL), + _end(NULL), + _cursor(NULL), + _trampolineSize(0), + _comment(NULL), + _unusedLinks(NULL) {} + +Assembler::~Assembler() { + reset(true); +} + +// ============================================================================ +// [asmjit::Assembler - Clear / Reset] +// ============================================================================ + +void Assembler::reset(bool releaseMemory) { + // CodeGen members. + _baseAddress = kNoBaseAddress; + _instOptions = 0; + _error = kErrorOk; + + _baseZone.reset(releaseMemory); + + // Assembler members. + if (releaseMemory && _buffer != NULL) { + ASMJIT_FREE(_buffer); + _buffer = NULL; + _end = NULL; + } + + _cursor = _buffer; + _trampolineSize = 0; + + _comment = NULL; + _unusedLinks = NULL; + + _labelList.reset(releaseMemory); + _relocList.reset(releaseMemory); +} + +// ============================================================================ +// [asmjit::Assembler - Buffer] +// ============================================================================ + +Error Assembler::_grow(size_t n) { + size_t capacity = getCapacity(); + size_t after = getOffset() + n; + + // Overflow. + if (n > IntUtil::maxUInt() - capacity) + return setError(kErrorNoHeapMemory); + + // Grow is called when allocation is needed, so it shouldn't happen, but on + // the other hand it is simple to catch and it's not an error. + if (after <= capacity) + return kErrorOk; + + if (capacity < kMemAllocOverhead) + capacity = kMemAllocOverhead; + else + capacity += kMemAllocOverhead; + + do { + size_t oldCapacity = capacity; + + if (capacity < kMemAllocGrowMax) + capacity *= 2; + else + capacity += kMemAllocGrowMax; + + // Overflow. + if (oldCapacity > capacity) + return setError(kErrorNoHeapMemory); + } while (capacity - kMemAllocOverhead < after); + + capacity -= kMemAllocOverhead; + return _reserve(capacity); +} + +Error Assembler::_reserve(size_t n) { + size_t capacity = getCapacity(); + if (n <= capacity) + return kErrorOk; + + uint8_t* newBuffer; + if (_buffer == NULL) + newBuffer = static_cast(ASMJIT_ALLOC(n)); + else + newBuffer = static_cast(ASMJIT_REALLOC(_buffer, n)); + + if (newBuffer == NULL) + return setError(kErrorNoHeapMemory); + + size_t offset = getOffset(); + + _buffer = newBuffer; + _end = _buffer + n; + _cursor = newBuffer + offset; + + return kErrorOk; +} + +// ============================================================================ +// [asmjit::Assembler - Label] +// ============================================================================ + +Error Assembler::_registerIndexedLabels(size_t index) { + size_t i = _labelList.getLength(); + if (index < i) + return kErrorOk; + + if (_labelList._grow(index - i) != kErrorOk) + return setError(kErrorNoHeapMemory); + + LabelData data; + data.offset = -1; + data.links = NULL; + + do { + _labelList.append(data); + } while (++i < index); + + return kErrorOk; +} + +Error Assembler::_newLabel(Label* dst) { + dst->_label.op = kOperandTypeLabel; + dst->_label.size = 0; + dst->_label.id = OperandUtil::makeLabelId(static_cast(_labelList.getLength())); + + LabelData data; + data.offset = -1; + data.links = NULL; + + if (_labelList.append(data) != kErrorOk) + goto _NoMemory; + return kErrorOk; + +_NoMemory: + dst->_label.id = kInvalidValue; + return setError(kErrorNoHeapMemory); +} + +LabelLink* Assembler::_newLabelLink() { + LabelLink* link = _unusedLinks; + + if (link) { + _unusedLinks = link->prev; + } + else { + link = _baseZone.allocT(); + if (link == NULL) + return NULL; + } + + link->prev = NULL; + link->offset = 0; + link->displacement = 0; + link->relocId = -1; + + return link; +} + +Error Assembler::bind(const Label& label) { + // Get label data based on label id. + uint32_t index = label.getId(); + LabelData* data = getLabelData(index); + + // Label can be bound only once. + if (data->offset != -1) + return setError(kErrorLabelAlreadyBound); + +#if !defined(ASMJIT_DISABLE_LOGGER) + if (_logger) + _logger->logFormat(kLoggerStyleLabel, "L%u:\n", index); +#endif // !ASMJIT_DISABLE_LOGGER + + Error error = kErrorOk; + size_t pos = getOffset(); + + LabelLink* link = data->links; + LabelLink* prev = NULL; + + while (link) { + intptr_t offset = link->offset; + + if (link->relocId != -1) { + // Handle RelocData - We have to update RelocData information instead of + // patching the displacement in LabelData. + _relocList[link->relocId].data += static_cast(pos); + } + else { + // Not using relocId, this means that we are overwriting a real + // displacement in the binary stream. + int32_t patchedValue = static_cast( + static_cast(pos) - offset + link->displacement); + + // Size of the value we are going to patch. Only BYTE/DWORD is allowed. + uint32_t size = getByteAt(offset); + ASMJIT_ASSERT(size == 1 || size == 4); + + if (size == 4) { + setInt32At(offset, patchedValue); + } + else { + ASMJIT_ASSERT(size == 1); + if (IntUtil::isInt8(patchedValue)) + setByteAt(offset, static_cast(patchedValue & 0xFF)); + else + error = kErrorIllegalDisplacement; + } + } + + prev = link->prev; + link = prev; + } + + // Chain unused links. + link = data->links; + if (link) { + if (prev == NULL) + prev = link; + + prev->prev = _unusedLinks; + _unusedLinks = link; + } + + // Set as bound (offset is zero or greater and no links). + data->offset = pos; + data->links = NULL; + + if (error != kErrorOk) + return setError(error); + + return error; +} + +// ============================================================================ +// [asmjit::Assembler - Embed] +// ============================================================================ + +Error Assembler::embed(const void* data, uint32_t size) { + if (getRemainingSpace() < size) { + Error error = _grow(size); + if (error != kErrorOk) + return setError(error); + } + + uint8_t* cursor = getCursor(); + ::memcpy(cursor, data, size); + setCursor(cursor + size); + +#if !defined(ASMJIT_DISABLE_LOGGER) + if (_logger) + _logger->logBinary(kLoggerStyleData, data, size); +#endif // !ASMJIT_DISABLE_LOGGER + + return kErrorOk; +} + +// ============================================================================ +// [asmjit::Assembler - Reloc] +// ============================================================================ + +size_t Assembler::relocCode(void* dst, Ptr baseAddress) const { + if (baseAddress == kNoBaseAddress) + baseAddress = hasBaseAddress() ? getBaseAddress() : static_cast((uintptr_t)dst); + else if (getBaseAddress() != baseAddress) + return 0; + + return _relocCode(dst, baseAddress); +} + +// ============================================================================ +// [asmjit::Assembler - Make] +// ============================================================================ + +void* Assembler::make() { + // Do nothing on error condition or if no instruction has been emitted. + if (_error != kErrorOk || getCodeSize() == 0) + return NULL; + + void* p; + Error error = _runtime->add(&p, this); + + if (error != kErrorOk) + setError(error); + + return p; +} + +// ============================================================================ +// [asmjit::Assembler - Emit (Helpers)] +// ============================================================================ + +#define NA noOperand + +Error Assembler::emit(uint32_t code) { + return _emit(code, NA, NA, NA, NA); +} + +Error Assembler::emit(uint32_t code, const Operand& o0) { + return _emit(code, o0, NA, NA, NA); +} + +Error Assembler::emit(uint32_t code, const Operand& o0, const Operand& o1) { + return _emit(code, o0, o1, NA, NA); +} + +Error Assembler::emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2) { + return _emit(code, o0, o1, o2, NA); +} + +Error Assembler::emit(uint32_t code, int o0) { + Imm imm(o0); + return _emit(code, imm, NA, NA, NA); +} + +Error Assembler::emit(uint32_t code, uint64_t o0) { + Imm imm(o0); + return _emit(code, imm, NA, NA, NA); +} + +Error Assembler::emit(uint32_t code, const Operand& o0, int o1) { + Imm imm(o1); + return _emit(code, o0, imm, NA, NA); +} + +Error Assembler::emit(uint32_t code, const Operand& o0, uint64_t o1) { + Imm imm(o1); + return _emit(code, o0, imm, NA, NA); +} + +Error Assembler::emit(uint32_t code, const Operand& o0, const Operand& o1, int o2) { + Imm imm(o2); + return _emit(code, o0, o1, imm, NA); +} + +Error Assembler::emit(uint32_t code, const Operand& o0, const Operand& o1, uint64_t o2) { + Imm imm(o2); + return _emit(code, o0, o1, imm, NA); +} + +Error Assembler::emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, int o3) { + Imm imm(o3); + return _emit(code, o0, o1, o2, imm); +} + +Error Assembler::emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, uint64_t o3) { + Imm imm(o3); + return _emit(code, o0, o1, o2, imm); +} + +#undef NA + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/assembler.h b/third/Blackbone/src/3rd_party/AsmJit/base/assembler.h new file mode 100644 index 0000000000000000000000000000000000000000..bfd8c53739607bc9b2d24c8cb1f5601c319dbc6b --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/assembler.h @@ -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(_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(_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(_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(_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(_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(_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(_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(_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(_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(_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(_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(_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(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(&_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 _buffer + size. + 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 _labelList; + //! RelocData list. + PodVector _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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/codegen.cpp b/third/Blackbone/src/3rd_party/AsmJit/base/codegen.cpp new file mode 100644 index 0000000000000000000000000000000000000000..55192ed0eac52dc980f296092e2cdfe1a24d951a --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/codegen.cpp @@ -0,0 +1,111 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Dependencies - AsmJit] +#include "../base/codegen.h" +#include "../base/intutil.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [asmjit::CodeGen - Construction / Destruction] +// ============================================================================ + +CodeGen::CodeGen(Runtime* runtime) : + _runtime(runtime), + _logger(NULL), + _errorHandler(NULL), + _baseAddress(runtime->getBaseAddress()), + _arch(kArchNone), + _regSize(0), + _reserved(0), + _features(IntUtil::mask(kCodeGenOptimizedAlign)), + _instOptions(0), + _error(kErrorOk), + _baseZone(16384 - kZoneOverhead) {} + +CodeGen::~CodeGen() { + if (_errorHandler != NULL) + _errorHandler->release(); +} + +// ============================================================================ +// [asmjit::CodeGen - Logging] +// ============================================================================ + +#if !defined(ASMJIT_DISABLE_LOGGER) +Error CodeGen::setLogger(Logger* logger) { + _logger = logger; + return kErrorOk; +} +#endif // !ASMJIT_DISABLE_LOGGER + +// ============================================================================ +// [asmjit::CodeGen - Error] +// ============================================================================ + +Error CodeGen::setError(Error error, const char* message) { + if (error == kErrorOk) { + _error = kErrorOk; + return kErrorOk; + } + + if (message == NULL) { +#if !defined(ASMJIT_DISABLE_NAMES) + message = ErrorUtil::asString(error); +#else + static const char noMessage[] = ""; + message = noMessage; +#endif // ASMJIT_DISABLE_NAMES + } + + // Error handler is called before logger so logging can be skipped if error + // has been handled. + ErrorHandler* handler = _errorHandler; + ASMJIT_TLOG("[ERROR] %s %s\n", message, !handler ? "(Possibly unhandled?)" : ""); + + if (handler != NULL && handler->handleError(error, message)) + return error; + +#if !defined(ASMJIT_DISABLE_LOGGER) + Logger* logger = _logger; + if (logger != NULL) { + logger->logFormat(kLoggerStyleComment, + "*** ERROR: %s (%u).\n", message, static_cast(error)); + } +#endif // !ASMJIT_DISABLE_LOGGER + + // The handler->handleError() function may throw an exception or longjmp() + // to terminate the execution of setError(). This is the reason why we have + // delayed changing the _error member until now. + _error = error; + + return error; +} + +Error CodeGen::setErrorHandler(ErrorHandler* handler) { + ErrorHandler* oldHandler = _errorHandler; + + if (oldHandler != NULL) + oldHandler->release(); + + if (handler != NULL) + handler = handler->addRef(); + + _errorHandler = handler; + return kErrorOk; +} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/codegen.h b/third/Blackbone/src/3rd_party/AsmJit/base/codegen.h new file mode 100644 index 0000000000000000000000000000000000000000..551b84bb1df5709a20f843bbb26953f6f2375440 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/codegen.h @@ -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(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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/compiler.cpp b/third/Blackbone/src/3rd_party/AsmJit/base/compiler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cc4aff9ef48604e380567453c4215fe4463e5dbb --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/compiler.cpp @@ -0,0 +1,621 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Guard] +#include "../build.h" +#if !defined(ASMJIT_DISABLE_COMPILER) + +// [Dependencies - AsmJit] +#include "../base/assembler.h" +#include "../base/compiler.h" +#include "../base/context_p.h" +#include "../base/cpuinfo.h" +#include "../base/intutil.h" +#include "../base/logger.h" + +// [Dependencies - C] +#include + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [Constants] +// ============================================================================ + +static const char noName[1] = { '\0' }; +enum { kBaseCompilerDefaultLookAhead = 64 }; + +// ============================================================================ +// [asmjit::Compiler - Construction / Destruction] +// ============================================================================ + +Compiler::Compiler(Runtime* runtime) : + CodeGen(runtime), + _assembler(NULL), + _nodeFlowId(0), + _nodeFlags(0), + _maxLookAhead(kBaseCompilerDefaultLookAhead), + _targetVarMapping(NULL), + _firstNode(NULL), + _lastNode(NULL), + _cursor(NULL), + _func(NULL), + _varZone(4096 - kZoneOverhead), + _stringZone(4096 - kZoneOverhead), + _localConstZone(4096 - kZoneOverhead), + _localConstPool(&_localConstZone), + _globalConstPool(&_baseZone) {} + +Compiler::~Compiler() { + reset(true); + + if (_assembler != NULL) + delete _assembler; +} + +// ============================================================================ +// [asmjit::Compiler - Clear / Reset] +// ============================================================================ + +void Compiler::reset(bool releaseMemory) { + // CodeGen members. + _baseAddress = kNoBaseAddress; + _instOptions = 0; + _error = kErrorOk; + + _baseZone.reset(releaseMemory); + + // Compiler members. + _nodeFlowId = 0; + _nodeFlags = 0; + + if (_assembler != NULL) + _assembler->reset(releaseMemory); + + _firstNode = NULL; + _lastNode = NULL; + + _cursor = NULL; + _func = NULL; + + _localConstPool.reset(); + _globalConstPool.reset(); + + _localConstPoolLabel.reset(); + _globalConstPoolLabel.reset(); + + _varZone.reset(releaseMemory); + _stringZone.reset(releaseMemory); + _localConstZone.reset(releaseMemory); + + _targetList.reset(releaseMemory); + _varList.reset(releaseMemory); +} + +// ============================================================================ +// [asmjit::Compiler - Node Management] +// ============================================================================ + +Node* Compiler::setCursor(Node* node) { + Node* old = _cursor; + _cursor = node; + return old; +} + +Node* Compiler::addNode(Node* node) { + ASMJIT_ASSERT(node != NULL); + ASMJIT_ASSERT(node->_prev == NULL); + ASMJIT_ASSERT(node->_next == NULL); + + if (_cursor == NULL) { + if (_firstNode == NULL) { + _firstNode = node; + _lastNode = node; + } + else { + node->_next = _firstNode; + _firstNode->_prev = node; + _firstNode = node; + } + } + else { + Node* prev = _cursor; + Node* next = _cursor->_next; + + node->_prev = prev; + node->_next = next; + + prev->_next = node; + if (next) + next->_prev = node; + else + _lastNode = node; + } + + _cursor = node; + return node; +} + +Node* Compiler::addNodeBefore(Node* node, Node* ref) { + ASMJIT_ASSERT(node != NULL); + ASMJIT_ASSERT(node->_prev == NULL); + ASMJIT_ASSERT(node->_next == NULL); + ASMJIT_ASSERT(ref != NULL); + + Node* prev = ref->_prev; + Node* next = ref; + + node->_prev = prev; + node->_next = next; + + next->_prev = node; + if (prev) + prev->_next = node; + else + _firstNode = node; + + return node; +} + +Node* Compiler::addNodeAfter(Node* node, Node* ref) { + ASMJIT_ASSERT(node != NULL); + ASMJIT_ASSERT(node->_prev == NULL); + ASMJIT_ASSERT(node->_next == NULL); + ASMJIT_ASSERT(ref != NULL); + + Node* prev = ref; + Node* next = ref->_next; + + node->_prev = prev; + node->_next = next; + + prev->_next = node; + if (next) + next->_prev = node; + else + _lastNode = node; + + return node; +} + +static ASMJIT_INLINE void BaseCompiler_nodeRemoved(Compiler* self, Node* node_) { + if (node_->isJmpOrJcc()) { + JumpNode* node = static_cast(node_); + TargetNode* target = node->getTarget(); + + // Disconnect. + JumpNode** pPrev = &target->_from; + for (;;) { + ASMJIT_ASSERT(*pPrev != NULL); + JumpNode* current = *pPrev; + + if (current == NULL) + break; + + if (current == node) { + *pPrev = node->_jumpNext; + break; + } + + pPrev = ¤t->_jumpNext; + } + + target->subNumRefs(); + } +} + +Node* Compiler::removeNode(Node* node) { + Node* prev = node->_prev; + Node* next = node->_next; + + if (_firstNode == node) + _firstNode = next; + else + prev->_next = next; + + if (_lastNode == node) + _lastNode = prev; + else + next->_prev = prev; + + node->_prev = NULL; + node->_next = NULL; + + if (_cursor == node) + _cursor = prev; + BaseCompiler_nodeRemoved(this, node); + + return node; +} + +void Compiler::removeNodes(Node* first, Node* last) { + if (first == last) { + removeNode(first); + return; + } + + Node* prev = first->_prev; + Node* next = last->_next; + + if (_firstNode == first) + _firstNode = next; + else + prev->_next = next; + + if (_lastNode == last) + _lastNode = prev; + else + next->_prev = prev; + + Node* node = first; + for (;;) { + Node* next = node->getNext(); + ASMJIT_ASSERT(next != NULL); + + node->_prev = NULL; + node->_next = NULL; + + if (_cursor == node) + _cursor = prev; + BaseCompiler_nodeRemoved(this, node); + + if (node == last) + break; + node = next; + } +} + +// ============================================================================ +// [asmjit::Compiler - Align] +// ============================================================================ + +AlignNode* Compiler::newAlign(uint32_t mode, uint32_t offset) { + AlignNode* node = newNode(mode, offset); + if (node == NULL) + goto _NoMemory; + return node; + +_NoMemory: + setError(kErrorNoHeapMemory); + return NULL; +} + +AlignNode* Compiler::addAlign(uint32_t mode, uint32_t offset) { + AlignNode* node = newAlign(mode, offset); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +// ============================================================================ +// [asmjit::Compiler - Target] +// ============================================================================ + +TargetNode* Compiler::newTarget() { + TargetNode* node = newNode( + OperandUtil::makeLabelId(static_cast(_targetList.getLength()))); + + if (node == NULL || _targetList.append(node) != kErrorOk) + goto _NoMemory; + return node; + +_NoMemory: + setError(kErrorNoHeapMemory); + return NULL; +} + +TargetNode* Compiler::addTarget() { + TargetNode* node = newTarget(); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +// ============================================================================ +// [asmjit::Compiler - Label] +// ============================================================================ + +Error Compiler::_newLabel(Label* dst) { + dst->_init_packed_op_sz_b0_b1_id(kOperandTypeLabel, 0, 0, 0, kInvalidValue); + dst->_init_packed_d2_d3(0, 0); + + TargetNode* node = newTarget(); + if (node == NULL) + goto _NoMemory; + + dst->_label.id = node->getLabelId(); + return kErrorOk; + +_NoMemory: + return setError(kErrorNoHeapMemory); +} + +Error Compiler::bind(const Label& label) { + uint32_t index = label.getId(); + ASMJIT_ASSERT(index < _targetList.getLength()); + + addNode(_targetList[index]); + return kErrorOk; +} + +// ============================================================================ +// [asmjit::Compiler - Embed] +// ============================================================================ + +EmbedNode* Compiler::newEmbed(const void* data, uint32_t size) { + EmbedNode* node; + + if (size > EmbedNode::kInlineBufferSize) { + void* clonedData = _stringZone.alloc(size); + if (clonedData == NULL) + goto _NoMemory; + + if (data != NULL) + ::memcpy(clonedData, data, size); + data = clonedData; + } + + node = newNode(const_cast(data), size); + if (node == NULL) + goto _NoMemory; + return node; + +_NoMemory: + setError(kErrorNoHeapMemory); + return NULL; +} + +EmbedNode* Compiler::addEmbed(const void* data, uint32_t size) { + EmbedNode* node = newEmbed(data, size); + if (node == NULL) + return node; + return static_cast(addNode(node)); +} + +// ============================================================================ +// [asmjit::Compiler - Comment] +// ============================================================================ + +CommentNode* Compiler::newComment(const char* str) { + CommentNode* node; + + if (str != NULL && str[0]) { + str = _stringZone.sdup(str); + if (str == NULL) + goto _NoMemory; + } + + node = newNode(str); + if (node == NULL) + goto _NoMemory; + return node; + +_NoMemory: + setError(kErrorNoHeapMemory); + return NULL; +} + +CommentNode* Compiler::addComment(const char* str) { + CommentNode* node = newComment(str); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +CommentNode* Compiler::comment(const char* fmt, ...) { + char buf[256]; + char* p = buf; + + if (fmt) { + *p++ = ';'; + *p++ = ' '; + + va_list ap; + va_start(ap, fmt); + p += vsnprintf(p, 254, fmt, ap); + va_end(ap); + } + + p[0] = '\n'; + p[1] = '\0'; + + return addComment(fmt); +} + +// ============================================================================ +// [asmjit::Compiler - Hint] +// ============================================================================ + +HintNode* Compiler::newHint(Var& var, uint32_t hint, uint32_t value) { + if (var.getId() == kInvalidValue) + return NULL; + VarData* vd = getVd(var); + + HintNode* node = newNode(vd, hint, value); + if (node == NULL) + goto _NoMemory; + return node; + +_NoMemory: + setError(kErrorNoHeapMemory); + return NULL; +} + +HintNode* Compiler::addHint(Var& var, uint32_t hint, uint32_t value) { + if (var.getId() == kInvalidValue) + return NULL; + + HintNode* node = newHint(var, hint, value); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +// ============================================================================ +// [asmjit::Compiler - Vars] +// ============================================================================ + +VarData* Compiler::_newVd(uint32_t type, uint32_t size, uint32_t c, const char* name) { + VarData* vd = reinterpret_cast(_varZone.alloc(sizeof(VarData))); + if (vd == NULL) + goto _NoMemory; + + vd->_name = noName; + vd->_id = OperandUtil::makeVarId(static_cast(_varList.getLength())); + vd->_contextId = kInvalidValue; + + if (name != NULL && name[0] != '\0') { + vd->_name = _stringZone.sdup(name); + } + + vd->_type = static_cast(type); + vd->_class = static_cast(c); + vd->_flags = 0; + vd->_priority = 10; + + vd->_state = kVarStateUnused; + vd->_regIndex = kInvalidReg; + vd->_isStack = false; + vd->_isMemArg = false; + vd->_isCalculated = false; + vd->_saveOnUnuse = false; + vd->_modified = false; + vd->_reserved0 = 0; + vd->_alignment = static_cast(IntUtil::iMin(size, 64)); + + vd->_size = size; + vd->_homeMask = 0; + + vd->_memOffset = 0; + vd->_memCell = NULL; + + vd->rReadCount = 0; + vd->rWriteCount = 0; + vd->mReadCount = 0; + vd->mWriteCount = 0; + + vd->_va = NULL; + + if (_varList.append(vd) != kErrorOk) + goto _NoMemory; + return vd; + +_NoMemory: + setError(kErrorNoHeapMemory); + return NULL; +} + +void Compiler::alloc(Var& var) { + addHint(var, kVarHintAlloc, kInvalidValue); +} + +void Compiler::alloc(Var& var, uint32_t regIndex) { + addHint(var, kVarHintAlloc, regIndex); +} + +void Compiler::alloc(Var& var, const Reg& reg) { + addHint(var, kVarHintAlloc, reg.getRegIndex()); +} + +void Compiler::save(Var& var) { + addHint(var, kVarHintSave, kInvalidValue); +} + +void Compiler::spill(Var& var) { + addHint(var, kVarHintSpill, kInvalidValue); +} + +void Compiler::unuse(Var& var) { + addHint(var, kVarHintUnuse, kInvalidValue); +} + +uint32_t Compiler::getPriority(Var& var) const { + if (var.getId() == kInvalidValue) + return kInvalidValue; + + VarData* vd = getVdById(var.getId()); + return vd->getPriority(); +} + +void Compiler::setPriority(Var& var, uint32_t priority) { + if (var.getId() == kInvalidValue) + return; + + if (priority > 255) + priority = 255; + + VarData* vd = getVdById(var.getId()); + vd->_priority = static_cast(priority); +} + +bool Compiler::getSaveOnUnuse(Var& var) const { + if (var.getId() == kInvalidValue) + return false; + + VarData* vd = getVdById(var.getId()); + return static_cast(vd->_saveOnUnuse); +} + +void Compiler::setSaveOnUnuse(Var& var, bool value) { + if (var.getId() == kInvalidValue) + return; + + VarData* vd = getVdById(var.getId()); + vd->_saveOnUnuse = value; +} + +void Compiler::rename(Var& var, const char* name) { + if (var.getId() == kInvalidValue) + return; + + VarData* vd = getVdById(var.getId()); + vd->_name = noName; + + if (name != NULL && name[0] != '\0') { + vd->_name = _stringZone.sdup(name); + } +} + +// ============================================================================ +// [asmjit::Compiler - Assembler] +// ============================================================================ + +Assembler* Compiler::getAssembler() { + Assembler* a = _assembler; + + if (a != NULL) { + a->reset(false); + } + else { + a = _newAssembler(); + _assembler = a; + } + +#if !defined(ASMJIT_DISABLE_LOGGER) + Logger* logger = _logger; + if (logger != NULL) + a->setLogger(logger); +#endif // !ASMJIT_DISABLE_LOGGER + + a->setBaseAddress(_baseAddress); + a->setFeatures(_features); + + return a; +} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // !ASMJIT_DISABLE_COMPILER diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/compiler.h b/third/Blackbone/src/3rd_party/AsmJit/base/compiler.h new file mode 100644 index 0000000000000000000000000000000000000000..9d3a5335cccac00c70835f043b809246410f7b98 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/compiler.h @@ -0,0 +1,3159 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Guard] +#ifndef _ASMJIT_BASE_COMPILER_H +#define _ASMJIT_BASE_COMPILER_H + +#include "../build.h" +#if !defined(ASMJIT_DISABLE_COMPILER) + +// [Dependencies - AsmJit] +#include "../base/assembler.h" +#include "../base/codegen.h" +#include "../base/constpool.h" +#include "../base/containers.h" +#include "../base/error.h" +#include "../base/intutil.h" +#include "../base/operand.h" +#include "../base/zone.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [Forward Declarations] +// ============================================================================ + +struct Compiler; + +struct VarAttr; +struct VarData; +struct VarMap; +struct VarState; + +struct Node; +struct EndNode; +struct InstNode; +struct JumpNode; + +// ============================================================================ +// [asmjit::kConstScope] +// ============================================================================ + +//! \addtogroup asmjit_base_compiler +//! \{ + +//! Scope of the constant. +ASMJIT_ENUM(kConstScope) { + //! Local constant, always embedded right after the current function. + kConstScopeLocal = 0, + //! Global constant, embedded at the end of the currently compiled code. + kConstScopeGlobal = 1 +}; + +// ============================================================================ +// [asmjit::kVarType] +// ============================================================================ + +ASMJIT_ENUM(kVarType) { + //! Variable is 8-bit signed integer. + kVarTypeInt8 = 0, + //! Variable is 8-bit unsigned integer. + kVarTypeUInt8 = 1, + //! Variable is 16-bit signed integer. + kVarTypeInt16 = 2, + //! Variable is 16-bit unsigned integer. + kVarTypeUInt16 = 3, + //! Variable is 32-bit signed integer. + kVarTypeInt32 = 4, + //! Variable is 32-bit unsigned integer. + kVarTypeUInt32 = 5, + //! Variable is 64-bit signed integer. + kVarTypeInt64 = 6, + //! Variable is 64-bit unsigned integer. + kVarTypeUInt64 = 7, + + //! Variable is target `intptr_t`, not compatible with host `intptr_t`. + kVarTypeIntPtr = 8, + //! Variable is target `uintptr_t`, not compatible with host `uintptr_t`. + kVarTypeUIntPtr = 9, + + //! Variable is 32-bit floating point (single precision). + kVarTypeFp32 = 10, + //! Variable is 64-bit floating point (double precision). + kVarTypeFp64 = 11, + + //! \internal + _kVarTypeIntStart = kVarTypeInt8, + //! \internal + _kVarTypeIntEnd = kVarTypeUIntPtr, + + //! \internal + _kVarTypeFpStart = kVarTypeFp32, + //! \internal + _kVarTypeFpEnd = kVarTypeFp64 +}; + +// ============================================================================ +// [asmjit::kVarFlags] +// ============================================================================ + +//! \internal +//! +//! X86/X64 variable flags. +ASMJIT_ENUM(kVarFlags) { + //! Variable contains single-precision floating-point(s). + kVarFlagSp = 0x10, + //! Variable contains double-precision floating-point(s). + kVarFlagDp = 0x20, + //! Variable is packed, i.e. packed floats, doubles, ... + kVarFlagPacked = 0x40 +}; + +// ============================================================================ +// [asmjit::kVarAttrFlags] +// ============================================================================ + +//! Variable attribute flags. +ASMJIT_ENUM(kVarAttrFlags) { + //! Variable is accessed through register on input. + kVarAttrInReg = 0x00000001, + //! Variable is accessed through register on output. + kVarAttrOutReg = 0x00000002, + //! Variable is accessed through register on input & output. + kVarAttrInOutReg = 0x00000003, + + //! Variable is accessed through memory on input. + kVarAttrInMem = 0x00000004, + //! Variable is accessed through memory on output. + kVarAttrOutMem = 0x00000008, + //! Variable is accessed through memory on input & output. + kVarAttrInOutMem = 0x0000000C, + + //! Register allocator can decide if input will be in register or memory. + kVarAttrInDecide = 0x00000010, + //! Register allocator can decide if output will be in register or memory. + kVarAttrOutDecide = 0x00000020, + //! Register allocator can decide if in/out will be in register or memory. + kVarAttrInOutDecide = 0x00000030, + + //! Variable is converted to other type/class on the input. + kVarAttrInConv = 0x00000040, + //! Variable is converted from other type/class on the output. + kVarAttrOutConv = 0x00000080, + //! Combination of `kVarAttrInConv` and `kVarAttrOutConv`. + kVarAttrInOutConv = 0x000000C0, + + //! Variable is a function call operand. + kVarAttrInCall = 0x00000100, + //! Variable is a function argument passed in register. + kVarAttrInArg = 0x00000200, + + //! Variable is a function return value passed in register. + kVarAttrOutRet = 0x00000400, + //! Variable should be spilled. + kVarAttrSpill = 0x00000800, + //! Variable should be unused at the end of the instruction/node. + kVarAttrUnuse = 0x00001000, + + //! \internal + //! + //! All in-flags. + kVarAttrInAll = + kVarAttrInReg | + kVarAttrInMem | + kVarAttrInDecide | + kVarAttrInCall | + kVarAttrInArg, + + //! \internal + //! + //! All out-flags. + kVarAttrOutAll = + kVarAttrOutReg | + kVarAttrOutMem | + kVarAttrOutDecide | + kVarAttrOutRet, + + //! Variable is already allocated on the input. + kVarAttrAllocInDone = 0x00400000, + //! Variable is already allocated on the output. + kVarAttrAllocOutDone = 0x00800000 +}; + +// ============================================================================ +// [asmjit::kVarHint] +// ============================================================================ + +//! Variable hint (used by `Compiler)`. +//! +//! \sa Compiler. +ASMJIT_ENUM(kVarHint) { + //! Alloc variable. + kVarHintAlloc = 0, + //! Spill variable. + kVarHintSpill = 1, + //! Save variable if modified. + kVarHintSave = 2, + //! Save variable if modified and mark it as unused. + kVarHintSaveAndUnuse = 3, + //! Mark variable as unused. + kVarHintUnuse = 4 +}; + +// ============================================================================ +// [asmjit::kVarState] +// ============================================================================ + +//! State of variable. +//! +//! \note State of variable is used only during make process and it's not +//! visible to the developer. +ASMJIT_ENUM(kVarState) { + //! Variable is currently not used. + kVarStateUnused = 0, + + //! Variable is in register. + //! + //! Variable is currently allocated in register. + kVarStateReg = 1, + + //! Variable is in memory location or spilled. + //! + //! Variable was spilled from register to memory or variable is used for + //! memory only storage. + kVarStateMem = 2 +}; + +// ============================================================================ +// [asmjit::kFuncConv] +// ============================================================================ + +//! Function calling convention. +//! +//! For a platform specific calling conventions, see: +//! - `kX86FuncConv` - X86/X64 calling conventions. +ASMJIT_ENUM(kFuncConv) { + //! Calling convention is invalid (can't be used). + kFuncConvNone = 0, + +#if defined(ASMJIT_DOCGEN) + //! Default calling convention for current platform / operating system. + kFuncConvHost = DependsOnHost, + + //! Default C calling convention based on current compiler's settings. + kFuncConvHostCDecl = DependsOnHost, + + //! Compatibility for `__stdcall` calling convention. + //! + //! \note This enumeration is always set to a value which is compatible with + //! current compilers __stdcall calling convention. In 64-bit mode the value + //! is compatible with `kX86FuncConvW64` or `kX86FuncConvU64`. + kFuncConvHostStdCall = DependsOnHost, + + //! Compatibility for `__fastcall` calling convention. + //! + //! \note This enumeration is always set to a value which is compatible with + //! current compilers `__fastcall` calling convention. In 64-bit mode the value + //! is compatible with `kX86FuncConvW64` or `kX86FuncConvU64`. + kFuncConvHostFastCall = DependsOnHost +#endif // ASMJIT_DOCGEN +}; + +// ============================================================================ +// [asmjit::kFuncHint] +// ============================================================================ + +//! Function hints. +//! +//! For a platform specific calling conventions, see: +//! - `kX86FuncHint` - X86/X64 function hints. +ASMJIT_ENUM(kFuncHint) { + //! Make a naked function (default true). + //! + //! Naked function is function without using standard prolog/epilog sequence). + //! + //! X86/X64 Specific + //! ---------------- + //! + //! Standard prolog sequence is: + //! + //! ~~~ + //! push zbp + //! mov zsp, zbp + //! sub zsp, StackAdjustment + //! ~~~ + //! + //! which is an equivalent to: + //! + //! ~~~ + //! enter StackAdjustment, 0 + //! ~~~ + //! + //! Standard epilog sequence is: + //! + //! ~~~ + //! mov zsp, zbp + //! pop zbp + //! ~~~ + //! + //! which is an equavalent to: + //! + //! ~~~ + //! leave + //! ~~~ + //! + //! Naked functions can omit the prolog/epilog sequence. The advantage of + //! doing such modification is that EBP/RBP register can be used by the + //! register allocator which can result in less spills/allocs. + kFuncHintNaked = 0, + + //! Generate compact function prolog/epilog if possible. + //! + //! X86/X64 Specific + //! ---------------- + //! + //! Use shorter, but possible slower prolog/epilog sequence to save/restore + //! registers. + kFuncHintCompact = 1 +}; + +// ============================================================================ +// [asmjit::kFuncFlags] +// ============================================================================ + +//! Function flags. +//! +//! For a platform specific calling conventions, see: +//! - `kX86FuncFlags` - X86/X64 function flags. +ASMJIT_ENUM(kFuncFlags) { + //! Whether the function is using naked (minimal) prolog / epilog. + kFuncFlagIsNaked = 0x00000001, + + //! Whether an another function is called from this function. + kFuncFlagIsCaller = 0x00000002, + + //! Whether the stack is not aligned to the required stack alignment, + //! thus it has to be aligned manually. + kFuncFlagIsStackMisaligned = 0x00000004, + + //! Whether the stack pointer is adjusted by the stack size needed + //! to save registers and function variables. + //! + //! X86/X64 Specific + //! ---------------- + //! + //! Stack pointer (ESP/RSP) is adjusted by 'sub' instruction in prolog and by + //! 'add' instruction in epilog (only if function is not naked). If function + //! needs to perform manual stack alignment more instructions are used to + //! adjust the stack (like "and zsp, -Alignment"). + kFuncFlagIsStackAdjusted = 0x00000008, + + //! Whether the function is finished using `Compiler::endFunc()`. + kFuncFlagIsFinished = 0x80000000 +}; + +// ============================================================================ +// [asmjit::kFuncDir] +// ============================================================================ + +//! Function arguments direction. +ASMJIT_ENUM(kFuncDir) { + //! Arguments are passed left to right. + //! + //! This arguments direction is unusual in C, however it's used in Pascal. + kFuncDirLtr = 0, + + //! Arguments are passed right ro left + //! + //! This is the default argument direction in C. + kFuncDirRtl = 1 +}; + +// ============================================================================ +// [asmjit::kFuncArg] +// ============================================================================ + +//! Function argument (lo/hi) specification. +ASMJIT_ENUM(kFuncArg) { + //! Maxumum number of function arguments supported by AsmJit. + kFuncArgCount = 16, + //! Extended maximum number of arguments (used internally). + kFuncArgCountLoHi = kFuncArgCount * 2, + + //! Index to the LO part of function argument (default). + //! + //! This value is typically omitted and added only if there is HI argument + //! accessed. + kFuncArgLo = 0, + //! Index to the HI part of function argument. + //! + //! HI part of function argument depends on target architecture. On x86 it's + //! typically used to transfer 64-bit integers (they form a pair of 32-bit + //! integers). + kFuncArgHi = kFuncArgCount +}; + +// ============================================================================ +// [asmjit::kFuncRet] +// ============================================================================ + +//! Function return value (lo/hi) specification. +ASMJIT_ENUM(kFuncRet) { + //! Index to the LO part of function return value. + kFuncRetLo = 0, + //! Index to the HI part of function return value. + kFuncRetHi = 1 +}; + +// ============================================================================ +// [asmjit::kFuncStackInvalid] +// ============================================================================ + +enum kFuncMisc { + //! Invalid stack offset in function or function parameter. + kFuncStackInvalid = -1 +}; + +// ============================================================================ +// [asmjit::kNodeType] +// ============================================================================ + +//! Type of node, see \ref Node. +ASMJIT_ENUM(kNodeType) { + //! Invalid node (internal, can't be used). + kNodeTypeNone = 0, + //! Node is an .align directive, see \ref AlignNode. + kNodeTypeAlign, + //! Node is an embedded data, see \ref EmbedNode. + kNodeTypeEmbed, + //! Node is a comment, see \ref CommentNode. + kNodeTypeComment, + //! Node is a variable hint (alloc, spill, use, unuse), see \ref HintNode. + kNodeTypeHint, + //! Node is a label, see \ref TargetNode. + kNodeTypeTarget, + //! Node is an instruction, see \ref InstNode. + kNodeTypeInst, + //! Node is a function declaration, see \ref FuncNode. + kNodeTypeFunc, + //! Node is an end of the function, see \ref EndNode. + kNodeTypeEnd, + //! Node is a return, see \ref RetNode. + kNodeTypeRet, + //! Node is a function call, see \ref CallNode. + kNodeTypeCall, + //! Node is a function call argument moved on stack, see \ref SArgNode. + kNodeTypeSArg +}; + +// ============================================================================ +// [asmjit::kNodeFlags] +// ============================================================================ + +ASMJIT_ENUM(kNodeFlags) { + //! Whether the node has been translated, thus contains only registers. + kNodeFlagIsTranslated = 0x0001, + + //! Whether the node was scheduled - possibly reordered, but basically this + //! is a mark that is set by scheduler after the node has been visited. + kNodeFlagIsScheduled = 0x0002, + + //! Whether the node is informative only and can be safely removed. + kNodeFlagIsInformative = 0x0004, + + //! Whether the `InstNode` is a jump. + kNodeFlagIsJmp = 0x0008, + //! Whether the `InstNode` is a conditional jump. + kNodeFlagIsJcc = 0x0010, + + //! Whether the `InstNode` is an unconditinal jump or conditional + //! jump that is likely to be taken. + kNodeFlagIsTaken = 0x0020, + + //! Whether the `Node` will return from a function. + //! + //! This flag is used by both `EndNode` and `RetNode`. + kNodeFlagIsRet = 0x0040, + + //! Whether the instruction is special. + kNodeFlagIsSpecial = 0x0080, + + //! Whether the instruction is an FPU instruction. + kNodeFlagIsFp = 0x0100 +}; + +// ============================================================================ +// [asmjit::MemCell] +// ============================================================================ + +struct MemCell { + ASMJIT_NO_COPY(MemCell) + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get cell offset. + ASMJIT_INLINE int32_t getOffset() const { return _offset; } + //! Set cell offset. + ASMJIT_INLINE void setOffset(int32_t offset) { _offset = offset; } + + //! Get cell size. + ASMJIT_INLINE uint32_t getSize() const { return _size; } + //! Set cell size. + ASMJIT_INLINE void setSize(uint32_t size) { _size = size; } + + //! Get cell alignment. + ASMJIT_INLINE uint32_t getAlignment() const { return _alignment; } + //! Set cell alignment. + ASMJIT_INLINE void setAlignment(uint32_t alignment) { _alignment = alignment; } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Next active cell. + MemCell* _next; + + //! Offset, relative to base-offset. + int32_t _offset; + //! Size. + uint32_t _size; + //! Alignment. + uint32_t _alignment; +}; + +// ============================================================================ +// [asmjit::Var] +// ============================================================================ + +//! Base class for all variables. +struct Var : public Operand { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE Var() : Operand(NoInit) { + _init_packed_op_sz_b0_b1_id(kOperandTypeVar, 0, 0, 0, kInvalidValue); + _init_packed_d2_d3(kInvalidValue, kInvalidValue); + } + + ASMJIT_INLINE Var(const Var& other) : Operand(other) {} + + explicit ASMJIT_INLINE Var(const _NoInit&) : Operand(NoInit) {} + + // -------------------------------------------------------------------------- + // [Var Specific] + // -------------------------------------------------------------------------- + + //! Clone `Var` operand. + ASMJIT_INLINE Var clone() const { + return Var(*this); + } + + //! Reset Var operand. + ASMJIT_INLINE void reset() { + _init_packed_op_sz_b0_b1_id(kOperandTypeVar, 0, kInvalidReg, kInvalidReg, kInvalidValue); + _init_packed_d2_d3(kInvalidValue, kInvalidValue); + } + + //! Get whether the variable has been initialized by `Compiler`. + ASMJIT_INLINE bool isInitialized() const { + return _vreg.id != kInvalidValue; + } + + //! Get variable type. + ASMJIT_INLINE uint32_t getVarType() const { + return _vreg.vType; + } + + // -------------------------------------------------------------------------- + // [Operator Overload] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE Var& operator=(const Var& other) { _copy(other); return *this; } + + ASMJIT_INLINE bool operator==(const Var& other) const { return _packed[0] == other._packed[0]; } + ASMJIT_INLINE bool operator!=(const Var& other) const { return !operator==(other); } +}; + +// ============================================================================ +// [asmjit::VarBits] +// ============================================================================ + +//! Bit-array used by variable-liveness analysis. +struct VarBits { + // -------------------------------------------------------------------------- + // [Enums] + // -------------------------------------------------------------------------- + + enum { + kEntitySize = static_cast(sizeof(uintptr_t)), + kEntityBits = kEntitySize * 8 + }; + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE uintptr_t getBit(uint32_t index) const { + return (data[index / kEntityBits] >> (index % kEntityBits)) & 1; + } + + ASMJIT_INLINE void setBit(uint32_t index) { + data[index / kEntityBits] |= static_cast(1) << (index % kEntityBits); + } + + ASMJIT_INLINE void delBit(uint32_t index) { + data[index / kEntityBits] &= ~(static_cast(1) << (index % kEntityBits)); + } + + // -------------------------------------------------------------------------- + // [Ops] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE bool copyBits(const VarBits* s0, uint32_t len) { + uintptr_t r = 0; + for (uint32_t i = 0; i < len; i++) { + uintptr_t t = s0->data[i]; + data[i] = t; + r |= t; + } + return r != 0; + } + + ASMJIT_INLINE bool addBits(const VarBits* s0, uint32_t len) { + return addBits(this, s0, len); + } + + ASMJIT_INLINE bool addBits(const VarBits* s0, const VarBits* s1, uint32_t len) { + uintptr_t r = 0; + for (uint32_t i = 0; i < len; i++) { + uintptr_t t = s0->data[i] | s1->data[i]; + data[i] = t; + r |= t; + } + return r != 0; + } + + ASMJIT_INLINE bool andBits(const VarBits* s1, uint32_t len) { + return andBits(this, s1, len); + } + + ASMJIT_INLINE bool andBits(const VarBits* s0, const VarBits* s1, uint32_t len) { + uintptr_t r = 0; + for (uint32_t i = 0; i < len; i++) { + uintptr_t t = s0->data[i] & s1->data[i]; + data[i] = t; + r |= t; + } + return r != 0; + } + + ASMJIT_INLINE bool delBits(const VarBits* s1, uint32_t len) { + return delBits(this, s1, len); + } + + ASMJIT_INLINE bool delBits(const VarBits* s0, const VarBits* s1, uint32_t len) { + uintptr_t r = 0; + for (uint32_t i = 0; i < len; i++) { + uintptr_t t = s0->data[i] & ~s1->data[i]; + data[i] = t; + r |= t; + } + return r != 0; + } + + ASMJIT_INLINE bool _addBitsDelSource(VarBits* s1, uint32_t len) { + return _addBitsDelSource(this, s1, len); + } + + ASMJIT_INLINE bool _addBitsDelSource(const VarBits* s0, VarBits* s1, uint32_t len) { + uintptr_t r = 0; + for (uint32_t i = 0; i < len; i++) { + uintptr_t a = s0->data[i]; + uintptr_t b = s1->data[i]; + + this->data[i] = a | b; + b &= ~a; + + s1->data[i] = b; + r |= b; + } + return r != 0; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + uintptr_t data[1]; +}; + +// ============================================================================ +// [asmjit::VarData] +// ============================================================================ + +//! Base variable data. +struct VarData { + // -------------------------------------------------------------------------- + // [Accessors - Base] + // -------------------------------------------------------------------------- + + //! Get variable name. + ASMJIT_INLINE const char* getName() const { + return _name; + } + + //! Get variable id. + ASMJIT_INLINE uint32_t getId() const { + return _id; + } + + //! Get variable type. + ASMJIT_INLINE uint32_t getType() const { + return _type; + } + + //! Get variable class. + ASMJIT_INLINE uint32_t getClass() const { + return _class; + } + + // -------------------------------------------------------------------------- + // [Accessors - ContextId] + // -------------------------------------------------------------------------- + + //! Get whether the variable has context id. + ASMJIT_INLINE bool hasContextId() const { + return _contextId != kInvalidValue; + } + + //! Get context variable id (used only by `Context)`. + ASMJIT_INLINE uint32_t getContextId() const { + return _contextId; + } + + //! Set context variable id (used only by `Context)`. + ASMJIT_INLINE void setContextId(uint32_t contextId) { + _contextId = contextId; + } + + //! Reset context variable id (used only by `Context)`. + ASMJIT_INLINE void resetContextId() { + _contextId = kInvalidValue; + } + + // -------------------------------------------------------------------------- + // [Accessors - Priority] + // -------------------------------------------------------------------------- + + //! Get variable priority, used by compiler to decide which variable to spill. + ASMJIT_INLINE uint32_t getPriority() const { + return _priority; + } + + //! Set variable priority. + ASMJIT_INLINE void setPriority(uint32_t priority) { + ASMJIT_ASSERT(priority <= 0xFF); + _priority = static_cast(priority); + } + + // -------------------------------------------------------------------------- + // [Accessors - State] + // -------------------------------------------------------------------------- + + //! Get variable state, only used by `Context`. + ASMJIT_INLINE uint32_t getState() const { + return _state; + } + + //! Set variable state, only used by `Context`. + ASMJIT_INLINE void setState(uint32_t state) { + ASMJIT_ASSERT(state <= 0xFF); + _state = static_cast(state); + } + + // -------------------------------------------------------------------------- + // [Accessors - RegIndex] + // -------------------------------------------------------------------------- + + //! Get register index. + ASMJIT_INLINE uint32_t getRegIndex() const { + return _regIndex; + } + + //! Set register index. + ASMJIT_INLINE void setRegIndex(uint32_t regIndex) { + ASMJIT_ASSERT(regIndex <= 0xFF); + _regIndex = static_cast(regIndex); + } + + //! Reset register index. + ASMJIT_INLINE void resetRegIndex() { + _regIndex = static_cast(kInvalidReg); + } + + // -------------------------------------------------------------------------- + // [Accessors - HomeIndex/Mask] + // -------------------------------------------------------------------------- + + //! Get home registers mask. + ASMJIT_INLINE uint32_t getHomeMask() const { + return _homeMask; + } + + //! Add a home register index to the home registers mask. + ASMJIT_INLINE void addHomeIndex(uint32_t regIndex) { + _homeMask |= IntUtil::mask(regIndex); + } + + // -------------------------------------------------------------------------- + // [Accessors - Flags] + // -------------------------------------------------------------------------- + + //! Get variable flags. + ASMJIT_INLINE uint32_t getFlags() const { + return _flags; + } + + //! Get whether the VarData is only memory allocated on the stack. + ASMJIT_INLINE bool isStack() const { return static_cast(_isStack); } + + //! Get whether the variable is a function argument passed through memory. + ASMJIT_INLINE bool isMemArg() const { return static_cast(_isMemArg); } + + //! Get variable content can be calculated by a simple instruction. + ASMJIT_INLINE bool isCalculated() const { return static_cast(_isCalculated); } + //! Get whether to save variable when it's unused (spill). + ASMJIT_INLINE bool saveOnUnuse() const { return static_cast(_saveOnUnuse); } + + //! Get whether the variable was changed. + ASMJIT_INLINE bool isModified() const { return static_cast(_modified); } + //! Set whether the variable was changed. + ASMJIT_INLINE void setModified(bool modified) { _modified = modified; } + + //! Get variable alignment. + ASMJIT_INLINE uint32_t getAlignment() const { return _alignment; } + //! Get variable size. + ASMJIT_INLINE uint32_t getSize() const { return _size; } + + //! Get home memory offset. + ASMJIT_INLINE int32_t getMemOffset() const { return _memOffset; } + //! Set home memory offset. + ASMJIT_INLINE void setMemOffset(int32_t offset) { _memOffset = offset; } + + //! Get home memory cell. + ASMJIT_INLINE MemCell* getMemCell() const { return _memCell; } + //! Set home memory cell. + ASMJIT_INLINE void setMemCell(MemCell* cell) { _memCell = cell; } + + // -------------------------------------------------------------------------- + // [Accessors - Temporary Usage] + // -------------------------------------------------------------------------- + + //! Get temporary VarAttr. + ASMJIT_INLINE VarAttr* getVa() const { return _va; } + //! Set temporary VarAttr. + ASMJIT_INLINE void setVa(VarAttr* va) { _va = va; } + //! Reset temporary VarAttr. + ASMJIT_INLINE void resetVa() { _va = NULL; } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Variable name. + const char* _name; + + //! Variable id. + uint32_t _id; + //! Context variable id, used by `Context` only, initially `kInvalidValue`. + uint32_t _contextId; + + //! Variable type. + uint8_t _type; + //! Variable class. + uint8_t _class; + //! Variable flags. + uint8_t _flags; + //! Variable priority. + uint8_t _priority; + + //! Variable state (connected with actual `VarState)`. + uint8_t _state; + //! Actual register index (only used by `Context)`, during translate. + uint8_t _regIndex; + + //! Whether the variable is only used as memory allocated on the stack. + uint8_t _isStack : 1; + //! Whether the variable is a function argument passed through memory. + uint8_t _isMemArg : 1; + //! Whether variable content can be calculated by a simple instruction. + //! + //! This is used mainly by MMX and SSE2 code. This flag indicates that + //! register allocator should never reserve memory for this variable, because + //! the content can be generated by a single instruction (for example PXOR). + uint8_t _isCalculated : 1; + //! Save on unuse (at end of the variable scope). + uint8_t _saveOnUnuse : 1; + //! Whether variable was changed (connected with actual `VarState)`. + uint8_t _modified : 1; + //! \internal + uint8_t _reserved0 : 3; + //! Variable natural alignment. + uint8_t _alignment; + + //! Variable size. + uint32_t _size; + + //! Mask of all registers variable has been allocated to. + uint32_t _homeMask; + + //! Home memory offset. + int32_t _memOffset; + //! Home memory cell, used by `Context` (initially NULL). + MemCell* _memCell; + + //! Register read access statistics. + uint32_t rReadCount; + //! Register write access statistics. + uint32_t rWriteCount; + + //! Memory read statistics. + uint32_t mReadCount; + //! Memory write statistics. + uint32_t mWriteCount; + + // -------------------------------------------------------------------------- + // [Members - Temporary Usage] + // -------------------------------------------------------------------------- + + // These variables are only used during register allocation. They are + // initialized by init() phase and reset by cleanup() phase. + + union { + //! Temporary link to VarAttr* used by the `Context` used in + //! various phases, but always set back to NULL when finished. + //! + //! This temporary data is designed to be used by algorithms that need to + //! store some data into variables themselves during compilation. But it's + //! expected that after variable is compiled & translated the data is set + //! back to zero/null. Initial value is NULL. + VarAttr* _va; + + //! \internal + //! + //! Same as `_va` just provided as `uintptr_t`. + uintptr_t _vaUInt; + }; +}; + +// ============================================================================ +// [asmjit::VarAttr] +// ============================================================================ + +struct VarAttr { + // -------------------------------------------------------------------------- + // [Setup] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE void setup(VarData* vd, uint32_t flags = 0, uint32_t inRegs = 0, uint32_t allocableRegs = 0) { + _vd = vd; + _flags = flags; + _varCount = 0; + _inRegIndex = kInvalidReg; + _outRegIndex = kInvalidReg; + _reserved = 0; + _inRegs = inRegs; + _allocableRegs = allocableRegs; + } + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get VarData. + ASMJIT_INLINE VarData* getVd() const { return _vd; } + //! Set VarData. + ASMJIT_INLINE void setVd(VarData* vd) { _vd = vd; } + + //! Get flags. + ASMJIT_INLINE uint32_t getFlags() const { return _flags; } + //! Set flags. + ASMJIT_INLINE void setFlags(uint32_t flags) { _flags = flags; } + + //! Get whether `flag` is on. + ASMJIT_INLINE bool hasFlag(uint32_t flag) { return (_flags & flag) != 0; } + //! Add `flags`. + ASMJIT_INLINE void orFlags(uint32_t flags) { _flags |= flags; } + //! Mask `flags`. + ASMJIT_INLINE void andFlags(uint32_t flags) { _flags &= flags; } + //! Clear `flags`. + ASMJIT_INLINE void andNotFlags(uint32_t flags) { _flags &= ~flags; } + + //! Get how many times the variable is used by the instruction/node. + ASMJIT_INLINE uint32_t getVarCount() const { return _varCount; } + //! Set how many times the variable is used by the instruction/node. + ASMJIT_INLINE void setVarCount(uint32_t count) { _varCount = static_cast(count); } + //! Add how many times the variable is used by the instruction/node. + ASMJIT_INLINE void addVarCount(uint32_t count = 1) { _varCount += static_cast(count); } + + //! Get whether the variable has to be allocated in a specific input register. + ASMJIT_INLINE uint32_t hasInRegIndex() const { return _inRegIndex != kInvalidReg; } + //! Get the input register index or `kInvalidReg`. + ASMJIT_INLINE uint32_t getInRegIndex() const { return _inRegIndex; } + //! Set the input register index. + ASMJIT_INLINE void setInRegIndex(uint32_t index) { _inRegIndex = static_cast(index); } + //! Reset the input register index. + ASMJIT_INLINE void resetInRegIndex() { _inRegIndex = kInvalidReg; } + + //! Get whether the variable has to be allocated in a specific output register. + ASMJIT_INLINE uint32_t hasOutRegIndex() const { return _outRegIndex != kInvalidReg; } + //! Get the output register index or `kInvalidReg`. + ASMJIT_INLINE uint32_t getOutRegIndex() const { return _outRegIndex; } + //! Set the output register index. + ASMJIT_INLINE void setOutRegIndex(uint32_t index) { _outRegIndex = static_cast(index); } + //! Reset the output register index. + ASMJIT_INLINE void resetOutRegIndex() { _outRegIndex = kInvalidReg; } + + //! Get whether the mandatory input registers are in used. + ASMJIT_INLINE bool hasInRegs() const { return _inRegs != 0; } + //! Get mandatory input registers (mask). + ASMJIT_INLINE uint32_t getInRegs() const { return _inRegs; } + //! Set mandatory input registers (mask). + ASMJIT_INLINE void setInRegs(uint32_t mask) { _inRegs = mask; } + //! Add mandatory input registers (mask). + ASMJIT_INLINE void addInRegs(uint32_t mask) { _inRegs |= mask; } + //! And mandatory input registers (mask). + ASMJIT_INLINE void andInRegs(uint32_t mask) { _inRegs &= mask; } + //! Clear mandatory input registers (mask). + ASMJIT_INLINE void delInRegs(uint32_t mask) { _inRegs &= ~mask; } + + //! Get allocable input registers (mask). + ASMJIT_INLINE uint32_t getAllocableRegs() const { return _allocableRegs; } + //! Set allocable input registers (mask). + ASMJIT_INLINE void setAllocableRegs(uint32_t mask) { _allocableRegs = mask; } + //! Add allocable input registers (mask). + ASMJIT_INLINE void addAllocableRegs(uint32_t mask) { _allocableRegs |= mask; } + //! And allocable input registers (mask). + ASMJIT_INLINE void andAllocableRegs(uint32_t mask) { _allocableRegs &= mask; } + //! Clear allocable input registers (mask). + ASMJIT_INLINE void delAllocableRegs(uint32_t mask) { _allocableRegs &= ~mask; } + + // -------------------------------------------------------------------------- + // [Operator Overload] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE VarAttr& operator=(const VarAttr& other) { + ::memcpy(this, &other, sizeof(VarAttr)); + return *this; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + VarData* _vd; + //! Flags. + uint32_t _flags; + + union { + struct { + //! How many times the variable is used by the instruction/node. + uint8_t _varCount; + //! Input register index or `kInvalidReg` if it's not given. + //! + //! Even if the input register index is not given (i.e. it may by any + //! register), register allocator should assign an index that will be + //! used to persist a variable into this specific index. It's helpful + //! in situations where one variable has to be allocated in multiple + //! registers to determine the register which will be persistent. + uint8_t _inRegIndex; + //! Output register index or `kInvalidReg` if it's not given. + //! + //! Typically `kInvalidReg` if variable is only used on input. + uint8_t _outRegIndex; + //! \internal + uint8_t _reserved; + }; + + //! \internal + //! + //! Packed data #0. + uint32_t _packed; + }; + + //! Mandatory input registers. + //! + //! Mandatory input registers are required by the instruction even if + //! there are duplicates. This schema allows us to allocate one variable + //! in one or more register when needed. Required mostly by instructions + //! that have implicit register operands (imul, cpuid, ...) and function + //! call. + uint32_t _inRegs; + + //! Allocable input registers. + //! + //! Optional input registers is a mask of all allocable registers for a given + //! variable where we have to pick one of them. This mask is usually not used + //! when _inRegs is set. If both masks are used then the register + //! allocator tries first to find an intersection between these and allocates + //! an extra slot if not found. + uint32_t _allocableRegs; +}; + +// ============================================================================ +// [asmjit::VarMap] +// ============================================================================ + +//! Variables' map related to a single node (instruction / other node). +struct VarMap { + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get count of variables (all). + ASMJIT_INLINE uint32_t getVaCount() const { + return _vaCount; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Variables count. + uint32_t _vaCount; +}; + +// ============================================================================ +// [asmjit::VarState] +// ============================================================================ + +//! Variables' state. +struct VarState {}; + +// ============================================================================ +// [asmjit::TypeId / VarMapping] +// ============================================================================ + +//! Function builder 'void' type. +struct Void {}; + +//! Function builder 'int8_t' type. +struct Int8Type {}; +//! Function builder 'uint8_t' type. +struct UInt8Type {}; + +//! Function builder 'int16_t' type. +struct Int16Type {}; +//! Function builder 'uint16_t' type. +struct UInt16Type {}; + +//! Function builder 'int32_t' type. +struct Int32Type {}; +//! Function builder 'uint32_t' type. +struct UInt32Type {}; + +//! Function builder 'int64_t' type. +struct Int64Type {}; +//! Function builder 'uint64_t' type. +struct UInt64Type {}; + +//! Function builder 'intptr_t' type. +struct IntPtrType {}; +//! Function builder 'uintptr_t' type. +struct UIntPtrType {}; + +//! Function builder 'float' type. +struct FloatType {}; +//! Function builder 'double' type. +struct DoubleType {}; + +#if !defined(ASMJIT_DOCGEN) +template +struct TypeId { + enum { kId = static_cast(::asmjit::kInvalidVar) }; +}; + +template +struct TypeId { + enum { kId = kVarTypeIntPtr }; +}; + +#define ASMJIT_TYPE_ID(_T_, _Id_) \ + template<> \ + struct TypeId<_T_> { enum { kId = _Id_ }; } + +ASMJIT_TYPE_ID(void, kInvalidVar); +ASMJIT_TYPE_ID(Void, kInvalidVar); + +ASMJIT_TYPE_ID(int8_t, kVarTypeInt8); +ASMJIT_TYPE_ID(Int8Type, kVarTypeInt8); + +ASMJIT_TYPE_ID(uint8_t, kVarTypeUInt8); +ASMJIT_TYPE_ID(UInt8Type, kVarTypeUInt8); + +ASMJIT_TYPE_ID(int16_t, kVarTypeInt16); +ASMJIT_TYPE_ID(Int16Type, kVarTypeInt16); + +ASMJIT_TYPE_ID(uint16_t, kVarTypeUInt8); +ASMJIT_TYPE_ID(UInt16Type, kVarTypeUInt8); + +ASMJIT_TYPE_ID(int32_t, kVarTypeInt32); +ASMJIT_TYPE_ID(Int32Type, kVarTypeUInt8); + +ASMJIT_TYPE_ID(uint32_t, kVarTypeUInt32); +ASMJIT_TYPE_ID(UInt32Type, kVarTypeUInt8); + +ASMJIT_TYPE_ID(int64_t, kVarTypeInt64); +ASMJIT_TYPE_ID(Int64Type, kVarTypeUInt8); + +ASMJIT_TYPE_ID(uint64_t, kVarTypeUInt64); +ASMJIT_TYPE_ID(UInt64Type, kVarTypeUInt8); + +ASMJIT_TYPE_ID(float, kVarTypeFp32); +ASMJIT_TYPE_ID(FloatType, kVarTypeFp32); + +ASMJIT_TYPE_ID(double, kVarTypeFp64); +ASMJIT_TYPE_ID(DoubleType, kVarTypeFp64); +#endif // !ASMJIT_DOCGEN + +// ============================================================================ +// [asmjit::FuncInOut] +// ============================================================================ + +//! Function in/out - argument or return value translated from `FuncPrototype`. +struct FuncInOut { + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE uint32_t getVarType() const { return _varType; } + + ASMJIT_INLINE bool hasRegIndex() const { return _regIndex != kInvalidReg; } + ASMJIT_INLINE uint32_t getRegIndex() const { return _regIndex; } + + ASMJIT_INLINE bool hasStackOffset() const { return _stackOffset != kFuncStackInvalid; } + ASMJIT_INLINE int32_t getStackOffset() const { return static_cast(_stackOffset); } + + //! Get whether the argument / return value is assigned. + ASMJIT_INLINE bool isSet() const { + return (_regIndex != kInvalidReg) | (_stackOffset != kFuncStackInvalid); + } + + // -------------------------------------------------------------------------- + // [Reset] + // -------------------------------------------------------------------------- + + //! Reset the function argument to "unassigned state". + ASMJIT_INLINE void reset() { _packed = 0xFFFFFFFF; } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + union { + struct { + //! Variable type, see `kVarType`. + uint8_t _varType; + //! Register index if argument / return value is a register. + uint8_t _regIndex; + //! Stack offset if argument / return value is on the stack. + int16_t _stackOffset; + }; + + //! All members packed into single 32-bit integer. + uint32_t _packed; + }; +}; + +// ============================================================================ +// [asmjit::FuncPrototype] +// ============================================================================ + +//! Function prototype. +//! +//! Function prototype contains information about function return type, count +//! of arguments and their types. Function prototype is a low level structure +//! which doesn't contain platform specific or calling convention specific +//! information. Function prototype is used to create a `FuncDecl`. +struct FuncPrototype { + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get function return value. + ASMJIT_INLINE uint32_t getRet() const { return _ret; } + + //! Get function arguments' IDs. + ASMJIT_INLINE const uint32_t* getArgList() const { return _argList; } + //! Get count of function arguments. + ASMJIT_INLINE uint32_t getArgCount() const { return _argCount; } + + //! Get argument at index `id`. + ASMJIT_INLINE uint32_t getArg(uint32_t id) const { + ASMJIT_ASSERT(id < _argCount); + return _argList[id]; + } + + //! Set function definition - return type and arguments. + ASMJIT_INLINE void _setPrototype(uint32_t ret, const uint32_t* argList, uint32_t argCount) { + _ret = ret; + _argList = argList; + _argCount = argCount; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + uint32_t _ret; + uint32_t _argCount; + const uint32_t* _argList; +}; + +// ============================================================================ +// [asmjit::FuncBuilderX] +// ============================================================================ + +//! Custom function builder for up to 32 function arguments. +struct FuncBuilderX : public FuncPrototype { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE FuncBuilderX() { + _setPrototype(kInvalidVar, _builderArgList, 0); + } + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Set return type to `retType`. + ASMJIT_INLINE void setRet(uint32_t retType) { + _ret = retType; + } + + ASMJIT_INLINE void setArg(uint32_t id, uint32_t type) { + ASMJIT_ASSERT(id < _argCount); + _builderArgList[id] = type; + } + + ASMJIT_INLINE void addArg(uint32_t type) { + ASMJIT_ASSERT(_argCount < kFuncArgCount); + _builderArgList[_argCount++] = type; + } + + template + ASMJIT_INLINE void setRetT() { + setRet(TypeId::kId); + } + + template + ASMJIT_INLINE void setArgT(uint32_t id) { + setArg(id, TypeId::kId); + } + + template + ASMJIT_INLINE void addArgT() { + addArg(TypeId::kId); + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + uint32_t _builderArgList[kFuncArgCount]; +}; + +//! \internal +#define T(_Type_) TypeId<_Type_>::kId + +//! Function prototype (no args). +template +struct FuncBuilder0 : public FuncPrototype { + ASMJIT_INLINE FuncBuilder0() { + _setPrototype(T(RET), NULL, 0); + } +}; + +//! Function prototype (1 argument). +template +struct FuncBuilder1 : public FuncPrototype { + ASMJIT_INLINE FuncBuilder1() { + static const uint32_t args[] = { T(P0) }; + _setPrototype(T(RET), args, ASMJIT_ARRAY_SIZE(args)); + } +}; + +//! Function prototype (2 arguments). +template +struct FuncBuilder2 : public FuncPrototype { + ASMJIT_INLINE FuncBuilder2() { + static const uint32_t args[] = { T(P0), T(P1) }; + _setPrototype(T(RET), args, ASMJIT_ARRAY_SIZE(args)); + } +}; + +//! Function prototype (3 arguments). +template +struct FuncBuilder3 : public FuncPrototype { + ASMJIT_INLINE FuncBuilder3() { + static const uint32_t args[] = { T(P0), T(P1), T(P2) }; + _setPrototype(T(RET), args, ASMJIT_ARRAY_SIZE(args)); + } +}; + +//! Function prototype (4 arguments). +template +struct FuncBuilder4 : public FuncPrototype { + ASMJIT_INLINE FuncBuilder4() { + static const uint32_t args[] = { T(P0), T(P1), T(P2), T(P3) }; + _setPrototype(T(RET), args, ASMJIT_ARRAY_SIZE(args)); + } +}; + +//! Function prototype (5 arguments). +template +struct FuncBuilder5 : public FuncPrototype { + ASMJIT_INLINE FuncBuilder5() { + static const uint32_t args[] = { T(P0), T(P1), T(P2), T(P3), T(P4) }; + _setPrototype(T(RET), args, ASMJIT_ARRAY_SIZE(args)); + } +}; + +//! Function prototype (6 arguments). +template +struct FuncBuilder6 : public FuncPrototype { + ASMJIT_INLINE FuncBuilder6() { + static const uint32_t args[] = { T(P0), T(P1), T(P2), T(P3), T(P4), T(P5) }; + _setPrototype(T(RET), args, ASMJIT_ARRAY_SIZE(args)); + } +}; + +//! Function prototype (7 arguments). +template +struct FuncBuilder7 : public FuncPrototype { + ASMJIT_INLINE FuncBuilder7() { + static const uint32_t args[] = { T(P0), T(P1), T(P2), T(P3), T(P4), T(P5), T(P6) }; + _setPrototype(T(RET), args, ASMJIT_ARRAY_SIZE(args)); + } +}; + +//! Function prototype (8 arguments). +template +struct FuncBuilder8 : public FuncPrototype { + ASMJIT_INLINE FuncBuilder8() { + static const uint32_t args[] = { T(P0), T(P1), T(P2), T(P3), T(P4), T(P5), T(P6), T(P7) }; + _setPrototype(T(RET), args, ASMJIT_ARRAY_SIZE(args)); + } +}; + +//! Function prototype (9 arguments). +template +struct FuncBuilder9 : public FuncPrototype { + ASMJIT_INLINE FuncBuilder9() { + static const uint32_t args[] = { T(P0), T(P1), T(P2), T(P3), T(P4), T(P5), T(P6), T(P7), T(P8) }; + _setPrototype(T(RET), args, ASMJIT_ARRAY_SIZE(args)); + } +}; + +//! Function prototype (10 arguments). +template +struct FuncBuilder10 : public FuncPrototype { + ASMJIT_INLINE FuncBuilder10() { + static const uint32_t args[] = { T(P0), T(P1), T(P2), T(P3), T(P4), T(P5), T(P6), T(P7), T(P8), T(P9) }; + _setPrototype(T(RET), args, ASMJIT_ARRAY_SIZE(args)); + } +}; + +#undef T + +// ============================================================================ +// [asmjit::FuncDecl] +// ============================================================================ + +//! Function declaration. +struct FuncDecl { + // -------------------------------------------------------------------------- + // [Accessors - Calling Convention] + // -------------------------------------------------------------------------- + + //! Get function calling convention, see `kFuncConv`. + ASMJIT_INLINE uint32_t getConvention() const { return _convention; } + + //! Get whether the callee pops the stack. + ASMJIT_INLINE uint32_t getCalleePopsStack() const { return _calleePopsStack; } + + //! Get direction of arguments passed on the stack. + //! + //! Direction should be always `kFuncDirRtl`. + //! + //! \note This is related to used calling convention, it's not affected by + //! number of function arguments or their types. + ASMJIT_INLINE uint32_t getDirection() const { return _direction; } + + //! Get stack size needed for function arguments passed on the stack. + ASMJIT_INLINE uint32_t getArgStackSize() const { return _argStackSize; } + //! Get size of "Red Zone". + ASMJIT_INLINE uint32_t getRedZoneSize() const { return _redZoneSize; } + //! Get size of "Spill Zone". + ASMJIT_INLINE uint32_t getSpillZoneSize() const { return _spillZoneSize; } + + // -------------------------------------------------------------------------- + // [Accessors - Arguments and Return] + // -------------------------------------------------------------------------- + + //! Get whether the function has a return value. + ASMJIT_INLINE bool hasRet() const { return _retCount != 0; } + //! Get count of function return values. + ASMJIT_INLINE uint32_t getRetCount() const { return _retCount; } + + //! Get function return value. + ASMJIT_INLINE FuncInOut& getRet(uint32_t index = kFuncRetLo) { return _retList[index]; } + //! Get function return value. + ASMJIT_INLINE const FuncInOut& getRet(uint32_t index = kFuncRetLo) const { return _retList[index]; } + + //! Get count of function arguments. + ASMJIT_INLINE uint32_t getArgCount() const { return _argCount; } + + //! Get function arguments array. + ASMJIT_INLINE FuncInOut* getArgList() { return _argList; } + //! Get function arguments array (const). + ASMJIT_INLINE const FuncInOut* getArgList() const { return _argList; } + + //! Get function argument at index `index`. + ASMJIT_INLINE FuncInOut& getArg(size_t index) { + ASMJIT_ASSERT(index < kFuncArgCountLoHi); + return _argList[index]; + } + + //! Get function argument at index `index`. + ASMJIT_INLINE const FuncInOut& getArg(size_t index) const { + ASMJIT_ASSERT(index < kFuncArgCountLoHi); + return _argList[index]; + } + + ASMJIT_INLINE void resetArg(size_t index) { + ASMJIT_ASSERT(index < kFuncArgCountLoHi); + _argList[index].reset(); + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Calling convention. + uint8_t _convention; + //! Whether a callee pops stack. + uint8_t _calleePopsStack : 1; + //! Direction for arguments passed on the stack, see `kFuncDir`. + uint8_t _direction : 1; + //! Reserved #0 (alignment). + uint8_t _reserved0 : 6; + + //! Count of arguments in `_argList`. + uint8_t _argCount; + //! Count of return value(s). + uint8_t _retCount; + + //! Count of bytes consumed by arguments on the stack (aligned). + uint32_t _argStackSize; + + //! Size of "Red Zone". + //! + //! \note Used by AMD64-ABI (128 bytes). + uint16_t _redZoneSize; + + //! Size of "Spill Zone". + //! + //! \note Used by WIN64-ABI (32 bytes). + uint16_t _spillZoneSize; + + //! Function arguments (including HI arguments) mapped to physical + //! registers and stack offset. + FuncInOut _argList[kFuncArgCountLoHi]; + + //! Function return value(s). + FuncInOut _retList[2]; +}; + +// ============================================================================ +// [asmjit::Node] +// ============================================================================ + +//! Base node. +//! +//! `Every` node represents an abstract instruction, directive, label, or +//! macro-instruction generated by compiler. +struct Node { + ASMJIT_NO_COPY(Node) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create new `Node`. + //! + //! \note Always use compiler to create nodes. + ASMJIT_INLINE Node(Compiler* compiler, uint32_t type); // Defined-Later. + + //! Destroy `Node`. + ASMJIT_INLINE ~Node() {} + + // -------------------------------------------------------------------------- + // [Accessors - List] + // -------------------------------------------------------------------------- + + //! Get previous node in the compiler stream. + ASMJIT_INLINE Node* getPrev() const { + return _prev; + } + + //! Get next node in the compiler stream. + ASMJIT_INLINE Node* getNext() const { + return _next; + } + + // -------------------------------------------------------------------------- + // [Accessors - Comment] + // -------------------------------------------------------------------------- + + //! Get comment string. + ASMJIT_INLINE const char* getComment() const { + return _comment; + } + + //! Set comment string to `str`. + ASMJIT_INLINE void setComment(const char* comment) { + _comment = comment; + } + + // -------------------------------------------------------------------------- + // [Accessors - Type and Flags] + // -------------------------------------------------------------------------- + + //! Get node type, see `kNodeType`. + ASMJIT_INLINE uint32_t getType() const { + return _type; + } + + //! Get node flags. + ASMJIT_INLINE uint32_t getFlags() const { + return _flags; + } + + //! Get whether the instruction has flag `flag`. + ASMJIT_INLINE bool hasFlag(uint32_t flag) const { + return (static_cast(_flags) & flag) != 0; + } + + //! Set node flags to `flags`. + ASMJIT_INLINE void setFlags(uint32_t flags) { + _flags = static_cast(flags); + } + + //! Add instruction `flags`. + ASMJIT_INLINE void orFlags(uint32_t flags) { + _flags |= static_cast(flags); + } + + //! And instruction `flags`. + ASMJIT_INLINE void andFlags(uint32_t flags) { + _flags &= static_cast(flags); + } + + //! Clear instruction `flags`. + ASMJIT_INLINE void andNotFlags(uint32_t flags) { + _flags &= ~static_cast(flags); + } + + //! Get whether the node has beed fetched. + ASMJIT_INLINE bool isFetched() const { + return _flowId != 0; + } + + //! Get whether the node has been translated. + ASMJIT_INLINE bool isTranslated() const { + return hasFlag(kNodeFlagIsTranslated); + } + + //! Get whether the node has been translated. + ASMJIT_INLINE bool isScheduled() const { + return hasFlag(kNodeFlagIsScheduled); + } + + //! Get whether the node is informative only and can be safely removed after + //! translation. + //! + //! Informative nodes are comments and hints. + ASMJIT_INLINE bool isInformative() const { + return hasFlag(kNodeFlagIsInformative); + } + + //! Whether the node is `InstNode` and unconditional jump. + ASMJIT_INLINE bool isJmp() const { return hasFlag(kNodeFlagIsJmp); } + //! Whether the node is `InstNode` and conditional jump. + ASMJIT_INLINE bool isJcc() const { return hasFlag(kNodeFlagIsJcc); } + //! Whether the node is `InstNode` and conditional/unconditional jump. + ASMJIT_INLINE bool isJmpOrJcc() const { return hasFlag(kNodeFlagIsJmp | kNodeFlagIsJcc); } + //! Whether the node is `InstNode` and return. + ASMJIT_INLINE bool isRet() const { return hasFlag(kNodeFlagIsRet); } + + //! Get whether the node is `InstNode` and the instruction is special. + ASMJIT_INLINE bool isSpecial() const { return hasFlag(kNodeFlagIsSpecial); } + //! Get whether the node is `InstNode` and the instruction uses x87-FPU. + ASMJIT_INLINE bool isFp() const { return hasFlag(kNodeFlagIsFp); } + + // -------------------------------------------------------------------------- + // [Accessors - FlowId] + // -------------------------------------------------------------------------- + + //! Get flow index. + ASMJIT_INLINE uint32_t getFlowId() const { return _flowId; } + //! Set flow index. + ASMJIT_INLINE void setFlowId(uint32_t flowId) { _flowId = flowId; } + + // -------------------------------------------------------------------------- + // [Accessors - VarMap] + // -------------------------------------------------------------------------- + + //! Get whether node contains variable allocation instructions. + ASMJIT_INLINE bool hasMap() const { + return _map != NULL; + } + + //! Get variable allocation instructions. + ASMJIT_INLINE VarMap* getMap() const { + return _map; + } + + //! Get variable allocation instructions casted to `T*`. + template + ASMJIT_INLINE T* getMap() const { + return static_cast(_map); + } + + //! Set variable allocation instructions. + ASMJIT_INLINE void setMap(VarMap* map) { + _map = map; + } + + // -------------------------------------------------------------------------- + // [Accessors - VarState] + // -------------------------------------------------------------------------- + + //! Get node state. + ASMJIT_INLINE VarState* getState() const { + return _state; + } + + //! Get node state casted to `T*`. + template + ASMJIT_INLINE T* getState() const { + return static_cast(_state); + } + + //! Set node state. + ASMJIT_INLINE void setState(VarState* state) { + _state = state; + } + + // -------------------------------------------------------------------------- + // [Accessors - Liveness] + // -------------------------------------------------------------------------- + + //! Get whether the node has variable liveness bits. + ASMJIT_INLINE bool hasLiveness() const { + return _liveness != NULL; + } + + //! Get variable liveness bits. + ASMJIT_INLINE VarBits* getLiveness() const { + return _liveness; + } + + //! Set variable liveness bits. + ASMJIT_INLINE void setLiveness(VarBits* liveness) { + _liveness = liveness; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Previous node. + Node* _prev; + //! Next node. + Node* _next; + + //! Node type, see `kNodeType`. + uint8_t _type; + //! Operands count (if the node has operands, otherwise zero). + uint8_t _opCount; + //! Node flags, different meaning for every node type. + uint16_t _flags; + + //! Flow index. + uint32_t _flowId; + + //! Inline comment string, initially set to NULL. + const char* _comment; + + //! Variable mapping (VarAttr to VarData), initially NULL, filled during + //! fetch phase. + VarMap* _map; + + //! Variable liveness bits (initially NULL, filled by analysis phase). + VarBits* _liveness; + + //! Saved state. + //! + //! Initially NULL, not all nodes have saved state, only branch/flow control + //! nodes. + VarState* _state; +}; + +// ============================================================================ +// [asmjit::AlignNode] +// ============================================================================ + +//! Align node. +struct AlignNode : public Node { + ASMJIT_NO_COPY(AlignNode) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new `AlignNode` instance. + ASMJIT_INLINE AlignNode(Compiler* compiler, uint32_t mode, uint32_t offset) : + Node(compiler, kNodeTypeAlign) { + + _mode = mode; + _offset = offset; + } + + //! Destroy the `AlignNode` instance. + ASMJIT_INLINE ~AlignNode() {} + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get alignment mode. + ASMJIT_INLINE uint32_t getMode() const { + return _mode; + } + + //! Set alignment mode. + ASMJIT_INLINE void setMode(uint32_t mode) { + _mode = mode; + } + + //! Get align offset in bytes. + ASMJIT_INLINE uint32_t getOffset() const { + return _offset; + } + + //! Set align offset in bytes to `offset`. + ASMJIT_INLINE void setOffset(uint32_t offset) { + _offset = offset; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Alignment mode, see \ref kAlignMode. + uint32_t _mode; + //! Alignment offset in bytes. + uint32_t _offset; +}; + +// ============================================================================ +// [asmjit::EmbedNode] +// ============================================================================ + +//! Embed node. +//! +//! Embed node is used to embed data into final assembler stream. The data is +//! considered to be RAW; No analysis is performed on RAW data. +struct EmbedNode : public Node { + ASMJIT_NO_COPY(EmbedNode) + + // -------------------------------------------------------------------------- + // [Enums] + // -------------------------------------------------------------------------- + + enum { kInlineBufferSize = 8 }; + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new `EmbedNode` instance. + ASMJIT_INLINE EmbedNode(Compiler* compiler, void* data, uint32_t size) : + Node(compiler, kNodeTypeEmbed) { + + _size = size; + if (size <= kInlineBufferSize) { + if (data != NULL) + ::memcpy(_data.buf, data, size); + } + else { + _data.ptr = static_cast(data); + } + } + + //! Destroy the `EmbedNode` instance. + ASMJIT_INLINE ~EmbedNode() {} + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get pointer to data. + uint8_t* getData() { return getSize() <= kInlineBufferSize ? const_cast(_data.buf) : _data.ptr; } + //! Get size of data. + uint32_t getSize() const { return _size; } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Size of the embedded data. + uint32_t _size; + + union { + //! data buffer. + uint8_t buf[kInlineBufferSize]; + //! Data buffer. + uint8_t* ptr; + } _data; +}; + +// ============================================================================ +// [asmjit::CommentNode] +// ============================================================================ + +//! Comment node. +//! +//! Comments allows to comment your assembler stream for better debugging +//! and visualization. Comments are usually ignored in release builds unless +//! the logger is present. +struct CommentNode : public Node { + ASMJIT_NO_COPY(CommentNode) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new `CommentNode` instance. + ASMJIT_INLINE CommentNode(Compiler* compiler, const char* comment) : Node(compiler, kNodeTypeComment) { + orFlags(kNodeFlagIsInformative); + _comment = comment; + } + + //! Destroy the `CommentNode` instance. + ASMJIT_INLINE ~CommentNode() {} +}; + +// ============================================================================ +// [asmjit::HintNode] +// ============================================================================ + +//! Hint node. +struct HintNode : public Node { + ASMJIT_NO_COPY(HintNode) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new `HintNode` instance. + ASMJIT_INLINE HintNode(Compiler* compiler, VarData* vd, uint32_t hint, uint32_t value) : + Node(compiler, kNodeTypeHint) { + + orFlags(kNodeFlagIsInformative); + _vd = vd; + _hint = hint; + _value = value; + } + + //! Destroy the `HintNode` instance. + ASMJIT_INLINE ~HintNode() {} + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get variable. + ASMJIT_INLINE VarData* getVd() const { return _vd; } + + //! Get hint it (see `kVarHint)`. + ASMJIT_INLINE uint32_t getHint() const{ return _hint; } + //! Set hint it (see `kVarHint)`. + ASMJIT_INLINE void setHint(uint32_t hint) { _hint = hint; } + + //! Get hint value. + ASMJIT_INLINE uint32_t getValue() const { return _value; } + //! Set hint value. + ASMJIT_INLINE void setValue(uint32_t value) { _value = value; } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Variable. + VarData* _vd; + //! Hint id. + uint32_t _hint; + //! Value. + uint32_t _value; +}; + +// ============================================================================ +// [asmjit::TargetNode] +// ============================================================================ + +//! label node. +struct TargetNode : public Node { + ASMJIT_NO_COPY(TargetNode) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new `TargetNode` instance. + ASMJIT_INLINE TargetNode(Compiler* compiler, uint32_t labelId) : Node(compiler, kNodeTypeTarget) { + _id = labelId; + _numRefs = 0; + _offset = -1; + _from = NULL; + } + + //! Destroy the `TargetNode` instance. + ASMJIT_INLINE ~TargetNode() {} + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get target label. + ASMJIT_INLINE Label getLabel() const { return Label(_id); } + //! Get target label id. + ASMJIT_INLINE uint32_t getLabelId() const { return _id; } + + //! Get first jmp instruction. + ASMJIT_INLINE JumpNode* getFrom() const { return _from; } + + //! Get whether the node has assigned state. + ASMJIT_INLINE bool hasState() const { return _state != NULL; } + //! Get state for this target. + ASMJIT_INLINE VarState* getState() const { return _state; } + //! Set state for this target. + ASMJIT_INLINE void setState(VarState* state) { _state = state; } + + //! Get number of jumps to this target. + ASMJIT_INLINE uint32_t getNumRefs() const { return _numRefs; } + //! Set number of jumps to this target. + ASMJIT_INLINE void setNumRefs(uint32_t i) { _numRefs = i; } + + //! Add number of jumps to this target. + ASMJIT_INLINE void addNumRefs(uint32_t i = 1) { _numRefs += i; } + //! Subtract number of jumps to this target. + ASMJIT_INLINE void subNumRefs(uint32_t i = 1) { _numRefs -= i; } + + //! Get the label offset. + //! + //! \note Only valid after the content has been serialized to the `Assembler`. + ASMJIT_INLINE intptr_t getOffset() const { return _offset; } + + //! Set the label offset. + ASMJIT_INLINE void setOffset(intptr_t offset) { _offset = offset; } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Label id. + uint32_t _id; + //! Count of jumps here. + uint32_t _numRefs; + + //! Label offset, after serialization. + intptr_t _offset; + //! First jump instruction that points to this target (label). + JumpNode* _from; +}; + +// ============================================================================ +// [asmjit::InstNode] +// ============================================================================ + +//! Instruction node. +struct InstNode : public Node { + ASMJIT_NO_COPY(InstNode) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new `InstNode` instance. + ASMJIT_INLINE InstNode(Compiler* compiler, uint32_t instId, uint32_t instOptions, Operand* opList, uint32_t opCount) : + Node(compiler, kNodeTypeInst) { + + _instId = static_cast(instId); + _reserved = 0; + _instOptions = instOptions; + + _opCount = static_cast(opCount); + _opList = opList; + + _updateMemOp(); + } + + //! Destroy the `InstNode` instance. + ASMJIT_INLINE ~InstNode() {} + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get instruction ID, see `kX86InstId`. + ASMJIT_INLINE uint32_t getInstId() const { + return _instId; + } + + //! Set instruction ID to `instId`. + //! + //! Please do not modify instruction code if you don't know what are you + //! doing. Incorrect instruction code or operands can cause assertion failure. + ASMJIT_INLINE void setInstId(uint32_t instId) { + _instId = static_cast(instId); + } + + //! Whether the instruction is an unconditional jump or whether the + //! instruction is a conditional jump which is likely to be taken. + ASMJIT_INLINE bool isTaken() const { + return hasFlag(kNodeFlagIsTaken); + } + + //! Get emit options. + ASMJIT_INLINE uint32_t getOptions() const { + return _instOptions; + } + //! Set emit options. + ASMJIT_INLINE void setOptions(uint32_t options) { + _instOptions = options; + } + //! Add emit options. + ASMJIT_INLINE void addOptions(uint32_t options) { + _instOptions |= options; + } + //! Mask emit options. + ASMJIT_INLINE void andOptions(uint32_t options) { + _instOptions &= options; + } + //! Clear emit options. + ASMJIT_INLINE void delOptions(uint32_t options) { + _instOptions &= ~options; + } + + //! Get operands list. + ASMJIT_INLINE Operand* getOpList() { + return _opList; + } + //! \overload + ASMJIT_INLINE const Operand* getOpList() const { + return _opList; + } + + //! Get operands count. + ASMJIT_INLINE uint32_t getOpCount() const { + return _opCount; + } + + //! Get whether the instruction contains a memory operand. + ASMJIT_INLINE bool hasMemOp() const { + return _memOpIndex != 0xFF; + } + + //! Set memory operand index (in opList), 0xFF means that instruction + //! doesn't have a memory operand. + ASMJIT_INLINE void setMemOpIndex(uint32_t index) { + _memOpIndex = static_cast(index); + } + //! Reset memory operand index, setting it to 0xFF. + ASMJIT_INLINE void resetMemOpIndex() { + _memOpIndex = 0xFF; + } + + //! Get memory operand. + //! + //! Can only be called if the instruction has such operand, see `hasMemOp()`. + ASMJIT_INLINE BaseMem* getMemOp() const { + ASMJIT_ASSERT(hasMemOp()); + return static_cast(&_opList[_memOpIndex]); + } + + //! \overload + template + ASMJIT_INLINE T* getMemOp() const { + ASMJIT_ASSERT(hasMemOp()); + return static_cast(&_opList[_memOpIndex]); + } + + // -------------------------------------------------------------------------- + // [Utils] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE void _updateMemOp() { + Operand* opList = getOpList(); + uint32_t opCount = getOpCount(); + + uint32_t i; + for (i = 0; i < opCount; i++) + if (opList[i].isMem()) + goto _Update; + i = 0xFF; + +_Update: + setMemOpIndex(i); + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Instruction ID, see `kInstId`. + uint16_t _instId; + //! \internal + uint8_t _memOpIndex; + //! \internal + uint8_t _reserved; + //! Instruction options, see `kInstOptions`. + uint32_t _instOptions; + + //! Operands list. + Operand* _opList; +}; + +// ============================================================================ +// [asmjit::JumpNode] +// ============================================================================ + +//! Jump node. +struct JumpNode : public InstNode { + ASMJIT_NO_COPY(JumpNode) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE JumpNode(Compiler* compiler, uint32_t code, uint32_t options, Operand* opList, uint32_t opCount) : + InstNode(compiler, code, options, opList, opCount) {} + ASMJIT_INLINE ~JumpNode() {} + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE TargetNode* getTarget() const { return _target; } + ASMJIT_INLINE JumpNode* getJumpNext() const { return _jumpNext; } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Target node. + TargetNode* _target; + //! Next jump to the same target in a single linked-list. + JumpNode *_jumpNext; +}; + +// ============================================================================ +// [asmjit::FuncNode] +// ============================================================================ + +//! Function declaration node. +//! +//! Functions are base blocks for generating assembler output. Each generated +//! assembler stream needs standard entry and leave sequences which are compatible +//! with the operating system ABI. +//! +//! `FuncNode` can be used to generate function prolog and epilog which are +//! compatible with a given function calling convention and to allocate and +//! manage variables that can be allocated/spilled during compilation phase. +struct FuncNode : public Node { + ASMJIT_NO_COPY(FuncNode) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new `FuncNode` instance. + //! + //! Always use `Compiler::addFunc()` to create a `FuncNode` instance. + ASMJIT_INLINE FuncNode(Compiler* compiler) : + Node(compiler, kNodeTypeFunc), + _entryNode(NULL), + _exitNode(NULL), + _decl(NULL), + _end(NULL), + _argList(NULL), + _funcHints(IntUtil::mask(kFuncHintNaked)), + _funcFlags(0), + _expectedStackAlignment(0), + _requiredStackAlignment(0), + _redZoneSize(0), + _spillZoneSize(0), + _argStackSize(0), + _memStackSize(0), + _callStackSize(0) {} + + //! Destroy the `FuncNode` instance. + ASMJIT_INLINE ~FuncNode() {} + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get function entry `TargetNode`. + ASMJIT_INLINE TargetNode* getEntryNode() const { return _entryNode; } + //! Get function exit `TargetNode`. + ASMJIT_INLINE TargetNode* getExitNode() const { return _exitNode; } + + //! Get function entry label. + ASMJIT_INLINE Label getEntryLabel() const { return _entryNode->getLabel(); } + //! Get function exit label. + ASMJIT_INLINE Label getExitLabel() const { return _exitNode->getLabel(); } + + //! Get function `EndNode`. + ASMJIT_INLINE EndNode* getEnd() const { return _end; } + //! Get function declaration. + ASMJIT_INLINE FuncDecl* getDecl() const { return _decl; } + + //! Get arguments list. + ASMJIT_INLINE VarData** getArgList() const { return _argList; } + //! Get arguments count. + ASMJIT_INLINE uint32_t getArgCount() const { return _decl->getArgCount(); } + + //! Get argument at `i`. + ASMJIT_INLINE VarData* getArg(uint32_t i) const { + ASMJIT_ASSERT(i < getArgCount()); + return _argList[i]; + } + + //! Set argument at `i`. + ASMJIT_INLINE void setArg(uint32_t i, VarData* vd) { + ASMJIT_ASSERT(i < getArgCount()); + _argList[i] = vd; + } + + //! Reset argument at `i`. + ASMJIT_INLINE void resetArg(uint32_t i) { + ASMJIT_ASSERT(i < getArgCount()); + _argList[i] = NULL; + } + + //! Get function hints. + ASMJIT_INLINE uint32_t getFuncHints() const { return _funcHints; } + //! Get function flags. + ASMJIT_INLINE uint32_t getFuncFlags() const { return _funcFlags; } + + //! Get whether the _funcFlags has `flag` + ASMJIT_INLINE bool hasFuncFlag(uint32_t flag) const { return (_funcFlags & flag) != 0; } + //! Set function `flag`. + ASMJIT_INLINE void addFuncFlags(uint32_t flags) { _funcFlags |= flags; } + //! Clear function `flag`. + ASMJIT_INLINE void clearFuncFlags(uint32_t flags) { _funcFlags &= ~flags; } + + //! Get whether the function is naked. + ASMJIT_INLINE bool isNaked() const { return hasFuncFlag(kFuncFlagIsNaked); } + //! Get whether the function is also a caller. + ASMJIT_INLINE bool isCaller() const { return hasFuncFlag(kFuncFlagIsCaller); } + //! Get whether the required stack alignment is lower than expected one, + //! thus it has to be aligned manually. + ASMJIT_INLINE bool isStackMisaligned() const { return hasFuncFlag(kFuncFlagIsStackMisaligned); } + //! Get whether the stack pointer is adjusted inside function prolog/epilog. + ASMJIT_INLINE bool isStackAdjusted() const { return hasFuncFlag(kFuncFlagIsStackAdjusted); } + + //! Get whether the function is finished. + ASMJIT_INLINE bool isFinished() const { return hasFuncFlag(kFuncFlagIsFinished); } + + //! Get expected stack alignment. + ASMJIT_INLINE uint32_t getExpectedStackAlignment() const { return _expectedStackAlignment; } + //! Set expected stack alignment. + ASMJIT_INLINE void setExpectedStackAlignment(uint32_t alignment) { _expectedStackAlignment = alignment; } + + //! Get required stack alignment. + ASMJIT_INLINE uint32_t getRequiredStackAlignment() const { return _requiredStackAlignment; } + //! Set required stack alignment. + ASMJIT_INLINE void setRequiredStackAlignment(uint32_t alignment) { _requiredStackAlignment = alignment; } + + //! Update required stack alignment so it's not lower than expected + //! stack alignment. + ASMJIT_INLINE void updateRequiredStackAlignment() { + if (_requiredStackAlignment <= _expectedStackAlignment) { + _requiredStackAlignment = _expectedStackAlignment; + clearFuncFlags(kFuncFlagIsStackMisaligned); + } + else { + addFuncFlags(kFuncFlagIsStackMisaligned); + } + } + + //! Set stack "Red Zone" size. + ASMJIT_INLINE uint32_t getRedZoneSize() const { return _redZoneSize; } + //! Get stack "Red Zone" size. + ASMJIT_INLINE void setRedZoneSize(uint32_t s) { _redZoneSize = static_cast(s); } + + //! Set stack "Spill Zone" size. + ASMJIT_INLINE uint32_t getSpillZoneSize() const { return _spillZoneSize; } + //! Get stack "Spill Zone" size. + ASMJIT_INLINE void setSpillZoneSize(uint32_t s) { _spillZoneSize = static_cast(s); } + + //! Get stack size used by function arguments. + ASMJIT_INLINE uint32_t getArgStackSize() const { return _argStackSize; } + + //! Get stack size used by variables and memory allocated on the stack. + ASMJIT_INLINE uint32_t getMemStackSize() const { return _memStackSize; } + + //! Get stack size used by function calls. + ASMJIT_INLINE uint32_t getCallStackSize() const { return _callStackSize; } + //! Merge stack size used by function call with `s`. + ASMJIT_INLINE void mergeCallStackSize(uint32_t s) { if (_callStackSize < s) _callStackSize = s; } + + // -------------------------------------------------------------------------- + // [Hints] + // -------------------------------------------------------------------------- + + //! Set function hint. + ASMJIT_INLINE void setHint(uint32_t hint, uint32_t value) { + ASMJIT_ASSERT(hint <= 31); + ASMJIT_ASSERT(value <= 1); + + _funcHints &= ~(1 << hint); + _funcHints |= (value << hint); + } + + //! Get function hint. + ASMJIT_INLINE uint32_t getHint(uint32_t hint) const { + ASMJIT_ASSERT(hint <= 31); + return (_funcHints >> hint) & 0x1; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Function entry. + TargetNode* _entryNode; + //! Function exit. + TargetNode* _exitNode; + + //! Function declaration. + FuncDecl* _decl; + //! Function end. + EndNode* _end; + + //! Arguments list as `VarData`. + VarData** _argList; + + //! Function hints; + uint32_t _funcHints; + //! Function flags. + uint32_t _funcFlags; + + //! Expected stack alignment (we depend on this value). + //! + //! \note It can be global alignment given by the OS or described by an + //! target platform ABI. + uint32_t _expectedStackAlignment; + //! Required stack alignment (usually for multimedia instructions). + uint32_t _requiredStackAlignment; + + //! The "Red Zone" size - count of bytes which might be accessed without + //! adjusting the stack pointer. + uint16_t _redZoneSize; + //! Spill zone size (used by WIN64 ABI). + uint16_t _spillZoneSize; + + //! Stack size needed for function arguments. + uint32_t _argStackSize; + //! Stack size needed for all variables and memory allocated on the stack. + uint32_t _memStackSize; + //! Stack size needed to call other functions. + uint32_t _callStackSize; +}; + +// ============================================================================ +// [asmjit::EndNode] +// ============================================================================ + +//! End of function/block node. +struct EndNode : public Node { + ASMJIT_NO_COPY(EndNode) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new `EndNode` instance. + ASMJIT_INLINE EndNode(Compiler* compiler) : Node(compiler, kNodeTypeEnd) { + _flags |= kNodeFlagIsRet; + } + + //! Destroy the `EndNode` instance. + ASMJIT_INLINE ~EndNode() {} +}; + +// ============================================================================ +// [asmjit::RetNode] +// ============================================================================ + +//! Function return node. +struct RetNode : public Node { + ASMJIT_NO_COPY(RetNode) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new `RetNode` instance. + ASMJIT_INLINE RetNode(Compiler* compiler, const Operand& o0, const Operand& o1) : Node(compiler, kNodeTypeRet) { + _flags |= kNodeFlagIsRet; + _ret[0] = o0; + _ret[1] = o1; + } + + //! Destroy the `RetNode` instance. + ASMJIT_INLINE ~RetNode() {} + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get the first return operand. + ASMJIT_INLINE Operand& getFirst() { return _ret[0]; } + //! \overload + ASMJIT_INLINE const Operand& getFirst() const { return _ret[0]; } + + //! Get the second return operand. + ASMJIT_INLINE Operand& getSecond() { return _ret[1]; } + //! \overload + ASMJIT_INLINE const Operand& getSecond() const { return _ret[1]; } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Ret operand(s). + Operand _ret[2]; +}; + +// ============================================================================ +// [asmjit::CallNode] +// ============================================================================ + +//! Function-call node. +struct CallNode : public Node { + ASMJIT_NO_COPY(CallNode) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new `CallNode` instance. + ASMJIT_INLINE CallNode(Compiler* compiler, const Operand& target) : + Node(compiler, kNodeTypeCall), + _decl(NULL), + _target(target), + _args(NULL) {} + + //! Destroy the `CallNode` instance. + ASMJIT_INLINE ~CallNode() {} + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get function declaration. + ASMJIT_INLINE FuncDecl* getDecl() const { return _decl; } + + //! Get target operand. + ASMJIT_INLINE Operand& getTarget() { return _target; } + //! \overload + ASMJIT_INLINE const Operand& getTarget() const { return _target; } + + //! Get return at `i`. + ASMJIT_INLINE Operand& getRet(uint32_t i = 0) { + ASMJIT_ASSERT(i < 2); + return _ret[i]; + } + //! \overload + ASMJIT_INLINE const Operand& getRet(uint32_t i = 0) const { + ASMJIT_ASSERT(i < 2); + return _ret[i]; + } + + //! Get argument at `i`. + ASMJIT_INLINE Operand& getArg(uint32_t i) { + ASMJIT_ASSERT(i < kFuncArgCountLoHi); + return _args[i]; + } + //! \overload + ASMJIT_INLINE const Operand& getArg(uint32_t i) const { + ASMJIT_ASSERT(i < kFuncArgCountLoHi); + return _args[i]; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Function declaration. + FuncDecl* _decl; + + //! Target (address of function, register, label, ...). + Operand _target; + //! Return. + Operand _ret[2]; + //! Arguments. + Operand* _args; +}; + +// ============================================================================ +// [asmjit::SArgNode] +// ============================================================================ + +//! Function-call 'argument on the stack' node. +struct SArgNode : public Node { + ASMJIT_NO_COPY(SArgNode) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new `SArgNode` instance. + ASMJIT_INLINE SArgNode(Compiler* compiler, CallNode* call, VarData* sVd, VarData* cVd) : + Node(compiler, kNodeTypeSArg), + _call(call), + _sVd(sVd), + _cVd(cVd), + _args(0) {} + + //! Destroy the `SArgNode` instance. + ASMJIT_INLINE ~SArgNode() {} + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get the associated function-call. + ASMJIT_INLINE CallNode* getCall() const { return _call; } + //! Get source variable. + ASMJIT_INLINE VarData* getSVd() const { return _sVd; } + //! Get conversion variable. + ASMJIT_INLINE VarData* getCVd() const { return _cVd; } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Associated `CallNode`. + CallNode* _call; + //! Source variable. + VarData* _sVd; + //! Temporary variable used for conversion (or NULL). + VarData* _cVd; + + //! Affected arguments bit-array. + uint32_t _args; +}; + +//! \} + +// ============================================================================ +// [asmjit::Compiler] +// ============================================================================ + +//! \addtogroup asmjit_base_general +//! \{ + +//! Base compiler. +//! +//! \sa Assembler. +struct ASMJIT_VCLASS Compiler : public CodeGen { + ASMJIT_NO_COPY(Compiler) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new `Compiler` instance. + ASMJIT_API Compiler(Runtime* runtime); + //! Destroy the `Compiler` instance. + ASMJIT_API virtual ~Compiler(); + + // -------------------------------------------------------------------------- + // [LookAhead] + // -------------------------------------------------------------------------- + + //! Get maximum look ahead. + ASMJIT_INLINE uint32_t getMaxLookAhead() const { + return _maxLookAhead; + } + + //! Set maximum look ahead to `val`. + ASMJIT_INLINE void setMaxLookAhead(uint32_t val) { + _maxLookAhead = val; + } + + // -------------------------------------------------------------------------- + // [Clear / Reset] + // -------------------------------------------------------------------------- + + //! Reset the compiler. + //! + //! If `releaseMemory` is true all buffers will be released to the system. + ASMJIT_API void reset(bool releaseMemory = false); + + // -------------------------------------------------------------------------- + // [Nodes] + // -------------------------------------------------------------------------- + + template + ASMJIT_INLINE T* newNode() { + void* p = _baseZone.alloc(sizeof(T)); + return new(p) T(this); + } + + template + ASMJIT_INLINE T* newNode(P0 p0) { + void* p = _baseZone.alloc(sizeof(T)); + return new(p) T(this, p0); + } + + template + ASMJIT_INLINE T* newNode(P0 p0, P1 p1) { + void* p = _baseZone.alloc(sizeof(T)); + return new(p) T(this, p0, p1); + } + + template + ASMJIT_INLINE T* newNode(P0 p0, P1 p1, P2 p2) { + void* p = _baseZone.alloc(sizeof(T)); + return new(p) T(this, p0, p1, p2); + } + + //! Get first node. + ASMJIT_INLINE Node* getFirstNode() const { return _firstNode; } + //! Get last node. + ASMJIT_INLINE Node* getLastNode() const { return _lastNode; } + + //! Get current node. + //! + //! \note If this method returns `NULL` it means that nothing has been emitted + //! yet. + ASMJIT_INLINE Node* getCursor() const { return _cursor; } + //! Set the current node without returning the previous node (private). + ASMJIT_INLINE void _setCursor(Node* node) { _cursor = node; } + //! Set the current node to `node` and return the previous one. + ASMJIT_API Node* setCursor(Node* node); + + //! Add node `node` after current and set current to `node`. + ASMJIT_API Node* addNode(Node* node); + //! Add node before `ref`. + ASMJIT_API Node* addNodeBefore(Node* node, Node* ref); + //! Add node after `ref`. + ASMJIT_API Node* addNodeAfter(Node* node, Node* ref); + //! Remove node `node`. + ASMJIT_API Node* removeNode(Node* node); + //! Remove multiple nodes. + ASMJIT_API void removeNodes(Node* first, Node* last); + + // -------------------------------------------------------------------------- + // [Func] + // -------------------------------------------------------------------------- + + //! Get current function. + ASMJIT_INLINE FuncNode* getFunc() const { return _func; } + + // -------------------------------------------------------------------------- + // [Align] + // -------------------------------------------------------------------------- + + //! Create a new `AlignNode`. + ASMJIT_API AlignNode* newAlign(uint32_t mode, uint32_t offset); + //! Add a new `AlignNode`. + ASMJIT_API AlignNode* addAlign(uint32_t mode, uint32_t offset); + + //! 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. + ASMJIT_INLINE AlignNode* align(uint32_t mode, uint32_t offset) { + return addAlign(mode, offset); + } + + // -------------------------------------------------------------------------- + // [Target] + // -------------------------------------------------------------------------- + + //! Create a new `TargetNode`. + ASMJIT_API TargetNode* newTarget(); + //! Add a new `TargetNode`. + ASMJIT_API TargetNode* addTarget(); + + //! Get `TargetNode` by `id`. + ASMJIT_INLINE TargetNode* getTargetById(uint32_t id) { + ASMJIT_ASSERT(OperandUtil::isLabelId(id)); + ASMJIT_ASSERT(id < _targetList.getLength()); + + return _targetList[id]; + } + + //! Get `TargetNode` by `label`. + ASMJIT_INLINE TargetNode* getTarget(const Label& label) { + return getTargetById(label.getId()); + } + + // -------------------------------------------------------------------------- + // [Label] + // -------------------------------------------------------------------------- + + //! Get count of created labels. + ASMJIT_INLINE size_t getLabelsCount() const { + return _targetList.getLength(); + } + + //! Get whether `label` is created. + ASMJIT_INLINE bool isLabelValid(const Label& label) const { + return isLabelValid(label.getId()); + } + + //! \overload + ASMJIT_INLINE bool isLabelValid(uint32_t id) const { + return static_cast(id) < _targetList.getLength(); + } + + //! Get `TargetNode` by `label`. + ASMJIT_INLINE TargetNode* getTargetByLabel(const Label& label) { + return getTargetByLabel(label.getId()); + } + + //! \overload + ASMJIT_INLINE TargetNode* getTargetByLabel(uint32_t id) { + ASMJIT_ASSERT(isLabelValid(id)); + return _targetList[id]; + } + + //! Get `label` offset or -1 if the label is not bound. + //! + //! This method can be only called after the code has been serialized to the + //! `Assembler`, otherwise the offset returned will be -1 (even if the label + //! has been 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 _targetList[id]->getOffset(); + } + + //! \internal + //! + //! Create and initialize a new `Label`. + ASMJIT_API Error _newLabel(Label* dst); + + //! 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 Error bind(const Label& label); + + // -------------------------------------------------------------------------- + // [Embed] + // -------------------------------------------------------------------------- + + //! Create a new `EmbedNode`. + ASMJIT_API EmbedNode* newEmbed(const void* data, uint32_t size); + //! Add a new `EmbedNode`. + ASMJIT_API EmbedNode* addEmbed(const void* data, uint32_t size); + + //! Embed data. + ASMJIT_INLINE EmbedNode* embed(const void* data, uint32_t size) { + return addEmbed(data, size); + } + + // -------------------------------------------------------------------------- + // [Comment] + // -------------------------------------------------------------------------- + + //! Create a new `CommentNode`. + ASMJIT_API CommentNode* newComment(const char* str); + //! Add a new `CommentNode`. + ASMJIT_API CommentNode* addComment(const char* str); + + //! Emit a single comment line. + ASMJIT_API CommentNode* comment(const char* fmt, ...); + + // -------------------------------------------------------------------------- + // [Hint] + // -------------------------------------------------------------------------- + + //! Create a new `HintNode`. + ASMJIT_API HintNode* newHint(Var& var, uint32_t hint, uint32_t value); + //! Add a new `HintNode`. + ASMJIT_API HintNode* addHint(Var& var, uint32_t hint, uint32_t value); + + // -------------------------------------------------------------------------- + // [Vars] + // -------------------------------------------------------------------------- + + //! Get whether variable `var` is created. + ASMJIT_INLINE bool isVarValid(const Var& var) const { + return static_cast(var.getId() & kOperandIdNum) < _varList.getLength(); + } + + //! \internal + //! + //! Get `VarData` by `var`. + ASMJIT_INLINE VarData* getVd(const Var& var) const { + return getVdById(var.getId()); + } + + //! \internal + //! + //! Get `VarData` by `id`. + ASMJIT_INLINE VarData* getVdById(uint32_t id) const { + ASMJIT_ASSERT(id != kInvalidValue); + ASMJIT_ASSERT(static_cast(id & kOperandIdNum) < _varList.getLength()); + + return _varList[id & kOperandIdNum]; + } + + //! \internal + //! + //! Get an array of 'VarData*'. + ASMJIT_INLINE VarData** _getVdArray() const { + return const_cast(_varList.getData()); + } + + //! \internal + //! + //! Create a new `VarData`. + ASMJIT_API VarData* _newVd(uint32_t type, uint32_t size, uint32_t c, const char* name); + + //! Create a new `Var`. + virtual Error _newVar(Var* var, uint32_t type, const char* name) = 0; + + //! Alloc variable `var`. + ASMJIT_API void alloc(Var& var); + //! Alloc variable `var` using `regIndex` as a register index. + ASMJIT_API void alloc(Var& var, uint32_t regIndex); + //! Alloc variable `var` using `reg` as a register operand. + ASMJIT_API void alloc(Var& var, const Reg& reg); + //! Spill variable `var`. + ASMJIT_API void spill(Var& var); + //! Save variable `var` if the status is `modified` at this point. + ASMJIT_API void save(Var& var); + //! Unuse variable `var`. + ASMJIT_API void unuse(Var& var); + + //! Alloc variable `var` (if initialized), but only if it's initialized. + ASMJIT_INLINE void allocUnsafe(Var& var) { + if (var.isInitialized()) + alloc(var); + } + + //! Alloc variable `var` (if initialized) using `regIndex` as a register index + ASMJIT_INLINE void allocUnsafe(Var& var, uint32_t regIndex) { + if (var.isInitialized()) + alloc(var, regIndex); + } + + //! Alloc variable `var` (if initialized) using `reg` as a register operand. + ASMJIT_INLINE void allocUnsafe(Var& var, const Reg& reg) { + if (var.isInitialized()) + alloc(var, reg); + } + + //! Spill variable `var` (if initialized). + ASMJIT_INLINE void spillUnsafe(Var& var) { + if (var.isInitialized()) + spill(var); + } + + //! Save variable `var` (if initialized) if the status is `modified` at this point. + ASMJIT_INLINE void saveUnsafe(Var& var) { + if (var.isInitialized()) + save(var); + } + + //! Unuse variable `var` (if initialized). + ASMJIT_INLINE void unuseUnsafe(Var& var) { + if (var.isInitialized()) + unuse(var); + } + + //! Get priority of variable `var`. + ASMJIT_API uint32_t getPriority(Var& var) const; + //! Set priority of variable `var` to `priority`. + ASMJIT_API void setPriority(Var& var, uint32_t priority); + + //! Get save-on-unuse `var` property. + ASMJIT_API bool getSaveOnUnuse(Var& var) const; + //! Set save-on-unuse `var` property to `value`. + ASMJIT_API void setSaveOnUnuse(Var& var, bool value); + + //! Rename variable `var` to `name`. + //! + //! \note Only new name will appear in the logger. + ASMJIT_API void rename(Var& var, const char* name); + + // -------------------------------------------------------------------------- + // [Stack] + // -------------------------------------------------------------------------- + + //! \internal + //! + //! Create a new memory chunk allocated on the current function's stack. + virtual Error _newStack(BaseMem* mem, uint32_t size, uint32_t alignment, const char* name) = 0; + + // -------------------------------------------------------------------------- + // [Const] + // -------------------------------------------------------------------------- + + //! \internal + //! + //! Put data to a constant-pool and get a memory reference to it. + virtual Error _newConst(BaseMem* mem, uint32_t scope, const void* data, size_t size) = 0; + + // -------------------------------------------------------------------------- + // [Assembler] + // -------------------------------------------------------------------------- + + //! Get an assembler instance that is associated with the compiler. + //! + //! \note One instance of `Assembler` is shared and has lifetime same as the + //! compiler, however, each call to `getAssembler()` resets the assembler so + //! new code can be serialized into it. + ASMJIT_API Assembler* getAssembler(); + + //! \internal + //! + //! Create a new `Assembler` instance associated with the compiler. + virtual Assembler* _newAssembler() = 0; + + // -------------------------------------------------------------------------- + // [Serialize] + // -------------------------------------------------------------------------- + + //! Serialize a compiled code to `assembler`. + virtual Error serialize(Assembler* assembler) = 0; + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Internal assembler. + Assembler* _assembler; + + //! Flow id added to each node created (used only by `Context)`. + uint32_t _nodeFlowId; + //! Flags added to each node created (used only by `Context)`. + uint32_t _nodeFlags; + + //! Maximum count of nodes to look ahead when allocating/spilling + //! registers. + uint32_t _maxLookAhead; + + //! Variable mapping (translates incoming kVarType into target). + const uint8_t* _targetVarMapping; + + //! First node. + Node* _firstNode; + //! Last node. + Node* _lastNode; + + //! Current node. + Node* _cursor; + //! Current function. + FuncNode* _func; + + //! Variable zone. + Zone _varZone; + //! String/data zone. + Zone _stringZone; + //! Local constant pool zone. + Zone _localConstZone; + + //! TargetNode list. + PodVector _targetList; + //! VarData list. + PodVector _varList; + + //! Local constant pool, flushed at the end of each function. + ConstPool _localConstPool; + //! Global constant pool, flushed at the end of the compilation. + ConstPool _globalConstPool; + + //! Label to start of the local constant pool. + Label _localConstPoolLabel; + //! Label to start of the global constant pool. + Label _globalConstPoolLabel; +}; + +//! \} + +// ============================================================================ +// [Defined-Later] +// ============================================================================ + +ASMJIT_INLINE Label::Label(Compiler& c) : Operand(NoInit) { + c._newLabel(this); +} + +ASMJIT_INLINE Node::Node(Compiler* compiler, uint32_t type) { + _prev = NULL; + _next = NULL; + _type = static_cast(type); + _opCount = 0; + _flags = static_cast(compiler->_nodeFlags); + _flowId = compiler->_nodeFlowId; + _comment = NULL; + _map = NULL; + _liveness = NULL; + _state = NULL; +} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // !ASMJIT_DISABLE_COMPILER +#endif // _ASMJIT_BASE_COMPILER_H diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/constpool.cpp b/third/Blackbone/src/3rd_party/AsmJit/base/constpool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cd7e6d7fb2fce6dbe92133e43b3bcaac973be6a2 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/constpool.cpp @@ -0,0 +1,523 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Dependencies - AsmJit] +#include "../base/constpool.h" +#include "../base/intutil.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// Binary tree code is based on Julienne Walker's "Andersson Binary Trees" +// article and implementation. However, only three operations are implemented - +// get, insert and traverse. + +// ============================================================================ +// [asmjit::ConstPoolTree - Ops] +// ============================================================================ + +//! \internal +//! +//! Remove left horizontal links. +static ASMJIT_INLINE ConstPoolNode* ConstPoolTree_skewNode(ConstPoolNode* node) { + ConstPoolNode* link = node->_link[0]; + uint32_t level = node->_level; + + if (level != 0 && link != NULL && link->_level == level) { + node->_link[0] = link->_link[1]; + link->_link[1] = node; + + node = link; + } + + return node; +} + +//! \internal +//! +//! Remove consecutive horizontal links. +static ASMJIT_INLINE ConstPoolNode* ConstPoolTree_splitNode(ConstPoolNode* node) { + ConstPoolNode* link = node->_link[1]; + uint32_t level = node->_level; + + if (level != 0 && link != NULL && link->_link[1] != NULL && link->_link[1]->_level == level) { + node->_link[1] = link->_link[0]; + link->_link[0] = node; + + node = link; + node->_level++; + } + + return node; +} + +ConstPoolNode* ConstPoolTree::get(const void* data) { + ConstPoolNode* node = _root; + size_t dataSize = _dataSize; + + while (node != NULL) { + int c = ::memcmp(node->getData(), data, dataSize); + if (c == 0) + return node; + node = node->_link[c < 0]; + } + + return NULL; +} + +void ConstPoolTree::put(ConstPoolNode* newNode) { + size_t dataSize = _dataSize; + + _length++; + if (_root == NULL) { + _root = newNode; + return; + } + + ConstPoolNode* node = _root; + ConstPoolNode* stack[kHeightLimit]; + + unsigned int top = 0; + unsigned int dir; + + // Find a spot and save the stack. + for (;;) { + stack[top++] = node; + dir = ::memcmp(node->getData(), newNode->getData(), dataSize) < 0; + + ConstPoolNode* link = node->_link[dir]; + if (link == NULL) + break; + + node = link; + } + + // Link and rebalance. + node->_link[dir] = newNode; + + while (top > 0) { + // Which child? + node = stack[--top]; + + if (top != 0) { + dir = stack[top - 1]->_link[1] == node; + } + + node = ConstPoolTree_skewNode(node); + node = ConstPoolTree_splitNode(node); + + // Fix the parent. + if (top != 0) + stack[top - 1]->_link[dir] = node; + else + _root = node; + } +} + +// ============================================================================ +// [asmjit::ConstPool - Construction / Destruction] +// ============================================================================ + +ConstPool::ConstPool(Zone* zone) { + _zone = zone; + + size_t dataSize = 1; + for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(_tree); i++) { + _tree[i].setDataSize(dataSize); + _gaps[i] = NULL; + dataSize <<= 1; + } + + _gapPool = NULL; + _size = 0; + _alignment = 0; +} + +ConstPool::~ConstPool() {} + +// ============================================================================ +// [asmjit::ConstPool - Reset] +// ============================================================================ + +void ConstPool::reset() { + for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(_tree); i++) { + _tree[i].reset(); + _gaps[i] = NULL; + } + + _gapPool = NULL; + _size = 0; + _alignment = 0; +} + +// ============================================================================ +// [asmjit::ConstPool - Ops] +// ============================================================================ + +static ASMJIT_INLINE ConstPoolGap* ConstPool_allocGap(ConstPool* self) { + ConstPoolGap* gap = self->_gapPool; + if (gap == NULL) + return self->_zone->allocT(); + + self->_gapPool = gap->_next; + return gap; +} + +static ASMJIT_INLINE void ConstPool_freeGap(ConstPool* self, ConstPoolGap* gap) { + gap->_next = self->_gapPool; + self->_gapPool = gap; +} + +static void ConstPool_addGap(ConstPool* self, size_t offset, size_t length) { + ASMJIT_ASSERT(length > 0); + + while (length > 0) { + size_t gapIndex; + size_t gapLength; + + if (length >= 16 && IntUtil::isAligned(offset, 16)) { + gapIndex = ConstPool::kIndex16; + gapLength = 16; + } + else if (length >= 8 && IntUtil::isAligned(offset, 8)) { + gapIndex = ConstPool::kIndex8; + gapLength = 8; + } + else if (length >= 4 && IntUtil::isAligned(offset, 4)) { + gapIndex = ConstPool::kIndex4; + gapLength = 4; + } + else if (length >= 2 && IntUtil::isAligned(offset, 2)) { + gapIndex = ConstPool::kIndex2; + gapLength = 2; + } + else { + gapIndex = ConstPool::kIndex1; + gapLength = 1; + } + + // We don't have to check for errors here, if this failed nothing really + // happened (just the gap won't be visible) and it will fail again at + // place where checking will cause kErrorNoHeapMemory. + ConstPoolGap* gap = ConstPool_allocGap(self); + if (gap == NULL) + return; + + gap->_next = self->_gaps[gapIndex]; + self->_gaps[gapIndex] = gap; + + gap->_offset = offset; + gap->_length = gapLength; + + offset += gapLength; + length -= gapLength; + } +} + +Error ConstPool::add(const void* data, size_t size, size_t& dstOffset) { + size_t treeIndex; + + if (size == 32) + treeIndex = kIndex32; + else if (size == 16) + treeIndex = kIndex16; + else if (size == 8) + treeIndex = kIndex8; + else if (size == 4) + treeIndex = kIndex4; + else if (size == 2) + treeIndex = kIndex2; + else if (size == 1) + treeIndex = kIndex1; + else + return kErrorInvalidArgument; + + ConstPoolNode* node = _tree[treeIndex].get(data); + if (node != NULL) { + dstOffset = node->_offset; + return kErrorOk; + } + + // Before incrementing the current offset try if there is a gap that can + // be used for the requested data. + size_t offset = ~static_cast(0); + size_t gapIndex = treeIndex; + + while (gapIndex != kIndexCount - 1) { + ConstPoolGap* gap = _gaps[treeIndex]; + + // Check if there is a gap. + if (gap != NULL) { + size_t gapOffset = gap->_offset; + size_t gapLength = gap->_length; + + // Destroy the gap for now. + _gaps[treeIndex] = gap->_next; + ConstPool_freeGap(this, gap); + + offset = gapOffset; + ASMJIT_ASSERT(IntUtil::isAligned(offset, size)); + + gapLength -= size; + if (gapLength > 0) + ConstPool_addGap(this, gapOffset, gapLength); + } + + gapIndex++; + } + + if (offset == ~static_cast(0)) { + // Get how many bytes have to be skipped so the address is aligned accordingly + // to the 'size'. + size_t deltaTo = IntUtil::deltaTo(_size, size); + + if (deltaTo != 0) { + ConstPool_addGap(this, _size, deltaTo); + _size += deltaTo; + } + + offset = _size; + _size += size; + } + + // Add the initial node to the right index. + node = ConstPoolTree::_newNode(_zone, data, size, offset, false); + if (node == NULL) + return kErrorNoHeapMemory; + + _tree[treeIndex].put(node); + _alignment = IntUtil::iMax(_alignment, size); + + dstOffset = offset; + + // Now create a bunch of shared constants that are based on the data pattern. + // We stop at size 4, it probably doesn't make sense to split constants down + // to 1 byte. + size_t pCount = 1; + while (size > 4) { + size >>= 1; + pCount <<= 1; + + ASMJIT_ASSERT(treeIndex != 0); + treeIndex--; + + const uint8_t* pData = static_cast(data); + for (size_t i = 0; i < pCount; i++, pData += size) { + node = _tree[treeIndex].get(pData); + + if (node != NULL) + continue; + + node = ConstPoolTree::_newNode(_zone, pData, size, offset + (i * size), true); + _tree[treeIndex].put(node); + } + } + + return kErrorOk; +} + +// ============================================================================ +// [asmjit::ConstPool - Reset] +// ============================================================================ + +struct ConstPoolFill { + ASMJIT_INLINE ConstPoolFill(uint8_t* dst, size_t dataSize) : + _dst(dst), + _dataSize(dataSize) {} + + ASMJIT_INLINE void visit(const ConstPoolNode* node) { + if (!node->_shared) + ::memcpy(_dst + node->_offset, node->getData(), _dataSize); + } + + uint8_t* _dst; + size_t _dataSize; +}; + +void ConstPool::fill(void* dst) { + // Clears possible gaps, asmjit should never emit garbage to the output. + ::memset(dst, 0, _size); + + ConstPoolFill filler(static_cast(dst), 1); + for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(_tree); i++) { + _tree[i].iterate(filler); + filler._dataSize <<= 1; + } +} + +// ============================================================================ +// [asmjit::ConstPool - Test] +// ============================================================================ + +#if defined(ASMJIT_TEST) +UNIT(base_constpool) { + Zone zone(32384 - kZoneOverhead); + ConstPool pool(&zone); + + uint32_t i; + uint32_t kCount = 1000000; + + INFO("Adding %u constants to the pool.", kCount); + { + size_t prevOffset; + size_t curOffset; + uint64_t c = ASMJIT_UINT64_C(0x0101010101010101); + + EXPECT(pool.add(&c, 8, prevOffset) == kErrorOk, + "pool.add() - Returned error."); + EXPECT(prevOffset == 0, + "pool.add() - First constant should have zero offset."); + + for (i = 1; i < kCount; i++) { + c++; + EXPECT(pool.add(&c, 8, curOffset) == kErrorOk, + "pool.add() - Returned error."); + EXPECT(prevOffset + 8 == curOffset, + "pool.add() - Returned incorrect curOffset."); + EXPECT(pool.getSize() == (i + 1) * 8, + "pool.getSize() - Reported incorrect size."); + prevOffset = curOffset; + } + + EXPECT(pool.getAlignment() == 8, + "pool.getAlignment() - Expected 8-byte alignment."); + } + + INFO("Retrieving %u constants from the pool.", kCount); + { + uint64_t c = ASMJIT_UINT64_C(0x0101010101010101); + + for (i = 0; i < kCount; i++) { + size_t offset; + EXPECT(pool.add(&c, 8, offset) == kErrorOk, + "pool.add() - Returned error."); + EXPECT(offset == i * 8, + "pool.add() - Should have reused constant."); + c++; + } + } + + INFO("Checking if the constants were split into 4-byte patterns."); + { + uint32_t c = 0x01010101; + for (i = 0; i < kCount; i++) { + size_t offset; + EXPECT(pool.add(&c, 4, offset) == kErrorOk, + "pool.add() - Returned error."); + EXPECT(offset == i * 8, + "pool.add() - Should reuse existing constant."); + c++; + } + } + + INFO("Adding 2 byte constant to misalign the current offset."); + { + uint16_t c = 0xFFFF; + size_t offset; + + EXPECT(pool.add(&c, 2, offset) == kErrorOk, + "pool.add() - Returned error."); + EXPECT(offset == kCount * 8, + "pool.add() - Didn't return expected position."); + EXPECT(pool.getAlignment() == 8, + "pool.getAlignment() - Expected 8-byte alignment."); + } + + INFO("Adding 8 byte constant to check if pool gets aligned again."); + { + uint64_t c = ASMJIT_UINT64_C(0xFFFFFFFFFFFFFFFF); + size_t offset; + + EXPECT(pool.add(&c, 8, offset) == kErrorOk, + "pool.add() - Returned error."); + EXPECT(offset == kCount * 8 + 8, + "pool.add() - Didn't return aligned offset."); + } + + INFO("Adding 2 byte constant to verify the gap is filled."); + { + uint16_t c = 0xFFFE; + size_t offset; + + EXPECT(pool.add(&c, 2, offset) == kErrorOk, + "pool.add() - Returned error."); + EXPECT(offset == kCount * 8 + 2, + "pool.add() - Didn't fill the gap."); + EXPECT(pool.getAlignment() == 8, + "pool.getAlignment() - Expected 8-byte alignment."); + } + + INFO("Checking reset functionality."); + { + pool.reset(); + + EXPECT(pool.getSize() == 0, + "pool.getSize() - Expected pool size to be zero."); + EXPECT(pool.getAlignment() == 0, + "pool.getSize() - Expected pool alignment to be zero."); + } + + INFO("Checking pool alignment when combined constants are added."); + { + uint8_t bytes[32] = { 0 }; + size_t offset; + + pool.add(bytes, 1, offset); + + EXPECT(pool.getSize() == 1, + "pool.getSize() - Expected pool size to be 1 byte."); + EXPECT(pool.getAlignment() == 1, + "pool.getSize() - Expected pool alignment to be 1 byte."); + EXPECT(offset == 0, + "pool.getSize() - Expected offset returned to be zero."); + + pool.add(bytes, 2, offset); + + EXPECT(pool.getSize() == 4, + "pool.getSize() - Expected pool size to be 4 bytes."); + EXPECT(pool.getAlignment() == 2, + "pool.getSize() - Expected pool alignment to be 2 bytes."); + EXPECT(offset == 2, + "pool.getSize() - Expected offset returned to be 2."); + + pool.add(bytes, 4, offset); + + EXPECT(pool.getSize() == 8, + "pool.getSize() - Expected pool size to be 8 bytes."); + EXPECT(pool.getAlignment() == 4, + "pool.getSize() - Expected pool alignment to be 4 bytes."); + EXPECT(offset == 4, + "pool.getSize() - Expected offset returned to be 4."); + + pool.add(bytes, 4, offset); + + EXPECT(pool.getSize() == 8, + "pool.getSize() - Expected pool size to be 8 bytes."); + EXPECT(pool.getAlignment() == 4, + "pool.getSize() - Expected pool alignment to be 4 bytes."); + EXPECT(offset == 4, + "pool.getSize() - Expected offset returned to be 8."); + + pool.add(bytes, 32, offset); + EXPECT(pool.getSize() == 64, + "pool.getSize() - Expected pool size to be 64 bytes."); + EXPECT(pool.getAlignment() == 32, + "pool.getSize() - Expected pool alignment to be 32 bytes."); + EXPECT(offset == 32, + "pool.getSize() - Expected offset returned to be 32."); + } +} +#endif // ASMJIT_TEST + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/constpool.h b/third/Blackbone/src/3rd_party/AsmJit/base/constpool.h new file mode 100644 index 0000000000000000000000000000000000000000..8f66b8b6627a8423dfad7b6202d88d5e745cd6fa --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/constpool.h @@ -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(const_cast(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 + ASMJIT_INLINE void iterate(Visitor& visitor) const { + ConstPoolNode* node = const_cast(_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(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(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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/containers.cpp b/third/Blackbone/src/3rd_party/AsmJit/base/containers.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b93181390832722f19cc77e1417c505a5d69d55b --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/containers.cpp @@ -0,0 +1,116 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Dependencies - AsmJit] +#include "../base/containers.h" +#include "../base/intutil.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [asmjit::PodVectorBase - NullData] +// ============================================================================ + +const PodVectorData PodVectorBase::_nullData = { 0, 0 }; + +// ============================================================================ +// [asmjit::PodVectorBase - Reset] +// ============================================================================ + +//! Clear vector data and free internal buffer. +void PodVectorBase::reset(bool releaseMemory) { + PodVectorData* d = _d; + + if (d == &_nullData) + return; + + if (releaseMemory) { + ASMJIT_FREE(d); + _d = const_cast(&_nullData); + return; + } + + d->length = 0; +} + +// ============================================================================ +// [asmjit::PodVectorBase - Helpers] +// ============================================================================ + +Error PodVectorBase::_grow(size_t n, size_t sizeOfT) { + PodVectorData* d = _d; + + size_t threshold = kMemAllocGrowMax / sizeOfT; + size_t capacity = d->capacity; + size_t after = d->length; + + if (IntUtil::maxUInt() - n < after) + return kErrorNoHeapMemory; + + after += n; + + if (capacity >= after) + return kErrorOk; + + // PodVector is used as a linear array for some data structures used by + // AsmJit code generation. The purpose of this agressive growing schema + // is to minimize memory reallocations, because AsmJit code generation + // classes live short life and will be freed or reused soon. + if (capacity < 32) + capacity = 32; + else if (capacity < 128) + capacity = 128; + else if (capacity < 512) + capacity = 512; + + while (capacity < after) { + if (capacity < threshold) + capacity *= 2; + else + capacity += threshold; + } + + return _reserve(capacity, sizeOfT); +} + +Error PodVectorBase::_reserve(size_t n, size_t sizeOfT) { + PodVectorData* d = _d; + + if (d->capacity >= n) + return kErrorOk; + + size_t nBytes = sizeof(PodVectorData) + n * sizeOfT; + if (nBytes < n) + return kErrorNoHeapMemory; + + if (d == &_nullData) { + d = static_cast(ASMJIT_ALLOC(nBytes)); + if (d == NULL) + return kErrorNoHeapMemory; + d->length = 0; + } + else { + d = static_cast(ASMJIT_REALLOC(d, nBytes)); + if (d == NULL) + return kErrorNoHeapMemory; + } + + d->capacity = n; + _d = d; + + return kErrorOk; +} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/containers.h b/third/Blackbone/src/3rd_party/AsmJit/base/containers.h new file mode 100644 index 0000000000000000000000000000000000000000..c6dc70d4647a4251ac60dbaf46dd8fa58b64ef18 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/containers.h @@ -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(&_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] +// ============================================================================ + +//! 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 +struct PodVector : PodVectorBase { + ASMJIT_NO_COPY(PodVector) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new instance of `PodVector`. + 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(_d->getData()); + } + + //! \overload + ASMJIT_INLINE const T* getData() const { + return static_cast(_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(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(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(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(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(d->getData()) + i; + d->length--; + ::memmove(data, data + 1, d->length - i); + } + + //! Swap this pod-vector with `other`. + void swap(PodVector& 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] +// ============================================================================ + +//! \internal +template +struct PodList { + ASMJIT_NO_COPY(PodList) + + // -------------------------------------------------------------------------- + // [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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/context.cpp b/third/Blackbone/src/3rd_party/AsmJit/base/context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae104edabaee09a7c5722bea9c88290e794e3f14 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/context.cpp @@ -0,0 +1,561 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Guard] +#include "../build.h" +#if !defined(ASMJIT_DISABLE_COMPILER) + +// [Dependencies - AsmJit] +#include "../base/context_p.h" +#include "../base/intutil.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [asmjit::Context - Construction / Destruction] +// ============================================================================ + +Context::Context(Compiler* compiler) : + _compiler(compiler), + _varMapToVaListOffset(0), + _baseZone(8192 - kZoneOverhead) { + + Context::reset(); +} + +Context::~Context() {} + +// ============================================================================ +// [asmjit::Context - Reset] +// ============================================================================ + +void Context::reset(bool releaseMemory) { + _baseZone.reset(releaseMemory); + + _func = NULL; + _start = NULL; + _end = NULL; + _extraBlock = NULL; + _stop = NULL; + + _unreachableList.reset(); + _jccList.reset(); + _contextVd.reset(releaseMemory); + + _memVarCells = NULL; + _memStackCells = NULL; + + _mem1ByteVarsUsed = 0; + _mem2ByteVarsUsed = 0; + _mem4ByteVarsUsed = 0; + _mem8ByteVarsUsed = 0; + _mem16ByteVarsUsed = 0; + _mem32ByteVarsUsed = 0; + _mem64ByteVarsUsed = 0; + _memStackCellsUsed = 0; + + _memMaxAlign = 0; + _memVarTotal = 0; + _memStackTotal = 0; + _memAllTotal = 0; + _annotationLength = 12; + + _state = NULL; +} + +// ============================================================================ +// [asmjit::Context - Mem] +// ============================================================================ + +static ASMJIT_INLINE uint32_t BaseContext_getDefaultAlignment(uint32_t size) { + if (size > 32) + return 64; + else if (size > 16) + return 32; + else if (size > 8) + return 16; + else if (size > 4) + return 8; + else if (size > 2) + return 4; + else if (size > 1) + return 2; + else + return 1; +} + +MemCell* Context::_newVarCell(VarData* vd) { + ASMJIT_ASSERT(vd->_memCell == NULL); + + MemCell* cell; + uint32_t size = vd->getSize(); + + if (vd->isStack()) { + cell = _newStackCell(size, vd->getAlignment()); + + if (cell == NULL) + return NULL; + } + else { + cell = static_cast(_baseZone.alloc(sizeof(MemCell))); + if (cell == NULL) + goto _NoMemory; + + cell->_next = _memVarCells; + _memVarCells = cell; + + cell->_offset = 0; + cell->_size = size; + cell->_alignment = size; + + _memMaxAlign = IntUtil::iMax(_memMaxAlign, size); + _memVarTotal += size; + + switch (size) { + case 1: _mem1ByteVarsUsed++ ; break; + case 2: _mem2ByteVarsUsed++ ; break; + case 4: _mem4ByteVarsUsed++ ; break; + case 8: _mem8ByteVarsUsed++ ; break; + case 16: _mem16ByteVarsUsed++; break; + case 32: _mem32ByteVarsUsed++; break; + case 64: _mem64ByteVarsUsed++; break; + default: ASMJIT_ASSERT(!"Reached"); + } + } + + vd->_memCell = cell; + return cell; + +_NoMemory: + _compiler->setError(kErrorNoHeapMemory); + return NULL; +} + +MemCell* Context::_newStackCell(uint32_t size, uint32_t alignment) { + MemCell* cell = static_cast(_baseZone.alloc(sizeof(MemCell))); + if (cell == NULL) + goto _NoMemory; + + if (alignment == 0) + alignment = BaseContext_getDefaultAlignment(size); + + if (alignment > 64) + alignment = 64; + + ASMJIT_ASSERT(IntUtil::isPowerOf2(alignment)); + size = IntUtil::alignTo(size, alignment); + + // Insert it sorted according to the alignment and size. + { + MemCell** pPrev = &_memStackCells; + MemCell* cur = *pPrev; + + for (cur = *pPrev; cur != NULL; cur = cur->_next) { + if (cur->getAlignment() > alignment) + continue; + if (cur->getAlignment() == alignment && cur->getSize() > size) + continue; + break; + } + + cell->_next = cur; + cell->_offset = 0; + cell->_size = size; + cell->_alignment = alignment; + + *pPrev = cell; + _memStackCellsUsed++; + + _memMaxAlign = IntUtil::iMax(_memMaxAlign, alignment); + _memStackTotal += size; + } + + return cell; + +_NoMemory: + _compiler->setError(kErrorNoHeapMemory); + return NULL; +} + +Error Context::resolveCellOffsets() { + MemCell* varCell = _memVarCells; + MemCell* stackCell = _memStackCells; + + uint32_t stackAlignment = 0; + if (stackCell != NULL) + stackAlignment = stackCell->getAlignment(); + + uint32_t pos64 = 0; + uint32_t pos32 = pos64 + _mem64ByteVarsUsed * 64; + uint32_t pos16 = pos32 + _mem32ByteVarsUsed * 32; + uint32_t pos8 = pos16 + _mem16ByteVarsUsed * 16; + uint32_t pos4 = pos8 + _mem8ByteVarsUsed * 8 ; + uint32_t pos2 = pos4 + _mem4ByteVarsUsed * 4 ; + uint32_t pos1 = pos2 + _mem2ByteVarsUsed * 2 ; + + uint32_t stackPos = pos1 + _mem1ByteVarsUsed; + + uint32_t gapAlignment = stackAlignment; + uint32_t gapSize = 0; + + if (gapAlignment) + IntUtil::deltaTo(stackPos, gapAlignment); + stackPos += gapSize; + + uint32_t gapPos = stackPos; + uint32_t allTotal = stackPos; + + // Vars - Allocated according to alignment/width. + while (varCell != NULL) { + uint32_t size = varCell->getSize(); + uint32_t offset = 0; + + switch (size) { + case 1: offset = pos1 ; pos1 += 1 ; break; + case 2: offset = pos2 ; pos2 += 2 ; break; + case 4: offset = pos4 ; pos4 += 4 ; break; + case 8: offset = pos8 ; pos8 += 8 ; break; + case 16: offset = pos16; pos16 += 16; break; + case 32: offset = pos32; pos32 += 32; break; + case 64: offset = pos64; pos64 += 64; break; + default: ASMJIT_ASSERT(!"Reached"); + } + + varCell->setOffset(static_cast(offset)); + varCell = varCell->_next; + } + + // Stack - Allocated according to alignment and width. + while (stackCell != NULL) { + uint32_t size = stackCell->getSize(); + uint32_t alignment = stackCell->getAlignment(); + uint32_t offset; + + // Try to fill the gap between variables / stack first. + if (size <= gapSize && alignment <= gapAlignment) { + offset = gapPos; + + gapSize -= size; + gapPos -= size; + + if (alignment < gapAlignment) + gapAlignment = alignment; + } + else { + offset = stackPos; + + stackPos += size; + allTotal += size; + } + + stackCell->setOffset(offset); + stackCell = stackCell->_next; + } + + _memAllTotal = allTotal; + return kErrorOk; +} + +// ============================================================================ +// [asmjit::Context - RemoveUnreachableCode] +// ============================================================================ + +Error Context::removeUnreachableCode() { + PodList::Link* link = _unreachableList.getFirst(); + Node* stop = getStop(); + + while (link != NULL) { + Node* node = link->getValue(); + if (node != NULL && node->getPrev() != NULL) { + // Locate all unreachable nodes. + Node* first = node; + do { + if (node->isFetched()) + break; + node = node->getNext(); + } while (node != stop); + + // Remove. + if (node != first) { + Node* last = (node != NULL) ? node->getPrev() : getCompiler()->getLastNode(); + getCompiler()->removeNodes(first, last); + } + } + + link = link->getNext(); + } + + return kErrorOk; +} + +// ============================================================================ +// [asmjit::Context - Liveness Analysis] +// ============================================================================ + +//! \internal +struct LivenessTarget { + //! Previous target. + LivenessTarget* prev; + + //! Target node. + TargetNode* node; + //! Jumped from. + JumpNode* from; +}; + +Error Context::livenessAnalysis() { + FuncNode* func = getFunc(); + JumpNode* from = NULL; + + Node* node = func->getEnd(); + uint32_t bLen = static_cast( + ((_contextVd.getLength() + VarBits::kEntityBits - 1) / VarBits::kEntityBits)); + + LivenessTarget* ltCur = NULL; + LivenessTarget* ltUnused = NULL; + + size_t varMapToVaListOffset = _varMapToVaListOffset; + + // No variables. + if (bLen == 0) + return kErrorOk; + + VarBits* bCur = newBits(bLen); + if (bCur == NULL) + goto _NoMemory; + + // Allocate bits for code visited first time. +_OnVisit: + for (;;) { + if (node->hasLiveness()) { + if (bCur->_addBitsDelSource(node->getLiveness(), bCur, bLen)) + goto _OnPatch; + else + goto _OnDone; + } + + VarBits* bTmp = copyBits(bCur, bLen); + if (bTmp == NULL) + goto _NoMemory; + + node->setLiveness(bTmp); + VarMap* map = node->getMap(); + + if (map != NULL) { + uint32_t vaCount = map->getVaCount(); + VarAttr* vaList = reinterpret_cast(((uint8_t*)map) + varMapToVaListOffset); + + for (uint32_t i = 0; i < vaCount; i++) { + VarAttr* va = &vaList[i]; + VarData* vd = va->getVd(); + + uint32_t flags = va->getFlags(); + uint32_t ctxId = vd->getContextId(); + + if ((flags & kVarAttrOutAll) && !(flags & kVarAttrInAll)) { + // Write-Only. + bTmp->setBit(ctxId); + bCur->delBit(ctxId); + } + else { + // Read-Only or Read/Write. + bTmp->setBit(ctxId); + bCur->setBit(ctxId); + } + } + } + + if (node->getType() == kNodeTypeTarget) + goto _OnTarget; + + if (node == func) + goto _OnDone; + + ASMJIT_ASSERT(node->getPrev()); + node = node->getPrev(); + } + + // Patch already generated liveness bits. +_OnPatch: + for (;;) { + ASMJIT_ASSERT(node->hasLiveness()); + VarBits* bNode = node->getLiveness(); + + if (!bNode->_addBitsDelSource(bCur, bLen)) + goto _OnDone; + + if (node->getType() == kNodeTypeTarget) + goto _OnTarget; + + if (node == func) + goto _OnDone; + + node = node->getPrev(); + } + +_OnTarget: + if (static_cast(node)->getNumRefs() != 0) { + // Push a new LivenessTarget onto the stack if needed. + if (ltCur == NULL || ltCur->node != node) { + // Allocate a new LivenessTarget object (from pool or zone). + LivenessTarget* ltTmp = ltUnused; + + if (ltTmp != NULL) { + ltUnused = ltUnused->prev; + } + else { + ltTmp = _baseZone.allocT( + sizeof(LivenessTarget) - sizeof(VarBits) + bLen * sizeof(uintptr_t)); + + if (ltTmp == NULL) + goto _NoMemory; + } + + // Initialize and make current - ltTmp->from will be set later on. + ltTmp->prev = ltCur; + ltTmp->node = static_cast(node); + ltCur = ltTmp; + + from = static_cast(node)->getFrom(); + ASMJIT_ASSERT(from != NULL); + } + else { + from = ltCur->from; + goto _OnJumpNext; + } + + // Visit/Patch. + do { + ltCur->from = from; + bCur->copyBits(node->getLiveness(), bLen); + + if (!from->hasLiveness()) { + node = from; + goto _OnVisit; + } + + // Issue #25: Moved '_OnJumpNext' here since it's important to patch + // code again if there are more live variables than before. +_OnJumpNext: + if (bCur->delBits(from->getLiveness(), bLen)) { + node = from; + goto _OnPatch; + } + + from = from->getJumpNext(); + } while (from != NULL); + + // Pop the current LivenessTarget from the stack. + { + LivenessTarget* ltTmp = ltCur; + + ltCur = ltCur->prev; + ltTmp->prev = ltUnused; + ltUnused = ltTmp; + } + } + + bCur->copyBits(node->getLiveness(), bLen); + node = node->getPrev(); + + if (node->isJmp() || !node->isFetched()) + goto _OnDone; + + if (!node->hasLiveness()) + goto _OnVisit; + + if (bCur->delBits(node->getLiveness(), bLen)) + goto _OnPatch; + +_OnDone: + if (ltCur != NULL) { + node = ltCur->node; + from = ltCur->from; + + goto _OnJumpNext; + } + return kErrorOk; + +_NoMemory: + return setError(kErrorNoHeapMemory); +} + +// ============================================================================ +// [asmjit::Context - Schedule] +// ============================================================================ + +Error Context::schedule() { + // By default there is no instruction scheduler implemented. + return kErrorOk; +} + +// ============================================================================ +// [asmjit::Context - Cleanup] +// ============================================================================ + +void Context::cleanup() { + VarData** array = _contextVd.getData(); + size_t length = _contextVd.getLength(); + + for (size_t i = 0; i < length; i++) { + VarData* vd = array[i]; + vd->resetContextId(); + vd->resetRegIndex(); + } + + _contextVd.reset(false); + _extraBlock = NULL; +} + +// ============================================================================ +// [asmjit::Context - CompileFunc] +// ============================================================================ + +Error Context::compile(FuncNode* func) { + Node* end = func->getEnd(); + Node* stop = end->getNext(); + + _func = func; + _stop = stop; + _extraBlock = end; + + ASMJIT_PROPAGATE_ERROR(fetch()); + ASMJIT_PROPAGATE_ERROR(removeUnreachableCode()); + ASMJIT_PROPAGATE_ERROR(livenessAnalysis()); + + Compiler* compiler = getCompiler(); + +#if !defined(ASMJIT_DISABLE_LOGGER) + if (compiler->hasLogger()) + ASMJIT_PROPAGATE_ERROR(annotate()); +#endif // !ASMJIT_DISABLE_LOGGER + + ASMJIT_PROPAGATE_ERROR(translate()); + + if (compiler->hasFeature(kCodeGenEnableScheduler)) + ASMJIT_PROPAGATE_ERROR(schedule()); + + // We alter the compiler cursor, because it doesn't make sense to reference + // it after compilation - some nodes may disappear and it's forbidden to add + // new code after the compilation is done. + compiler->_setCursor(NULL); + + return kErrorOk; +} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // !ASMJIT_DISABLE_COMPILER diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/context_p.h b/third/Blackbone/src/3rd_party/AsmJit/base/context_p.h new file mode 100644 index 0000000000000000000000000000000000000000..bd235013eb5c08918ef13d5846bac8d1f91d8c87 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/context_p.h @@ -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(_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( + _baseZone.allocZeroed(static_cast(len) * VarBits::kEntitySize)); + } + + ASMJIT_INLINE VarBits* copyBits(const VarBits* src, uint32_t len) { + return static_cast( + _baseZone.dup(src, static_cast(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 _unreachableList; + //! Jump nodes. + PodList _jccList; + + //! All variables used by the current function. + PodVector _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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/cpuinfo.cpp b/third/Blackbone/src/3rd_party/AsmJit/base/cpuinfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..71d6858dd0bd5b1dfe06593c9e3ab1a975a97ea5 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/cpuinfo.cpp @@ -0,0 +1,79 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Dependencies - AsmJit] +#include "../base/cpuinfo.h" + +#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64) +#include "../x86/x86cpuinfo.h" +#else +// ? +#endif // ASMJIT_HOST || ASMJIT_HOST_X64 + +// [Dependencies - Posix] +#if defined(ASMJIT_OS_POSIX) +# include +# include +# include +# include +#endif // ASMJIT_OS_POSIX + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [asmjit::CpuInfo - DetectHwThreadsCount] +// ============================================================================ + +uint32_t CpuInfo::detectHwThreadsCount() { +#if defined(ASMJIT_OS_WINDOWS) + SYSTEM_INFO info; + ::GetSystemInfo(&info); + return info.dwNumberOfProcessors; +#elif defined(ASMJIT_OS_POSIX) && defined(_SC_NPROCESSORS_ONLN) + // It seems that sysconf returns the number of "logical" processors on both + // mac and linux. So we get the number of "online logical" processors. + long res = ::sysconf(_SC_NPROCESSORS_ONLN); + if (res == -1) return 1; + + return static_cast(res); +#else + return 1; +#endif +} + +// ============================================================================ +// [asmjit::CpuInfo - GetHost] +// ============================================================================ + +#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64) +struct AutoX86CpuInfo : public X86CpuInfo { + ASMJIT_INLINE AutoX86CpuInfo() : X86CpuInfo() { + X86CpuUtil::detect(this); + } +}; +#else +#error "AsmJit - Unsupported CPU." +#endif // ASMJIT_HOST || ASMJIT_HOST_X64 + +const CpuInfo* CpuInfo::getHost() { +#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64) + static AutoX86CpuInfo cpuInfo; +#else +#error "AsmJit - Unsupported CPU." +#endif // ASMJIT_HOST || ASMJIT_HOST_X64 + return &cpuInfo; +} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/cpuinfo.h b/third/Blackbone/src/3rd_party/AsmJit/base/cpuinfo.h new file mode 100644 index 0000000000000000000000000000000000000000..06ff636c53f161d34b0e24293cbc0baee43fbfc3 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/cpuinfo.h @@ -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(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( + (_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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/cputicks.cpp b/third/Blackbone/src/3rd_party/AsmJit/base/cputicks.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb10ff14fa4d21f5d6b1cd52f322505da5180d34 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/cputicks.cpp @@ -0,0 +1,131 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Dependencies - AsmJit] +#include "../base/cputicks.h" + +// [Dependencies - Posix] +#if defined(ASMJIT_OS_POSIX) +# include +# include +#endif // ASMJIT_OS_POSIX + +// [Dependencies - Mac] +#if defined(ASMJIT_OS_MAC) +# include +#endif // ASMJIT_OS_MAC + +// [Dependencies - Windows] +#if defined(ASMJIT_OS_WINDOWS) +// `_InterlockedCompareExchange` is only available as intrinsic (MS Compiler). +# if defined(_MSC_VER) +# include +# pragma intrinsic(_InterlockedCompareExchange) +# else +# define _InterlockedCompareExchange InterlockedCompareExchange +# endif // _MSC_VER +#endif // ASMJIT_OS_WINDOWS + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [asmjit::CpuTicks - Windows] +// ============================================================================ + +#if defined(ASMJIT_OS_WINDOWS) +static volatile uint32_t CpuTicks_hiResOk; +static volatile double CpuTicks_hiResFreq; + +uint32_t CpuTicks::now() { + do { + uint32_t hiResOk = CpuTicks_hiResOk; + + if (hiResOk == 1) { + LARGE_INTEGER now; + if (!::QueryPerformanceCounter(&now)) + break; + return (int64_t)(double(now.QuadPart) / CpuTicks_hiResFreq); + } + + if (hiResOk == 0) { + LARGE_INTEGER qpf; + if (!::QueryPerformanceFrequency(&qpf)) { + _InterlockedCompareExchange((LONG*)&CpuTicks_hiResOk, 0xFFFFFFFF, 0); + break; + } + + LARGE_INTEGER now; + if (!::QueryPerformanceCounter(&now)) { + _InterlockedCompareExchange((LONG*)&CpuTicks_hiResOk, 0xFFFFFFFF, 0); + break; + } + + double freqDouble = double(qpf.QuadPart) / 1000.0; + + CpuTicks_hiResFreq = freqDouble; + _InterlockedCompareExchange((LONG*)&CpuTicks_hiResOk, 1, 0); + + return static_cast( + static_cast(double(now.QuadPart) / freqDouble) & 0xFFFFFFFF); + } + } while (0); + + // Bail to a less precise GetTickCount(). + return ::GetTickCount(); +} + +// ============================================================================ +// [asmjit::CpuTicks - Mac] +// ============================================================================ + +#elif defined(ASMJIT_OS_MAC) +static mach_timebase_info_data_t CpuTicks_machTime; + +uint32_t CpuTicks::now() { + // Initialize the first time CpuTicks::now() is called (See Apple's QA1398). + if (CpuTicks_machTime.denom == 0) { + if (mach_timebase_info(&CpuTicks_machTime) != KERN_SUCCESS); + return 0; + } + + // mach_absolute_time() returns nanoseconds, we need just milliseconds. + uint64_t t = mach_absolute_time() / 1000000; + + t = t * CpuTicks_machTime.numer / CpuTicks_machTime.denom; + return static_cast(t & 0xFFFFFFFFU); +} + +// ============================================================================ +// [asmjit::CpuTicks - Posix] +// ============================================================================ + +#else +uint32_t CpuTicks::now() { +#if defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 + struct timespec ts; + + if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) + return 0; + + uint64_t t = (uint64_t(ts.tv_sec ) * 1000) + (uint64_t(ts.tv_nsec) / 1000000); + return static_cast(t & 0xFFFFFFFFU); +#else // _POSIX_MONOTONIC_CLOCK +#error "AsmJit - Unsupported OS." + return 0; +#endif // _POSIX_MONOTONIC_CLOCK +} +#endif // ASMJIT_OS + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/cputicks.h b/third/Blackbone/src/3rd_party/AsmJit/base/cputicks.h new file mode 100644 index 0000000000000000000000000000000000000000..1732c2eb61f7c41636d90c9b32d094bc272c834f --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/cputicks.h @@ -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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/error.cpp b/third/Blackbone/src/3rd_party/AsmJit/base/error.cpp new file mode 100644 index 0000000000000000000000000000000000000000..51516fba47ba8722dcf5eb88cd28974d2a99e385 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/error.cpp @@ -0,0 +1,83 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Dependencies - AsmJit] +#include "../base/error.h" +#include "../base/intutil.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [asmjit::ErrorHandler - Construction / Destruction] +// ============================================================================ + +ErrorHandler::ErrorHandler() {} +ErrorHandler::~ErrorHandler() {} + +// ============================================================================ +// [asmjit::ErrorHandler - Interface] +// ============================================================================ + +ErrorHandler* ErrorHandler::addRef() const { + return const_cast(this); +} + +void ErrorHandler::release() {} + +// ============================================================================ +// [asmjit::ErrorUtil - AsString] +// ============================================================================ + +#if !defined(ASMJIT_DISABLE_NAMES) +static const char errorMessages[] = { + "Ok\0" + "No heap memory\0" + "No virtual memory\0" + "Invalid argument\0" + "Invalid state\0" + "No code generated\0" + "Code too large\0" + "Label already bound\0" + "Unknown instruction\0" + "Illegal instruction\0" + "Illegal addressing\0" + "Illegal displacement\0" + "Overlapped arguments\0" + "Unknown error\0" +}; + +static const char* findPackedString(const char* p, uint32_t id, uint32_t maxId) { + uint32_t i = 0; + + if (id > maxId) + id = maxId; + + while (i < id) { + while (p[0]) + p++; + + p++; + i++; + } + + return p; +} + +const char* ErrorUtil::asString(Error e) { + return findPackedString(errorMessages, e, kErrorCount); +} +#endif // ASMJIT_DISABLE_NAMES + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/error.h b/third/Blackbone/src/3rd_party/AsmJit/base/error.h new file mode 100644 index 0000000000000000000000000000000000000000..46b40892fa114b63366c9148f372703f36606608 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/error.h @@ -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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/globals.cpp b/third/Blackbone/src/3rd_party/AsmJit/base/globals.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2971e002bdcaf1d58bbeb8b3748a797c60d6c48c --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/globals.cpp @@ -0,0 +1,30 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Dependencies - AsmJit] +#include "../base/globals.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [asmjit::Assert] +// ============================================================================ + +void assertionFailed(const char* exp, const char* file, int line) { + ::fprintf(stderr, "Assertion failed: %s\n, file %s, line %d\n", exp, file, line); + ::abort(); +} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/globals.h b/third/Blackbone/src/3rd_party/AsmJit/base/globals.h new file mode 100644 index 0000000000000000000000000000000000000000..036457895a9546cc11a96dccf88b0cf36424c283 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/globals.h @@ -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(0); + +//! Invalid base address. +static const Ptr kNoBaseAddress = static_cast(static_cast(-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 +static ASMJIT_INLINE T asmjit_cast(Z* p) { return (T)p; } + +//! \} + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // _ASMJIT_BASE_GLOBALS_H diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/intutil.cpp b/third/Blackbone/src/3rd_party/AsmJit/base/intutil.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3a811b66edddfd3258e5a7dda31f3d22e85dac77 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/intutil.cpp @@ -0,0 +1,210 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Dependencies - AsmJit] +#include "../base/intutil.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +#if defined(ASMJIT_TEST) +UNIT(base_intutil) { + uint32_t i; + + INFO("IntTraits<>."); + EXPECT(IntTraits::kIsSigned, + "IntTraits should report signed."); + EXPECT(IntTraits::kIsUnsigned, + "IntTraits should report unsigned."); + + EXPECT(IntTraits::kIsSigned, + "IntTraits should report signed."); + EXPECT(IntTraits::kIsUnsigned, + "IntTraits should report unsigned."); + + EXPECT(IntTraits::kIsSigned, + "IntTraits should report signed."); + EXPECT(IntTraits::kIsUnsigned, + "IntTraits should report unsigned."); + + EXPECT(IntTraits::kIsSigned, + "IntTraits should report signed."); + EXPECT(IntTraits::kIsUnsigned, + "IntTraits should report unsigned."); + + EXPECT(IntTraits::kIsSigned, + "IntTraits should report signed."); + EXPECT(IntTraits::kIsUnsigned, + "IntTraits should report unsigned."); + + EXPECT(IntTraits::kIsIntPtr, + "IntTraits should report intptr_t type."); + EXPECT(IntTraits::kIsIntPtr, + "IntTraits should report intptr_t type."); + + INFO("IntUtil::iMin()/iMax()."); + EXPECT(IntUtil::iMin(0, -1) == -1, + "IntUtil::iMin should return a minimum value."); + EXPECT(IntUtil::iMin(-1, -2) == -2, + "IntUtil::iMin should return a minimum value."); + EXPECT(IntUtil::iMin(1, 2) == 1, + "IntUtil::iMin should return a minimum value."); + + EXPECT(IntUtil::iMax(0, -1) == 0, + "IntUtil::iMax should return a maximum value."); + EXPECT(IntUtil::iMax(-1, -2) == -1, + "IntUtil::iMax should return a maximum value."); + EXPECT(IntUtil::iMax(1, 2) == 2, + "IntUtil::iMax should return a maximum value."); + + INFO("IntUtil::inInterval()."); + EXPECT(IntUtil::inInterval(11, 10, 20) == true, + "IntUtil::inInterval should return true if inside."); + EXPECT(IntUtil::inInterval(101, 10, 20) == false, + "IntUtil::inInterval should return false if outside."); + + INFO("IntUtil::isInt8()."); + EXPECT(IntUtil::isInt8(-128) == true, + "IntUtil::isInt8<> should return true if inside."); + EXPECT(IntUtil::isInt8(127) == true, + "IntUtil::isInt8<> should return true if inside."); + EXPECT(IntUtil::isInt8(-129) == false, + "IntUtil::isInt8<> should return false if outside."); + EXPECT(IntUtil::isInt8(128) == false, + "IntUtil::isInt8<> should return false if outside."); + + INFO("IntUtil::isUInt8()."); + EXPECT(IntUtil::isUInt8(255) == true, + "IntUtil::isUInt8<> should return true if inside."); + EXPECT(IntUtil::isUInt8(256) == false, + "IntUtil::isUInt8<> should return false if outside."); + EXPECT(IntUtil::isUInt8(-1) == false, + "IntUtil::isUInt8<> should return false if negative."); + + INFO("IntUtil::isInt16()."); + EXPECT(IntUtil::isInt16(-32768) == true, + "IntUtil::isInt16<> should return true if inside."); + EXPECT(IntUtil::isInt16(32767) == true, + "IntUtil::isInt16<> should return true if inside."); + EXPECT(IntUtil::isInt16(-32769) == false, + "IntUtil::isInt16<> should return false if outside."); + EXPECT(IntUtil::isInt16(32768) == false, + "IntUtil::isInt16<> should return false if outside."); + + INFO("IntUtil::isUInt16()."); + EXPECT(IntUtil::isUInt16(65535) == true, + "IntUtil::isUInt16<> should return true if inside."); + EXPECT(IntUtil::isUInt16(65536) == false, + "IntUtil::isUInt16<> should return false if outside."); + EXPECT(IntUtil::isUInt16(-1) == false, + "IntUtil::isUInt16<> should return false if negative."); + + INFO("IntUtil::isInt32()."); + EXPECT(IntUtil::isInt32(2147483647) == true, + "IntUtil::isInt32 should return true if inside."); + EXPECT(IntUtil::isInt32(-2147483647 - 1) == true, + "IntUtil::isInt32 should return true if inside."); + EXPECT(IntUtil::isInt32(ASMJIT_UINT64_C(2147483648)) == false, + "IntUtil::isInt32 should return false if outside."); + EXPECT(IntUtil::isInt32(ASMJIT_UINT64_C(0xFFFFFFFF)) == false, + "IntUtil::isInt32 should return false if outside."); + EXPECT(IntUtil::isInt32(ASMJIT_UINT64_C(0xFFFFFFFF) + 1) == false, + "IntUtil::isInt32 should return false if outside."); + + INFO("IntUtil::isUInt32()."); + EXPECT(IntUtil::isUInt32(ASMJIT_UINT64_C(0xFFFFFFFF)) == true, + "IntUtil::isUInt32 should return true if inside."); + EXPECT(IntUtil::isUInt32(ASMJIT_UINT64_C(0xFFFFFFFF) + 1) == false, + "IntUtil::isUInt32 should return false if outside."); + EXPECT(IntUtil::isUInt32(-1) == false, + "IntUtil::isUInt32 should return false if negative."); + + INFO("IntUtil::isPower2()."); + for (i = 0; i < 64; i++) { + EXPECT(IntUtil::isPowerOf2(static_cast(1) << i) == true, + "IntUtil::isPower2() didn't report power of 2."); + EXPECT(IntUtil::isPowerOf2((static_cast(1) << i) ^ 0x001101) == false, + "IntUtil::isPower2() didn't report not power of 2."); + } + + INFO("IntUtil::mask()."); + for (i = 0; i < 32; i++) { + EXPECT(IntUtil::mask(i) == (1 << i), + "IntUtil::mask(%u) should return %X.", i, (1 << i)); + } + + INFO("IntUtil::bits()."); + for (i = 0; i < 32; i++) { + uint32_t expectedBits = 0; + + for (uint32_t b = 0; b < i; b++) + expectedBits |= static_cast(1) << b; + + EXPECT(IntUtil::bits(i) == expectedBits, + "IntUtil::bits(%u) should return %X.", i, expectedBits); + } + + INFO("IntUtil::hasBit()."); + for (i = 0; i < 32; i++) { + EXPECT(IntUtil::hasBit((1 << i), i) == true, + "IntUtil::hasBit(%X, %u) should return true.", (1 << i), i); + } + + INFO("IntUtil::bitCount()."); + for (i = 0; i < 32; i++) { + EXPECT(IntUtil::bitCount((1 << i)) == 1, + "IntUtil::bitCount(%X) should return true.", (1 << i)); + } + EXPECT(IntUtil::bitCount(0x000000F0) == 4, ""); + EXPECT(IntUtil::bitCount(0x10101010) == 4, ""); + EXPECT(IntUtil::bitCount(0xFF000000) == 8, ""); + EXPECT(IntUtil::bitCount(0xFFFFFFF7) == 31, ""); + EXPECT(IntUtil::bitCount(0x7FFFFFFF) == 31, ""); + + INFO("IntUtil::findFirstBit()."); + for (i = 0; i < 32; i++) { + EXPECT(IntUtil::findFirstBit((1 << i)) == i, + "IntUtil::findFirstBit(%X) should return %u.", (1 << i), i); + } + + INFO("IntUtil::isAligned()."); + EXPECT(IntUtil::isAligned(0xFFFF, 4) == false, ""); + EXPECT(IntUtil::isAligned(0xFFF4, 4) == true , ""); + EXPECT(IntUtil::isAligned(0xFFF8, 8) == true , ""); + EXPECT(IntUtil::isAligned(0xFFF0, 16) == true , ""); + + INFO("IntUtil::alignTo()."); + EXPECT(IntUtil::alignTo(0xFFFF, 4) == 0x10000, ""); + EXPECT(IntUtil::alignTo(0xFFF4, 4) == 0x0FFF4, ""); + EXPECT(IntUtil::alignTo(0xFFF8, 8) == 0x0FFF8, ""); + EXPECT(IntUtil::alignTo(0xFFF0, 16) == 0x0FFF0, ""); + EXPECT(IntUtil::alignTo(0xFFF0, 32) == 0x10000, ""); + + INFO("IntUtil::alignToPowerOf2()."); + EXPECT(IntUtil::alignToPowerOf2(0xFFFF) == 0x10000, ""); + EXPECT(IntUtil::alignToPowerOf2(0xF123) == 0x10000, ""); + EXPECT(IntUtil::alignToPowerOf2(0x0F00) == 0x01000, ""); + EXPECT(IntUtil::alignToPowerOf2(0x0100) == 0x00100, ""); + EXPECT(IntUtil::alignToPowerOf2(0x1001) == 0x02000, ""); + + INFO("IntUtil::deltaTo()."); + EXPECT(IntUtil::deltaTo(0xFFFF, 4) == 1, ""); + EXPECT(IntUtil::deltaTo(0xFFF4, 4) == 0, ""); + EXPECT(IntUtil::deltaTo(0xFFF8, 8) == 0, ""); + EXPECT(IntUtil::deltaTo(0xFFF0, 16) == 0, ""); + EXPECT(IntUtil::deltaTo(0xFFF0, 32) == 16, ""); +} +#endif // ASMJIT_TEST + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/intutil.h b/third/Blackbone/src/3rd_party/AsmJit/base/intutil.h new file mode 100644 index 0000000000000000000000000000000000000000..c58d9576bd691c7745c44be56aeacd50a175bd88 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/intutil.h @@ -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 +struct IntTraits { + enum { + kIsSigned = static_cast(~static_cast(0)) < static_cast(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(u1) << 32) + u0; +#else + return (static_cast(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 + static ASMJIT_INLINE T iMin(const T& a, const T& b) { return a < b ? a : b; } + + //! Get maximum value of `a` and `b`. + template + 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 + 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 + 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 + static ASMJIT_INLINE bool isInt8(T x) { + if (IntTraits::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 + static ASMJIT_INLINE bool isUInt8(T x) { + if (IntTraits::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 + static ASMJIT_INLINE bool isInt16(T x) { + if (IntTraits::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 + static ASMJIT_INLINE bool isUInt16(T x) { + if (IntTraits::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 + static ASMJIT_INLINE bool isInt32(T x) { + if (IntTraits::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 + static ASMJIT_INLINE bool isUInt32(T x) { + if (IntTraits::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 + 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( + -static_cast(x >= sizeof(uint32_t) * 8)); + + return ((static_cast(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((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(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 + static ASMJIT_INLINE bool isAligned(T base, T alignment) { + return (base % alignment) == 0; + } + + //! Align `base` to `alignment`. + template + static ASMJIT_INLINE T alignTo(T base, T alignment) { + return (base + (alignment - 1)) & ~(alignment - 1); + } + + template + 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 + 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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/lock.h b/third/Blackbone/src/3rd_party/AsmJit/base/lock.h new file mode 100644 index 0000000000000000000000000000000000000000..f2e2042ac78b6d046e9194c10d16bdfb11e47b44 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/lock.h @@ -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 +#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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/logger.cpp b/third/Blackbone/src/3rd_party/AsmJit/base/logger.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3e64301c32e4273070d60784f68b97d7901875b3 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/logger.cpp @@ -0,0 +1,158 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Guard] +#include "../build.h" +#if !defined(ASMJIT_DISABLE_LOGGER) + +// [Dependencies - AsmJit] +#include "../base/intutil.h" +#include "../base/logger.h" +#include "../base/string.h" + +// [Dependencies - C] +#include + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [asmjit::Logger - Construction / Destruction] +// ============================================================================ + +Logger::Logger() { + _options = 0; + ::memset(_indentation, 0, ASMJIT_ARRAY_SIZE(_indentation)); +} + +Logger::~Logger() {} + +// ============================================================================ +// [asmjit::Logger - Logging] +// ============================================================================ + +void Logger::logFormat(uint32_t style, const char* fmt, ...) { + char buf[1024]; + size_t len; + + va_list ap; + va_start(ap, fmt); + len = vsnprintf(buf, 1023, fmt, ap); + va_end(ap); + + logString(style, buf, len); +} + +void Logger::logBinary(uint32_t style, const void* data, size_t size) { + static const char prefix[] = ".data "; + static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + const uint8_t* s = static_cast(data); + size_t i = size; + + char buffer[128]; + ::memcpy(buffer, prefix, ASMJIT_ARRAY_SIZE(prefix) - 1); + + while (i) { + uint32_t n = static_cast(IntUtil::iMin(i, 16)); + char* p = buffer + ASMJIT_ARRAY_SIZE(prefix) - 1; + + i -= n; + do { + uint32_t c = s[0]; + + p[0] = hex[c >> 4]; + p[1] = hex[c & 15]; + + p += 2; + s += 1; + } while (--n); + + *p++ = '\n'; + logString(style, buffer, (size_t)(p - buffer)); + } +} + +// ============================================================================ +// [asmjit::Logger - LogBinary] +// ============================================================================ + +void Logger::setOption(uint32_t id, bool value) { + if (id >= kLoggerOptionCount) + return; + + uint32_t mask = 1 << id; + + if (value) + _options |= mask; + else + _options &= ~mask; +} + +// ============================================================================ +// [asmjit::Logger - Indentation] +// ============================================================================ + +void Logger::setIndentation(const char* indentation) { + ::memset(_indentation, 0, ASMJIT_ARRAY_SIZE(_indentation)); + if (!indentation) + return; + + size_t length = StringUtil::nlen(indentation, ASMJIT_ARRAY_SIZE(_indentation) - 1); + ::memcpy(_indentation, indentation, length); +} + +// ============================================================================ +// [asmjit::FileLogger - Construction / Destruction] +// ============================================================================ + +FileLogger::FileLogger(FILE* stream) : _stream(NULL) { + setStream(stream); +} + +FileLogger::~FileLogger() {} + +// ============================================================================ +// [asmjit::FileLogger - Logging] +// ============================================================================ + +void FileLogger::logString(uint32_t style, const char* buf, size_t len) { + if (!_stream) + return; + + if (len == kInvalidIndex) + len = strlen(buf); + + fwrite(buf, 1, len, _stream); +} + +// ============================================================================ +// [asmjit::StringLogger - Construction / Destruction] +// ============================================================================ + +StringLogger::StringLogger() {} +StringLogger::~StringLogger() {} + +// ============================================================================ +// [asmjit::StringLogger - Logging] +// ============================================================================ + +void StringLogger::logString(uint32_t style, const char* buf, size_t len) { + _stringBuilder.appendString(buf, len); +} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // !ASMJIT_DISABLE_LOGGER diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/logger.h b/third/Blackbone/src/3rd_party/AsmJit/base/logger.h new file mode 100644 index 0000000000000000000000000000000000000000..b3adc4020620bbe76ec8f835519bf6bb69b720e9 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/logger.h @@ -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 + +// [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((_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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/operand.cpp b/third/Blackbone/src/3rd_party/AsmJit/base/operand.cpp new file mode 100644 index 0000000000000000000000000000000000000000..04a84936e999d03ae88cc82fbb697bcc76d65fb8 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/operand.cpp @@ -0,0 +1,38 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Dependencies - AsmJit] +#include "../base/globals.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [asmjit::Operand] +// ============================================================================ + +// Prevent static initialization. +struct Operand { + uint8_t op; + uint8_t size; + uint8_t reserved_2_1; + uint8_t reserved_3_1; + uint32_t id; + uint64_t reserved_8_8; +}; + +ASMJIT_VAR const Operand noOperand; +const Operand noOperand = { 0, 0, 0, 0, kInvalidValue, 0 }; + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/operand.h b/third/Blackbone/src/3rd_party/AsmJit/base/operand.h new file mode 100644 index 0000000000000000000000000000000000000000..4553e339990145cdeb194c0f8716b5e120ba6ae2 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/operand.h @@ -0,0 +1,1090 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Guard] +#ifndef _ASMJIT_BASE_OPERAND_H +#define _ASMJIT_BASE_OPERAND_H + +// [Dependencies - AsmJit] +#include "../base/intutil.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [Forward Declarations] +// ============================================================================ + +struct Assembler; +struct Compiler; + +//! \addtogroup asmjit_base_general +//! \{ + +// ============================================================================ +// [asmjit::kOperandType] +// ============================================================================ + +//! Operand types that can be encoded in `Operand`. +ASMJIT_ENUM(kOperandType) { + //! Invalid operand, used only internally (not initialized Operand). + kOperandTypeNone = 0, + //! Operand is a register. + kOperandTypeReg = 1, + //! Operand is a variable. + kOperandTypeVar = 2, + //! Operand is a memory. + kOperandTypeMem = 3, + //! Operand is an immediate value. + kOperandTypeImm = 4, + //! Operand is a label. + kOperandTypeLabel = 5 +}; + +// ============================================================================ +// [asmjit::kOperandId] +// ============================================================================ + +//! Operand id masks used to determine the operand type. +ASMJIT_ENUM(kOperandId) { + //! Operand id refers to `Var`. + kOperandIdVar = 0x80000000U, + //! Operand id to real index mask. + kOperandIdNum = 0x7FFFFFFFU +}; + +// ============================================================================ +// [asmjit::kRegClass] +// ============================================================================ + +//! Register class. +ASMJIT_ENUM(kRegClass) { + //! Gp register class, compatible with all architectures. + kRegClassGp = 0 +}; + +// ============================================================================ +// [asmjit::kSize] +// ============================================================================ + +//! Common size of registers and pointers. +ASMJIT_ENUM(kSize) { + //! 1 byte size (BYTE). + kSizeByte = 1, + //! 2 bytes size (WORD). + kSizeWord = 2, + //! 4 bytes size (DWORD). + kSizeDWord = 4, + //! 8 bytes size (QWORD). + kSizeQWord = 8, + //! 10 bytes size (TWORD). + kSizeTWord = 10, + //! 16 bytes size (OWORD / DQWORD). + kSizeOWord = 16, + //! 32 bytes size (YWORD / QQWORD). + kSizeYWord = 32 +}; + +// ============================================================================ +// [asmjit::kMemType] +// ============================================================================ + +//! Type of memory operand. +ASMJIT_ENUM(kMemType) { + //! Memory operand is a combination of base register and optional index register + //! and displacement. + //! + //! The `Assembler` interprets `kMemTypeBaseIndex` and `kMemTypeStackIndex` + //! types the same way, but `Compiler` interprets `kMemTypeBaseIndex` as + //! `[base + index]` and `kMemTypeStackIndex` as `[stack(base) + index]`. + kMemTypeBaseIndex = 0, + + //! Memory operand is a combination of variable's memory location, + //! optional index register and displacement. + //! + //! The `Assembler` interprets `kMemTypeBaseIndex` and `kMemTypeStackIndex` + //! types in the same way, but `Compiler` interprets `kMemTypeBaseIndex` as + //! `[base + index]` and `kMemTypeStackIndex` as `[stack(base) + index]`. + kMemTypeStackIndex = 1, + + //! Memory operand refers to the memory location specified by a label. + kMemTypeLabel = 2, + //! Memory operand is an absolute memory location. + //! + //! Supported mostly by x86, truncated to a 32-bit value when running in + //! 64-bit mode (x64). + kMemTypeAbsolute = 3 +}; + +// ============================================================================ +// [asmjit::Operand] +// ============================================================================ + +//! Operand can contain register, memory location, immediate, or label. +struct Operand { + // -------------------------------------------------------------------------- + // [Structs] + // -------------------------------------------------------------------------- + + //! \internal + //! + //! Base operand data. + struct BaseOp { + //! Type of operand, see `kOperandType`. + uint8_t op; + //! Size of operand (register, address, immediate, or variable). + uint8_t size; + //! \internal + uint8_t reserved_2_1; + //! \internal + uint8_t reserved_3_1; + + //! Operand id, identifier used by `Assembler` and `Compiler`. + //! + //! \note Uninitialized operand has always set id to `kInvalidValue`. + uint32_t id; + + //! \internal + uint32_t reserved_8_4; + //! \internal + uint32_t reserved_12_4; + }; + + //! \internal + //! + //! Register or Variable operand data. + struct VRegOp { + //! Type of operand, `kOperandTypeReg`. + uint8_t op; + //! Size of register or variable. + uint8_t size; + + union { + //! Register code = (type << 8) | index. + uint16_t code; + + //! Register type and index access. + struct { +#if defined(ASMJIT_HOST_LE) + //! Register index. + uint8_t index; + //! Register type. + uint8_t type; +#else + //! Register type. + uint8_t type; + //! Register index. + uint8_t index; +#endif // ASMJIT_HOST + }; + }; + + //! Variable id, used by `Compiler` to identify variables. + uint32_t id; + + union { + struct { + //! Variable type. + uint32_t vType; + //! \internal + uint32_t reserved_12_4; + }; + + //! \internal + //! + //! This is not needed or used, it's just to force compiler to always + //! align this struct to 8-bytes (so the struct is compatible to others + //! when it comes to alignment). It should fix VS linker warning as well. + uint64_t reserved8_8; + }; + }; + + //! \internal + //! + //! Memory or Variable operand data. + struct VMemOp { + //! Type of operand, `kOperandTypeMem`. + uint8_t op; + //! Size of the pointer in bytes. + uint8_t size; + //! Type of the memory operand, see `kMemType`. + uint8_t type; + //! X86/X64 layout: + //! - segment [3 bits], see `kX86Seg`. + //! - shift [2 bits], index register shift (0 to 3). + uint8_t flags; + + //! Base register, variable or label id. + uint32_t base; + //! Index register or variable. + uint32_t index; + //! 32-bit displacement or absolute address. + int32_t displacement; + }; + + //! \internal + //! + //! Immediate operand data. + struct ImmOp { + //! Type of operand, `kOperandTypeImm`. + uint8_t op; + //! Size of immediate (or 0 to autodetect). + uint8_t size; + //! \internal + uint8_t reserved_2_1; + //! \internal + uint8_t reserved_3_1; + + //! Operand id, always set to `kInvalidValue` (immediates don't have IDs). + uint32_t id; + + union { + //! 8x8-bit signed immediate values. + int8_t _i8[8]; + //! 8x8-bit unsigned immediate values. + uint8_t _u8[8]; + + //! 4x16-bit signed immediate values. + int16_t _i16[4]; + //! 4x16-bit unsigned immediate values. + uint16_t _u16[4]; + + //! 2x32-bit signed immediate values. + int32_t _i32[2]; + //! 2x32-bit unsigned immediate values. + uint32_t _u32[2]; + + //! 1x64-bit signed immediate value. + int64_t _i64[1]; + //! 1x64-bit unsigned immediate value. + uint64_t _u64[1]; + + //! 2x SP-FP values. + float _f32[2]; + //! 1x DP-FP value. + double _f64[1]; + } value; + }; + + //! \internal + //! + //! Label operand data. + struct LabelOp { + //! Type of operand, `kOperandTypeLabel`. + uint8_t op; + //! Always zero, labels don't have size. + uint8_t size; + //! \internal + uint8_t reserved_2_1; + //! \internal + uint8_t reserved_3_1; + + //! Operand id (`kInvalidValue` if the label is not initialized by code + //! generator). + uint32_t id; + + //! \internal + uint32_t reserved_8_4; + //! \internal + uint32_t reserved_12_4; + }; + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create an uninitialized operand. + ASMJIT_INLINE Operand() { + _init_packed_op_sz_b0_b1_id(kOperandTypeNone, 0, 0, 0, kInvalidValue); + _init_packed_d2_d3(0, 0); + } + + //! Create a reference to `other` operand. + ASMJIT_INLINE Operand(const Operand& other) { + _init(other); + } + + explicit ASMJIT_INLINE Operand(const _NoInit&) {} + + // -------------------------------------------------------------------------- + // [Operand] + // -------------------------------------------------------------------------- + + //! Clone `Operand`. + ASMJIT_INLINE Operand clone() const { + return Operand(*this); + } + + // -------------------------------------------------------------------------- + // [Init & Copy] + // -------------------------------------------------------------------------- + + //! \internal + //! + //! Initialize operand to `other` (used by constructors). + ASMJIT_INLINE void _init(const Operand& other) { + ::memcpy(this, &other, sizeof(Operand)); + } + + ASMJIT_INLINE void _init_packed_op_sz_b0_b1_id(uint32_t op, uint32_t sz, uint32_t r0, uint32_t r1, uint32_t id) { + // This hack is not for performance, but to decrease the size of the binary + // generated when constructing AsmJit operands (mostly for third parties). + // Some compilers are not able to join four BYTE writes to a single DWORD + // write. Because the 'a', 'b', 'c' and 'd' variables are usually compile + // time constants the compiler can do a really nice job if they are joined + // by using bitwise operations. + _packed[0].setPacked_2x32(IntUtil::pack32_4x8(op, sz, r0, r1), id); + } + + ASMJIT_INLINE void _init_packed_op_sz_w0_id(uint32_t op, uint32_t sz, uint32_t w0, uint32_t id) { + _packed[0].setPacked_2x32(IntUtil::pack32_2x8_1x16(op, sz, w0), id); + } + + ASMJIT_INLINE void _init_packed_d0_d1(uint32_t u0, uint32_t u1) { + _packed[0].setPacked_2x32(u0, u1); + } + + ASMJIT_INLINE void _init_packed_d2_d3(uint32_t u2, uint32_t u3) { + _packed[1].setPacked_2x32(u2, u3); + } + + //! \internal + //! + //! Initialize operand to `other` (used by assign operators). + ASMJIT_INLINE void _copy(const Operand& other) { + ::memcpy(this, &other, sizeof(Operand)); + } + + // -------------------------------------------------------------------------- + // [Data] + // -------------------------------------------------------------------------- + + template + ASMJIT_INLINE T& getData() { + return reinterpret_cast(_base); + } + + template + ASMJIT_INLINE const T& getData() const { + return reinterpret_cast(_base); + } + + // -------------------------------------------------------------------------- + // [Type] + // -------------------------------------------------------------------------- + + //! Get type of the operand, see `kOperandType`. + ASMJIT_INLINE uint32_t getOp() const { return _base.op; } + + //! Get whether the operand is none - `kOperandTypeNone`. + ASMJIT_INLINE bool isNone() const { return (_base.op == kOperandTypeNone); } + //! Get whether the operand is a register - `kOperandTypeReg`. + ASMJIT_INLINE bool isReg() const { return (_base.op == kOperandTypeReg); } + //! Get whether the operand is a variable - `kOperandTypeVar`. + ASMJIT_INLINE bool isVar() const { return (_base.op == kOperandTypeVar); } + //! Get whether the operand is a memory address - `kOperandTypeMem`. + ASMJIT_INLINE bool isMem() const { return (_base.op == kOperandTypeMem); } + //! Get whether the operand is an immediate value - `kOperandTypeImm`. + ASMJIT_INLINE bool isImm() const { return (_base.op == kOperandTypeImm); } + //! Get whether the operand is a label - `kOperandTypeLabel`. + ASMJIT_INLINE bool isLabel() const { return (_base.op == kOperandTypeLabel); } + + // -------------------------------------------------------------------------- + // [Type - Combined] + // -------------------------------------------------------------------------- + + //! Get register type. + ASMJIT_INLINE uint32_t getRegType() const { + return _vreg.type; + } + + //! Get register index. + ASMJIT_INLINE uint32_t getRegIndex() const { + return _vreg.index; + } + + //! Get whether the operand is register of `type`. + ASMJIT_INLINE bool isRegType(uint32_t type) const { + return (_packed[0].u32[0] & IntUtil::pack32_2x8_1x16(0xFF, 0, 0xFF00)) == IntUtil::pack32_2x8_1x16(kOperandTypeReg, 0, (type << 8)); + } + + //! Get whether the operand is register and of `type` and `index`. + ASMJIT_INLINE bool isRegCode(uint32_t type, uint32_t index) const { + return (_packed[0].u32[0] & IntUtil::pack32_2x8_1x16(0xFF, 0, 0xFFFF)) == IntUtil::pack32_2x8_1x16(kOperandTypeReg, 0, (type << 8) + index); + } + + //! Get whether the operand is a register or memory. + ASMJIT_INLINE bool isRegOrMem() const { + ASMJIT_ASSERT(kOperandTypeReg == 1); + ASMJIT_ASSERT(kOperandTypeMem == 3); + return (static_cast(_base.op) | 0x2U) == 0x3U; + } + + //! Get whether the operand is variable or memory. + ASMJIT_INLINE bool isVarOrMem() const { + ASMJIT_ASSERT(kOperandTypeVar == 2); + ASMJIT_ASSERT(kOperandTypeMem == 3); + return (static_cast(_base.op) - 2U) <= 1; + } + + // -------------------------------------------------------------------------- + // [Size] + // -------------------------------------------------------------------------- + + //! Get size of the operand in bytes. + ASMJIT_INLINE uint32_t getSize() const { + return _base.size; + } + + // -------------------------------------------------------------------------- + // [Id] + // -------------------------------------------------------------------------- + + //! Get operand id. + //! + //! Operand id's are used internally by `Assembler` and `Compiler`. + //! + //! There is no way to change or remove operand id. Unneeded operands can be + //! simply reassigned by `operator=`. + ASMJIT_INLINE uint32_t getId() const { + return _base.id; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + union { + //! Base data. + BaseOp _base; + //! Register or variable data. + VRegOp _vreg; + //! Memory data. + VMemOp _vmem; + //! Immediate data. + ImmOp _imm; + //! Label data. + LabelOp _label; + + //! Packed operand as two 64-bit integers. + UInt64 _packed[2]; + }; +}; + +// ============================================================================ +// [asmjit::OperandUtil] +// ============================================================================ + +//! Operand utilities. +struct OperandUtil { + //! Make variable id. + static ASMJIT_INLINE uint32_t makeVarId(uint32_t id) { + return id | kOperandIdVar; + } + + //! Make label id. + static ASMJIT_INLINE uint32_t makeLabelId(uint32_t id) { + return id; + } + + //! Strip variable id bit so it becomes a pure index to `VarData[]` array. + static ASMJIT_INLINE uint32_t stripVarId(uint32_t id) { + return id & 0x7FFFFFFFU; + } + + //! Get whether the id refers to `Var`. + //! + //! \note The function will never return `true` if the id is `kInvalidValue`. + //! The trick is to compare a given id to -1 (kInvalidValue) so we check both + //! using only one comparison. + static ASMJIT_INLINE bool isVarId(uint32_t id) { + return static_cast(id) < -1; + } + + //! Get whether the id refers to `Label`. + //! + //! \note The function will never return `true` if the id is `kInvalidValue`. + static ASMJIT_INLINE bool isLabelId(uint32_t id) { + return static_cast(id) >= 0; + } +}; + +// ============================================================================ +// [asmjit::Reg] +// ============================================================================ + +//! Base class for all register operands. +struct Reg : public Operand { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a dummy base register. + ASMJIT_INLINE Reg() : Operand(NoInit) { + _init_packed_op_sz_w0_id(kOperandTypeReg, 0, (kInvalidReg << 8) + kInvalidReg, kInvalidValue); + _init_packed_d2_d3(kInvalidVar, 0); + } + + //! Create a new base register. + ASMJIT_INLINE Reg(uint32_t type, uint32_t index, uint32_t size) : Operand(NoInit) { + _init_packed_op_sz_w0_id(kOperandTypeReg, size, (type << 8) + index, kInvalidValue); + _init_packed_d2_d3(kInvalidVar, 0); + } + + //! Create a new reference to `other`. + ASMJIT_INLINE Reg(const Reg& other) : Operand(other) {} + + //! Create a new reference to `other` and change the index to `index`. + ASMJIT_INLINE Reg(const Reg& other, uint32_t index) : Operand(other) { + _vreg.index = static_cast(index); + } + + explicit ASMJIT_INLINE Reg(const _NoInit&) : Operand(NoInit) {} + + // -------------------------------------------------------------------------- + // [Reg Specific] + // -------------------------------------------------------------------------- + + //! Clone `Reg` operand. + ASMJIT_INLINE Reg clone() const { + return Reg(*this); + } + + //! Get whether register code is equal to `type`. + ASMJIT_INLINE bool isRegType(uint32_t type) const { + return _vreg.type == type; + } + + //! Get whether register code is equal to `type`. + ASMJIT_INLINE bool isRegCode(uint32_t code) const { + return _vreg.code == code; + } + + //! Get whether register code is equal to `type`. + ASMJIT_INLINE bool isRegCode(uint32_t type, uint32_t index) const { + return _vreg.code == (type << 8) + index; + } + + //! Get register code that equals to '(type << 8) + index'. + ASMJIT_INLINE uint32_t getRegCode() const { + return _vreg.code; + } + + //! Get register type. + ASMJIT_INLINE uint32_t getRegType() const { + return _vreg.type; + } + + //! Get register index. + ASMJIT_INLINE uint32_t getRegIndex() const { + return _vreg.index; + } + +#define ASMJIT_REG_OP(_Type_) \ + ASMJIT_INLINE _Type_ clone() const { \ + return _Type_(*this); \ + } \ + \ + /*! Set register `size`. */ \ + ASMJIT_INLINE _Type_& setSize(uint32_t size) { \ + _vreg.size = static_cast(size); \ + return *this; \ + } \ + \ + /*! Set register `code`. */ \ + ASMJIT_INLINE _Type_& setCode(uint32_t code) { \ + _vreg.code = static_cast(code); \ + return *this; \ + } \ + \ + /*! Set register `type` and `index`. */ \ + ASMJIT_INLINE _Type_& setCode(uint32_t type, uint32_t index) { \ + _vreg.type = static_cast(type); \ + _vreg.index = static_cast(index); \ + return *this; \ + } \ + \ + /*! Set register `type`. */ \ + ASMJIT_INLINE _Type_& setType(uint32_t type) { \ + _vreg.type = static_cast(type); \ + return *this; \ + } \ + \ + /*! Set register `index`. */ \ + ASMJIT_INLINE _Type_& setIndex(uint32_t index) { \ + _vreg.index = static_cast(index); \ + return *this; \ + } \ + \ + ASMJIT_INLINE _Type_& operator=(const _Type_& other) { _copy(other); return *this; } \ + \ + ASMJIT_INLINE bool operator==(const _Type_& other) const { return _packed[0].u32[0] == other._packed[0].u32[0]; } \ + ASMJIT_INLINE bool operator!=(const _Type_& other) const { return !operator==(other); } +}; + +// ============================================================================ +// [asmjit::BaseMem] +// ============================================================================ + +//! Base class for all memory operands. +struct BaseMem : public Operand { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE BaseMem() : Operand(NoInit) { + reset(); + } + + ASMJIT_INLINE BaseMem(const BaseMem& other) : Operand(other) {} + explicit ASMJIT_INLINE BaseMem(const _NoInit&) : Operand(NoInit) {} + + // -------------------------------------------------------------------------- + // [BaseMem Specific] + // -------------------------------------------------------------------------- + + //! Clone `BaseMem` operand. + ASMJIT_INLINE BaseMem clone() const { + return BaseMem(*this); + } + + //! Reset `BaseMem` operand. + ASMJIT_INLINE void reset() { + _init_packed_op_sz_b0_b1_id(kOperandTypeMem, 0, kMemTypeBaseIndex, 0, kInvalidValue); + _init_packed_d2_d3(kInvalidValue, 0); + } + + //! Get the type of the memory operand, see `kMemType`. + ASMJIT_INLINE uint32_t getMemType() const { + return _vmem.type; + } + + //! Get whether the type of the memory operand is either `kMemTypeBaseIndex` + //! or `kMemTypeStackIndex`. + ASMJIT_INLINE bool isBaseIndexType() const { + return _vmem.type <= kMemTypeStackIndex; + } + + //! Get whether the memory operand has base register. + ASMJIT_INLINE bool hasBase() const { + return _vmem.base != kInvalidValue; + } + + //! Get memory operand base id, or `kInvalidValue`. + ASMJIT_INLINE uint32_t getBase() const { + return _vmem.base; + } + + //! Set memory operand size. + ASMJIT_INLINE BaseMem& setSize(uint32_t size) { + _vmem.size = static_cast(size); + return *this; + } + + //! Get memory operand relative displacement. + ASMJIT_INLINE int32_t getDisplacement() const { + return _vmem.displacement; + } + + //! Set memory operand relative displacement. + ASMJIT_INLINE BaseMem& setDisplacement(int32_t disp) { + _vmem.displacement = disp; + return *this; + } + + // -------------------------------------------------------------------------- + // [Operator Overload] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE BaseMem& operator=(const BaseMem& other) { + _copy(other); + return *this; + } + + ASMJIT_INLINE bool operator==(const BaseMem& other) const { + return (_packed[0] == other._packed[0]) & (_packed[1] == other._packed[1]); + } + + ASMJIT_INLINE bool operator!=(const BaseMem& other) const { + return !(*this == other); + } +}; + +// ============================================================================ +// [asmjit::Imm] +// ============================================================================ + +//! Immediate operand. +//! +//! Immediate operand is usually part of instruction itself. It's inlined after +//! or before the instruction opcode. Immediates can be only signed or unsigned +//! integers. +//! +//! To create immediate operand use `imm()` or `imm_u()` non-members or `Imm` +//! constructors. +struct Imm : public Operand { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new immediate value (initial value is 0). + Imm() : Operand(NoInit) { + _init_packed_op_sz_b0_b1_id(kOperandTypeImm, 0, 0, 0, kInvalidValue); + _imm.value._i64[0] = 0; + } + + //! Create a new signed immediate value, assigning the value to `val`. + explicit Imm(int64_t val) : Operand(NoInit) { + _init_packed_op_sz_b0_b1_id(kOperandTypeImm, 0, 0, 0, kInvalidValue); + _imm.value._i64[0] = val; + } + + //! Create a new immediate value from `other`. + ASMJIT_INLINE Imm(const Imm& other) : Operand(other) {} + + explicit ASMJIT_INLINE Imm(const _NoInit&) : Operand(NoInit) {} + + // -------------------------------------------------------------------------- + // [Immediate Specific] + // -------------------------------------------------------------------------- + + //! Clone `Imm` operand. + ASMJIT_INLINE Imm clone() const { + return Imm(*this); + } + + //! Get whether the immediate can be casted to 8-bit signed integer. + ASMJIT_INLINE bool isInt8() const { return IntUtil::isInt8(_imm.value._i64[0]); } + //! Get whether the immediate can be casted to 8-bit unsigned integer. + ASMJIT_INLINE bool isUInt8() const { return IntUtil::isUInt8(_imm.value._i64[0]); } + + //! Get whether the immediate can be casted to 16-bit signed integer. + ASMJIT_INLINE bool isInt16() const { return IntUtil::isInt16(_imm.value._i64[0]); } + //! Get whether the immediate can be casted to 16-bit unsigned integer. + ASMJIT_INLINE bool isUInt16() const { return IntUtil::isUInt16(_imm.value._i64[0]); } + + //! Get whether the immediate can be casted to 32-bit signed integer. + ASMJIT_INLINE bool isInt32() const { return IntUtil::isInt32(_imm.value._i64[0]); } + //! Get whether the immediate can be casted to 32-bit unsigned integer. + ASMJIT_INLINE bool isUInt32() const { return IntUtil::isUInt32(_imm.value._i64[0]); } + + //! Get immediate value as 8-bit signed integer. + ASMJIT_INLINE int8_t getInt8() const { return _imm.value._i8[_ASMJIT_HOST_INDEX(8, 0)]; } + //! Get immediate value as 8-bit unsigned integer. + ASMJIT_INLINE uint8_t getUInt8() const { return _imm.value._u8[_ASMJIT_HOST_INDEX(8, 0)]; } + //! Get immediate value as 16-bit signed integer. + ASMJIT_INLINE int16_t getInt16() const { return _imm.value._i16[_ASMJIT_HOST_INDEX(4, 0)]; } + //! Get immediate value as 16-bit unsigned integer. + ASMJIT_INLINE uint16_t getUInt16() const { return _imm.value._u16[_ASMJIT_HOST_INDEX(4, 0)]; } + //! Get immediate value as 32-bit signed integer. + ASMJIT_INLINE int32_t getInt32() const { return _imm.value._i32[_ASMJIT_HOST_INDEX(2, 0)]; } + //! Get immediate value as 32-bit unsigned integer. + ASMJIT_INLINE uint32_t getUInt32() const { return _imm.value._u32[_ASMJIT_HOST_INDEX(2, 0)]; } + //! Get immediate value as 64-bit signed integer. + ASMJIT_INLINE int64_t getInt64() const { return _imm.value._i64[0]; } + //! Get immediate value as 64-bit unsigned integer. + ASMJIT_INLINE uint64_t getUInt64() const { return _imm.value._u64[0]; } + + //! Get immediate value as `intptr_t`. + ASMJIT_INLINE intptr_t getIntPtr() const { + if (sizeof(intptr_t) == sizeof(int64_t)) + return static_cast(getInt64()); + else + return static_cast(getInt32()); + } + + //! Get immediate value as `uintptr_t`. + ASMJIT_INLINE uintptr_t getUIntPtr() const { + if (sizeof(uintptr_t) == sizeof(uint64_t)) + return static_cast(getUInt64()); + else + return static_cast(getUInt32()); + } + + //! Get low 32-bit signed integer. + ASMJIT_INLINE int32_t getInt32Lo() const { return _imm.value._i32[_ASMJIT_HOST_INDEX(2, 0)]; } + //! Get low 32-bit signed integer. + ASMJIT_INLINE uint32_t getUInt32Lo() const { return _imm.value._u32[_ASMJIT_HOST_INDEX(2, 0)]; } + //! Get high 32-bit signed integer. + ASMJIT_INLINE int32_t getInt32Hi() const { return _imm.value._i32[_ASMJIT_HOST_INDEX(2, 1)]; } + //! Get high 32-bit signed integer. + ASMJIT_INLINE uint32_t getUInt32Hi() const { return _imm.value._u32[_ASMJIT_HOST_INDEX(2, 1)]; } + + //! Set immediate value to 8-bit signed integer `val`. + ASMJIT_INLINE Imm& setInt8(int8_t val) { + if (kArchHost64Bit) { + _imm.value._i64[0] = static_cast(val); + } + else { + int32_t val32 = static_cast(val); + _imm.value._i32[_ASMJIT_HOST_INDEX(2, 0)] = val32; + _imm.value._i32[_ASMJIT_HOST_INDEX(2, 1)] = val32 >> 31; + } + return *this; + } + + //! Set immediate value to 8-bit unsigned integer `val`. + ASMJIT_INLINE Imm& setUInt8(uint8_t val) { + if (kArchHost64Bit) { + _imm.value._u64[0] = static_cast(val); + } + else { + _imm.value._u32[_ASMJIT_HOST_INDEX(2, 0)] = static_cast(val); + _imm.value._u32[_ASMJIT_HOST_INDEX(2, 1)] = 0; + } + return *this; + } + + //! Set immediate value to 16-bit signed integer `val`. + ASMJIT_INLINE Imm& setInt16(int16_t val) { + if (kArchHost64Bit) { + _imm.value._i64[0] = static_cast(val); + } + else { + int32_t val32 = static_cast(val); + _imm.value._i32[_ASMJIT_HOST_INDEX(2, 0)] = val32; + _imm.value._i32[_ASMJIT_HOST_INDEX(2, 1)] = val32 >> 31; + } + return *this; + } + + //! Set immediate value to 16-bit unsigned integer `val`. + ASMJIT_INLINE Imm& setUInt16(uint16_t val) { + if (kArchHost64Bit) { + _imm.value._u64[0] = static_cast(val); + } + else { + _imm.value._u32[_ASMJIT_HOST_INDEX(2, 0)] = static_cast(val); + _imm.value._u32[_ASMJIT_HOST_INDEX(2, 1)] = 0; + } + return *this; + } + + //! Set immediate value to 32-bit signed integer `val`. + ASMJIT_INLINE Imm& setInt32(int32_t val) { + if (kArchHost64Bit) { + _imm.value._i64[0] = static_cast(val); + } + else { + _imm.value._i32[_ASMJIT_HOST_INDEX(2, 0)] = val; + _imm.value._i32[_ASMJIT_HOST_INDEX(2, 1)] = val >> 31; + } + return *this; + } + + //! Set immediate value to 32-bit unsigned integer `val`. + ASMJIT_INLINE Imm& setUInt32(uint32_t val) { + if (kArchHost64Bit) { + _imm.value._u64[0] = static_cast(val); + } + else { + _imm.value._u32[_ASMJIT_HOST_INDEX(2, 0)] = val; + _imm.value._u32[_ASMJIT_HOST_INDEX(2, 1)] = 0; + } + return *this; + } + + //! Set immediate value to 64-bit signed integer `val`. + ASMJIT_INLINE Imm& setInt64(int64_t val) { + _imm.value._i64[0] = val; + return *this; + } + + //! Set immediate value to 64-bit unsigned integer `val`. + ASMJIT_INLINE Imm& setUInt64(uint64_t val) { + _imm.value._u64[0] = val; + return *this; + } + + //! Set immediate value to intptr_t `val`. + ASMJIT_INLINE Imm& setIntPtr(intptr_t val) { + _imm.value._i64[0] = static_cast(val); + return *this; + } + + //! Set immediate value to uintptr_t `val`. + ASMJIT_INLINE Imm& setUIntPtr(uintptr_t val) { + _imm.value._u64[0] = static_cast(val); + return *this; + } + + //! Set immediate value as unsigned type to `val`. + ASMJIT_INLINE Imm& setPtr(void* p) { return setIntPtr((intptr_t)p); } + + // -------------------------------------------------------------------------- + // [Float] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE Imm& setFloat(float f) { + _imm.value._f32[_ASMJIT_HOST_INDEX(2, 0)] = f; + _imm.value._u32[_ASMJIT_HOST_INDEX(2, 1)] = 0; + return *this; + } + + ASMJIT_INLINE Imm& setDouble(double d) { + _imm.value._f64[0] = d; + return *this; + } + + // -------------------------------------------------------------------------- + // [Truncate] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE Imm& truncateTo8Bits() { + if (kArchHost64Bit) { + _imm.value._u64[0] &= static_cast(0x000000FFU); + } + else { + _imm.value._u32[_ASMJIT_HOST_INDEX(2, 0)] &= 0x000000FFU; + _imm.value._u32[_ASMJIT_HOST_INDEX(2, 1)] = 0; + } + return *this; + } + + ASMJIT_INLINE Imm& truncateTo16Bits() { + if (kArchHost64Bit) { + _imm.value._u64[0] &= static_cast(0x0000FFFFU); + } + else { + _imm.value._u32[_ASMJIT_HOST_INDEX(2, 0)] &= 0x0000FFFFU; + _imm.value._u32[_ASMJIT_HOST_INDEX(2, 1)] = 0; + } + return *this; + } + + ASMJIT_INLINE Imm& truncateTo32Bits() { + _imm.value._u32[_ASMJIT_HOST_INDEX(2, 1)] = 0; + return *this; + } + + // -------------------------------------------------------------------------- + // [Operator Overload] + // -------------------------------------------------------------------------- + + //! Assign `other` to the immediate operand. + ASMJIT_INLINE Imm& operator=(const Imm& other) { + _copy(other); + return *this; + } +}; + +// ============================================================================ +// [asmjit::Label] +// ============================================================================ + +//! Label (jump target or data location). +//! +//! Label represents a location in code typically used as jump targets, but may +//! be also reference data or static variables. Label has to be explicitly +//! created by a code-generator by calling `CodeGen::newLabel()` where `CodeGen` +//! is your code generator, which derives from `Assembler` or `Compiler`. +//! +//! Example of using labels: +//! +//! ~~~ +//! // Create Assembler/Compiler. +//! host::Assembler a; +//! +//! // Create Label instance. +//! Label L_1(a); +//! +//! // ... your code ... +//! +//! // Using label. +//! a.jump(L_1); +//! +//! // ... your code ... +//! +//! // Bind label to the current position, see `CodeGen::bind()`. +//! a.bind(L_1); +//! ~~~ +struct Label : public Operand { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create new, unassociated label. + ASMJIT_INLINE Label() : Operand(NoInit) { + reset(); + } + + explicit ASMJIT_INLINE Label(uint32_t id) : Operand(NoInit) { + _init_packed_op_sz_b0_b1_id(kOperandTypeLabel, 0, 0, 0, id); + _init_packed_d2_d3(0, 0); + } + + //! Create new initialized label. + explicit ASMJIT_INLINE Label(Assembler& a); + //! Create new initialized label. + explicit ASMJIT_INLINE Label(Compiler& c); + + //! Create reference to another label. + ASMJIT_INLINE Label(const Label& other) : Operand(other) {} + + explicit ASMJIT_INLINE Label(const _NoInit&) : Operand(NoInit) {} + + // -------------------------------------------------------------------------- + // [Reset] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE void reset() { + _init_packed_op_sz_b0_b1_id(kOperandTypeLabel, 0, 0, 0, kInvalidValue); + _init_packed_d2_d3(0, 0); + } + + // -------------------------------------------------------------------------- + // [Label Specific] + // -------------------------------------------------------------------------- + + //! Get whether the label has been initialized by `Assembler` or `Compiler`. + ASMJIT_INLINE bool isInitialized() const { + return _label.id != kInvalidValue; + } + + // -------------------------------------------------------------------------- + // [Operator Overload] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE Label& operator=(const Label& other) { _copy(other); return *this; } + + ASMJIT_INLINE bool operator==(const Label& other) const { return _base.id == other._base.id; } + ASMJIT_INLINE bool operator!=(const Label& other) const { return _base.id != other._base.id; } +}; + +// ============================================================================ +// [asmjit::Operand - Globals] +// ============================================================================ + +//! No operand, can be used to reset an operand by assignment or to refer to an +//! operand that doesn't exist. +ASMJIT_VAR const Operand noOperand; + +//! Create signed immediate value operand. +static ASMJIT_INLINE Imm imm(int64_t val) { + return Imm(val); +} + +//! Create unsigned immediate value operand. +static ASMJIT_INLINE Imm imm_u(uint64_t val) { + return Imm(static_cast(val)); +} + +//! Create void* pointer immediate value operand. +static ASMJIT_INLINE Imm imm_ptr(void* p) { + return Imm(static_cast((intptr_t)p)); +} + +//! \} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // _ASMJIT_BASE_OPERAND_H diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/runtime.cpp b/third/Blackbone/src/3rd_party/AsmJit/base/runtime.cpp new file mode 100644 index 0000000000000000000000000000000000000000..258dbd1e5eb27294ab386777b7bd7592e43d3796 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/runtime.cpp @@ -0,0 +1,191 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Dependencies - AsmJit] +#include "../base/assembler.h" +#include "../base/cpuinfo.h" +#include "../base/error.h" +#include "../base/runtime.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [asmjit::Runtime - Construction / Destruction] +// ============================================================================ + +Runtime::Runtime() { + _sizeLimit = 0; + + _runtimeType = kRuntimeTypeNone; + _allocType = kVMemAllocFreeable; + ::memset(_reserved, 0, sizeof(_reserved)); + + _baseAddress = kNoBaseAddress; +} + +Runtime::~Runtime() {} + +// ============================================================================ +// [asmjit::HostRuntime - Construction / Destruction] +// ============================================================================ + +HostRuntime::HostRuntime() { + _runtimeType = kRuntimeTypeJit; +} + +HostRuntime::~HostRuntime() {} + +// ============================================================================ +// [asmjit::HostRuntime - Interface] +// ============================================================================ + +const CpuInfo* HostRuntime::getCpuInfo() { + return CpuInfo::getHost(); +} + +uint32_t HostRuntime::getStackAlignment() { + uint32_t alignment = sizeof(intptr_t); + +#if defined(ASMJIT_HOST_X86) + // Modern Linux, APPLE and UNIX guarantees 16-byte stack alignment, but I'm + // not sure about all other UNIX operating systems, because 16-byte alignment + // is addition to an older specification. +# if (defined(__linux__) || \ + defined(__linux) || \ + defined(__unix__) || \ + defined(__FreeBSD__) || \ + defined(__NetBSD__) || \ + defined(__OpenBSD__) || \ + defined(__DARWIN__) || \ + defined(__APPLE__) ) + alignment = 16; +# endif +#elif defined(ASMJIT_HOST_X64) + alignment = 16; +#endif + + return alignment; +} + +void HostRuntime::flush(void* p, size_t size) { + // Only useful on non-x86 architectures. +#if !defined(ASMJIT_HOST_X86) && !defined(ASMJIT_HOST_X64) + + // Windows has built-in support in kernel32.dll. +#if defined(ASMJIT_OS_WINDOWS) + ::FlushInstructionCache(_memMgr.getProcessHandle(), p, size); +#endif // ASMJIT_OS_WINDOWS + +#endif // !ASMJIT_HOST_X86 && !ASMJIT_HOST_X64 +} + +// ============================================================================ +// [asmjit::StaticRuntime - Construction / Destruction] +// ============================================================================ + +StaticRuntime::StaticRuntime(void* baseAddress, size_t sizeLimit) { + _sizeLimit = sizeLimit; + _baseAddress = static_cast((uintptr_t)baseAddress); +} + +StaticRuntime::~StaticRuntime() {} + +// ============================================================================ +// [asmjit::StaticRuntime - Interface] +// ============================================================================ + +Error StaticRuntime::add(void** dst, Assembler* assembler) { + size_t codeSize = assembler->getCodeSize(); + size_t sizeLimit = _sizeLimit; + + if (codeSize == 0) { + *dst = NULL; + return kErrorNoCodeGenerated; + } + + if (sizeLimit != 0 && sizeLimit < codeSize) { + *dst = NULL; + return kErrorCodeTooLarge; + } + + Ptr baseAddress = _baseAddress; + uint8_t* p = static_cast((void*)static_cast(baseAddress)); + + // Since the base address is known the `relocSize` returned should be equal + // to `codeSize`. It's better to fail if they don't match instead of passsing + // silently. + size_t relocSize = assembler->relocCode(p, baseAddress); + if (relocSize == 0 || codeSize != relocSize) { + *dst = NULL; + return kErrorInvalidState; + } + + _baseAddress += codeSize; + if (sizeLimit) + sizeLimit -= codeSize; + + flush(p, codeSize); + *dst = p; + + return kErrorOk; +} + +Error StaticRuntime::release(void* p) { + // There is nothing to release as `StaticRuntime` doesn't manage any memory. + ASMJIT_UNUSED(p); + return kErrorOk; +} + +// ============================================================================ +// [asmjit::JitRuntime - Construction / Destruction] +// ============================================================================ + +JitRuntime::JitRuntime() {} +JitRuntime::~JitRuntime() {} + +// ============================================================================ +// [asmjit::JitRuntime - Interface] +// ============================================================================ + +Error JitRuntime::add(void** dst, Assembler* assembler) { + size_t codeSize = assembler->getCodeSize(); + if (codeSize == 0) { + *dst = NULL; + return kErrorNoCodeGenerated; + } + + void* p = _memMgr.alloc(codeSize, getAllocType()); + if (p == NULL) { + *dst = NULL; + return kErrorNoVirtualMemory; + } + + // Relocate the code and release the unused memory back to `VMemMgr`. + size_t relocSize = assembler->relocCode(p); + if (relocSize < codeSize) { + _memMgr.shrink(p, relocSize); + } + + flush(p, relocSize); + *dst = p; + + return kErrorOk; +} + +Error JitRuntime::release(void* p) { + return _memMgr.release(p); +} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/runtime.h b/third/Blackbone/src/3rd_party/AsmJit/base/runtime.h new file mode 100644 index 0000000000000000000000000000000000000000..b355fc4a7fffa5a2dbcd22993f941240cbc99d3d --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/runtime.h @@ -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(&_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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/string.cpp b/third/Blackbone/src/3rd_party/AsmJit/base/string.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aa65dbea66319e65dcd6614e89c2d858fb891c59 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/string.cpp @@ -0,0 +1,374 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Dependencies - AsmJit] +#include "../base/intutil.h" +#include "../base/string.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// Should be placed in read-only memory. +static const char StringBuilder_empty[4] = { 0 }; + +// ============================================================================ +// [asmjit::StringBuilder - Construction / Destruction] +// ============================================================================ + +StringBuilder::StringBuilder() : + _data(const_cast(StringBuilder_empty)), + _length(0), + _capacity(0), + _canFree(false) {} + +StringBuilder::~StringBuilder() { + if (_canFree) + ASMJIT_FREE(_data); +} + +// ============================================================================ +// [asmjit::StringBuilder - Prepare / Reserve] +// ============================================================================ + +char* StringBuilder::prepare(uint32_t op, size_t len) { + // -------------------------------------------------------------------------- + // [Set] + // -------------------------------------------------------------------------- + + if (op == kStringOpSet) { + // We don't care here, but we can't return a NULL pointer since it indicates + // failure in memory allocation. + if (len == 0) { + if (_data != StringBuilder_empty) + _data[0] = 0; + + _length = 0; + return _data; + } + + if (_capacity < len) { + if (len >= IntUtil::maxUInt() - sizeof(intptr_t) * 2) + return NULL; + + size_t to = IntUtil::alignTo(len, sizeof(intptr_t)); + if (to < 256 - sizeof(intptr_t)) + to = 256 - sizeof(intptr_t); + + char* newData = static_cast(ASMJIT_ALLOC(to + sizeof(intptr_t))); + if (newData == NULL) { + clear(); + return NULL; + } + + if (_canFree) + ASMJIT_FREE(_data); + + _data = newData; + _capacity = to + sizeof(intptr_t) - 1; + _canFree = true; + } + + _data[len] = 0; + _length = len; + + ASMJIT_ASSERT(_length <= _capacity); + return _data; + } + + // -------------------------------------------------------------------------- + // [Append] + // -------------------------------------------------------------------------- + + else { + // We don't care here, but we can't return a NULL pointer since it indicates + // failure in memory allocation. + if (len == 0) + return _data + _length; + + // Overflow. + if (IntUtil::maxUInt() - sizeof(intptr_t) * 2 - _length < len) + return NULL; + + size_t after = _length + len; + if (_capacity < after) { + size_t to = _capacity; + + if (to < 256) + to = 256; + + while (to < 1024 * 1024 && to < after) + to *= 2; + + if (to < after) { + to = after; + if (to < (IntUtil::maxUInt() - 1024 * 32)) + to = IntUtil::alignTo(to, 1024 * 32); + } + + to = IntUtil::alignTo(to, sizeof(intptr_t)); + char* newData = static_cast(ASMJIT_ALLOC(to + sizeof(intptr_t))); + + if (newData == NULL) + return NULL; + + ::memcpy(newData, _data, _length); + if (_canFree) + ASMJIT_FREE(_data); + + _data = newData; + _capacity = to + sizeof(intptr_t) - 1; + _canFree = true; + } + + char* ret = _data + _length; + _data[after] = 0; + _length = after; + + ASMJIT_ASSERT(_length <= _capacity); + return ret; + } +} + +bool StringBuilder::reserve(size_t to) { + if (_capacity >= to) + return true; + + if (to >= IntUtil::maxUInt() - sizeof(intptr_t) * 2) + return false; + + to = IntUtil::alignTo(to, sizeof(intptr_t)); + + char* newData = static_cast(ASMJIT_ALLOC(to + sizeof(intptr_t))); + if (newData == NULL) + return false; + + ::memcpy(newData, _data, _length + 1); + if (_canFree) + ASMJIT_FREE(_data); + + _data = newData; + _capacity = to + sizeof(intptr_t) - 1; + _canFree = true; + return true; +} + +// ============================================================================ +// [asmjit::StringBuilder - Clear] +// ============================================================================ + +void StringBuilder::clear() { + if (_data != StringBuilder_empty) + _data[0] = 0; + _length = 0; +} + +// ============================================================================ +// [asmjit::StringBuilder - Methods] +// ============================================================================ + +bool StringBuilder::_opString(uint32_t op, const char* str, size_t len) { + if (len == kInvalidIndex) + len = str != NULL ? ::strlen(str) : static_cast(0); + + char* p = prepare(op, len); + if (p == NULL) + return false; + + ::memcpy(p, str, len); + return true; +} + +bool StringBuilder::_opChar(uint32_t op, char c) { + char* p = prepare(op, 1); + if (p == NULL) + return false; + + *p = c; + return true; +} + +bool StringBuilder::_opChars(uint32_t op, char c, size_t len) { + char* p = prepare(op, len); + if (p == NULL) + return false; + + ::memset(p, c, len); + return true; +} + +static const char StringBuilder_numbers[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +bool StringBuilder::_opNumber(uint32_t op, uint64_t i, uint32_t base, size_t width, uint32_t flags) { + if (base < 2 || base > 36) + base = 10; + + char buf[128]; + char* p = buf + ASMJIT_ARRAY_SIZE(buf); + + uint64_t orig = i; + char sign = '\0'; + + // -------------------------------------------------------------------------- + // [Sign] + // -------------------------------------------------------------------------- + + if ((flags & kStringFormatSigned) != 0 && static_cast(i) < 0) { + i = static_cast(-static_cast(i)); + sign = '-'; + } + else if ((flags & kStringFormatShowSign) != 0) { + sign = '+'; + } + else if ((flags & kStringFormatShowSpace) != 0) { + sign = ' '; + } + + // -------------------------------------------------------------------------- + // [Number] + // -------------------------------------------------------------------------- + + do { + uint64_t d = i / base; + uint64_t r = i % base; + + *--p = StringBuilder_numbers[r]; + i = d; + } while (i); + + size_t numberLength = (size_t)(buf + ASMJIT_ARRAY_SIZE(buf) - p); + + // -------------------------------------------------------------------------- + // [Alternate Form] + // -------------------------------------------------------------------------- + + if ((flags & kStringFormatAlternate) != 0) { + if (base == 8) { + if (orig != 0) + *--p = '0'; + } + if (base == 16) { + *--p = 'x'; + *--p = '0'; + } + } + + // -------------------------------------------------------------------------- + // [Width] + // -------------------------------------------------------------------------- + + if (sign != 0) + *--p = sign; + + if (width > 256) + width = 256; + + if (width <= numberLength) + width = 0; + else + width -= numberLength; + + // -------------------------------------------------------------------------- + // Write] + // -------------------------------------------------------------------------- + + size_t prefixLength = (size_t)(buf + ASMJIT_ARRAY_SIZE(buf) - p) - numberLength; + char* data = prepare(op, prefixLength + width + numberLength); + + if (data == NULL) + return false; + + ::memcpy(data, p, prefixLength); + data += prefixLength; + + ::memset(data, '0', width); + data += width; + + ::memcpy(data, p + prefixLength, numberLength); + return true; +} + +bool StringBuilder::_opHex(uint32_t op, const void* data, size_t len) { + if (len >= IntUtil::maxUInt() / 2) + return false; + + char* dst = prepare(op, len * 2); + if (dst == NULL) + return false; + + const char* src = static_cast(data); + for (size_t i = 0; i < len; i++, dst += 2, src += 1) + { + dst[0] = StringBuilder_numbers[(src[0] >> 4) & 0xF]; + dst[1] = StringBuilder_numbers[(src[0] ) & 0xF]; + } + + return true; +} + +bool StringBuilder::_opVFormat(uint32_t op, const char* fmt, va_list ap) { + char buf[1024]; + + vsnprintf(buf, ASMJIT_ARRAY_SIZE(buf), fmt, ap); + buf[ASMJIT_ARRAY_SIZE(buf) - 1] = '\0'; + + return _opString(op, buf); +} + +bool StringBuilder::setFormat(const char* fmt, ...) { + bool result; + + va_list ap; + va_start(ap, fmt); + result = _opVFormat(kStringOpSet, fmt, ap); + va_end(ap); + + return result; +} + +bool StringBuilder::appendFormat(const char* fmt, ...) { + bool result; + + va_list ap; + va_start(ap, fmt); + result = _opVFormat(kStringOpAppend, fmt, ap); + va_end(ap); + + return result; +} + +bool StringBuilder::eq(const char* str, size_t len) const { + const char* aData = _data; + const char* bData = str; + + size_t aLength = _length; + size_t bLength = len; + + if (bLength == kInvalidIndex) { + size_t i; + for (i = 0; i < aLength; i++) { + if (aData[i] != bData[i] || bData[i] == 0) + return false; + } + + return bData[i] == 0; + } + else { + if (aLength != bLength) + return false; + + return ::memcmp(aData, bData, aLength) == 0; + } +} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/string.h b/third/Blackbone/src/3rd_party/AsmJit/base/string.h new file mode 100644 index 0000000000000000000000000000000000000000..145a68978635fb03486d2d1e5f04660718af4e5a --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/string.h @@ -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 + +// [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(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(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 +struct StringBuilderT : public StringBuilder { + ASMJIT_NO_COPY(StringBuilderT) + + // -------------------------------------------------------------------------- + // [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( + N + 1 + sizeof(intptr_t)) & ~static_cast(sizeof(intptr_t) - 1)]; +}; + +//! \} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // _ASMJIT_BASE_STRING_H diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/vectypes.h b/third/Blackbone/src/3rd_party/AsmJit/base/vectypes.h new file mode 100644 index 0000000000000000000000000000000000000000..d675ec208cd58ad6b93aa7076ca8f60a12062a27 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/vectypes.h @@ -0,0 +1,1251 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Guard] +#ifndef _ASMJIT_BASE_VECTYPES_H +#define _ASMJIT_BASE_VECTYPES_H + +// [Dependencies - AsmJit] +#include "../base/globals.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +//! \addtogroup asmjit_base_util +//! \{ + +// ============================================================================ +// [asmjit::Vec64] +// ============================================================================ + +//! 64-bit vector register data. +union Vec64 { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Set all eight 8-bit signed integers. + static ASMJIT_INLINE Vec64 fromSb( + int8_t x0, int8_t x1, int8_t x2, int8_t x3, int8_t x4, int8_t x5, int8_t x6, int8_t x7) + { + Vec64 self; + self.setSb(x0, x1, x2, x3, x4, x5, x6, x7); + return self; + } + + //! Set all eight 8-bit signed integers. + static ASMJIT_INLINE Vec64 fromSb( + int8_t x0) + { + Vec64 self; + self.setSb(x0); + return self; + } + + //! Set all eight 8-bit unsigned integers. + static ASMJIT_INLINE Vec64 fromUb( + uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7) + { + Vec64 self; + self.setUb(x0, x1, x2, x3, x4, x5, x6, x7); + return self; + } + + //! Set all eight 8-bit unsigned integers. + static ASMJIT_INLINE Vec64 fromUb( + uint8_t x0) + { + Vec64 self; + self.setUb(x0); + return self; + } + + //! Set all four 16-bit signed integers. + static ASMJIT_INLINE Vec64 fromSw( + int16_t x0, int16_t x1, int16_t x2, int16_t x3) + { + Vec64 self; + self.setSw(x0, x1, x2, x3); + return self; + } + + //! Set all four 16-bit signed integers. + static ASMJIT_INLINE Vec64 fromSw( + int16_t x0) + { + Vec64 self; + self.setSw(x0); + return self; + } + + //! Set all four 16-bit unsigned integers. + static ASMJIT_INLINE Vec64 fromUw( + uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3) + { + Vec64 self; + self.setUw(x0, x1, x2, x3); + return self; + } + + //! Set all four 16-bit unsigned integers. + static ASMJIT_INLINE Vec64 fromUw( + uint16_t x0) + { + Vec64 self; + self.setUw(x0); + return self; + } + + //! Set all two 32-bit signed integers. + static ASMJIT_INLINE Vec64 fromSd( + int32_t x0, int32_t x1) + { + Vec64 self; + self.setSd(x0, x1); + return self; + } + + //! Set all two 32-bit signed integers. + static ASMJIT_INLINE Vec64 fromSd( + int32_t x0) + { + Vec64 self; + self.setSd(x0); + return self; + } + + //! Set all two 32-bit unsigned integers. + static ASMJIT_INLINE Vec64 fromUd( + uint32_t x0, uint32_t x1) + { + Vec64 self; + self.setUd(x0, x1); + return self; + } + + //! Set all two 32-bit unsigned integers. + static ASMJIT_INLINE Vec64 fromUd( + uint32_t x0) + { + Vec64 self; + self.setUd(x0); + return self; + } + + //! Set 64-bit signed integer. + static ASMJIT_INLINE Vec64 fromSq( + int64_t x0) + { + Vec64 self; + self.setSq(x0); + return self; + } + + //! Set 64-bit unsigned integer. + static ASMJIT_INLINE Vec64 fromUq( + uint64_t x0) + { + Vec64 self; + self.setUq(x0); + return self; + } + + //! Set all two SP-FP values. + static ASMJIT_INLINE Vec64 fromSf( + float x0, float x1) + { + Vec64 self; + self.setSf(x0, x1); + return self; + } + + //! Set all two SP-FP values. + static ASMJIT_INLINE Vec64 fromSf( + float x0) + { + Vec64 self; + self.setSf(x0); + return self; + } + + //! Set all two SP-FP values. + static ASMJIT_INLINE Vec64 fromDf( + double x0) + { + Vec64 self; + self.setDf(x0); + return self; + } + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Set all eight 8-bit signed integers. + ASMJIT_INLINE void setSb( + int8_t x0, int8_t x1, int8_t x2, int8_t x3, int8_t x4, int8_t x5, int8_t x6, int8_t x7) + { + sb[0] = x0; sb[1] = x1; sb[2] = x2; sb[3] = x3; + sb[4] = x4; sb[5] = x5; sb[6] = x6; sb[7] = x7; + } + + //! Set all eight 8-bit signed integers. + ASMJIT_INLINE void setSb( + int8_t x0) + { + setUb(static_cast(x0)); + } + + //! Set all eight 8-bit unsigned integers. + ASMJIT_INLINE void setUb( + uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7) + { + ub[0] = x0; ub[1] = x1; ub[2] = x2; ub[3] = x3; + ub[4] = x4; ub[5] = x5; ub[6] = x6; ub[7] = x7; + } + + //! Set all eight 8-bit unsigned integers. + ASMJIT_INLINE void setUb( + uint8_t x0) + { + if (kArchHost64Bit) { + uint64_t t = static_cast(x0) * ASMJIT_UINT64_C(0x0101010101010101); + uq[0] = t; + } + else { + uint32_t t = static_cast(x0) * static_cast(0x01010101U); + ud[0] = t; + ud[1] = t; + } + } + + //! Set all four 16-bit signed integers. + ASMJIT_INLINE void setSw( + int16_t x0, int16_t x1, int16_t x2, int16_t x3) + { + sw[0] = x0; sw[1] = x1; sw[2] = x2; sw[3] = x3; + } + + //! Set all four 16-bit signed integers. + ASMJIT_INLINE void setSw( + int16_t x0) + { + setUw(static_cast(x0)); + } + + //! Set all four 16-bit unsigned integers. + ASMJIT_INLINE void setUw( + uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3) + { + uw[0] = x0; uw[1] = x1; uw[2] = x2; uw[3] = x3; + } + + //! Set all four 16-bit unsigned integers. + ASMJIT_INLINE void setUw( + uint16_t x0) + { + if (kArchHost64Bit) { + uint64_t t = static_cast(x0) * ASMJIT_UINT64_C(0x0001000100010001); + uq[0] = t; + } + else { + uint32_t t = static_cast(x0) * static_cast(0x00010001U); + ud[0] = t; + ud[1] = t; + } + } + + //! Set all two 32-bit signed integers. + ASMJIT_INLINE void setSd( + int32_t x0, int32_t x1) + { + sd[0] = x0; sd[1] = x1; + } + + //! Set all two 32-bit signed integers. + ASMJIT_INLINE void setSd( + int32_t x0) + { + sd[0] = x0; sd[1] = x0; + } + + //! Set all two 32-bit unsigned integers. + ASMJIT_INLINE void setUd( + uint32_t x0, uint32_t x1) + { + ud[0] = x0; ud[1] = x1; + } + + //! Set all two 32-bit unsigned integers. + ASMJIT_INLINE void setUd( + uint32_t x0) + { + ud[0] = x0; ud[1] = x0; + } + + //! Set 64-bit signed integer. + ASMJIT_INLINE void setSq( + int64_t x0) + { + sq[0] = x0; + } + + //! Set 64-bit unsigned integer. + ASMJIT_INLINE void setUq( + uint64_t x0) + { + uq[0] = x0; + } + + //! Set all two SP-FP values. + ASMJIT_INLINE void setSf( + float x0, float x1) + { + sf[0] = x0; sf[1] = x1; + } + + //! Set all two SP-FP values. + ASMJIT_INLINE void setSf( + float x0) + { + sf[0] = x0; sf[1] = x0; + } + + //! Set all two SP-FP values. + ASMJIT_INLINE void setDf( + double x0) + { + df[0] = x0; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Array of eight 8-bit signed integers. + int8_t sb[8]; + //! Array of eight 8-bit unsigned integers. + uint8_t ub[8]; + //! Array of four 16-bit signed integers. + int16_t sw[4]; + //! Array of four 16-bit unsigned integers. + uint16_t uw[4]; + //! Array of two 32-bit signed integers. + int32_t sd[2]; + //! Array of two 32-bit unsigned integers. + uint32_t ud[2]; + //! Array of one 64-bit signed integer. + int64_t sq[1]; + //! Array of one 64-bit unsigned integer. + uint64_t uq[1]; + + //! Array of two SP-FP values. + float sf[2]; + //! Array of one DP-FP value. + double df[1]; +}; + +// ============================================================================ +// [asmjit::Vec128] +// ============================================================================ + +//! 128-bit vector register data. +union Vec128 { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Set all sixteen 8-bit signed integers. + static ASMJIT_INLINE Vec128 fromSb( + int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 , + int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , + int8_t x8 , int8_t x9 , int8_t x10, int8_t x11, + int8_t x12, int8_t x13, int8_t x14, int8_t x15) + { + Vec128 self; + self.setSb(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15); + return self; + } + + //! Set all sixteen 8-bit signed integers. + static ASMJIT_INLINE Vec128 fromSb( + int8_t x0) + { + Vec128 self; + self.setSb(x0); + return self; + } + + //! Set all sixteen 8-bit unsigned integers. + static ASMJIT_INLINE Vec128 fromUb( + uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 , + uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , + uint8_t x8 , uint8_t x9 , uint8_t x10, uint8_t x11, + uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15) + { + Vec128 self; + self.setUb(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15); + return self; + } + + //! Set all sixteen 8-bit unsigned integers. + static ASMJIT_INLINE Vec128 fromUb( + uint8_t x0) + { + Vec128 self; + self.setUb(x0); + return self; + } + + //! Set all eight 16-bit signed integers. + static ASMJIT_INLINE Vec128 fromSw( + int16_t x0, int16_t x1, int16_t x2, int16_t x3, int16_t x4, int16_t x5, int16_t x6, int16_t x7) + { + Vec128 self; + self.setSw(x0, x1, x2, x3, x4, x5, x6, x7); + return self; + } + + //! Set all eight 16-bit signed integers. + static ASMJIT_INLINE Vec128 fromSw( + int16_t x0) + { + Vec128 self; + self.setSw(x0); + return self; + } + + //! Set all eight 16-bit unsigned integers. + static ASMJIT_INLINE Vec128 fromUw( + uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t x4, uint16_t x5, uint16_t x6, uint16_t x7) + { + Vec128 self; + self.setUw(x0, x1, x2, x3, x4, x5, x6, x7); + return self; + } + + //! Set all eight 16-bit unsigned integers. + static ASMJIT_INLINE Vec128 fromUw( + uint16_t x0) + { + Vec128 self; + self.setUw(x0); + return self; + } + + //! Set all four 32-bit signed integers. + static ASMJIT_INLINE Vec128 fromSd( + int32_t x0, int32_t x1, int32_t x2, int32_t x3) + { + Vec128 self; + self.setSd(x0, x1, x2, x3); + return self; + } + + //! Set all four 32-bit signed integers. + static ASMJIT_INLINE Vec128 fromSd( + int32_t x0) + { + Vec128 self; + self.setSd(x0); + return self; + } + + //! Set all four 32-bit unsigned integers. + static ASMJIT_INLINE Vec128 fromUd( + uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) + { + Vec128 self; + self.setUd(x0, x1, x2, x3); + return self; + } + + //! Set all four 32-bit unsigned integers. + static ASMJIT_INLINE Vec128 fromUd( + uint32_t x0) + { + Vec128 self; + self.setUd(x0); + return self; + } + + //! Set all two 64-bit signed integers. + static ASMJIT_INLINE Vec128 fromSq( + int64_t x0, int64_t x1) + { + Vec128 self; + self.setSq(x0, x1); + return self; + } + + //! Set all two 64-bit signed integers. + static ASMJIT_INLINE Vec128 fromSq( + int64_t x0) + { + Vec128 self; + self.setSq(x0); + return self; + } + + //! Set all two 64-bit unsigned integers. + static ASMJIT_INLINE Vec128 fromUq( + uint64_t x0, uint64_t x1) + { + Vec128 self; + self.setUq(x0, x1); + return self; + } + + //! Set all two 64-bit unsigned integers. + static ASMJIT_INLINE Vec128 fromUq( + uint64_t x0) + { + Vec128 self; + self.setUq(x0); + return self; + } + + //! Set all four SP-FP floats. + static ASMJIT_INLINE Vec128 fromSf( + float x0, float x1, float x2, float x3) + { + Vec128 self; + self.setSf(x0, x1, x2, x3); + return self; + } + + //! Set all four SP-FP floats. + static ASMJIT_INLINE Vec128 fromSf( + float x0) + { + Vec128 self; + self.setSf(x0); + return self; + } + + //! Set all two DP-FP floats. + static ASMJIT_INLINE Vec128 fromDf( + double x0, double x1) + { + Vec128 self; + self.setDf(x0, x1); + return self; + } + + //! Set all two DP-FP floats. + static ASMJIT_INLINE Vec128 fromDf( + double x0) + { + Vec128 self; + self.setDf(x0); + return self; + } + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Set all sixteen 8-bit signed integers. + ASMJIT_INLINE void setSb( + int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 , + int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , + int8_t x8 , int8_t x9 , int8_t x10, int8_t x11, + int8_t x12, int8_t x13, int8_t x14, int8_t x15) + { + sb[0 ] = x0 ; sb[1 ] = x1 ; sb[2 ] = x2 ; sb[3 ] = x3 ; + sb[4 ] = x4 ; sb[5 ] = x5 ; sb[6 ] = x6 ; sb[7 ] = x7 ; + sb[8 ] = x8 ; sb[9 ] = x9 ; sb[10] = x10; sb[11] = x11; + sb[12] = x12; sb[13] = x13; sb[14] = x14; sb[15] = x15; + } + + //! Set all sixteen 8-bit signed integers. + ASMJIT_INLINE void setSb( + int8_t x0) + { + setUb(static_cast(x0)); + } + + //! Set all sixteen 8-bit unsigned integers. + ASMJIT_INLINE void setUb( + uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 , + uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , + uint8_t x8 , uint8_t x9 , uint8_t x10, uint8_t x11, + uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15) + { + ub[0 ] = x0 ; ub[1 ] = x1 ; ub[2 ] = x2 ; ub[3 ] = x3 ; + ub[4 ] = x4 ; ub[5 ] = x5 ; ub[6 ] = x6 ; ub[7 ] = x7 ; + ub[8 ] = x8 ; ub[9 ] = x9 ; ub[10] = x10; ub[11] = x11; + ub[12] = x12; ub[13] = x13; ub[14] = x14; ub[15] = x15; + } + + //! Set all sixteen 8-bit unsigned integers. + ASMJIT_INLINE void setUb( + uint8_t x0) + { + if (kArchHost64Bit) { + uint64_t t = static_cast(x0) * ASMJIT_UINT64_C(0x0101010101010101); + uq[0] = t; + uq[1] = t; + } + else { + uint32_t t = static_cast(x0) * static_cast(0x01010101U); + ud[0] = t; + ud[1] = t; + ud[2] = t; + ud[3] = t; + } + } + + //! Set all eight 16-bit signed integers. + ASMJIT_INLINE void setSw( + int16_t x0, int16_t x1, int16_t x2, int16_t x3, int16_t x4, int16_t x5, int16_t x6, int16_t x7) + { + sw[0] = x0; sw[1] = x1; sw[2] = x2; sw[3] = x3; + sw[4] = x4; sw[5] = x5; sw[6] = x6; sw[7] = x7; + } + + //! Set all eight 16-bit signed integers. + ASMJIT_INLINE void setSw( + int16_t x0) + { + setUw(static_cast(x0)); + } + + //! Set all eight 16-bit unsigned integers. + ASMJIT_INLINE void setUw( + uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t x4, uint16_t x5, uint16_t x6, uint16_t x7) + { + uw[0] = x0; uw[1] = x1; uw[2] = x2; uw[3] = x3; + uw[4] = x4; uw[5] = x5; uw[6] = x6; uw[7] = x7; + } + + //! Set all eight 16-bit unsigned integers. + ASMJIT_INLINE void setUw( + uint16_t x0) + { + if (kArchHost64Bit) { + uint64_t t = static_cast(x0) * ASMJIT_UINT64_C(0x0001000100010001); + uq[0] = t; + uq[1] = t; + } + else { + uint32_t t = static_cast(x0) * static_cast(0x00010001U); + ud[0] = t; + ud[1] = t; + ud[2] = t; + ud[3] = t; + } + } + + //! Set all four 32-bit signed integers. + ASMJIT_INLINE void setSd( + int32_t x0, int32_t x1, int32_t x2, int32_t x3) + { + sd[0] = x0; sd[1] = x1; sd[2] = x2; sd[3] = x3; + } + + //! Set all four 32-bit signed integers. + ASMJIT_INLINE void setSd( + int32_t x0) + { + setUd(static_cast(x0)); + } + + //! Set all four 32-bit unsigned integers. + ASMJIT_INLINE void setUd( + uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) + { + ud[0] = x0; ud[1] = x1; ud[2] = x2; ud[3] = x3; + } + + //! Set all four 32-bit unsigned integers. + ASMJIT_INLINE void setUd( + uint32_t x0) + { + if (kArchHost64Bit) { + uint64_t t = (static_cast(x0) << 32) + x0; + uq[0] = t; + uq[1] = t; + } + else { + ud[0] = x0; + ud[1] = x0; + ud[2] = x0; + ud[3] = x0; + } + } + + //! Set all two 64-bit signed integers. + ASMJIT_INLINE void setSq( + int64_t x0, int64_t x1) + { + sq[0] = x0; sq[1] = x1; + } + + //! Set all two 64-bit signed integers. + ASMJIT_INLINE void setSq( + int64_t x0) + { + sq[0] = x0; sq[1] = x0; + } + + //! Set all two 64-bit unsigned integers. + ASMJIT_INLINE void setUq( + uint64_t x0, uint64_t x1) + { + uq[0] = x0; uq[1] = x1; + } + + //! Set all two 64-bit unsigned integers. + ASMJIT_INLINE void setUq( + uint64_t x0) + { + uq[0] = x0; uq[1] = x0; + } + + //! Set all four SP-FP floats. + ASMJIT_INLINE void setSf( + float x0, float x1, float x2, float x3) + { + sf[0] = x0; sf[1] = x1; sf[2] = x2; sf[3] = x3; + } + + //! Set all four SP-FP floats. + ASMJIT_INLINE void setSf( + float x0) + { + sf[0] = x0; sf[1] = x0; sf[2] = x0; sf[3] = x0; + } + + //! Set all two DP-FP floats. + ASMJIT_INLINE void setDf( + double x0, double x1) + { + df[0] = x0; df[1] = x1; + } + + //! Set all two DP-FP floats. + ASMJIT_INLINE void setDf( + double x0) + { + df[0] = x0; df[1] = x0; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Array of sixteen 8-bit signed integers. + int8_t sb[16]; + //! Array of sixteen 8-bit unsigned integers. + uint8_t ub[16]; + //! Array of eight 16-bit signed integers. + int16_t sw[8]; + //! Array of eight 16-bit unsigned integers. + uint16_t uw[8]; + //! Array of four 32-bit signed integers. + int32_t sd[4]; + //! Array of four 32-bit unsigned integers. + uint32_t ud[4]; + //! Array of two 64-bit signed integers. + int64_t sq[2]; + //! Array of two 64-bit unsigned integers. + uint64_t uq[2]; + + //! Array of four 32-bit single precision floating points. + float sf[4]; + //! Array of two 64-bit double precision floating points. + double df[2]; +}; + +// ============================================================================ +// [asmjit::Vec256] +// ============================================================================ + +//! 256-bit vector register data. +union Vec256 { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Set all thirty two 8-bit signed integers. + static ASMJIT_INLINE Vec256 fromSb( + int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 , + int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , + int8_t x8 , int8_t x9 , int8_t x10, int8_t x11, + int8_t x12, int8_t x13, int8_t x14, int8_t x15, + int8_t x16, int8_t x17, int8_t x18, int8_t x19, + int8_t x20, int8_t x21, int8_t x22, int8_t x23, + int8_t x24, int8_t x25, int8_t x26, int8_t x27, + int8_t x28, int8_t x29, int8_t x30, int8_t x31) + { + Vec256 self; + self.setSb( + x0, x1 , x2 , x3 , x4 , x5 , x6 , x7 , x8 , x9 , x10, x11, x12, x13, x14, x15, + x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31); + return self; + } + + //! Set all thirty two 8-bit signed integers. + static ASMJIT_INLINE Vec256 fromSb( + int8_t x0) + { + Vec256 self; + self.setSb(x0); + return self; + } + + //! Set all thirty two 8-bit unsigned integers. + static ASMJIT_INLINE Vec256 fromUb( + uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 , + uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , + uint8_t x8 , uint8_t x9 , uint8_t x10, uint8_t x11, + uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15, + uint8_t x16, uint8_t x17, uint8_t x18, uint8_t x19, + uint8_t x20, uint8_t x21, uint8_t x22, uint8_t x23, + uint8_t x24, uint8_t x25, uint8_t x26, uint8_t x27, + uint8_t x28, uint8_t x29, uint8_t x30, uint8_t x31) + { + Vec256 self; + self.setUb( + x0, x1 , x2 , x3 , x4 , x5 , x6 , x7 , x8 , x9 , x10, x11, x12, x13, x14, x15, + x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31); + return self; + } + + //! Set all thirty two 8-bit unsigned integers. + static ASMJIT_INLINE Vec256 fromUb( + uint8_t x0) + { + Vec256 self; + self.setUb(x0); + return self; + } + + //! Set all sixteen 16-bit signed integers. + static ASMJIT_INLINE Vec256 fromSw( + int16_t x0, int16_t x1, int16_t x2 , int16_t x3 , int16_t x4 , int16_t x5 , int16_t x6 , int16_t x7 , + int16_t x8, int16_t x9, int16_t x10, int16_t x11, int16_t x12, int16_t x13, int16_t x14, int16_t x15) + { + Vec256 self; + self.setSw(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15); + return self; + } + + //! Set all sixteen 16-bit signed integers. + static ASMJIT_INLINE Vec256 fromSw( + int16_t x0) + { + Vec256 self; + self.setSw(x0); + return self; + } + + //! Set all sixteen 16-bit unsigned integers. + static ASMJIT_INLINE Vec256 fromUw( + uint16_t x0, uint16_t x1, uint16_t x2 , uint16_t x3 , uint16_t x4 , uint16_t x5 , uint16_t x6 , uint16_t x7 , + uint16_t x8, uint16_t x9, uint16_t x10, uint16_t x11, uint16_t x12, uint16_t x13, uint16_t x14, uint16_t x15) + { + Vec256 self; + self.setUw(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15); + return self; + } + + //! Set all sixteen 16-bit unsigned integers. + static ASMJIT_INLINE Vec256 fromUw( + uint16_t x0) + { + Vec256 self; + self.setUw(x0); + return self; + } + + //! Set all eight 32-bit signed integers. + static ASMJIT_INLINE Vec256 fromSd( + int32_t x0, int32_t x1, int32_t x2, int32_t x3, + int32_t x4, int32_t x5, int32_t x6, int32_t x7) + { + Vec256 self; + self.setSd(x0, x1, x2, x3, x4, x5, x6, x7); + return self; + } + + //! Set all eight 32-bit signed integers. + static ASMJIT_INLINE Vec256 fromSd( + int32_t x0) + { + Vec256 self; + self.setSd(x0); + return self; + } + + //! Set all eight 32-bit unsigned integers. + static ASMJIT_INLINE Vec256 fromUd( + uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, + uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7) + { + Vec256 self; + self.setUd(x0, x1, x2, x3, x4, x5, x6, x7); + return self; + } + + //! Set all eight 32-bit unsigned integers. + static ASMJIT_INLINE Vec256 fromUd( + uint32_t x0) + { + Vec256 self; + self.setUd(x0); + return self; + } + + //! Set all four 64-bit signed integers. + static ASMJIT_INLINE Vec256 fromSq( + int64_t x0, int64_t x1, int64_t x2, int64_t x3) + { + Vec256 self; + self.setSq(x0, x1, x2, x3); + return self; + } + + //! Set all four 64-bit signed integers. + static ASMJIT_INLINE Vec256 fromSq( + int64_t x0) + { + Vec256 self; + self.setSq(x0); + return self; + } + + //! Set all four 64-bit unsigned integers. + static ASMJIT_INLINE Vec256 fromUq( + uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3) + { + Vec256 self; + self.setUq(x0, x1, x2, x3); + return self; + } + + //! Set all four 64-bit unsigned integers. + static ASMJIT_INLINE Vec256 fromUq( + uint64_t x0) + { + Vec256 self; + self.setUq(x0); + return self; + } + + //! Set all eight SP-FP floats. + static ASMJIT_INLINE Vec256 fromSf( + float x0, float x1, float x2, float x3, + float x4, float x5, float x6, float x7) + { + Vec256 self; + self.setSf(x0, x1, x2, x3, x4, x5, x6, x7); + return self; + } + + //! Set all eight SP-FP floats. + static ASMJIT_INLINE Vec256 fromSf( + float x0) + { + Vec256 self; + self.setSf(x0); + return self; + } + + //! Set all four DP-FP floats. + static ASMJIT_INLINE Vec256 fromDf( + double x0, double x1, double x2, double x3) + { + Vec256 self; + self.setDf(x0, x1, x2, x3); + return self; + } + + //! Set all four DP-FP floats. + static ASMJIT_INLINE Vec256 fromDf( + double x0) + { + Vec256 self; + self.setDf(x0); + return self; + } + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Set all thirty two 8-bit signed integers. + ASMJIT_INLINE void setSb( + int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 , + int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , + int8_t x8 , int8_t x9 , int8_t x10, int8_t x11, + int8_t x12, int8_t x13, int8_t x14, int8_t x15, + int8_t x16, int8_t x17, int8_t x18, int8_t x19, + int8_t x20, int8_t x21, int8_t x22, int8_t x23, + int8_t x24, int8_t x25, int8_t x26, int8_t x27, + int8_t x28, int8_t x29, int8_t x30, int8_t x31) + { + sb[0 ] = x0 ; sb[1 ] = x1 ; sb[2 ] = x2 ; sb[3 ] = x3 ; + sb[4 ] = x4 ; sb[5 ] = x5 ; sb[6 ] = x6 ; sb[7 ] = x7 ; + sb[8 ] = x8 ; sb[9 ] = x9 ; sb[10] = x10; sb[11] = x11; + sb[12] = x12; sb[13] = x13; sb[14] = x14; sb[15] = x15; + sb[16] = x16; sb[17] = x17; sb[18] = x18; sb[19] = x19; + sb[20] = x20; sb[21] = x21; sb[22] = x22; sb[23] = x23; + sb[24] = x24; sb[25] = x25; sb[26] = x26; sb[27] = x27; + sb[28] = x28; sb[29] = x29; sb[30] = x30; sb[31] = x31; + } + + //! Set all thirty two 8-bit signed integers. + ASMJIT_INLINE void setSb( + int8_t x0) + { + setUb(static_cast(x0)); + } + + //! Set all thirty two 8-bit unsigned integers. + ASMJIT_INLINE void setUb( + uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 , + uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , + uint8_t x8 , uint8_t x9 , uint8_t x10, uint8_t x11, + uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15, + uint8_t x16, uint8_t x17, uint8_t x18, uint8_t x19, + uint8_t x20, uint8_t x21, uint8_t x22, uint8_t x23, + uint8_t x24, uint8_t x25, uint8_t x26, uint8_t x27, + uint8_t x28, uint8_t x29, uint8_t x30, uint8_t x31) + { + ub[0 ] = x0 ; ub[1 ] = x1 ; ub[2 ] = x2 ; ub[3 ] = x3 ; + ub[4 ] = x4 ; ub[5 ] = x5 ; ub[6 ] = x6 ; ub[7 ] = x7 ; + ub[8 ] = x8 ; ub[9 ] = x9 ; ub[10] = x10; ub[11] = x11; + ub[12] = x12; ub[13] = x13; ub[14] = x14; ub[15] = x15; + ub[16] = x16; ub[17] = x17; ub[18] = x18; ub[19] = x19; + ub[20] = x20; ub[21] = x21; ub[22] = x22; ub[23] = x23; + ub[24] = x24; ub[25] = x25; ub[26] = x26; ub[27] = x27; + ub[28] = x28; ub[29] = x29; ub[30] = x30; ub[31] = x31; + } + + //! Set all thirty two 8-bit unsigned integers. + ASMJIT_INLINE void setUb( + uint8_t x0) + { + if (kArchHost64Bit) { + uint64_t t = static_cast(x0)* ASMJIT_UINT64_C(0x0101010101010101); + uq[0] = t; + uq[1] = t; + uq[2] = t; + uq[3] = t; + } + else { + uint32_t t = static_cast(x0)* static_cast(0x01010101U); + ud[0] = t; + ud[1] = t; + ud[2] = t; + ud[3] = t; + ud[4] = t; + ud[5] = t; + ud[6] = t; + ud[7] = t; + } + } + + //! Set all sixteen 16-bit signed integers. + ASMJIT_INLINE void setSw( + int16_t x0, int16_t x1, int16_t x2, int16_t x3, int16_t x4, int16_t x5, int16_t x6, int16_t x7, + int16_t x8, int16_t x9, int16_t x10, int16_t x11, int16_t x12, int16_t x13, int16_t x14, int16_t x15) + { + sw[0 ] = x0 ; sw[1 ] = x1 ; sw[2 ] = x2 ; sw[3 ] = x3 ; + sw[4 ] = x4 ; sw[5 ] = x5 ; sw[6 ] = x6 ; sw[7 ] = x7 ; + sw[8 ] = x8 ; sw[9 ] = x9 ; sw[10] = x10; sw[11] = x11; + sw[12] = x12; sw[13] = x13; sw[14] = x14; sw[15] = x15; + } + + //! Set all sixteen 16-bit signed integers. + ASMJIT_INLINE void setSw( + int16_t x0) + { + setUw(static_cast(x0)); + } + + //! Set all sixteen 16-bit unsigned integers. + ASMJIT_INLINE void setUw( + uint16_t x0, uint16_t x1, uint16_t x2 , uint16_t x3 , uint16_t x4 , uint16_t x5 , uint16_t x6 , uint16_t x7 , + uint16_t x8, uint16_t x9, uint16_t x10, uint16_t x11, uint16_t x12, uint16_t x13, uint16_t x14, uint16_t x15) + { + uw[0 ] = x0 ; uw[1 ] = x1 ; uw[2 ] = x2 ; uw[3 ] = x3 ; + uw[4 ] = x4 ; uw[5 ] = x5 ; uw[6 ] = x6 ; uw[7 ] = x7 ; + uw[8 ] = x8 ; uw[9 ] = x9 ; uw[10] = x10; uw[11] = x11; + uw[12] = x12; uw[13] = x13; uw[14] = x14; uw[15] = x15; + } + + //! Set all eight 16-bit unsigned integers. + ASMJIT_INLINE void setUw( + uint16_t x0) + { + if (kArchHost64Bit) { + uint64_t t = static_cast(x0)* ASMJIT_UINT64_C(0x0001000100010001); + uq[0] = t; + uq[1] = t; + uq[2] = t; + uq[3] = t; + } + else { + uint32_t t = static_cast(x0)* static_cast(0x00010001U); + ud[0] = t; + ud[1] = t; + ud[2] = t; + ud[3] = t; + ud[4] = t; + ud[5] = t; + ud[6] = t; + ud[7] = t; + } + } + + //! Set all eight 32-bit signed integers. + ASMJIT_INLINE void setSd( + int32_t x0, int32_t x1, int32_t x2, int32_t x3, + int32_t x4, int32_t x5, int32_t x6, int32_t x7) + { + sd[0] = x0; sd[1] = x1; sd[2] = x2; sd[3] = x3; + sd[4] = x4; sd[5] = x5; sd[6] = x6; sd[7] = x7; + } + + //! Set all eight 32-bit signed integers. + ASMJIT_INLINE void setSd( + int32_t x0) + { + setUd(static_cast(x0)); + } + + //! Set all eight 32-bit unsigned integers. + ASMJIT_INLINE void setUd( + uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, + uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7) + { + ud[0] = x0; ud[1] = x1; ud[2] = x2; ud[3] = x3; + ud[4] = x4; ud[5] = x5; ud[6] = x6; ud[7] = x7; + } + + //! Set all eight 32-bit unsigned integers. + ASMJIT_INLINE void setUd( + uint32_t x0) + { + if (kArchHost64Bit) { + uint64_t t = (static_cast(x0) << 32) + x0; + uq[0] = t; + uq[1] = t; + uq[2] = t; + uq[3] = t; + } + else { + ud[0] = x0; + ud[1] = x0; + ud[2] = x0; + ud[3] = x0; + ud[4] = x0; + ud[5] = x0; + ud[6] = x0; + ud[7] = x0; + } + } + + //! Set all four 64-bit signed integers. + ASMJIT_INLINE void setSq( + int64_t x0, int64_t x1, int64_t x2, int64_t x3) + { + sq[0] = x0; sq[1] = x1; sq[2] = x2; sq[3] = x3; + } + + //! Set all four 64-bit signed integers. + ASMJIT_INLINE void setSq( + int64_t x0) + { + sq[0] = x0; sq[1] = x0; sq[2] = x0; sq[3] = x0; + } + + //! Set all four 64-bit unsigned integers. + ASMJIT_INLINE void setUq( + uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3) + { + uq[0] = x0; uq[1] = x1; uq[2] = x2; uq[3] = x3; + } + + //! Set all four 64-bit unsigned integers. + ASMJIT_INLINE void setUq( + uint64_t x0) + { + uq[0] = x0; uq[1] = x0; uq[2] = x0; uq[3] = x0; + } + + //! Set all eight SP-FP floats. + ASMJIT_INLINE void setSf( + float x0, float x1, float x2, float x3, + float x4, float x5, float x6, float x7) + { + sf[0] = x0; sf[1] = x1; sf[2] = x2; sf[3] = x3; + sf[4] = x4; sf[5] = x5; sf[6] = x6; sf[7] = x7; + } + + //! Set all eight SP-FP floats. + ASMJIT_INLINE void setSf( + float x0) + { + sf[0] = x0; sf[1] = x0; sf[2] = x0; sf[3] = x0; + sf[4] = x0; sf[5] = x0; sf[6] = x0; sf[7] = x0; + } + + //! Set all four DP-FP floats. + ASMJIT_INLINE void setDf( + double x0, double x1, double x2, double x3) + { + df[0] = x0; df[1] = x1; df[2] = x2; df[3] = x3; + } + + //! Set all four DP-FP floats. + ASMJIT_INLINE void setDf( + double x0) + { + df[0] = x0; df[1] = x0; df[2] = x0; df[3] = x0; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Array of thirty two 8-bit signed integers. + int8_t sb[32]; + //! Array of thirty two 8-bit unsigned integers. + uint8_t ub[32]; + //! Array of sixteen 16-bit signed integers. + int16_t sw[16]; + //! Array of sixteen 16-bit unsigned integers. + uint16_t uw[16]; + //! Array of eight 32-bit signed integers. + int32_t sd[8]; + //! Array of eight 32-bit unsigned integers. + uint32_t ud[8]; + //! Array of four 64-bit signed integers. + int64_t sq[4]; + //! Array of four 64-bit unsigned integers. + uint64_t uq[4]; + + //! Array of eight 32-bit single precision floating points. + float sf[8]; + //! Array of four 64-bit double precision floating points. + double df[4]; +}; + +//! \} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // _ASMJIT_BASE_VECTYPES_H diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/vmem.cpp b/third/Blackbone/src/3rd_party/AsmJit/base/vmem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..965b8a1a241416cd5092f0f52f29ccad6f1cdd42 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/vmem.cpp @@ -0,0 +1,1286 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Dependencies - AsmJit] +#include "../base/error.h" +#include "../base/globals.h" +#include "../base/intutil.h" +#include "../base/lock.h" +#include "../base/vmem.h" + +// [Dependencies - Posix] +#if defined(ASMJIT_OS_POSIX) +# include +# include +# include +#endif // ASMJIT_OS_POSIX + +// [Api-Begin] +#include "../apibegin.h" + +// This file contains implementation of virtual memory management for AsmJit +// library. The initial concept is to keep this implementation simple but +// efficient. There are several goals I decided to write implementation myself. +// +// Goals: +// +// - Granularity of allocated blocks is different than granularity for a typical +// C malloc. It is at least 64-bytes so Assembler/Compiler can guarantee the +// alignment required. Alignment requirements can grow in the future, but at +// the moment 64 bytes is safe (we may jump to 128 bytes if necessary or make +// it configurable). +// +// - Keep memory manager information outside of the allocated virtual memory +// pages, because these pages allow executing of machine code and there should +// not be data required to keep track of these blocks. Another reason is that +// some environments (i.e. iOS) allow to generate and run JIT code, but this +// code has to be set to [Executable, but not Writable]. +// +// - Keep implementation simple and easy to follow. +// +// Implementation is based on bit arrays and binary trees. Bit arrays contain +// information related to allocated and unused blocks of memory. The size of +// a block is described by `MemNode::density`. Count of blocks is stored in +// `MemNode::blocks`. For example if density is 64 and count of blocks is 20, +// memory node contains 64*20 bytes of memory and smallest possible allocation +// (and also alignment) is 64 bytes. So density is also related to memory +// alignment. Binary trees (RB) are used to enable fast lookup into all addresses +// allocated by memory manager instance. This is used mainly by `VMemPrivate::release()`. +// +// Bit array looks like this (empty = unused, X = used) - Size of block 64: +// +// ------------------------------------------------------------------------- +// | |X|X| | | | | |X|X|X|X|X|X| | | | | | | | | | | | |X| | | | |X|X|X| | | +// ------------------------------------------------------------------------- +// (Maximum continuous block) +// +// These bits show that there are 12 allocated blocks (X) of 64 bytes, so total +// size allocated is 768 bytes. Maximum count of continuous memory is 12 * 64. + +namespace asmjit { + +// ============================================================================ +// [asmjit::VMemUtil - Windows] +// ============================================================================ + +// Windows specific implementation using `VirtualAllocEx` and `VirtualFree`. +#if defined(ASMJIT_OS_WINDOWS) +struct VMemLocal { + // AsmJit allows to pass a `NULL` handle to `VMemUtil`. This function is just + // a convenient way to convert such handle to the current process one. + ASMJIT_INLINE HANDLE getSafeProcessHandle(HANDLE hParam) const { + return hParam != NULL ? hParam : hProcess; + } + + size_t pageSize; + size_t pageGranularity; + HANDLE hProcess; +}; +static VMemLocal vMemLocal; + +static const VMemLocal& vMemGet() { + VMemLocal& vMem = vMemLocal; + + if (!vMem.hProcess) { + SYSTEM_INFO info; + ::GetSystemInfo(&info); + + vMem.pageSize = IntUtil::alignToPowerOf2(info.dwPageSize); + vMem.pageGranularity = info.dwAllocationGranularity; + + vMem.hProcess = ::GetCurrentProcess(); + } + + return vMem; +}; + +size_t VMemUtil::getPageSize() { + const VMemLocal& vMem = vMemGet(); + return vMem.pageSize; +} + +size_t VMemUtil::getPageGranularity() { + const VMemLocal& vMem = vMemGet(); + return vMem.pageGranularity; +} + +void* VMemUtil::alloc(size_t length, size_t* allocated, uint32_t flags) { + return allocProcessMemory(static_cast(0), length, allocated, flags); +} + +void* VMemUtil::allocProcessMemory(HANDLE hProcess, size_t length, size_t* allocated, uint32_t flags) { + if (length == 0) + return NULL; + + const VMemLocal& vMem = vMemGet(); + hProcess = vMem.getSafeProcessHandle(hProcess); + + // VirtualAlloc rounds allocated size to a page size automatically. + size_t mSize = IntUtil::alignTo(length, vMem.pageSize); + + // Windows XP SP2 / Vista allow Data Excution Prevention (DEP). + DWORD protectFlags = 0; + + if (flags & kVMemFlagExecutable) + protectFlags |= (flags & kVMemFlagWritable) ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ; + else + protectFlags |= (flags & kVMemFlagWritable) ? PAGE_READWRITE : PAGE_READONLY; + + LPVOID mBase = ::VirtualAllocEx(hProcess, NULL, mSize, MEM_COMMIT | MEM_RESERVE, protectFlags); + if (mBase == NULL) + return NULL; + + ASMJIT_ASSERT(IntUtil::isAligned( + reinterpret_cast(mBase), vMem.pageSize)); + + if (allocated != NULL) + *allocated = mSize; + return mBase; +} + +Error VMemUtil::release(void* addr, size_t length) { + return releaseProcessMemory(static_cast(0), addr, length); +} + +Error VMemUtil::releaseProcessMemory(HANDLE hProcess, void* addr, size_t /* length */) { + hProcess = vMemGet().getSafeProcessHandle(hProcess); + if (!::VirtualFreeEx(hProcess, addr, 0, MEM_RELEASE)) + return kErrorInvalidState; + return kErrorOk; +} +#endif // ASMJIT_OS_WINDOWS + +// ============================================================================ +// [asmjit::VMemUtil - Posix] +// ============================================================================ + +// Posix specific implementation using `mmap` and `munmap`. +#if defined(ASMJIT_OS_POSIX) + +// MacOS uses MAP_ANON instead of MAP_ANONYMOUS. +#if !defined(MAP_ANONYMOUS) +# define MAP_ANONYMOUS MAP_ANON +#endif // MAP_ANONYMOUS + +struct VMemLocal { + size_t pageSize; + size_t pageGranularity; +}; +static VMemLocal vMemLocal; + +static const VMemLocal& vMemGet() { + VMemLocal& vMem = vMemLocal; + + if (!vMem.pageSize) { + size_t pageSize = ::getpagesize(); + vMem.pageSize = pageSize; + vMem.pageGranularity = IntUtil::iMax(pageSize, 65536); + } + + return vMem; +}; + +size_t VMemUtil::getPageSize() { + const VMemLocal& vMem = vMemGet(); + return vMem.pageSize; +} + +size_t VMemUtil::getPageGranularity() { + const VMemLocal& vMem = vMemGet(); + return vMem.pageGranularity; +} + +void* VMemUtil::alloc(size_t length, size_t* allocated, uint32_t flags) { + const VMemLocal& vMem = vMemGet(); + size_t msize = IntUtil::alignTo(length, vMem.pageSize); + int protection = PROT_READ; + + if (flags & kVMemFlagWritable ) protection |= PROT_WRITE; + if (flags & kVMemFlagExecutable) protection |= PROT_EXEC; + + void* mbase = ::mmap(NULL, msize, protection, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (mbase == MAP_FAILED) + return NULL; + + if (allocated != NULL) + *allocated = msize; + return mbase; +} + +Error VMemUtil::release(void* addr, size_t length) { + if (::munmap(addr, length) != 0) + return kErrorInvalidState; + + return kErrorOk; +} +#endif // ASMJIT_OS_POSIX + +// ============================================================================ +// [asmjit::VMemMgr - BitOps] +// ============================================================================ + +#define M_DIV(x, y) ((x) / (y)) +#define M_MOD(x, y) ((x) % (y)) + +//! \internal +enum { + kBitsPerEntity = (sizeof(size_t) * 8) +}; + +//! \internal +//! +//! Set `len` bits in `buf` starting at `index` bit index. +static void _SetBits(size_t* buf, size_t index, size_t len) { + if (len == 0) + return; + + size_t i = index / kBitsPerEntity; // size_t[] + size_t j = index % kBitsPerEntity; // size_t[][] bit index + + // How many bytes process in the first group. + size_t c = kBitsPerEntity - j; + if (c > len) + c = len; + + // Offset. + buf += i; + + *buf++ |= ((~(size_t)0) >> (kBitsPerEntity - c)) << j; + len -= c; + + while (len >= kBitsPerEntity) { + *buf++ = ~(size_t)0; + len -= kBitsPerEntity; + } + + if (len) + *buf |= ((~(size_t)0) >> (kBitsPerEntity - len)); +} + +// ============================================================================ +// [asmjit::VMemMgr::TypeDefs] +// ============================================================================ + +typedef VMemMgr::RbNode RbNode; +typedef VMemMgr::MemNode MemNode; +typedef VMemMgr::PermanentNode PermanentNode; + +// ============================================================================ +// [asmjit::VMemMgr::RbNode] +// ============================================================================ + +//! \internal +//! +//! Base red-black tree node. +struct VMemMgr::RbNode { + // Implementation is based on article by Julienne Walker (Public Domain), + // including C code and original comments. Thanks for the excellent article. + + // Left[0] and right[1] nodes. + RbNode* node[2]; + // Virtual memory address. + uint8_t* mem; + // Whether the node is RED. + uint32_t red; +}; + +//! \internal +//! +//! Get whether the node is red (NULL or node with red flag). +static ASMJIT_INLINE bool rbIsRed(RbNode* node) { + return node != NULL && node->red; +} + +//! \internal +//! +//! Check whether the RB tree is valid. +static int rbAssert(RbNode* root) { + if (root == NULL) + return 1; + + RbNode* ln = root->node[0]; + RbNode* rn = root->node[1]; + + // Red violation. + ASMJIT_ASSERT( !(rbIsRed(root) && (rbIsRed(ln) || rbIsRed(rn))) ); + + int lh = rbAssert(ln); + int rh = rbAssert(rn); + + // Invalid btree. + ASMJIT_ASSERT(ln == NULL || ln->mem < root->mem); + ASMJIT_ASSERT(rn == NULL || rn->mem > root->mem); + + // Black violation. + ASMJIT_ASSERT( !(lh != 0 && rh != 0 && lh != rh) ); + + // Only count black links. + if (lh != 0 && rh != 0) + return rbIsRed(root) ? lh : lh + 1; + else + return 0; +} + +//! \internal +//! +//! Single rotation. +static ASMJIT_INLINE RbNode* rbRotateSingle(RbNode* root, int dir) { + RbNode* save = root->node[!dir]; + + root->node[!dir] = save->node[dir]; + save->node[dir] = root; + + root->red = 1; + save->red = 0; + + return save; +} + +//! \internal +//! +//! Double rotation. +static ASMJIT_INLINE RbNode* rbRotateDouble(RbNode* root, int dir) { + root->node[!dir] = rbRotateSingle(root->node[!dir], !dir); + return rbRotateSingle(root, dir); +} + +// ============================================================================ +// [asmjit::VMemMgr::MemNode] +// ============================================================================ + +struct VMemMgr::MemNode : public RbNode { + // -------------------------------------------------------------------------- + // [Helpers] + // -------------------------------------------------------------------------- + + // Get available space. + ASMJIT_INLINE size_t getAvailable() const { + return size - used; + } + + ASMJIT_INLINE void fillData(MemNode* other) { + mem = other->mem; + + size = other->size; + used = other->used; + blocks = other->blocks; + density = other->density; + largestBlock = other->largestBlock; + + baUsed = other->baUsed; + baCont = other->baCont; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + MemNode* prev; // Prev node in list. + MemNode* next; // Next node in list. + + size_t size; // How many bytes contain this node. + size_t used; // How many bytes are used in this node. + size_t blocks; // How many blocks are here. + size_t density; // Minimum count of allocated bytes in this node (also alignment). + size_t largestBlock; // Contains largest block that can be allocated. + + size_t* baUsed; // Contains bits about used blocks (0 = unused, 1 = used). + size_t* baCont; // Contains bits about continuous blocks (0 = stop , 1 = continue). +}; + +// ============================================================================ +// [asmjit::VMemMgr::PermanentNode] +// ============================================================================ + +//! \internal +//! +//! Permanent node. +struct VMemMgr::PermanentNode { + // -------------------------------------------------------------------------- + // [Helpers] + // -------------------------------------------------------------------------- + + //! Get available space. + ASMJIT_INLINE size_t getAvailable() const { + return size - used; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + PermanentNode* prev; // Pointer to prev chunk or NULL. + uint8_t* mem; // Base pointer (virtual memory address). + size_t size; // Count of bytes allocated. + size_t used; // Count of bytes used. +}; + +// ============================================================================ +// [asmjit::VMemMgr - Private] +// ============================================================================ + +//! \internal +//! +//! Helper to avoid `#ifdef`s in the code. +ASMJIT_INLINE uint8_t* vMemMgrAllocVMem(VMemMgr* self, size_t size, size_t* vSize) { + uint32_t flags = kVMemFlagWritable | kVMemFlagExecutable; +#if !defined(ASMJIT_OS_WINDOWS) + return static_cast(VMemUtil::alloc(size, vSize, flags)); +#else + return static_cast(VMemUtil::allocProcessMemory(self->_hProcess, size, vSize, flags)); +#endif +} + +//! \internal +//! +//! Helper to avoid `#ifdef`s in the code. +ASMJIT_INLINE Error vMemMgrReleaseVMem(VMemMgr* self, void* p, size_t vSize) { +#if !defined(ASMJIT_OS_WINDOWS) + return VMemUtil::release(p, vSize); +#else + return VMemUtil::releaseProcessMemory(self->_hProcess, p, vSize); +#endif +} + +//! \internal +//! +//! Check whether the Red-Black tree is valid. +static bool vMemMgrCheckTree(VMemMgr* self) { + return rbAssert(self->_root) > 0; +} + +//! \internal +//! +//! Alloc virtual memory including a heap memory needed for `MemNode` data. +//! +//! Returns set-up `MemNode*` or NULL if allocation failed. +static MemNode* vMemMgrCreateNode(VMemMgr* self, size_t size, size_t density) { + size_t vSize; + uint8_t* vmem = vMemMgrAllocVMem(self, size, &vSize); + + // Out of memory. + if (vmem == NULL) + return NULL; + + size_t blocks = (vSize / density); + size_t bsize = (((blocks + 7) >> 3) + sizeof(size_t) - 1) & ~(size_t)(sizeof(size_t) - 1); + + MemNode* node = static_cast(ASMJIT_ALLOC(sizeof(MemNode))); + uint8_t* data = static_cast(ASMJIT_ALLOC(bsize * 2)); + + // Out of memory. + if (node == NULL || data == NULL) { + vMemMgrReleaseVMem(self, vmem, vSize); + if (node) ASMJIT_FREE(node); + if (data) ASMJIT_FREE(data); + return NULL; + } + + // Initialize RbNode data. + node->node[0] = NULL; + node->node[1] = NULL; + node->mem = vmem; + node->red = 1; + + // Initialize MemNode data. + node->prev = NULL; + node->next = NULL; + + node->size = vSize; + node->used = 0; + node->blocks = blocks; + node->density = density; + node->largestBlock = vSize; + + ::memset(data, 0, bsize * 2); + node->baUsed = reinterpret_cast(data); + node->baCont = reinterpret_cast(data + bsize); + + return node; +} + +static void vMemMgrInsertNode(VMemMgr* self, MemNode* node) { + if (self->_root == NULL) { + // Empty tree case. + self->_root = node; + } + else { + // False tree root. + RbNode head = { { 0 } }; + + // Grandparent & parent. + RbNode* g = NULL; + RbNode* t = &head; + + // Iterator & parent. + RbNode* p = NULL; + RbNode* q = t->node[1] = self->_root; + + int dir = 0, last = 0; + + // Search down the tree. + for (;;) { + if (q == NULL) { + // Insert new node at the bottom. + q = node; + p->node[dir] = node; + } + else if (rbIsRed(q->node[0]) && rbIsRed(q->node[1])) { + // Color flip. + q->red = 1; + q->node[0]->red = 0; + q->node[1]->red = 0; + } + + // Fix red violation. + if (rbIsRed(q) && rbIsRed(p)) { + int dir2 = t->node[1] == g; + t->node[dir2] = q == p->node[last] ? rbRotateSingle(g, !last) : rbRotateDouble(g, !last); + } + + // Stop if found. + if (q == node) + break; + + last = dir; + dir = q->mem < node->mem; + + // Update helpers. + if (g != NULL) + t = g; + + g = p; + p = q; + q = q->node[dir]; + } + + // Update root. + self->_root = static_cast(head.node[1]); + } + + // Make root black. + self->_root->red = 0; + + // Link with others. + node->prev = self->_last; + + if (self->_first == NULL) { + self->_first = node; + self->_last = node; + self->_optimal = node; + } + else { + node->prev = self->_last; + self->_last->next = node; + self->_last = node; + } +} + +//! \internal +//! +//! Remove node from Red-Black tree. +//! +//! Returns node that should be freed, but it doesn't have to be necessarily +//! the `node` passed. +static MemNode* vMemMgrRemoveNode(VMemMgr* self, MemNode* node) { + // False tree root. + RbNode head = { { 0 } }; + + // Helpers. + RbNode* q = &head; + RbNode* p = NULL; + RbNode* g = NULL; + + // Found item. + RbNode* f = NULL; + int dir = 1; + + // Set up. + q->node[1] = self->_root; + + // Search and push a red down. + while (q->node[dir] != NULL) { + int last = dir; + + // Update helpers. + g = p; + p = q; + q = q->node[dir]; + dir = q->mem < node->mem; + + // Save found node. + if (q == node) + f = q; + + // Push the red node down. + if (!rbIsRed(q) && !rbIsRed(q->node[dir])) { + if (rbIsRed(q->node[!dir])) { + p = p->node[last] = rbRotateSingle(q, dir); + } + else if (!rbIsRed(q->node[!dir])) { + RbNode* s = p->node[!last]; + + if (s != NULL) { + if (!rbIsRed(s->node[!last]) && !rbIsRed(s->node[last])) { + // Color flip. + p->red = 0; + s->red = 1; + q->red = 1; + } + else { + int dir2 = g->node[1] == p; + + if (rbIsRed(s->node[last])) + g->node[dir2] = rbRotateDouble(p, last); + else if (rbIsRed(s->node[!last])) + g->node[dir2] = rbRotateSingle(p, last); + + // Ensure correct coloring. + q->red = g->node[dir2]->red = 1; + g->node[dir2]->node[0]->red = 0; + g->node[dir2]->node[1]->red = 0; + } + } + } + } + } + + // Replace and remove. + ASMJIT_ASSERT(f != NULL); + ASMJIT_ASSERT(f != &head); + ASMJIT_ASSERT(q != &head); + + if (f != q) { + ASMJIT_ASSERT(f != &head); + static_cast(f)->fillData(static_cast(q)); + } + + p->node[p->node[1] == q] = q->node[q->node[0] == NULL]; + + // Update root and make it black. + self->_root = static_cast(head.node[1]); + if (self->_root != NULL) + self->_root->red = 0; + + // Unlink. + MemNode* next = static_cast(q)->next; + MemNode* prev = static_cast(q)->prev; + + if (prev) + prev->next = next; + else + self->_first = next; + + if (next) + next->prev = prev; + else + self->_last = prev; + + if (self->_optimal == q) + self->_optimal = prev ? prev : next; + + return static_cast(q); +} + +static MemNode* vMemMgrFindNodeByPtr(VMemMgr* self, uint8_t* mem) { + MemNode* node = self->_root; + while (node != NULL) { + uint8_t* nodeMem = node->mem; + + // Go left. + if (mem < nodeMem) { + node = static_cast(node->node[0]); + continue; + } + + // Go right. + uint8_t* nodeEnd = nodeMem + node->size; + if (mem >= nodeEnd) { + node = static_cast(node->node[1]); + continue; + } + + // Match. + break; + } + return node; +} + +static void* vMemMgrAllocPermanent(VMemMgr* self, size_t vSize) { + static const size_t permanentAlignment = 32; + static const size_t permanentNodeSize = 32768; + + vSize = IntUtil::alignTo(vSize, permanentAlignment); + + AutoLock locked(self->_lock); + PermanentNode* node = self->_permanent; + + // Try to find space in allocated chunks. + while (node && vSize > node->getAvailable()) + node = node->prev; + + // Or allocate new node. + if (node == NULL) { + size_t nodeSize = permanentNodeSize; + + if (nodeSize < vSize) + nodeSize = vSize; + + node = static_cast(ASMJIT_ALLOC(sizeof(PermanentNode))); + + // Out of memory. + if (node == NULL) + return NULL; + + node->mem = vMemMgrAllocVMem(self, nodeSize, &node->size); + + // Out of memory. + if (node->mem == NULL) { + ASMJIT_FREE(node); + return NULL; + } + + node->used = 0; + node->prev = self->_permanent; + self->_permanent = node; + } + + // Finally, copy function code to our space we reserved for. + uint8_t* result = node->mem + node->used; + + // Update Statistics. + node->used += vSize; + self->_usedBytes += vSize; + + // Code can be null to only reserve space for code. + return static_cast(result); +} + +static void* vMemMgrAllocFreeable(VMemMgr* self, size_t vSize) { + // Current index. + size_t i; + + // How many we need to be freed. + size_t need; + size_t minVSize; + + // Align to 32 bytes by default. + vSize = IntUtil::alignTo(vSize, 32); + if (vSize == 0) + return NULL; + + AutoLock locked(self->_lock); + MemNode* node = self->_optimal; + minVSize = self->_blockSize; + + // Try to find memory block in existing nodes. + while (node) { + // Skip this node? + if ((node->getAvailable() < vSize) || (node->largestBlock < vSize && node->largestBlock != 0)) { + MemNode* next = node->next; + + if (node->getAvailable() < minVSize && node == self->_optimal && next) + self->_optimal = next; + + node = next; + continue; + } + + size_t* up = node->baUsed; // Current ubits address. + size_t ubits; // Current ubits[0] value. + size_t bit; // Current bit mask. + size_t blocks = node->blocks; // Count of blocks in node. + size_t cont = 0; // How many bits are currently freed in find loop. + size_t maxCont = 0; // Largest continuous block (bits count). + size_t j; + + need = M_DIV((vSize + node->density - 1), node->density); + i = 0; + + // Try to find node that is large enough. + while (i < blocks) { + ubits = *up++; + + // Fast skip used blocks. + if (ubits == ~(size_t)0) { + if (cont > maxCont) + maxCont = cont; + cont = 0; + + i += kBitsPerEntity; + continue; + } + + size_t max = kBitsPerEntity; + if (i + max > blocks) + max = blocks - i; + + for (j = 0, bit = 1; j < max; bit <<= 1) { + j++; + if ((ubits & bit) == 0) { + if (++cont == need) { + i += j; + i -= cont; + goto _Found; + } + + continue; + } + + if (cont > maxCont) maxCont = cont; + cont = 0; + } + + i += kBitsPerEntity; + } + + // Because we traversed the entire node, we can set largest node size that + // will be used to cache next traversing. + node->largestBlock = maxCont * node->density; + + node = node->next; + } + + // If we are here, we failed to find existing memory block and we must + // allocate a new one. + { + size_t blockSize = self->_blockSize; + if (blockSize < vSize) + blockSize = vSize; + + node = vMemMgrCreateNode(self, blockSize, self->_blockDensity); + if (node == NULL) + return NULL; + + // Update binary tree. + vMemMgrInsertNode(self, node); + ASMJIT_ASSERT(vMemMgrCheckTree(self)); + + // Alloc first node at start. + i = 0; + need = (vSize + node->density - 1) / node->density; + + // Update statistics. + self->_allocatedBytes += node->size; + } + +_Found: + // Update bits. + _SetBits(node->baUsed, i, need); + _SetBits(node->baCont, i, need - 1); + + // Update statistics. + { + size_t u = need * node->density; + node->used += u; + node->largestBlock = 0; + self->_usedBytes += u; + } + + // And return pointer to allocated memory. + uint8_t* result = node->mem + i * node->density; + ASMJIT_ASSERT(result >= node->mem && result <= node->mem + node->size - vSize); + return result; +} + +//! \internal +//! +//! Reset the whole `VMemMgr` instance, freeing all heap memory allocated an +//! virtual memory allocated unless `keepVirtualMemory` is true (and this is +//! only used when writing data to a remote process). +static void vMemMgrReset(VMemMgr* self, bool keepVirtualMemory) { + MemNode* node = self->_first; + + while (node != NULL) { + MemNode* next = node->next; + + if (!keepVirtualMemory) + vMemMgrReleaseVMem(self, node->mem, node->size); + + ASMJIT_FREE(node->baUsed); + ASMJIT_FREE(node); + + node = next; + } + + self->_allocatedBytes = 0; + self->_usedBytes = 0; + + self->_root = NULL; + self->_first = NULL; + self->_last = NULL; + self->_optimal = NULL; +} + +// ============================================================================ +// [asmjit::VMemMgr - Construction / Destruction] +// ============================================================================ + +#if !defined(ASMJIT_OS_WINDOWS) +VMemMgr::VMemMgr() +#else +VMemMgr::VMemMgr(HANDLE hProcess) : + _hProcess(vMemGet().getSafeProcessHandle(hProcess)) +#endif // ASMJIT_OS_WINDOWS +{ + + _blockSize = VMemUtil::getPageGranularity(); + _blockDensity = 64; + + _allocatedBytes = 0; + _usedBytes = 0; + + _root = NULL; + _first = NULL; + _last = NULL; + _optimal = NULL; + + _permanent = NULL; + _keepVirtualMemory = false; +} + +VMemMgr::~VMemMgr() { + // Freeable memory cleanup - Also frees the virtual memory if configured to. + vMemMgrReset(this, _keepVirtualMemory); + + // Permanent memory cleanup - Never frees the virtual memory. + PermanentNode* node = _permanent; + while (node) { + PermanentNode* prev = node->prev; + ASMJIT_FREE(node); + node = prev; + } +} + +// ============================================================================ +// [asmjit::VMemMgr - Reset] +// ============================================================================ + +void VMemMgr::reset() { + vMemMgrReset(this, false); +} + +// ============================================================================ +// [asmjit::VMemMgr - Alloc / Release] +// ============================================================================ + +void* VMemMgr::alloc(size_t size, uint32_t type) { + if (type == kVMemAllocPermanent) + return vMemMgrAllocPermanent(this, size); + else + return vMemMgrAllocFreeable(this, size); +} + +Error VMemMgr::release(void* p) { + if (p == NULL) + return kErrorOk; + + AutoLock locked(_lock); + MemNode* node = vMemMgrFindNodeByPtr(this, static_cast(p)); + + if (node == NULL) + return kErrorInvalidArgument; + + size_t offset = (size_t)((uint8_t*)p - (uint8_t*)node->mem); + size_t bitpos = M_DIV(offset, node->density); + size_t i = (bitpos / kBitsPerEntity); + + size_t* up = node->baUsed + i; // Current ubits address. + size_t* cp = node->baCont + i; // Current cbits address. + size_t ubits = *up; // Current ubits[0] value. + size_t cbits = *cp; // Current cbits[0] value. + size_t bit = (size_t)1 << (bitpos % kBitsPerEntity); + + size_t cont = 0; + bool stop; + + for (;;) { + stop = (cbits & bit) == 0; + ubits &= ~bit; + cbits &= ~bit; + + bit <<= 1; + cont++; + + if (stop || bit == 0) { + *up = ubits; + *cp = cbits; + if (stop) + break; + + ubits = *++up; + cbits = *++cp; + bit = 1; + } + } + + // If the freed block is fully allocated node then it's needed to + // update 'optimal' pointer in memory manager. + if (node->used == node->size) { + MemNode* cur = _optimal; + + do { + cur = cur->prev; + if (cur == node) { + _optimal = node; + break; + } + } while (cur); + } + + // Statistics. + cont *= node->density; + if (node->largestBlock < cont) + node->largestBlock = cont; + + node->used -= cont; + _usedBytes -= cont; + + // If page is empty, we can free it. + if (node->used == 0) { + // Free memory associated with node (this memory is not accessed + // anymore so it's safe). + vMemMgrReleaseVMem(this, node->mem, node->size); + ASMJIT_FREE(node->baUsed); + + node->baUsed = NULL; + node->baCont = NULL; + + // Statistics. + _allocatedBytes -= node->size; + + // Remove node. This function can return different node than + // passed into, but data is copied into previous node if needed. + ASMJIT_FREE(vMemMgrRemoveNode(this, node)); + ASMJIT_ASSERT(vMemMgrCheckTree(this)); + } + + return kErrorOk; +} + +Error VMemMgr::shrink(void* p, size_t used) { + if (p == NULL) + return kErrorOk; + + if (used == 0) + return release(p); + + AutoLock locked(_lock); + + MemNode* node = vMemMgrFindNodeByPtr(this, (uint8_t*)p); + if (node == NULL) + return kErrorInvalidArgument; + + size_t offset = (size_t)((uint8_t*)p - (uint8_t*)node->mem); + size_t bitpos = M_DIV(offset, node->density); + size_t i = (bitpos / kBitsPerEntity); + + size_t* up = node->baUsed + i; // Current ubits address. + size_t* cp = node->baCont + i; // Current cbits address. + size_t ubits = *up; // Current ubits[0] value. + size_t cbits = *cp; // Current cbits[0] value. + size_t bit = (size_t)1 << (bitpos % kBitsPerEntity); + + size_t cont = 0; + size_t usedBlocks = (used + node->density - 1) / node->density; + + bool stop; + + // Find the first block we can mark as free. + for (;;) { + stop = (cbits & bit) == 0; + if (stop) + return kErrorOk; + + if (++cont == usedBlocks) + break; + + bit <<= 1; + if (bit == 0) { + ubits = *++up; + cbits = *++cp; + bit = 1; + } + } + + // Free the tail blocks. + cont = ~(size_t)0; + goto _EnterFreeLoop; + + for (;;) { + stop = (cbits & bit) == 0; + ubits &= ~bit; + +_EnterFreeLoop: + cbits &= ~bit; + + bit <<= 1; + cont++; + + if (stop || bit == 0) { + *up = ubits; + *cp = cbits; + if (stop) + break; + + ubits = *++up; + cbits = *++cp; + bit = 1; + } + } + + // Statistics. + cont *= node->density; + if (node->largestBlock < cont) + node->largestBlock = cont; + + node->used -= cont; + _usedBytes -= cont; + + return kErrorOk; +} + +// ============================================================================ +// [asmjit::VMem - Test] +// ============================================================================ + +#if defined(ASMJIT_TEST) +static void VMemTest_fill(void* a, void* b, int i) { + int pattern = rand() % 256; + *(int *)a = i; + *(int *)b = i; + ::memset((char*)a + sizeof(int), pattern, i - sizeof(int)); + ::memset((char*)b + sizeof(int), pattern, i - sizeof(int)); +} + +static void VMemTest_verify(void* a, void* b) { + int ai = *(int*)a; + int bi = *(int*)b; + + EXPECT(ai == bi, + "The length of 'a' (%d) and 'b' (%d) should be same", ai, bi); + + EXPECT(::memcmp(a, b, ai) == 0, + "Pattern (%p) doesn't match", a); +} + +static void VMemTest_stats(VMemMgr& memmgr) { + INFO("Used : %u", static_cast(memmgr.getUsedBytes())); + INFO("Allocated: %u", static_cast(memmgr.getAllocatedBytes())); +} + +static void VMemTest_shuffle(void **a, void **b, size_t count) { + for (size_t i = 0; i < count; ++i) { + size_t si = (size_t)rand() % count; + + void *ta = a[i]; + void *tb = b[i]; + + a[i] = a[si]; + b[i] = b[si]; + + a[si] = ta; + b[si] = tb; + } +} + +UNIT(base_vmem) { + VMemMgr memmgr; + + // Should be predictible. + srand(100); + + int i; + int kCount = 200000; + + INFO("Memory alloc/free test - %d allocations.", static_cast(kCount)); + + void** a = (void**)ASMJIT_ALLOC(sizeof(void*) * kCount); + void** b = (void**)ASMJIT_ALLOC(sizeof(void*) * kCount); + + EXPECT(a != NULL && b != NULL, + "Couldn't allocate %u bytes on heap.", kCount * 2); + + INFO("Allocating virtual memory..."); + for (i = 0; i < kCount; i++) { + int r = (rand() % 1000) + 4; + + a[i] = memmgr.alloc(r); + EXPECT(a[i] != NULL, + "Couldn't allocate %d bytes of virtual memory", r); + ::memset(a[i], 0, r); + } + VMemTest_stats(memmgr); + + INFO("Freeing virtual memory..."); + for (i = 0; i < kCount; i++) { + EXPECT(memmgr.release(a[i]) == kErrorOk, + "Failed to free %p.", b[i]); + } + VMemTest_stats(memmgr); + + INFO("Verified alloc/free test - %d allocations.", static_cast(kCount)); + for (i = 0; i < kCount; i++) { + int r = (rand() % 1000) + 4; + + a[i] = memmgr.alloc(r); + EXPECT(a[i] != NULL, + "Couldn't allocate %d bytes of virtual memory.", r); + + b[i] = ASMJIT_ALLOC(r); + EXPECT(b[i] != NULL, + "Couldn't allocate %d bytes on heap.", r); + + VMemTest_fill(a[i], b[i], r); + } + VMemTest_stats(memmgr); + + INFO("Shuffling..."); + VMemTest_shuffle(a, b, kCount); + + INFO("Verify and free..."); + for (i = 0; i < kCount / 2; i++) { + VMemTest_verify(a[i], b[i]); + EXPECT(memmgr.release(a[i]) == kErrorOk, + "Failed to free %p.", a[i]); + ASMJIT_FREE(b[i]); + } + VMemTest_stats(memmgr); + + INFO("Alloc again."); + for (i = 0; i < kCount / 2; i++) { + int r = (rand() % 1000) + 4; + + a[i] = memmgr.alloc(r); + EXPECT(a[i] != NULL, + "Couldn't allocate %d bytes of virtual memory.", r); + + b[i] = ASMJIT_ALLOC(r); + EXPECT(b[i] != NULL, + "Couldn't allocate %d bytes on heap."); + + VMemTest_fill(a[i], b[i], r); + } + VMemTest_stats(memmgr); + + INFO("Verify and free..."); + for (i = 0; i < kCount; i++) { + VMemTest_verify(a[i], b[i]); + EXPECT(memmgr.release(a[i]) == kErrorOk, + "Failed to free %p.", a[i]); + ASMJIT_FREE(b[i]); + } + VMemTest_stats(memmgr); + + ASMJIT_FREE(a); + ASMJIT_FREE(b); +} +#endif // ASMJIT_TEST + +} // asmjit namespace diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/vmem.h b/third/Blackbone/src/3rd_party/AsmJit/base/vmem.h new file mode 100644 index 0000000000000000000000000000000000000000..998a49bb6aef2d6de6a91c53eab4ea5234d2df04 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/vmem.h @@ -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(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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/zone.cpp b/third/Blackbone/src/3rd_party/AsmJit/base/zone.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f182392afc42d391821d14ae251029707cb10945 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/zone.cpp @@ -0,0 +1,195 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Dependencies - AsmJit] +#include "../base/intutil.h" +#include "../base/zone.h" + +// [Dependencies - C] +#include + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +//! Zero size block used by `Zone` that doesn't have any memory allocated. +static const Zone::Block Zone_zeroBlock = { + NULL, NULL, NULL, NULL, { 0 } +}; + +// ============================================================================ +// [asmjit::Zone - Construction / Destruction] +// ============================================================================ + +Zone::Zone(size_t blockSize) { + _block = const_cast(&Zone_zeroBlock); + _blockSize = blockSize; +} + +Zone::~Zone() { + reset(true); +} + +// ============================================================================ +// [asmjit::Zone - Reset] +// ============================================================================ + +void Zone::reset(bool releaseMemory) { + Block* cur = _block; + + // Can't be altered. + if (cur == &Zone_zeroBlock) + return; + + if (releaseMemory) { + // Since cur can be in the middle of the double-linked list, we have to + // traverse to both directions `prev` and `next` separately. + Block* next = cur->next; + do { + Block* prev = cur->prev; + ASMJIT_FREE(cur); + cur = prev; + } while (cur != NULL); + + cur = next; + while (cur != NULL) { + next = cur->next; + ASMJIT_FREE(cur); + cur = next; + } + + _block = const_cast(&Zone_zeroBlock); + } + else { + while (cur->prev != NULL) + cur = cur->prev; + + cur->pos = cur->data; + _block = cur; + } +} + +// ============================================================================ +// [asmjit::Zone - Alloc] +// ============================================================================ + +void* Zone::_alloc(size_t size) { + Block* curBlock = _block; + size_t blockSize = IntUtil::iMax(_blockSize, size); + + // The `_alloc()` method can only be called if there is not enough space + // in the current block, see `alloc()` implementation for more details. + ASMJIT_ASSERT(curBlock == &Zone_zeroBlock || curBlock->getRemainingSize() < size); + + // If the `Zone` has been reset the current block doesn't have to be the + // last one. Check if there is a block that can be used instead of allocating + // a new one. If there is a `next` block it's completely unused, we don't have + // to check for remaining bytes. + Block* next = curBlock->next; + if (next != NULL && next->getBlockSize() >= size) { + next->pos = next->data + size; + _block = next; + return static_cast(next->data); + } + + // Prevent arithmetic overflow. + if (blockSize > ~static_cast(0) - sizeof(Block)) + return NULL; + + Block* newBlock = static_cast(ASMJIT_ALLOC(sizeof(Block) - sizeof(void*) + blockSize)); + if (newBlock == NULL) + return NULL; + + newBlock->pos = newBlock->data + size; + newBlock->end = newBlock->data + blockSize; + newBlock->prev = NULL; + newBlock->next = NULL; + + if (curBlock != &Zone_zeroBlock) { + newBlock->prev = curBlock; + curBlock->next = newBlock; + + // Does only happen if there is a next block, but the requested memory + // can't fit into it. In this case a new buffer is allocated and inserted + // between the current block and the next one. + if (next != NULL) { + newBlock->next = next; + next->prev = newBlock; + } + } + + _block = newBlock; + return static_cast(newBlock->data); +} + +void* Zone::allocZeroed(size_t size) { + void* p = alloc(size); + if (p != NULL) + ::memset(p, 0, size); + return p; +} + +void* Zone::dup(const void* data, size_t size) { + if (data == NULL) + return NULL; + + if (size == 0) + return NULL; + + void* m = alloc(size); + if (m == NULL) + return NULL; + + ::memcpy(m, data, size); + return m; +} + +char* Zone::sdup(const char* str) { + if (str == NULL) + return NULL; + + size_t len = ::strlen(str); + if (len == 0) + return NULL; + + // Include NULL terminator and limit string length. + if (++len > 256) + len = 256; + + char* m = static_cast(alloc(len)); + if (m == NULL) + return NULL; + + ::memcpy(m, str, len); + m[len - 1] = '\0'; + return m; +} + +char* Zone::sformat(const char* fmt, ...) { + if (fmt == NULL) + return NULL; + + char buf[512]; + size_t len; + + va_list ap; + va_start(ap, fmt); + + len = vsnprintf(buf, ASMJIT_ARRAY_SIZE(buf) - 1, fmt, ap); + buf[len++] = 0; + + va_end(ap); + return static_cast(dup(buf, len)); +} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" diff --git a/third/Blackbone/src/3rd_party/AsmJit/base/zone.h b/third/Blackbone/src/3rd_party/AsmJit/base/zone.h new file mode 100644 index 0000000000000000000000000000000000000000..357890274f4f8c48dd7491c624d69bea118f6377 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/base/zone.h @@ -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( 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 + ASMJIT_INLINE T* allocT(size_t size = sizeof(T)) { + return static_cast(alloc(size)); + } + + //! Like `allocZeroed()`, but the return pointer is casted to `T*`. + template + ASMJIT_INLINE T* allocZeroedT(size_t size = sizeof(T)) { + return static_cast(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(sizeof(Zone::Block) - sizeof(void*)) + kMemAllocOverhead +}; + +//! \} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // _ASMJIT_BASE_ZONE_H diff --git a/third/Blackbone/src/3rd_party/AsmJit/host.h b/third/Blackbone/src/3rd_party/AsmJit/host.h new file mode 100644 index 0000000000000000000000000000000000000000..48d8ce4b19a1363e8d8f1b96f45752f1a0ed521c --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/host.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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/x86.h b/third/Blackbone/src/3rd_party/AsmJit/x86.h new file mode 100644 index 0000000000000000000000000000000000000000..ef5e00664efc1607f87c695554d8a5e385cd62a1 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/x86.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 diff --git a/third/Blackbone/src/3rd_party/AsmJit/x86/x86assembler.cpp b/third/Blackbone/src/3rd_party/AsmJit/x86/x86assembler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aaae69b3be2b7172880052825b273b56295802b0 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/x86/x86assembler.cpp @@ -0,0 +1,4241 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Guard] +#include "../build.h" +#if defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64) + +// [Dependencies - AsmJit] +#include "../base/intutil.h" +#include "../base/logger.h" +#include "../base/runtime.h" +#include "../base/string.h" +#include "../base/vmem.h" +#include "../x86/x86assembler.h" +#include "../x86/x86cpuinfo.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [Constants] +// ============================================================================ + +enum { kMaxCommentLength = 80 }; +enum { kX86RexNoRexMask = kX86InstOptionRex | _kX86InstOptionNoRex }; + +//! \internal +//! +//! X86/X64 bytes used to encode important prefixes. +enum kX86Byte { + //! 1-byte REX prefix + kX86ByteRex = 0x40, + + //! 1-byte REX.W component. + kX86ByteRexW = 0x08, + + //! 2-byte VEX prefix: + //! - `[0]` - `0xC5`. + //! - `[1]` - `RvvvvLpp`. + kX86ByteVex2 = 0xC5, + + //! 3-byte VEX prefix. + //! - `[0]` - `0xC4`. + //! - `[1]` - `RXBmmmmm`. + //! - `[2]` - `WvvvvLpp`. + kX86ByteVex3 = 0xC4, + + //! 3-byte XOP prefix. + //! - `[0]` - `0x8F`. + //! - `[1]` - `RXBmmmmm`. + //! - `[2]` - `WvvvvLpp`. + kX86ByteXop3 = 0x8F, + + //! 4-byte EVEX prefix. + //! - `[0]` - `0x62`. + //! - `[1]` - Payload0 or `P[ 7: 0]` - `[R X B R' 0 0 m m]`. + //! - `[2]` - Payload1 or `P[15: 8]` - `[W v v v v 1 p p]`. + //! - `[3]` - Payload2 or `P[23:16]` - `[z L' L b V' a a a]`. + //! + //! Groups: + //! - `P[ 1: 0]` - EXT: VEX.mmmmm, only lowest 2 bits used. + //! - `P[ 3: 2]` - ___: Must be 0. + //! - `P[ 4]` - REG: EVEX.R'. + //! - `P[ 5]` - REG: EVEX.B. + //! - `P[ 6]` - REG: EVEX.X. + //! - `P[ 7]` - REG: EVEX.R. + //! - `P[ 9: 8]` - EXT: VEX.pp. + //! - `P[ 10]` - ___: Must be 1. + //! - `P[14:11]` - REG: 2nd SRC vector register (4 bits). + //! - `P[ 15]` - EXT: VEX.W. + //! - `P[18:16]` - REG: K registers k0...k7 (Merging/Zeroing Vector Ops.). + //! - `P[ 19]` - REG: 2nd SRC vector register (Hi bit). + //! - `P[ 20]` - EXT: Broadcast/Static-Rounding/SAE bit. + //! - `P[22.21]` - EXT: Vector Length/Rounding Control. + //! - `P[ 23]` - EXT: Destination result behavior (Merging/Zeroing Vector Ops.). + kX86ByteEvex4 = 0x62 +}; + +// AsmJit specific (used to encode VVVV field in XOP/VEX). +enum kVexVVVV { + kVexVVVVShift = 12, + kVexVVVVMask = 0xF << kVexVVVVShift +}; + +//! \internal +//! +//! Instruction 2-byte/3-byte opcode prefix definition. +struct X86OpCodeMM { + uint8_t len; + uint8_t data[3]; +}; + +//! \internal +//! +//! Mandatory prefixes encoded in 'asmjit' opcode [66, F3, F2] and asmjit +//! extensions +static const uint8_t x86OpCodePP[8] = { + 0x00, + 0x66, + 0xF3, + 0xF2, + 0x00, + 0x00, + 0x00, + 0x9B +}; + +//! \internal +//! +//! Instruction 2-byte/3-byte opcode prefix data. +static const X86OpCodeMM x86OpCodeMM[] = { + { 0, { 0x00, 0x00, 0 } }, + { 1, { 0x0F, 0x00, 0 } }, + { 2, { 0x0F, 0x38, 0 } }, + { 2, { 0x0F, 0x3A, 0 } }, + { 0, { 0x00, 0x00, 0 } }, + { 0, { 0x00, 0x00, 0 } }, + { 0, { 0x00, 0x00, 0 } }, + { 0, { 0x00, 0x00, 0 } }, + { 0, { 0x00, 0x00, 0 } }, + { 0, { 0x00, 0x00, 0 } }, + { 0, { 0x00, 0x00, 0 } }, + { 0, { 0x00, 0x00, 0 } }, + { 0, { 0x00, 0x00, 0 } }, + { 0, { 0x00, 0x00, 0 } }, + { 0, { 0x00, 0x00, 0 } }, + { 2, { 0x0F, 0x01, 0 } } +}; + +static const uint8_t x86SegmentPrefix[8] = { 0x00, 0x26, 0x2E, 0x36, 0x3E, 0x64, 0x65 }; +static const uint8_t x86OpCodePushSeg[8] = { 0x00, 0x06, 0x0E, 0x16, 0x1E, 0xA0, 0xA8 }; +static const uint8_t x86OpCodePopSeg[8] = { 0x00, 0x07, 0x00, 0x17, 0x1F, 0xA1, 0xA9 }; + +// ============================================================================ +// [Utils] +// ============================================================================ + +static ASMJIT_INLINE uint32_t x86RexFromOpCodeAndOptions(uint32_t opCode, uint32_t options) { + uint32_t rex = (opCode >> (kX86InstOpCode_W_Shift - 3)); + ASMJIT_ASSERT((rex & ~static_cast(0x08)) == 0); + + return rex + (options & kX86RexNoRexMask); +} + +static ASMJIT_INLINE bool x86RexIsInvalid(uint32_t rex) { + return rex >= _kX86InstOptionNoRex; +} + +//! Encode ModR/M. +static ASMJIT_INLINE uint32_t x86EncodeMod(uint32_t m, uint32_t o, uint32_t rm) { + return (m << 6) + (o << 3) + rm; +} + +//! Encode SIB. +static ASMJIT_INLINE uint32_t x86EncodeSib(uint32_t s, uint32_t i, uint32_t b) { + return (s << 6) + (i << 3) + b; +} + +//! Get whether the two pointers `a` and `b` can be encoded by using relative +//! displacement, which fits into a signed 32-bit integer. +static ASMJIT_INLINE bool x64IsRelative(Ptr a, Ptr b) { + SignedPtr diff = static_cast(a) - static_cast(b); + return IntUtil::isInt32(diff); +} + +//! Cast `reg` to `X86Reg` and get the register index. +static ASMJIT_INLINE uint32_t x86OpReg(const Operand* reg) { + return static_cast(reg)->getRegIndex(); +} + +//! Cast `mem` to `X86Mem` and return it. +static ASMJIT_INLINE const X86Mem* x86OpMem(const Operand* mem) { + return static_cast(mem); +} + +//! Combine `regIndex` and `vvvvIndex` into single value (used by AVX and AVX-512). +static ASMJIT_INLINE uint32_t x86RegAndVvvv(uint32_t regIndex, uint32_t vvvvIndex) { + return regIndex + (vvvvIndex << kVexVVVVShift); +} + +//! Get `O` field of `opCode`. +static ASMJIT_INLINE uint32_t x86ExtractO(uint32_t opCode) { + return (opCode >> kX86InstOpCode_O_Shift) & 0x7; +} + +// ============================================================================ +// [Macros] +// ============================================================================ + +#define ENC_OPS(_Op0_, _Op1_, _Op2_) \ + ((kOperandType##_Op0_) + ((kOperandType##_Op1_) << 3) + ((kOperandType##_Op2_) << 6)) + +#define ADD_66H_P(_Exp_) \ + do { \ + opCode |= (static_cast(_Exp_) << kX86InstOpCode_PP_Shift); \ + } while (0) + +#define ADD_66H_P_BY_SIZE(_Size_) \ + do { \ + opCode |= (static_cast(_Size_) & 0x02) << (kX86InstOpCode_PP_Shift - 1); \ + } while (0) + +#define ADD_REX_W(_Exp_) \ + do { \ + if (Arch == kArchX64) \ + opCode |= static_cast(_Exp_) << kX86InstOpCode_W_Shift; \ + } while (0) + +#define ADD_REX_W_BY_SIZE(_Size_) \ + do { \ + if (Arch == kArchX64 && (_Size_) == 8) \ + opCode |= kX86InstOpCode_W; \ + } while (0) + +#define ADD_VEX_W(_Exp_) \ + do { \ + opCode |= static_cast(_Exp_) << kX86InstOpCode_W_Shift; \ + } while (0) + +#define ADD_VEX_L(_Exp_) \ + do { \ + opCode |= static_cast(_Exp_) << kX86InstOpCode_L_Shift; \ + } while (0) + +#define EMIT_BYTE(_Val_) \ + do { \ + cursor[0] = static_cast(_Val_); \ + cursor += 1; \ + } while (0) + +#define EMIT_WORD(_Val_) \ + do { \ + reinterpret_cast(cursor)[0] = static_cast(_Val_); \ + cursor += 2; \ + } while (0) + +#define EMIT_DWORD(_Val_) \ + do { \ + reinterpret_cast(cursor)[0] = static_cast(_Val_); \ + cursor += 4; \ + } while (0) + +#define EMIT_QWORD(_Val_) \ + do { \ + reinterpret_cast(cursor)[0] = static_cast(_Val_); \ + cursor += 8; \ + } while (0) + +#define EMIT_OP(_Val_) \ + do { \ + EMIT_BYTE((_Val_) & 0xFF); \ + } while (0) + +#define EMIT_PP(_Val_) \ + do { \ + uint32_t ppIndex = ((_Val_) >> kX86InstOpCode_PP_Shift) & (kX86InstOpCode_PP_Mask >> kX86InstOpCode_PP_Shift); \ + uint8_t ppCode = x86OpCodePP[ppIndex]; \ + \ + if (!ppIndex) \ + break; \ + \ + cursor[0] = ppCode; \ + cursor++; \ + } while (0) + +#define EMIT_MM(_Val_) \ + do { \ + uint32_t mmIndex = ((_Val_) >> kX86InstOpCode_MM_Shift) & (kX86InstOpCode_MM_Mask >> kX86InstOpCode_MM_Shift); \ + const X86OpCodeMM& mmCode = x86OpCodeMM[mmIndex]; \ + \ + if (!mmIndex) \ + break; \ + \ + cursor[0] = mmCode.data[0]; \ + cursor[1] = mmCode.data[1]; \ + cursor += mmCode.len; \ + } while (0) + +// ============================================================================ +// [asmjit::X86Assembler - Construction / Destruction] +// ============================================================================ + +X86Assembler::X86Assembler(Runtime* runtime, uint32_t arch) : + Assembler(runtime), + zax(NoInit), + zcx(NoInit), + zdx(NoInit), + zbx(NoInit), + zsp(NoInit), + zbp(NoInit), + zsi(NoInit), + zdi(NoInit) { + + setArch(arch); +} + +X86Assembler::~X86Assembler() {} + +// ============================================================================ +// [asmjit::X86Assembler - Arch] +// ============================================================================ + +Error X86Assembler::setArch(uint32_t arch) { +#if defined(ASMJIT_BUILD_X86) + if (arch == kArchX86) { + _arch = kArchX86; + _regSize = 4; + + _regCount.reset(); + _regCount._gp = 8; + _regCount._mm = 8; + _regCount._k = 8; + _regCount._xyz = 8; + ::memcpy(&zax, &x86RegData.gpd, sizeof(Operand) * 8); + + return kErrorOk; + } +#endif // ASMJIT_BUILD_X86 + +#if defined(ASMJIT_BUILD_X64) + if (arch == kArchX64) { + _arch = kArchX64; + _regSize = 8; + + _regCount.reset(); + _regCount._gp = 16; + _regCount._mm = 8; + _regCount._k = 8; + _regCount._xyz = 16; + ::memcpy(&zax, &x86RegData.gpq, sizeof(Operand) * 8); + + return kErrorOk; + } +#endif // ASMJIT_BUILD_X64 + + ASMJIT_ASSERT(!"Reached"); + return kErrorInvalidArgument; +} + +// ============================================================================ +// [asmjit::X86Assembler - Embed] +// ============================================================================ + +Error X86Assembler::embedLabel(const Label& op) { + ASMJIT_ASSERT(op.getId() != kInvalidValue); + uint32_t regSize = _regSize; + + if (getRemainingSpace() < regSize) + ASMJIT_PROPAGATE_ERROR(_grow(regSize)); + + uint8_t* cursor = getCursor(); + + LabelData* label = getLabelData(op.getId()); + RelocData rd; + +#if !defined(ASMJIT_DISABLE_LOGGER) + if (_logger) + _logger->logFormat(kLoggerStyleData, regSize == 4 ? ".dd L%u\n" : ".dq L%u\n", op.getId()); +#endif // !ASMJIT_DISABLE_LOGGER + + rd.type = kRelocRelToAbs; + rd.size = regSize; + rd.from = static_cast(getOffset()); + rd.data = 0; + + if (label->offset != -1) { + // Bound label. + rd.data = static_cast(static_cast(label->offset)); + } + else { + // Non-bound label. Need to chain. + LabelLink* link = _newLabelLink(); + + link->prev = (LabelLink*)label->links; + link->offset = getOffset(); + link->displacement = 0; + link->relocId = _relocList.getLength(); + + label->links = link; + } + + if (_relocList.append(rd) != kErrorOk) + return setError(kErrorNoHeapMemory); + + // Emit dummy intptr_t (4 or 8 bytes; depends on the address size). + if (regSize == 4) + EMIT_DWORD(0); + else + EMIT_QWORD(0); + + setCursor(cursor); + return kErrorOk; +} + +// ============================================================================ +// [asmjit::X86Assembler - Align] +// ============================================================================ + +Error X86Assembler::align(uint32_t mode, uint32_t offset) { +#if !defined(ASMJIT_DISABLE_LOGGER) + if (_logger) + _logger->logFormat(kLoggerStyleDirective, + "%s.align %u\n", _logger->getIndentation(), static_cast(offset)); +#endif // !ASMJIT_DISABLE_LOGGER + + if (offset <= 1 || !IntUtil::isPowerOf2(offset) || offset > 64) + return setError(kErrorInvalidArgument); + + uint32_t i = static_cast(IntUtil::deltaTo(getOffset(), offset)); + if (i == 0) + return kErrorOk; + + if (getRemainingSpace() < i) + ASMJIT_PROPAGATE_ERROR(_grow(i)); + + uint8_t* cursor = getCursor(); + uint8_t alignPattern = 0xCC; + + if (mode == kAlignCode) { + alignPattern = 0x90; + + if (hasFeature(kCodeGenOptimizedAlign)) { + const X86CpuInfo* cpuInfo = static_cast(getRuntime()->getCpuInfo()); + + // NOPs optimized for Intel: + // Intel 64 and IA-32 Architectures Software Developer's Manual + // - Volume 2B + // - Instruction Set Reference N-Z + // - NOP + + // NOPs optimized for AMD: + // Software Optimization Guide for AMD Family 10h Processors (Quad-Core) + // - 4.13 - Code Padding with Operand-Size Override and Multibyte NOP + + // Intel and AMD. + static const uint8_t nop1[] = { 0x90 }; + static const uint8_t nop2[] = { 0x66, 0x90 }; + static const uint8_t nop3[] = { 0x0F, 0x1F, 0x00 }; + static const uint8_t nop4[] = { 0x0F, 0x1F, 0x40, 0x00 }; + static const uint8_t nop5[] = { 0x0F, 0x1F, 0x44, 0x00, 0x00 }; + static const uint8_t nop6[] = { 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00 }; + static const uint8_t nop7[] = { 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00 }; + static const uint8_t nop8[] = { 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static const uint8_t nop9[] = { 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + // AMD. + static const uint8_t nop10[] = { 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static const uint8_t nop11[] = { 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + const uint8_t* p; + uint32_t n; + + if (cpuInfo->getVendorId() == kCpuVendorIntel && ( + (cpuInfo->getFamily() & 0x0F) == 0x06 || + (cpuInfo->getFamily() & 0x0F) == 0x0F)) { + do { + switch (i) { + case 1: p = nop1; n = 1; break; + case 2: p = nop2; n = 2; break; + case 3: p = nop3; n = 3; break; + case 4: p = nop4; n = 4; break; + case 5: p = nop5; n = 5; break; + case 6: p = nop6; n = 6; break; + case 7: p = nop7; n = 7; break; + case 8: p = nop8; n = 8; break; + default: p = nop9; n = 9; break; + } + + i -= n; + do { + EMIT_BYTE(*p++); + } while (--n); + } while (i); + } + else if (cpuInfo->getVendorId() == kCpuVendorAmd && cpuInfo->getFamily() >= 0x0F) { + do { + switch (i) { + case 1: p = nop1 ; n = 1; break; + case 2: p = nop2 ; n = 2; break; + case 3: p = nop3 ; n = 3; break; + case 4: p = nop4 ; n = 4; break; + case 5: p = nop5 ; n = 5; break; + case 6: p = nop6 ; n = 6; break; + case 7: p = nop7 ; n = 7; break; + case 8: p = nop8 ; n = 8; break; + case 9: p = nop9 ; n = 9; break; + case 10: p = nop10; n = 10; break; + default: p = nop11; n = 11; break; + } + + i -= n; + do { + EMIT_BYTE(*p++); + } while (--n); + } while (i); + } + } + } + + while (i) { + EMIT_BYTE(alignPattern); + i--; + } + + setCursor(cursor); + return kErrorOk; +} + +// ============================================================================ +// [asmjit::X86Assembler - Reloc] +// ============================================================================ + +size_t X86Assembler::_relocCode(void* _dst, Ptr baseAddress) const { + uint32_t arch = getArch(); + uint8_t* dst = static_cast(_dst); + +#if !defined(ASMJIT_DISABLE_LOGGER) + Logger* logger = getLogger(); +#endif // ASMJIT_DISABLE_LOGGER + + size_t minCodeSize = getOffset(); // Current offset is the minimum code size. + size_t maxCodeSize = getCodeSize(); // Includes all possible trampolines. + + // We will copy the exact size of the generated code. Extra code for trampolines + // is generated on-the-fly by the relocator (this code doesn't exist at the moment). + ::memcpy(dst, _buffer, minCodeSize); + + // Trampoline pointer. + uint8_t* tramp = dst + minCodeSize; + + // Relocate all recorded locations. + size_t relocCount = _relocList.getLength(); + const RelocData* rdList = _relocList.getData(); + + for (size_t i = 0; i < relocCount; i++) { + const RelocData& rd = rdList[i]; + + // Make sure that the `RelocData` is correct. + Ptr ptr = rd.data; + + size_t offset = static_cast(rd.from); + ASMJIT_ASSERT(offset + rd.size <= static_cast(maxCodeSize)); + + // Whether to use trampoline, can be only used if relocation type is + // kRelocAbsToRel on 64-bit. + bool useTrampoline = false; + + switch (rd.type) { + case kRelocAbsToAbs: + break; + + case kRelocRelToAbs: + ptr += baseAddress; + break; + + case kRelocAbsToRel: + ptr -= baseAddress + rd.from + 4; + break; + + case kRelocTrampoline: + ptr -= baseAddress + rd.from + 4; + if (!IntUtil::isInt32(static_cast(ptr))) { + ptr = (Ptr)tramp - (baseAddress + rd.from + 4); + useTrampoline = true; + } + break; + + default: + ASMJIT_ASSERT(!"Reached"); + } + + switch (rd.size) { + case 8: + *reinterpret_cast(dst + offset) = static_cast(ptr); + break; + + case 4: + *reinterpret_cast(dst + offset) = static_cast(static_cast(ptr)); + break; + + default: + ASMJIT_ASSERT(!"Reached"); + } + + // Handle the trampoline case. + if (useTrampoline) { + // Bytes that replace [REX, OPCODE] bytes. + uint32_t byte0 = 0xFF; + uint32_t byte1 = dst[offset - 1]; + + // Call, patch to FF/2 (-> 0x15). + if (byte1 == 0xE8) + byte1 = x86EncodeMod(0, 2, 5); + // Jmp, patch to FF/4 (-> 0x25). + else if (byte1 == 0xE9) + byte1 = x86EncodeMod(0, 4, 5); + + // Patch `jmp/call` instruction. + ASMJIT_ASSERT(offset >= 2); + dst[offset - 2] = byte0; + dst[offset - 1] = byte1; + + // Absolute address. + ((uint64_t*)tramp)[0] = static_cast(rd.data); + + // Advance trampoline pointer. + tramp += 8; + +#if !defined(ASMJIT_DISABLE_LOGGER) + if (logger) + logger->logFormat(kLoggerStyleComment, "; Trampoline %llX\n", rd.data); +#endif // !ASMJIT_DISABLE_LOGGER + } + } + + if (arch == kArchX64) + return (size_t)(tramp - dst); + else + return (size_t)(minCodeSize); +} + +// ============================================================================ +// [asmjit::X86Assembler - Logging] +// ============================================================================ + +#if !defined(ASMJIT_DISABLE_LOGGER) +// Logging helpers. +static const char* AssemblerX86_operandSize[] = { + "", + "byte ptr ", + "word ptr ", + NULL, + "dword ptr ", + NULL, + NULL, + NULL, + "qword ptr ", + NULL, + "tword ptr ", + NULL, + NULL, + NULL, + NULL, + NULL, + "oword ptr " +}; + +static const char X86Assembler_segName[] = + "\0\0\0\0" + "es:\0" + "cs:\0" + "ss:\0" + "ds:\0" + "fs:\0" + "gs:\0" + "\0\0\0\0"; + +static void X86Assembler_dumpRegister(StringBuilder& sb, uint32_t type, uint32_t index) { + // -- (Not-Encodable). + static const char reg8l[] = "al\0\0" "cl\0\0" "dl\0\0" "bl\0\0" "spl\0" "bpl\0" "sil\0" "dil\0" ; + static const char reg8h[] = "ah\0\0" "ch\0\0" "dh\0\0" "bh\0\0" "--\0\0" "--\0\0" "--\0\0" "--\0\0"; + static const char reg16[] = "ax\0\0" "cx\0\0" "dx\0\0" "bx\0\0" "sp\0\0" "bp\0\0" "si\0\0" "di\0\0"; + + char suffix = '\0'; + + switch (type) { + case kX86RegTypeGpbLo: + if (index >= 8) { + sb._appendChar('r'); + suffix = 'b'; + goto _EmitID; + } + + sb._appendString(®8l[index * 4]); + return; + + case _kX86RegTypePatchedGpbHi: + if (index < 4) + goto _EmitNE; + + index -= 4; + // ... Fall through ... + + case kX86RegTypeGpbHi: + if (index >= 4) + goto _EmitNE; + + sb._appendString(®8h[index * 4]); + return; + +_EmitNE: + sb._appendString("--", 2); + return; + + case kX86RegTypeGpw: + if (index >= 8) { + sb._appendChar('r'); + suffix = 'w'; + goto _EmitID; + } + + sb._appendString(®16[index * 4]); + return; + + case kX86RegTypeGpd: + if (index >= 8) { + sb._appendChar('r'); + suffix = 'd'; + goto _EmitID; + } + + sb._appendChar('e'); + sb._appendString(®16[index * 4]); + return; + + case kX86RegTypeGpq: + sb._appendChar('r'); + if (index >= 8) + goto _EmitID; + + sb._appendString(®16[index * 4]); + return; + + case kX86RegTypeFp: + sb._appendString("fp", 2); + goto _EmitID; + + case kX86RegTypeMm: + sb._appendString("mm", 2); + goto _EmitID; + + case kX86RegTypeXmm: + sb._appendString("xmm", 3); + goto _EmitID; + + case kX86RegTypeYmm: + sb._appendString("ymm", 3); + goto _EmitID; + + case kX86RegTypeSeg: + if (index >= kX86SegCount) + goto _EmitNE; + + sb._appendString(&X86Assembler_segName[index * 4], 2); + return; + + default: + return; + } + +_EmitID: + sb._appendUInt32(index); + + if (suffix) + sb._appendChar(suffix); +} + +static void X86Assembler_dumpOperand(StringBuilder& sb, uint32_t arch, const Operand* op, uint32_t loggerOptions) { + if (op->isReg()) { + X86Assembler_dumpRegister(sb, + static_cast(op)->getRegType(), + static_cast(op)->getRegIndex()); + } + else if (op->isMem()) { + const X86Mem* m = static_cast(op); + + uint32_t type = kX86RegTypeGpd; + uint32_t seg = m->getSegment(); + bool isAbsolute = false; + + if (arch == kArchX86) { + if (!m->hasGpdBase()) + type = kX86RegTypeGpw; + } + else { + if (!m->hasGpdBase()) + type = kX86RegTypeGpq; + } + + if (op->getSize() <= 16) + sb._appendString(AssemblerX86_operandSize[op->getSize()]); + + if (seg < kX86SegCount) + sb._appendString(&X86Assembler_segName[seg * 4]); + + sb._appendChar('['); + switch (m->getMemType()) { + case kMemTypeBaseIndex: + case kMemTypeStackIndex: + // [base + index << shift + displacement] + X86Assembler_dumpRegister(sb, type, m->getBase()); + break; + + case kMemTypeLabel: + // [label + index << shift + displacement] + sb.appendFormat("L%u", m->getBase()); + break; + + case kMemTypeAbsolute: + // [absolute] + isAbsolute = true; + sb.appendUInt(static_cast(m->getDisplacement()), 16); + break; + } + + if (m->hasIndex()) { + switch (m->getVSib()) { + case kX86MemVSibXmm: type = kX86RegTypeXmm; break; + case kX86MemVSibYmm: type = kX86RegTypeYmm; break; + } + + sb._appendChar('+'); + X86Assembler_dumpRegister(sb, type, m->getIndex()); + + if (m->getShift()) { + sb._appendChar('*'); + sb._appendChar("1248"[m->getShift() & 3]); + } + } + + if (m->getDisplacement() && !isAbsolute) { + uint32_t base = 10; + int32_t dispOffset = m->getDisplacement(); + + char prefix = '+'; + if (dispOffset < 0) { + dispOffset = -dispOffset; + prefix = '-'; + } + + sb._appendChar(prefix); + if ((loggerOptions & (1 << kLoggerOptionHexDisplacement)) != 0 && dispOffset > 9) { + sb._appendString("0x", 2); + base = 16; + } + sb.appendUInt(static_cast(dispOffset), base); + } + + sb._appendChar(']'); + } + else if (op->isImm()) { + const Imm* i = static_cast(op); + int64_t val = i->getInt64(); + + if ((loggerOptions & (1 << kLoggerOptionHexImmediate)) && static_cast(val) > 9) + sb.appendUInt(static_cast(val), 16); + else + sb.appendInt(val, 10); + } + else if (op->isLabel()) { + sb.appendFormat("L%u", op->getId()); + } + else { + sb._appendString("None", 4); + } +} + +static bool X86Assembler_dumpInstruction(StringBuilder& sb, + uint32_t arch, + uint32_t code, + uint32_t options, + const Operand* o0, + const Operand* o1, + const Operand* o2, + const Operand* o3, + uint32_t loggerOptions) { + + if (!sb.reserve(sb.getLength() + 128)) + return false; + + // Rex, lock and short prefix. + if (options & kX86InstOptionRex) + sb._appendString("rex ", 4); + + if (options & kX86InstOptionLock) + sb._appendString("lock ", 5); + + if (options & kInstOptionShortForm) + sb._appendString("short ", 6); + + // Dump instruction name. + sb._appendString(_x86InstInfo[code].getInstName()); + + // Dump operands. + if (!o0->isNone()) { + sb._appendChar(' '); + X86Assembler_dumpOperand(sb, arch, o0, loggerOptions); + } + + if (!o1->isNone()) { + sb._appendString(", ", 2); + X86Assembler_dumpOperand(sb, arch, o1, loggerOptions); + } + + if (!o2->isNone()) { + sb._appendString(", ", 2); + X86Assembler_dumpOperand(sb, arch, o2, loggerOptions); + } + + if (!o3->isNone()) { + sb._appendString(", ", 2); + X86Assembler_dumpOperand(sb, arch, o3, loggerOptions); + } + + return true; +} + +static bool X86Assembler_dumpComment(StringBuilder& sb, size_t len, const uint8_t* binData, size_t binLen, size_t dispLen, size_t imLen, const char* comment) { + size_t currentLen = len; + size_t commentLen = comment ? StringUtil::nlen(comment, kMaxCommentLength) : 0; + + ASMJIT_ASSERT(binLen >= dispLen); + + if (binLen || commentLen) { + size_t align = 36; + char sep = ';'; + + for (size_t i = (binLen == 0); i < 2; i++) { + size_t begin = sb.getLength(); + + // Append align. + if (currentLen < align) { + if (!sb.appendChars(' ', align - currentLen)) + return false; + } + + // Append separator. + if (sep) { + if (!(sb.appendChar(sep) & sb.appendChar(' '))) + return false; + } + + // Append binary data or comment. + if (i == 0) { + if (!sb.appendHex(binData, binLen - dispLen - imLen)) + return false; + if (!sb.appendChars('.', dispLen * 2)) + return false; + if (!sb.appendHex(binData + binLen - imLen, imLen)) + return false; + if (commentLen == 0) + break; + } + else { + if (!sb.appendString(comment, commentLen)) + return false; + } + + currentLen += sb.getLength() - begin; + align += 22; + sep = '|'; + } + } + + return sb.appendChar('\n'); +} +#endif // !ASMJIT_DISABLE_LOGGER + +// ============================================================================ +// [asmjit::X86Assembler - Emit] +// ============================================================================ + +#define HI_REG(_Index_) ((_kX86RegTypePatchedGpbHi << 8) | _Index_) +//! \internal +static const Operand::VRegOp x86PatchedHiRegs[4] = { + // --------------+---+--------------+--------------+------------+ + // Operand | S | Reg. Code | OperandId | Unused | + // --------------+---+--------------+--------------+------------+ + { kOperandTypeReg, 1 , { HI_REG(4) }, kInvalidValue, {{ 0, 0 }} }, + { kOperandTypeReg, 1 , { HI_REG(5) }, kInvalidValue, {{ 0, 0 }} }, + { kOperandTypeReg, 1 , { HI_REG(6) }, kInvalidValue, {{ 0, 0 }} }, + { kOperandTypeReg, 1 , { HI_REG(7) }, kInvalidValue, {{ 0, 0 }} } +}; +#undef HI_REG + +template +static Error ASMJIT_CDECL X86Assembler_emit(Assembler* self_, uint32_t code, const Operand* o0, const Operand* o1, const Operand* o2, const Operand* o3) { + X86Assembler* self = static_cast(self_); + + uint8_t* cursor = self->getCursor(); + uint32_t encoded = o0->getOp() + (o1->getOp() << 3) + (o2->getOp() << 6); + uint32_t options = self->getInstOptionsAndReset(); + + // Invalid instruction. + if (code >= _kX86InstIdCount) { + self->_comment = NULL; + return self->setError(kErrorUnknownInst); + } + + // Instruction opcode. + uint32_t opCode; + // ModR/M opcode or register code. + uint32_t opReg; + + // ModR/M, both rmReg and rmMem should refer to the same variable since they + // are never used together - either `rmReg` or `rmMem`. + union { + // ModR/M - register code. + uintptr_t rmReg; + // ModR/M - Memory operand. + const X86Mem* rmMem; + }; + + // Immediate value. + int64_t imVal = 0; + // Immediate length. + uint32_t imLen = 0; + + // Memory operand base register index. + uint32_t mBase; + // Memory operand index register index. + uint32_t mIndex; + + // Label. + LabelData* label; + // Displacement offset + int32_t dispOffset; + // Displacement size. + uint32_t dispSize = 0; + // Displacement relocation id. + intptr_t relocId; + +#if defined(ASMJIT_DEBUG) + bool assertIllegal = false; +#endif // ASMJIT_DEBUG + + const X86InstInfo& info = _x86InstInfo[code]; + const X86InstExtendedInfo& extendedInfo = info.getExtendedInfo(); + + // Grow request happens rarely. C++ compiler generates better code if it is + // handled at the end of the function. + if ((size_t)(self->_end - cursor) < 16) + goto _GrowBuffer; + + // -------------------------------------------------------------------------- + // [Prepare] + // -------------------------------------------------------------------------- + +_Prepare: + opCode = info.getPrimaryOpCode(); + opReg = x86ExtractO(opCode); + + if (Arch == kArchX86) { + // Check if one or more register operand is one of AH, BH, CH, or DH and + // patch them to ensure that the binary code with correct byte-index (4-7) + // is generated. + if (o0->isRegType(kX86RegTypeGpbHi)) + o0 = (const Operand*)(&x86PatchedHiRegs[x86OpReg(o0)]); + + if (o1->isRegType(kX86RegTypeGpbHi)) + o1 = (const Operand*)(&x86PatchedHiRegs[x86OpReg(o1)]); + } + else { + // `W` field. + ASMJIT_ASSERT(static_cast(kX86InstOptionRex) == + static_cast(kX86ByteRex)); + + // Check if one or more register operand is one of BPL, SPL, SIL, DIL and + // force a REX prefix to be emitted in such case. + if (X86Reg::isGpbReg(*o0)) { + uint32_t index = x86OpReg(o0); + if (static_cast(o0)->isGpbLo()) { + options |= (index >= 4) ? kX86InstOptionRex : 0; + } + else { + options |= _kX86InstOptionNoRex; + o0 = reinterpret_cast(&x86PatchedHiRegs[index]); + } + } + + if (X86Reg::isGpbReg(*o1)) { + uint32_t index = x86OpReg(o1); + if (static_cast(o1)->isGpbLo()) { + options |= (index >= 4) ? kX86InstOptionRex : 0; + } + else { + options |= _kX86InstOptionNoRex; + o1 = reinterpret_cast(&x86PatchedHiRegs[index]); + } + } + } + + // -------------------------------------------------------------------------- + // [Lock-Prefix] + // -------------------------------------------------------------------------- + + if (options & kX86InstOptionLock) { + if (!extendedInfo.isLockable()) + goto _IllegalInst; + EMIT_BYTE(0xF0); + } + + // -------------------------------------------------------------------------- + // [Group] + // -------------------------------------------------------------------------- + + switch (info.getEncodingId()) { + // ------------------------------------------------------------------------ + // [None] + // ------------------------------------------------------------------------ + + case kX86InstEncodingIdNone: + goto _EmitDone; + + // ------------------------------------------------------------------------ + // [X86] + // ------------------------------------------------------------------------ + + case kX86InstEncodingIdX86Op_66H: + ADD_66H_P(true); + // ... Fall through ... + + case kX86InstEncodingIdX86Op: + goto _EmitX86Op; + + case kX86InstEncodingIdX86Rm_B: + opCode += o0->getSize() != 1; + // ... Fall through ... + + case kX86InstEncodingIdX86Rm: + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + if (encoded == ENC_OPS(Reg, None, None)) { + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Mem, None, None)) { + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdX86RmReg: + if (encoded == ENC_OPS(Reg, Reg, None)) { + opCode += o0->getSize() != 1; + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + opReg = x86OpReg(o1); + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Mem, Reg, None)) { + opCode += o1->getSize() != 1; + ADD_66H_P_BY_SIZE(o1->getSize()); + ADD_REX_W_BY_SIZE(o1->getSize()); + + opReg = x86OpReg(o1); + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdX86RegRm: + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + if (encoded == ENC_OPS(Reg, Reg, None)) { + ASMJIT_ASSERT(o0->getSize() != 1); + + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + ASMJIT_ASSERT(o0->getSize() != 1); + + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdX86M: + if (encoded == ENC_OPS(Mem, None, None)) { + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdX86Arith: + if (encoded == ENC_OPS(Reg, Reg, None)) { + opCode +=(o0->getSize() != 1) + 2; + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + opCode +=(o0->getSize() != 1) + 2; + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + + if (encoded == ENC_OPS(Mem, Reg, None)) { + opCode += o1->getSize() != 1; + ADD_66H_P_BY_SIZE(o1->getSize()); + ADD_REX_W_BY_SIZE(o1->getSize()); + + opReg = x86OpReg(o1); + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + + // The remaining instructions use 0x80 opcode. + opCode = 0x80; + + if (encoded == ENC_OPS(Reg, Imm, None)) { + imVal = static_cast(o1)->getInt64(); + imLen = IntUtil::isInt8(imVal) ? static_cast(1) : IntUtil::iMin(o0->getSize(), 4); + rmReg = x86OpReg(o0); + + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + // Alternate Form - AL, AX, EAX, RAX. + if (rmReg == 0 && (o0->getSize() == 1 || imLen != 1)) { + opCode = ((opReg << 3) | (0x04 + (o0->getSize() != 1))); + imLen = IntUtil::iMin(o0->getSize(), 4); + goto _EmitX86Op; + } + + opCode += o0->getSize() != 1 ? (imLen != 1 ? 1 : 3) : 0; + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Mem, Imm, None)) { + uint32_t memSize = o0->getSize(); + + if (memSize == 0) + goto _IllegalInst; + + imVal = static_cast(o1)->getInt64(); + imLen = IntUtil::isInt8(imVal) ? static_cast(1) : IntUtil::iMin(memSize, 4); + + opCode += memSize != 1 ? (imLen != 1 ? 1 : 3) : 0; + ADD_66H_P_BY_SIZE(memSize); + ADD_REX_W_BY_SIZE(memSize); + + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdX86BSwap: + if (encoded == ENC_OPS(Reg, None, None)) { + opReg = x86OpReg(o0); + ADD_REX_W_BY_SIZE(o0->getSize()); + goto _EmitX86OpWithOpReg; + } + break; + + case kX86InstEncodingIdX86BTest: + if (encoded == ENC_OPS(Reg, Reg, None)) { + ADD_66H_P_BY_SIZE(o1->getSize()); + ADD_REX_W_BY_SIZE(o1->getSize()); + + opReg = x86OpReg(o1); + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Mem, Reg, None)) { + ADD_66H_P_BY_SIZE(o1->getSize()); + ADD_REX_W_BY_SIZE(o1->getSize()); + + opReg = x86OpReg(o1); + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + + // The remaining instructions use the secondary opcode/r. + imVal = static_cast(o1)->getInt64(); + imLen = 1; + + opCode = extendedInfo.getSecondaryOpCode(); + opReg = x86ExtractO(opCode); + + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + if (encoded == ENC_OPS(Reg, Imm, None)) { + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Mem, Imm, None)) { + if (o0->getSize() == 0) + goto _IllegalInst; + + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdX86Call: + if (encoded == ENC_OPS(Reg, None, None)) { + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Mem, None, None)) { + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + + // The following instructions use the secondary opcode. + opCode = extendedInfo.getSecondaryOpCode(); + + if (encoded == ENC_OPS(Imm, None, None)) { + imVal = static_cast(o0)->getInt64(); + goto _EmitJmpOrCallAbs; + } + + if (encoded == ENC_OPS(Label, None, None)) { + label = self->getLabelData(static_cast(o0)->getId()); + if (label->offset != -1) { + // Bound label. + static const intptr_t kRel32Size = 5; + intptr_t offs = label->offset - (intptr_t)(cursor - self->_buffer); + + ASMJIT_ASSERT(offs <= 0); + EMIT_OP(opCode); + EMIT_DWORD(static_cast(offs - kRel32Size)); + } + else { + // Non-bound label. + EMIT_OP(opCode); + dispOffset = -4; + dispSize = 4; + relocId = -1; + goto _EmitDisplacement; + } + goto _EmitDone; + } + break; + + case kX86InstEncodingIdX86Enter: + if (encoded == ENC_OPS(Imm, Imm, None)) { + EMIT_BYTE(0xC8); + EMIT_WORD(static_cast(o1)->getUInt16()); + EMIT_BYTE(static_cast(o0)->getUInt8()); + goto _EmitDone; + } + break; + + case kX86InstEncodingIdX86Imul: + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + if (encoded == ENC_OPS(Reg, None, None)) { + opCode &= kX86InstOpCode_PP_66 | kX86InstOpCode_W; + opCode |= 0xF6 + (o0->getSize() != 1); + + opReg = 5; + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Mem, None, None)) { + opCode &= kX86InstOpCode_PP_66 | kX86InstOpCode_W; + opCode |= 0xF6 + (o0->getSize() != 1); + + opReg = 5; + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + + // The following instructions use 0x0FAF opcode. + opCode &= kX86InstOpCode_PP_66 | kX86InstOpCode_W; + opCode |= kX86InstOpCode_MM_0F | 0xAF; + + if (encoded == ENC_OPS(Reg, Reg, None)) { + ASMJIT_ASSERT(o0->getSize() != 1); + + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + ASMJIT_ASSERT(o0->getSize() != 1); + + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + + goto _EmitX86M; + } + + // The following instructions use 0x69/0x6B opcode. + opCode &= kX86InstOpCode_PP_66 | kX86InstOpCode_W; + opCode |= 0x6B; + + if (encoded == ENC_OPS(Reg, Imm, None)) { + ASMJIT_ASSERT(o0->getSize() != 1); + + imVal = static_cast(o1)->getInt64(); + imLen = 1; + + if (!IntUtil::isInt8(imVal)) { + opCode -= 2; + imLen = o0->getSize() == 2 ? 2 : 4; + } + + opReg = x86OpReg(o0); + rmReg = opReg; + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Reg, Reg, Imm)) { + ASMJIT_ASSERT(o0->getSize() != 1); + + imVal = static_cast(o2)->getInt64(); + imLen = 1; + + if (!IntUtil::isInt8(imVal)) { + opCode -= 2; + imLen = o0->getSize() == 2 ? 2 : 4; + } + + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Reg, Mem, Imm)) { + ASMJIT_ASSERT(o0->getSize() != 1); + + imVal = static_cast(o2)->getInt64(); + imLen = 1; + + if (!IntUtil::isInt8(imVal)) { + opCode -= 2; + imLen = o0->getSize() == 2 ? 2 : 4; + } + + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdX86IncDec: + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + if (encoded == ENC_OPS(Reg, None, None)) { + rmReg = x86OpReg(o0); + + // INC r16|r32 is not encodable in 64-bit mode. + if (Arch == kArchX86 && (o0->getSize() == 2 || o0->getSize() == 4)) { + opCode &= kX86InstOpCode_PP_66 | kX86InstOpCode_W; + opCode |= extendedInfo.getSecondaryOpCode() + (static_cast(rmReg) & 0x7); + goto _EmitX86Op; + } + else { + opCode += o0->getSize() != 1; + goto _EmitX86R; + } + } + + if (encoded == ENC_OPS(Mem, None, None)) { + opCode += o0->getSize() != 1; + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdX86Int: + if (encoded == ENC_OPS(Imm, None, None)) { + imVal = static_cast(o0)->getInt64(); + uint8_t imm8 = static_cast(imVal & 0xFF); + + if (imm8 == 0x03) { + EMIT_OP(opCode); + } + else { + EMIT_OP(opCode + 1); + EMIT_BYTE(imm8); + } + goto _EmitDone; + } + break; + + case kX86InstEncodingIdX86Jcc: + if (encoded == ENC_OPS(Label, None, None)) { + label = self->getLabelData(static_cast(o0)->getId()); + + if (self->hasFeature(kCodeGenPredictedJumps)) { + if (options & kInstOptionTaken) + EMIT_BYTE(0x3E); + if (options & kInstOptionNotTaken) + EMIT_BYTE(0x2E); + } + + if (label->offset != -1) { + // Bound label. + static const intptr_t kRel8Size = 2; + static const intptr_t kRel32Size = 6; + + intptr_t offs = label->offset - (intptr_t)(cursor - self->_buffer); + ASMJIT_ASSERT(offs <= 0); + + if ((options & kInstOptionLongForm) == 0 && IntUtil::isInt8(offs - kRel8Size)) { + EMIT_OP(opCode); + EMIT_BYTE(offs - kRel8Size); + + options |= kInstOptionShortForm; + goto _EmitDone; + } + else { + EMIT_BYTE(0x0F); + EMIT_OP(opCode + 0x10); + EMIT_DWORD(static_cast(offs - kRel32Size)); + + options &= ~kInstOptionShortForm; + goto _EmitDone; + } + } + else { + // Non-bound label. + if (options & kInstOptionShortForm) { + EMIT_OP(opCode); + dispOffset = -1; + dispSize = 1; + relocId = -1; + goto _EmitDisplacement; + } + else { + EMIT_BYTE(0x0F); + EMIT_OP(opCode + 0x10); + dispOffset = -4; + dispSize = 4; + relocId = -1; + goto _EmitDisplacement; + } + } + } + break; + + case kX86InstEncodingIdX86Jecxz: + if (encoded == ENC_OPS(Reg, Label, None)) { + ASMJIT_ASSERT(x86OpReg(o0) == kX86RegIndexCx); + + if ((Arch == kArchX86 && o0->getSize() == 2) || + (Arch == kArchX64 && o0->getSize() == 4)) { + EMIT_BYTE(0x67); + } + + EMIT_BYTE(0xE3); + label = self->getLabelData(static_cast(o1)->getId()); + + if (label->offset != -1) { + // Bound label. + intptr_t offs = label->offset - (intptr_t)(cursor - self->_buffer) - 1; + if (!IntUtil::isInt8(offs)) + goto _IllegalInst; + + EMIT_BYTE(offs); + goto _EmitDone; + } + else { + // Non-bound label. + dispOffset = -1; + dispSize = 1; + relocId = -1; + goto _EmitDisplacement; + } + } + break; + + case kX86InstEncodingIdX86Jmp: + if (encoded == ENC_OPS(Reg, None, None)) { + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Mem, None, None)) { + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + + // The following instructions use the secondary opcode (0xE9). + opCode = 0xE9; + + if (encoded == ENC_OPS(Imm, None, None)) { + imVal = static_cast(o0)->getInt64(); + goto _EmitJmpOrCallAbs; + } + + if (encoded == ENC_OPS(Label, None, None)) { + label = self->getLabelData(static_cast(o0)->getId()); + if (label->offset != -1) { + // Bound label. + const intptr_t kRel8Size = 2; + const intptr_t kRel32Size = 5; + + intptr_t offs = label->offset - (intptr_t)(cursor - self->_buffer); + + if ((options & kInstOptionLongForm) == 0 && IntUtil::isInt8(offs - kRel8Size)) { + options |= kInstOptionShortForm; + + EMIT_BYTE(0xEB); + EMIT_BYTE(offs - kRel8Size); + goto _EmitDone; + } + else { + options &= ~kInstOptionShortForm; + + EMIT_BYTE(0xE9); + EMIT_DWORD(static_cast(offs - kRel32Size)); + goto _EmitDone; + } + } + else { + // Non-bound label. + if ((options & kInstOptionShortForm) != 0) { + EMIT_BYTE(0xEB); + dispOffset = -1; + dispSize = 1; + relocId = -1; + goto _EmitDisplacement; + } + else { + EMIT_BYTE(0xE9); + dispOffset = -4; + dispSize = 4; + relocId = -1; + goto _EmitDisplacement; + } + } + } + break; + + case kX86InstEncodingIdX86Lea: + if (encoded == ENC_OPS(Reg, Mem, None)) { + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdX86Mov: + if (encoded == ENC_OPS(Reg, Reg, None)) { + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + + // Sreg <- Reg + if (static_cast(o0)->isSeg()) { + ASMJIT_ASSERT(static_cast(o1)->isGpw() || + static_cast(o1)->isGpd() || + static_cast(o1)->isGpq() ); + opCode = 0x8E; + ADD_66H_P_BY_SIZE(o1->getSize()); + ADD_REX_W_BY_SIZE(o1->getSize()); + goto _EmitX86R; + } + + // Reg <- Sreg + if (static_cast(o1)->isSeg()) { + ASMJIT_ASSERT(static_cast(o0)->isGpw() || + static_cast(o0)->isGpd() || + static_cast(o0)->isGpq() ); + opCode = 0x8C; + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + goto _EmitX86R; + } + // Reg <- Reg + else { + ASMJIT_ASSERT(static_cast(o0)->isGpb() || + static_cast(o0)->isGpw() || + static_cast(o0)->isGpd() || + static_cast(o0)->isGpq() ); + opCode = 0x8A + (o0->getSize() != 1); + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + goto _EmitX86R; + } + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + + // Sreg <- Mem + if (static_cast(o0)->isRegType(kX86RegTypeSeg)) { + opCode = 0x8E; + opReg--; + ADD_66H_P_BY_SIZE(o1->getSize()); + ADD_REX_W_BY_SIZE(o1->getSize()); + goto _EmitX86M; + } + // Reg <- Mem + else { + ASMJIT_ASSERT(static_cast(o0)->isGpb() || + static_cast(o0)->isGpw() || + static_cast(o0)->isGpd() || + static_cast(o0)->isGpq() ); + opCode = 0x8A + (o0->getSize() != 1); + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + goto _EmitX86M; + } + } + + if (encoded == ENC_OPS(Mem, Reg, None)) { + opReg = x86OpReg(o1); + rmMem = x86OpMem(o0); + + // X86Mem <- Sreg + if (static_cast(o1)->isSeg()) { + opCode = 0x8C; + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + goto _EmitX86M; + } + // X86Mem <- Reg + else { + ASMJIT_ASSERT(static_cast(o1)->isGpb() || + static_cast(o1)->isGpw() || + static_cast(o1)->isGpd() || + static_cast(o1)->isGpq() ); + opCode = 0x88 + (o1->getSize() != 1); + ADD_66H_P_BY_SIZE(o1->getSize()); + ADD_REX_W_BY_SIZE(o1->getSize()); + goto _EmitX86M; + } + } + + if (encoded == ENC_OPS(Reg, Imm, None)) { + // 64-bit immediate in 64-bit mode is allowed. + imVal = static_cast(o1)->getInt64(); + imLen = o0->getSize(); + + opReg = 0; + rmReg = x86OpReg(o0); + + // Optimize instruction size by using 32-bit immediate if possible. + if (Arch == kArchX64 && imLen == 8 && IntUtil::isInt32(imVal)) { + opCode = 0xC7; + ADD_REX_W(1); + imLen = 4; + goto _EmitX86R; + } + else { + opCode = 0xB0 + (static_cast(o0->getSize() != 1) << 3); + opReg = rmReg; + + ADD_REX_W_BY_SIZE(imLen); + goto _EmitX86OpWithOpReg; + } + } + + if (encoded == ENC_OPS(Mem, Imm, None)) { + uint32_t memSize = o0->getSize(); + + if (memSize == 0) + goto _IllegalInst; + + imVal = static_cast(o1)->getInt64(); + imLen = IntUtil::iMin(memSize, 4); + + opCode = 0xC6 + (memSize != 1); + opReg = 0; + ADD_66H_P_BY_SIZE(memSize); + ADD_REX_W_BY_SIZE(memSize); + + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdX86MovSxZx: + if (encoded == ENC_OPS(Reg, Reg, None)) { + opCode += o1->getSize() != 1; + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + opCode += o1->getSize() != 1; + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdX86MovSxd: + if (encoded == ENC_OPS(Reg, Reg, None)) { + ADD_REX_W(true); + + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + ADD_REX_W(true); + + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdX86MovPtr: + if (encoded == ENC_OPS(Reg, Imm, None)) { + ASMJIT_ASSERT(x86OpReg(o0) == 0); + + opCode += o0->getSize() != 1; + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + imVal = static_cast(o1)->getInt64(); + imLen = self->_regSize; + goto _EmitX86Op; + } + + // The following instruction uses the secondary opcode. + opCode = extendedInfo.getSecondaryOpCode(); + + if (encoded == ENC_OPS(Imm, Reg, None)) { + ASMJIT_ASSERT(x86OpReg(o1) == 0); + + opCode += o1->getSize() != 1; + ADD_66H_P_BY_SIZE(o1->getSize()); + ADD_REX_W_BY_SIZE(o1->getSize()); + + imVal = static_cast(o0)->getInt64(); + imLen = self->_regSize; + goto _EmitX86Op; + } + break; + + case kX86InstEncodingIdX86Push: + if (encoded == ENC_OPS(Reg, None, None)) { + if (o0->isRegType(kX86RegTypeSeg)) { + uint32_t segment = x86OpReg(o0); + ASMJIT_ASSERT(segment < kX86SegCount); + + if (segment >= kX86SegFs) + EMIT_BYTE(0x0F); + + EMIT_BYTE(x86OpCodePushSeg[segment]); + goto _EmitDone; + } + else { + goto _GroupPop_Gp; + } + } + + if (encoded == ENC_OPS(Imm, None, None)) { + imVal = static_cast(o0)->getInt64(); + imLen = IntUtil::isInt8(imVal) ? 1 : 4; + + EMIT_BYTE(imLen == 1 ? 0x6A : 0x68); + goto _EmitImm; + } + // ... Fall through ... + + case kX86InstEncodingIdX86Pop: + if (encoded == ENC_OPS(Reg, None, None)) { + if (o0->isRegType(kX86RegTypeSeg)) { + uint32_t segment = x86OpReg(o0); + ASMJIT_ASSERT(segment < kX86SegCount); + + if (segment >= kX86SegFs) + EMIT_BYTE(0x0F); + + EMIT_BYTE(x86OpCodePopSeg[segment]); + goto _EmitDone; + } + else { +_GroupPop_Gp: + ASMJIT_ASSERT(static_cast(o0)->getSize() == 2 || + static_cast(o0)->getSize() == self->_regSize); + + opCode = extendedInfo.getSecondaryOpCode(); + opReg = x86OpReg(o0); + + ADD_66H_P_BY_SIZE(o0->getSize()); + goto _EmitX86OpWithOpReg; + } + } + + if (encoded == ENC_OPS(Mem, None, None)) { + ADD_66H_P_BY_SIZE(o0->getSize()); + + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdX86Rep: + // Emit REP 0xF2 or 0xF3 prefix first. + EMIT_BYTE(0xF2 + opReg); + goto _EmitX86Op; + + case kX86InstEncodingIdX86Ret: + if (encoded == ENC_OPS(None, None, None)) { + EMIT_BYTE(0xC3); + goto _EmitDone; + } + + if (encoded == ENC_OPS(Imm, None, None)) { + imVal = static_cast(o0)->getInt64(); + if (imVal == 0) { + EMIT_BYTE(0xC3); + goto _EmitDone; + } + else { + EMIT_BYTE(0xC2); + imLen = 2; + goto _EmitImm; + } + } + break; + + case kX86InstEncodingIdX86Rot: + opCode += o0->getSize() != 1; + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + if (encoded == ENC_OPS(Reg, Reg, None)) { + ASMJIT_ASSERT(static_cast(o1)->isRegCode(kX86RegTypeGpbLo, kX86RegIndexCx)); + opCode += 2; + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Mem, Reg, None)) { + ASMJIT_ASSERT(static_cast(o1)->isRegCode(kX86RegTypeGpbLo, kX86RegIndexCx)); + opCode += 2; + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + + if (encoded == ENC_OPS(Reg, Imm, None)) { + imVal = static_cast(o1)->getInt64() & 0xFF; + imLen = imVal != 1; + if (imLen) + opCode -= 0x10; + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Mem, Imm, None)) { + if (o0->getSize() == 0) + goto _IllegalInst; + + imVal = static_cast(o1)->getInt64() & 0xFF; + imLen = imVal != 1; + if (imLen) + opCode -= 0x10; + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdX86Set: + if (encoded == ENC_OPS(Reg, None, None)) { + ASMJIT_ASSERT(o0->getSize() == 1); + + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Mem, None, None)) { + ASMJIT_ASSERT(o0->getSize() <= 1); + + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdX86Shlrd: + if (encoded == ENC_OPS(Reg, Reg, Imm)) { + ASMJIT_ASSERT(o0->getSize() == o1->getSize()); + + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + imVal = static_cast(o2)->getInt64(); + imLen = 1; + + opReg = x86OpReg(o1); + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Mem, Reg, Imm)) { + ADD_66H_P_BY_SIZE(o1->getSize()); + ADD_REX_W_BY_SIZE(o1->getSize()); + + imVal = static_cast(o2)->getInt64(); + imLen = 1; + + opReg = x86OpReg(o1); + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + + // The following instructions use opCode + 1. + opCode++; + + if (encoded == ENC_OPS(Reg, Reg, Reg)) { + ASMJIT_ASSERT(static_cast(o2)->isRegCode(kX86RegTypeGpbLo, kX86RegIndexCx)); + ASMJIT_ASSERT(o0->getSize() == o1->getSize()); + + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + opReg = x86OpReg(o1); + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Mem, Reg, Reg)) { + ASMJIT_ASSERT(static_cast(o2)->isRegCode(kX86RegTypeGpbLo, kX86RegIndexCx)); + + ADD_66H_P_BY_SIZE(o1->getSize()); + ADD_REX_W_BY_SIZE(o1->getSize()); + + opReg = x86OpReg(o1); + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdX86Test: + if (encoded == ENC_OPS(Reg, Reg, None)) { + ASMJIT_ASSERT(o0->getSize() == o1->getSize()); + + opCode += o0->getSize() != 1; + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + opReg = x86OpReg(o1); + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Mem, Reg, None)) { + opCode += o1->getSize() != 1; + ADD_66H_P_BY_SIZE(o1->getSize()); + ADD_REX_W_BY_SIZE(o1->getSize()); + + opReg = x86OpReg(o1); + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + + // The following instructions use the secondary opcode. + opCode = extendedInfo.getSecondaryOpCode() + (o0->getSize() != 1); + opReg = x86ExtractO(opCode); + + if (encoded == ENC_OPS(Reg, Imm, None)) { + imVal = static_cast(o1)->getInt64(); + imLen = IntUtil::iMin(o0->getSize(), 4); + + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + // Alternate Form - AL, AX, EAX, RAX. + if (x86OpReg(o0) == 0) { + opCode &= kX86InstOpCode_PP_66 | kX86InstOpCode_W; + opCode |= 0xA8 + (o0->getSize() != 1); + goto _EmitX86Op; + } + + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Mem, Imm, None)) { + if (o0->getSize() == 0) + goto _IllegalInst; + + imVal = static_cast(o1)->getInt64(); + imLen = IntUtil::iMin(o0->getSize(), 4); + + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdX86Xchg: + if (encoded == ENC_OPS(Reg, Mem, None)) { + opCode += o0->getSize() != 1; + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + // ... fall through ... + + case kX86InstEncodingIdX86Xadd: + if (encoded == ENC_OPS(Reg, Reg, None)) { + opReg = x86OpReg(o1); + rmReg = x86OpReg(o0); + + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + // Special opcode for 'xchg ?ax, reg'. + if (code == kX86InstIdXchg && o0->getSize() > 1 && (opReg == 0 || rmReg == 0)) { + opCode &= kX86InstOpCode_PP_66 | kX86InstOpCode_W; + opCode |= 0x90; + // One of `xchg a, b` or `xchg b, a` is AX/EAX/RAX. + opReg += rmReg; + goto _EmitX86OpWithOpReg; + } + + opCode += o0->getSize() != 1; + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Mem, Reg, None)) { + opCode += o1->getSize() != 1; + ADD_66H_P_BY_SIZE(o1->getSize()); + ADD_REX_W_BY_SIZE(o1->getSize()); + + opReg = x86OpReg(o1); + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + // ------------------------------------------------------------------------ + // [Fpu] + // ------------------------------------------------------------------------ + + case kX86InstEncodingIdFpuOp: + goto _EmitFpuOp; + + case kX86InstEncodingIdFpuArith: + if (encoded == ENC_OPS(Reg, Reg, None)) { + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + rmReg += opReg; + + // We switch to the alternative opcode if the first operand is zero. + if (opReg == 0) { +_EmitFpArith_Reg: + opCode = 0xD800 + ((opCode >> 8) & 0xFF) + static_cast(rmReg); + goto _EmitFpuOp; + } + else { + opCode = 0xDC00 + ((opCode >> 0) & 0xFF) + static_cast(rmReg); + goto _EmitFpuOp; + } + } + + if (encoded == ENC_OPS(Mem, None, None)) { + // 0xD8/0xDC, depends on the size of the memory operand; opReg has been + // set already. +_EmitFpArith_Mem: + opCode = (o0->getSize() == 4) ? 0xD8 : 0xDC; + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdFpuCom: + if (encoded == ENC_OPS(None, None, None)) { + rmReg = 1; + goto _EmitFpArith_Reg; + } + + if (encoded == ENC_OPS(Reg, None, None)) { + rmReg = x86OpReg(o0); + goto _EmitFpArith_Reg; + } + + if (encoded == ENC_OPS(Mem, None, None)) { + goto _EmitFpArith_Mem; + } + break; + + case kX86InstEncodingIdFpuFldFst: + if (encoded == ENC_OPS(Mem, None, None)) { + rmMem = x86OpMem(o0); + + if (o0->getSize() == 4 && info.hasInstFlag(kX86InstFlagMem4)) { + goto _EmitX86M; + } + + if (o0->getSize() == 8 && info.hasInstFlag(kX86InstFlagMem8)) { + opCode += 4; + goto _EmitX86M; + } + + if (o0->getSize() == 10 && info.hasInstFlag(kX86InstFlagMem10)) { + opCode = extendedInfo.getSecondaryOpCode(); + opReg = x86ExtractO(opCode); + goto _EmitX86M; + } + } + + if (encoded == ENC_OPS(Reg, None, None)) { + if (code == kX86InstIdFld) { + opCode = 0xD9C0 + x86OpReg(o0); + goto _EmitFpuOp; + } + + if (code == kX86InstIdFst) { + opCode = 0xDDD0 + x86OpReg(o0); + goto _EmitFpuOp; + } + + if (code == kX86InstIdFstp) { + opCode = 0xDDD8 + x86OpReg(o0); + goto _EmitFpuOp; + } + } + break; + + + case kX86InstEncodingIdFpuM: + if (encoded == ENC_OPS(Mem, None, None)) { + rmMem = x86OpMem(o0); + + if (o0->getSize() == 2 && info.hasInstFlag(kX86InstFlagMem2)) { + opCode += 4; + goto _EmitX86M; + } + + if (o0->getSize() == 4 && info.hasInstFlag(kX86InstFlagMem4)) { + goto _EmitX86M; + } + + if (o0->getSize() == 8 && info.hasInstFlag(kX86InstFlagMem8)) { + opCode = extendedInfo.getSecondaryOpCode(); + opReg = x86ExtractO(opCode); + goto _EmitX86M; + } + } + break; + + case kX86InstEncodingIdFpuRDef: + if (encoded == ENC_OPS(None, None, None)) { + opCode += 1; + goto _EmitFpuOp; + } + // ... Fall through ... + + case kX86InstEncodingIdFpuR: + if (encoded == ENC_OPS(Reg, None, None)) { + opCode += x86OpReg(o0); + goto _EmitFpuOp; + } + break; + + case kX86InstEncodingIdFpuStsw: + if (encoded == ENC_OPS(Reg, None, None)) { + if (x86OpReg(o0) != 0) + goto _IllegalInst; + + opCode = extendedInfo.getSecondaryOpCode(); + goto _EmitX86Op; + } + + if (encoded == ENC_OPS(Mem, None, None)) { + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + // ------------------------------------------------------------------------ + // [Ext] + // ------------------------------------------------------------------------ + + case kX86InstEncodingIdExtCrc: + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + if (encoded == ENC_OPS(Reg, Reg, None)) { + ASMJIT_ASSERT(static_cast(o0)->getRegType() == kX86RegTypeGpd || + static_cast(o0)->getRegType() == kX86RegTypeGpq); + + opCode += o0->getSize() != 1; + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + ASMJIT_ASSERT(static_cast(o0)->getRegType() == kX86RegTypeGpd || + static_cast(o0)->getRegType() == kX86RegTypeGpq); + + opCode += o0->getSize() != 1; + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdExtExtract: + if (encoded == ENC_OPS(Reg, Reg, Imm)) { + ADD_66H_P(static_cast(o1)->isXmm()); + + imVal = static_cast(o2)->getInt64(); + imLen = 1; + + opReg = x86OpReg(o1); + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Mem, Reg, Imm)) { + // Secondary opcode for 'pextrw' instruction (SSE2). + opCode = extendedInfo.getSecondaryOpCode(); + ADD_66H_P(static_cast(o1)->isXmm()); + + imVal = static_cast(o2)->getInt64(); + imLen = 1; + + opReg = x86OpReg(o1); + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdExtFence: + if (Arch == kArchX64 && (opCode & kX86InstOpCode_W_Mask)) { + EMIT_BYTE(kX86ByteRex | kX86ByteRexW); + } + + EMIT_BYTE(0x0F); + EMIT_OP(opCode); + EMIT_BYTE(0xC0 | (opReg << 3)); + goto _EmitDone; + + case kX86InstEncodingIdExtMov: + case kX86InstEncodingIdExtMovNoRexW: + ASMJIT_ASSERT(extendedInfo._opFlags[0] != 0); + ASMJIT_ASSERT(extendedInfo._opFlags[1] != 0); + + // Check parameters Gpd|Gpq|Mm|Xmm <- Gpd|Gpq|Mm|Xmm|X86Mem|Imm. + ASMJIT_ASSERT(!((o0->isMem() && (extendedInfo._opFlags[0] & kX86InstOpMem) == 0) || + (o0->isRegType(kX86RegTypeMm ) && (extendedInfo._opFlags[0] & kX86InstOpMm ) == 0) || + (o0->isRegType(kX86RegTypeXmm) && (extendedInfo._opFlags[0] & kX86InstOpXmm) == 0) || + (o0->isRegType(kX86RegTypeGpd) && (extendedInfo._opFlags[0] & kX86InstOpGd ) == 0) || + (o0->isRegType(kX86RegTypeGpq) && (extendedInfo._opFlags[0] & kX86InstOpGq ) == 0) || + (o1->isMem() && (extendedInfo._opFlags[1] & kX86InstOpMem) == 0) || + (o1->isRegType(kX86RegTypeMm ) && (extendedInfo._opFlags[1] & kX86InstOpMm ) == 0) || + (o1->isRegType(kX86RegTypeXmm) && (extendedInfo._opFlags[1] & kX86InstOpXmm) == 0) || + (o1->isRegType(kX86RegTypeGpd) && (extendedInfo._opFlags[1] & kX86InstOpGd ) == 0) || + (o1->isRegType(kX86RegTypeGpq) && (extendedInfo._opFlags[1] & kX86InstOpGq ) == 0) )); + + // Gp|Mm|Xmm <- Gp|Mm|Xmm + if (encoded == ENC_OPS(Reg, Reg, None)) { + ADD_REX_W(static_cast(o0)->isGpq() && (info.getEncodingId() != kX86InstEncodingIdExtMovNoRexW)); + ADD_REX_W(static_cast(o1)->isGpq() && (info.getEncodingId() != kX86InstEncodingIdExtMovNoRexW)); + + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitX86R; + } + + // Gp|Mm|Xmm <- Mem + if (encoded == ENC_OPS(Reg, Mem, None)) { + ADD_REX_W(static_cast(o0)->isGpq() && (info.getEncodingId() != kX86InstEncodingIdExtMovNoRexW)); + + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + + // The following instruction uses opCode[1]. + opCode = extendedInfo.getSecondaryOpCode(); + + // X86Mem <- Gp|Mm|Xmm + if (encoded == ENC_OPS(Mem, Reg, None)) { + ADD_REX_W(static_cast(o1)->isGpq() && (info.getEncodingId() != kX86InstEncodingIdExtMovNoRexW)); + + opReg = x86OpReg(o1); + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdExtMovBe: + if (encoded == ENC_OPS(Reg, Mem, None)) { + ADD_66H_P_BY_SIZE(o0->getSize()); + ADD_REX_W_BY_SIZE(o0->getSize()); + + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + + // The following instruction uses the secondary opcode. + opCode = extendedInfo.getSecondaryOpCode(); + + if (encoded == ENC_OPS(Mem, Reg, None)) { + ADD_66H_P_BY_SIZE(o1->getSize()); + ADD_REX_W_BY_SIZE(o1->getSize()); + + opReg = x86OpReg(o1); + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdExtMovD: +_EmitMmMovD: + opReg = x86OpReg(o0); + ADD_66H_P(static_cast(o0)->isXmm()); + + // Mm/Xmm <- Gp + if (encoded == ENC_OPS(Reg, Reg, None) && static_cast(o1)->isGp()) { + rmReg = x86OpReg(o1); + goto _EmitX86R; + } + + // Mm/Xmm <- Mem + if (encoded == ENC_OPS(Reg, Mem, None)) { + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + + // The following instructions use the secondary opcode. + opCode = extendedInfo.getSecondaryOpCode(); + opReg = x86OpReg(o1); + ADD_66H_P(static_cast(o1)->isXmm()); + + // Gp <- Mm/Xmm + if (encoded == ENC_OPS(Reg, Reg, None) && static_cast(o0)->isGp()) { + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + + // X86Mem <- Mm/Xmm + if (encoded == ENC_OPS(Mem, Reg, None)) { + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdExtMovQ: + if (encoded == ENC_OPS(Reg, Reg, None)) { + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + + // Mm <- Mm + if (static_cast(o0)->isMm() && static_cast(o1)->isMm()) { + opCode = kX86InstOpCode_PP_00 | kX86InstOpCode_MM_0F | 0x6F; + goto _EmitX86R; + } + + // Xmm <- Xmm + if (static_cast(o0)->isXmm() && static_cast(o1)->isXmm()) { + opCode = kX86InstOpCode_PP_F3 | kX86InstOpCode_MM_0F | 0x7E; + goto _EmitX86R; + } + + // Mm <- Xmm (Movdq2q) + if (static_cast(o0)->isMm() && static_cast(o1)->isXmm()) { + opCode = kX86InstOpCode_PP_F2 | kX86InstOpCode_MM_0F | 0xD6; + goto _EmitX86R; + } + + // Xmm <- Mm (Movq2dq) + if (static_cast(o0)->isXmm() && static_cast(o1)->isMm()) { + opCode = kX86InstOpCode_PP_F3 | kX86InstOpCode_MM_0F | 0xD6; + goto _EmitX86R; + } + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + + // Mm <- Mem + if (static_cast(o0)->isMm()) { + opCode = kX86InstOpCode_PP_00 | kX86InstOpCode_MM_0F | 0x6F; + goto _EmitX86M; + } + + // Xmm <- Mem + if (static_cast(o0)->isXmm()) { + opCode = kX86InstOpCode_PP_F3 | kX86InstOpCode_MM_0F | 0x7E; + goto _EmitX86M; + } + } + + if (encoded == ENC_OPS(Mem, Reg, None)) { + opReg = x86OpReg(o1); + rmMem = x86OpMem(o0); + + // X86Mem <- Mm + if (static_cast(o1)->isMm()) { + opCode = kX86InstOpCode_PP_00 | kX86InstOpCode_MM_0F | 0x7F; + goto _EmitX86M; + } + + // X86Mem <- Xmm + if (static_cast(o1)->isXmm()) { + opCode = kX86InstOpCode_PP_66 | kX86InstOpCode_MM_0F | 0xD6; + goto _EmitX86M; + } + } + + if (Arch == kArchX64) { + // Movq in other case is simply a MOVD instruction promoted to 64-bit. + opCode |= kX86InstOpCode_W; + goto _EmitMmMovD; + } + break; + + case kX86InstEncodingIdExtPrefetch: + if (encoded == ENC_OPS(Mem, Imm, None)) { + opReg = static_cast(o1)->getUInt32() & 0x3; + rmMem = x86OpMem(o0); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdExtRm_PQ: + ADD_66H_P(o0->isRegType(kX86RegTypeXmm) || o1->isRegType(kX86RegTypeXmm)); + // ... Fall through ... + + case kX86InstEncodingIdExtRm_Q: + ADD_REX_W(o0->isRegType(kX86RegTypeGpq) || o1->isRegType(kX86RegTypeGpq) || (o1->isMem() && o1->getSize() == 8)); + // ... Fall through ... + + case kX86InstEncodingIdExtRm: + if (encoded == ENC_OPS(Reg, Reg, None)) { + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdExtRm_P: + if (encoded == ENC_OPS(Reg, Reg, None)) { + ADD_66H_P(static_cast(o0)->isXmm() | static_cast(o1)->isXmm()); + + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + ADD_66H_P(static_cast(o0)->isXmm()); + + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdExtRmRi: + if (encoded == ENC_OPS(Reg, Reg, None)) { + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + + // The following instruction uses the secondary opcode. + opCode = extendedInfo.getSecondaryOpCode(); + opReg = x86ExtractO(opCode); + + if (encoded == ENC_OPS(Reg, Imm, None)) { + imVal = static_cast(o1)->getInt64(); + imLen = 1; + + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + break; + + case kX86InstEncodingIdExtRmRi_P: + if (encoded == ENC_OPS(Reg, Reg, None)) { + ADD_66H_P(static_cast(o0)->isXmm() | static_cast(o1)->isXmm()); + + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + ADD_66H_P(static_cast(o0)->isXmm()); + + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + + // The following instruction uses the secondary opcode. + opCode = extendedInfo.getSecondaryOpCode(); + opReg = x86ExtractO(opCode); + + if (encoded == ENC_OPS(Reg, Imm, None)) { + ADD_66H_P(static_cast(o0)->isXmm()); + + imVal = static_cast(o1)->getInt64(); + imLen = 1; + + rmReg = x86OpReg(o0); + goto _EmitX86R; + } + break; + + case kX86InstEncodingIdExtRmi: + imVal = static_cast(o2)->getInt64(); + imLen = 1; + + if (encoded == ENC_OPS(Reg, Reg, Imm)) { + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Reg, Mem, Imm)) { + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + break; + + case kX86InstEncodingIdExtRmi_P: + imVal = static_cast(o2)->getInt64(); + imLen = 1; + + if (encoded == ENC_OPS(Reg, Reg, Imm)) { + ADD_66H_P(static_cast(o0)->isXmm() | static_cast(o1)->isXmm()); + + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Reg, Mem, Imm)) { + ADD_66H_P(static_cast(o0)->isXmm()); + + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + break; + + // ------------------------------------------------------------------------ + // [Group - Extrq / Insertq (SSE4a)] + // ------------------------------------------------------------------------ + + case kX86InstEncodingIdExtExtrq: + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + + if (encoded == ENC_OPS(Reg, Reg, None)) + goto _EmitX86R; + + // The following instruction uses the secondary opcode. + opCode = extendedInfo.getSecondaryOpCode(); + + if (encoded == ENC_OPS(Reg, Imm, Imm)) { + imVal = (static_cast(o1)->getUInt32() ) + + (static_cast(o2)->getUInt32() << 8) ; + imLen = 2; + + rmReg = opReg; + opReg = x86ExtractO(opCode); + goto _EmitX86R; + } + break; + + case kX86InstEncodingIdExtInsertq: + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + + if (encoded == ENC_OPS(Reg, Reg, None)) + goto _EmitX86R; + + // The following instruction uses the secondary opcode. + opCode = extendedInfo.getSecondaryOpCode(); + + if (encoded == ENC_OPS(Reg, Reg, Imm) && o3->isImm()) { + imVal = (static_cast(o2)->getUInt32() ) + + (static_cast(o3)->getUInt32() << 8) ; + imLen = 2; + goto _EmitX86R; + } + break; + + // ------------------------------------------------------------------------ + // [Group - 3dNow] + // ------------------------------------------------------------------------ + + case kX86InstEncodingId3dNow: + // Every 3dNow instruction starts with 0x0F0F and the actual opcode is + // stored as 8-bit immediate. + imVal = opCode & 0xFF; + imLen = 1; + + opCode = kX86InstOpCode_MM_0F | 0x0F; + opReg = x86OpReg(o0); + + if (encoded == ENC_OPS(Reg, Reg, None)) { + rmReg = x86OpReg(o1); + goto _EmitX86R; + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + rmMem = x86OpMem(o1); + goto _EmitX86M; + } + break; + + // ------------------------------------------------------------------------ + // [Avx] + // ------------------------------------------------------------------------ + + case kX86InstEncodingIdAvxOp: + goto _EmitAvxOp; + + case kX86InstEncodingIdAvxM: + if (encoded == ENC_OPS(Mem, None, None)) { + rmMem = x86OpMem(o0); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxMr_P: + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdAvxMr: + if (encoded == ENC_OPS(Reg, Reg, None)) { + opReg = x86OpReg(o1); + rmReg = x86OpReg(o0); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Mem, Reg, None)) { + opReg = x86OpReg(o1); + rmMem = x86OpMem(o0); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxMri_P: + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdAvxMri: + imVal = static_cast(o2)->getInt64(); + imLen = 1; + + if (encoded == ENC_OPS(Reg, Reg, Imm)) { + opReg = x86OpReg(o1); + rmReg = x86OpReg(o0); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Mem, Reg, Imm)) { + opReg = x86OpReg(o1); + rmMem = x86OpMem(o0); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxRm_P: + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdAvxRm: + if (encoded == ENC_OPS(Reg, Reg, None)) { + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxRmi_P: + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdAvxRmi: + imVal = static_cast(o2)->getInt64(); + imLen = 1; + + if (encoded == ENC_OPS(Reg, Reg, Imm)) { + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Mem, Imm)) { + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxRvm_P: + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdAvxRvm: + if (encoded == ENC_OPS(Reg, Reg, Reg)) { +_EmitAvxRvm: + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmReg = x86OpReg(o2); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Reg, Mem)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmMem = x86OpMem(o2); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxRvmr_P: + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdAvxRvmr: + if (!o3->isReg()) + goto _IllegalInst; + + imVal = x86OpReg(o3) << 4; + imLen = 1; + + if (encoded == ENC_OPS(Reg, Reg, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmReg = x86OpReg(o2); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Reg, Mem)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmMem = x86OpMem(o2); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxRvmi_P: + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdAvxRvmi: + if (!o3->isImm()) + goto _IllegalInst; + + imVal = static_cast(o3)->getInt64(); + imLen = 1; + + if (encoded == ENC_OPS(Reg, Reg, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmReg = x86OpReg(o2); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Reg, Mem)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmMem = x86OpMem(o2); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxRmv: + if (encoded == ENC_OPS(Reg, Reg, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o2)); + rmReg = x86OpReg(o1); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Mem, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o2)); + rmMem = x86OpMem(o1); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxRmvi: + if (!o3->isImm()) + goto _IllegalInst; + + imVal = static_cast(o3)->getInt64(); + imLen = 1; + + if (encoded == ENC_OPS(Reg, Reg, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o2)); + rmReg = x86OpReg(o1); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Mem, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o2)); + rmMem = x86OpMem(o1); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxRmMr_P: + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdAvxRmMr: + if (encoded == ENC_OPS(Reg, Reg, None)) { + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitAvxM; + } + + // The following instruction uses the secondary opcode. + opCode &= kX86InstOpCode_L_Mask; + opCode |= extendedInfo.getSecondaryOpCode(); + + if (encoded == ENC_OPS(Mem, Reg, None)) { + opReg = x86OpReg(o1); + rmMem = x86OpMem(o0); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxRvmRmi_P: + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdAvxRvmRmi: + if (encoded == ENC_OPS(Reg, Reg, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmReg = x86OpReg(o2); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Reg, Mem)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmMem = x86OpMem(o2); + goto _EmitAvxM; + } + + // The following instructions use the secondary opcode. + opCode &= kX86InstOpCode_L_Mask; + opCode |= extendedInfo.getSecondaryOpCode(); + + imVal = static_cast(o2)->getInt64(); + imLen = 1; + + if (encoded == ENC_OPS(Reg, Reg, Imm)) { + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Mem, Imm)) { + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxRvmMr: + if (encoded == ENC_OPS(Reg, Reg, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmReg = x86OpReg(o2); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Reg, Mem)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmMem = x86OpMem(o2); + goto _EmitAvxM; + } + + // The following instructions use the secondary opcode. + opCode = extendedInfo.getSecondaryOpCode(); + + if (encoded == ENC_OPS(Reg, Reg, None)) { + opReg = x86OpReg(o1); + rmReg = x86OpReg(o0); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Mem, Reg, None)) { + opReg = x86OpReg(o1); + rmMem = x86OpMem(o0); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxRvmMvr_P: + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdAvxRvmMvr: + if (encoded == ENC_OPS(Reg, Reg, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmReg = x86OpReg(o2); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Reg, Mem)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmMem = x86OpMem(o2); + goto _EmitAvxM; + } + + // The following instruction uses the secondary opcode. + opCode &= kX86InstOpCode_L_Mask; + opCode |= extendedInfo.getSecondaryOpCode(); + + if (encoded == ENC_OPS(Mem, Reg, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o2), x86OpReg(o1)); + rmMem = x86OpMem(o0); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxRvmVmi_P: + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdAvxRvmVmi: + if (encoded == ENC_OPS(Reg, Reg, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmReg = x86OpReg(o2); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Reg, Mem)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmMem = x86OpMem(o2); + goto _EmitAvxM; + } + + // The following instruction uses the secondary opcode. + opCode &= kX86InstOpCode_L_Mask; + opCode |= extendedInfo.getSecondaryOpCode(); + opReg = x86ExtractO(opCode); + + imVal = static_cast(o2)->getInt64(); + imLen = 1; + + if (encoded == ENC_OPS(Reg, Reg, Imm)) { + opReg = x86RegAndVvvv(opReg, x86OpReg(o0)); + rmReg = x86OpReg(o1); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Mem, Imm)) { + opReg = x86RegAndVvvv(opReg, x86OpReg(o0)); + rmMem = x86OpMem(o1); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxVm: + if (encoded == ENC_OPS(Reg, Reg, None)) { + opReg = x86RegAndVvvv(opReg, x86OpReg(o0)); + rmReg = x86OpReg(o1); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + opReg = x86RegAndVvvv(opReg, x86OpReg(o0)); + rmMem = x86OpMem(o1); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxVmi_P: + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdAvxVmi: + imVal = static_cast(o3)->getInt64(); + imLen = 1; + + if (encoded == ENC_OPS(Reg, Reg, Imm)) { + opReg = x86RegAndVvvv(opReg, x86OpReg(o0)); + rmReg = x86OpReg(o1); + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Mem, Imm)) { + opReg = x86RegAndVvvv(opReg, x86OpReg(o0)); + rmMem = x86OpMem(o1); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxRvrmRvmr_P: + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdAvxRvrmRvmr: + if (encoded == ENC_OPS(Reg, Reg, Reg) && o3->isReg()) { + imVal = x86OpReg(o3) << 4; + imLen = 1; + + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmReg = x86OpReg(o2); + + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Reg, Reg) && o3->isMem()) { + imVal = x86OpReg(o2) << 4; + imLen = 1; + + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmMem = x86OpMem(o3); + + ADD_VEX_W(true); + goto _EmitAvxM; + } + + if (encoded == ENC_OPS(Reg, Reg, Mem) && o3->isReg()) { + imVal = x86OpReg(o3) << 4; + imLen = 1; + + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmMem = x86OpMem(o2); + + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxMovSsSd: + if (encoded == ENC_OPS(Reg, Reg, Reg)) { + goto _EmitAvxRvm; + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + opReg = x86RegAndVvvv(opReg, x86OpReg(o0)); + rmMem = x86OpMem(o1); + goto _EmitAvxM; + } + + if (encoded == ENC_OPS(Mem, Reg, None)) { + opReg = x86OpReg(o1); + rmMem = x86OpMem(o0); + goto _EmitAvxM; + } + break; + + case kX86InstEncodingIdAvxGatherEx: + if (encoded == ENC_OPS(Reg, Mem, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o2)); + rmMem = x86OpMem(o1); + + uint32_t vSib = rmMem->getVSib(); + if (vSib == kX86MemVSibGpz) + goto _IllegalInst; + + ADD_VEX_L(vSib == kX86MemVSibYmm); + goto _EmitAvxV; + } + break; + + case kX86InstEncodingIdAvxGather: + if (encoded == ENC_OPS(Reg, Mem, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o2)); + rmMem = x86OpMem(o1); + + uint32_t vSib = rmMem->getVSib(); + if (vSib == kX86MemVSibGpz) + goto _IllegalInst; + + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o2)->isYmm()); + goto _EmitAvxV; + } + break; + + // ------------------------------------------------------------------------ + // [FMA4] + // ------------------------------------------------------------------------ + + case kX86InstEncodingIdFma4_P: + // It's fine to just check the first operand, second is just for sanity. + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdFma4: + if (encoded == ENC_OPS(Reg, Reg, Reg) && o3->isReg()) { + imVal = x86OpReg(o3) << 4; + imLen = 1; + + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmReg = x86OpReg(o2); + + goto _EmitAvxR; + } + + if (encoded == ENC_OPS(Reg, Reg, Reg) && o3->isMem()) { + imVal = x86OpReg(o2) << 4; + imLen = 1; + + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmMem = x86OpMem(o3); + + ADD_VEX_W(true); + goto _EmitAvxM; + } + + if (encoded == ENC_OPS(Reg, Reg, Mem) && o3->isReg()) { + imVal = x86OpReg(o3) << 4; + imLen = 1; + + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmMem = x86OpMem(o2); + + goto _EmitAvxM; + } + break; + + // ------------------------------------------------------------------------ + // [XOP] + // ------------------------------------------------------------------------ + + case kX86InstEncodingIdXopRm_P: + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdXopRm: + if (encoded == ENC_OPS(Reg, Reg, None)) { + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitXopR; + } + + if (encoded == ENC_OPS(Reg, Mem, None)) { + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitXopM; + } + break; + + case kX86InstEncodingIdXopRvmRmv: + if (encoded == ENC_OPS(Reg, Reg, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o2)); + rmReg = x86OpReg(o1); + + goto _EmitXopR; + } + + if (encoded == ENC_OPS(Reg, Mem, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o2)); + rmMem = x86OpMem(o1); + + goto _EmitXopM; + } + + if (encoded == ENC_OPS(Reg, Reg, Mem)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmMem = x86OpMem(o2); + + ADD_VEX_W(true); + goto _EmitXopM; + } + + break; + + case kX86InstEncodingIdXopRvmRmi: + if (encoded == ENC_OPS(Reg, Reg, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o2)); + rmReg = x86OpReg(o1); + goto _EmitXopR; + } + + if (encoded == ENC_OPS(Reg, Mem, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o2)); + rmMem = x86OpMem(o1); + + goto _EmitXopM; + } + + if (encoded == ENC_OPS(Reg, Reg, Mem)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmMem = x86OpMem(o2); + + ADD_VEX_W(true); + goto _EmitXopM; + } + + // The following instructions use the secondary opcode. + opCode = extendedInfo.getSecondaryOpCode(); + + imVal = static_cast(o2)->getInt64(); + imLen = 1; + + if (encoded == ENC_OPS(Reg, Reg, Imm)) { + opReg = x86OpReg(o0); + rmReg = x86OpReg(o1); + goto _EmitXopR; + } + + if (encoded == ENC_OPS(Reg, Mem, Imm)) { + opReg = x86OpReg(o0); + rmMem = x86OpMem(o1); + goto _EmitXopM; + } + break; + + case kX86InstEncodingIdXopRvmr_P: + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdXopRvmr: + if (!o3->isReg()) + goto _IllegalInst; + + imVal = x86OpReg(o3) << 4; + imLen = 1; + + if (encoded == ENC_OPS(Reg, Reg, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmReg = x86OpReg(o2); + goto _EmitXopR; + } + + if (encoded == ENC_OPS(Reg, Reg, Mem)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmMem = x86OpMem(o2); + goto _EmitXopM; + } + break; + + case kX86InstEncodingIdXopRvmi_P: + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdXopRvmi: + if (!o3->isImm()) + goto _IllegalInst; + + imVal = static_cast(o3)->getInt64(); + imLen = 1; + + if (encoded == ENC_OPS(Reg, Reg, Reg)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmReg = x86OpReg(o2); + goto _EmitXopR; + } + + if (encoded == ENC_OPS(Reg, Reg, Mem)) { + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmMem = x86OpMem(o2); + goto _EmitXopM; + } + break; + + case kX86InstEncodingIdXopRvrmRvmr_P: + ADD_VEX_L(static_cast(o0)->isYmm() | static_cast(o1)->isYmm()); + // ... Fall through ... + + case kX86InstEncodingIdXopRvrmRvmr: + if (encoded == ENC_OPS(Reg, Reg, Reg) && o3->isReg()) { + imVal = x86OpReg(o3) << 4; + imLen = 1; + + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmReg = x86OpReg(o2); + + goto _EmitXopR; + } + + if (encoded == ENC_OPS(Reg, Reg, Reg) && o3->isMem()) { + imVal = x86OpReg(o2) << 4; + imLen = 1; + + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmMem = x86OpMem(o3); + + ADD_VEX_W(true); + goto _EmitXopM; + } + + if (encoded == ENC_OPS(Reg, Reg, Mem) && o3->isReg()) { + imVal = x86OpReg(o3) << 4; + imLen = 1; + + opReg = x86RegAndVvvv(x86OpReg(o0), x86OpReg(o1)); + rmMem = x86OpMem(o2); + + goto _EmitXopM; + } + break; + } + + // -------------------------------------------------------------------------- + // [Illegal] + // -------------------------------------------------------------------------- + +_IllegalInst: + self->setError(kErrorIllegalInst); +#if defined(ASMJIT_DEBUG) + assertIllegal = true; +#endif // ASMJIT_DEBUG + goto _EmitDone; + +_IllegalAddr: + self->setError(kErrorIllegalAddresing); +#if defined(ASMJIT_DEBUG) + assertIllegal = true; +#endif // ASMJIT_DEBUG + goto _EmitDone; + +_IllegalDisp: + self->setError(kErrorIllegalDisplacement); +#if defined(ASMJIT_DEBUG) + assertIllegal = true; +#endif // ASMJIT_DEBUG + goto _EmitDone; + + // -------------------------------------------------------------------------- + // [Emit - X86] + // -------------------------------------------------------------------------- + +_EmitX86Op: + // Mandatory instruction prefix. + EMIT_PP(opCode); + + // Rex prefix (64-bit only). + if (Arch == kArchX64) { + uint32_t rex = x86RexFromOpCodeAndOptions(opCode, options); + + if (rex) { + rex |= kX86ByteRex; + EMIT_BYTE(rex); + + if (x86RexIsInvalid(rex)) + goto _IllegalInst; + } + } + + // Instruction opcodes. + EMIT_MM(opCode); + EMIT_OP(opCode); + + if (imLen != 0) + goto _EmitImm; + else + goto _EmitDone; + +_EmitX86OpWithOpReg: + // Mandatory instruction prefix. + EMIT_PP(opCode); + + // Rex prefix (64-bit only). + if (Arch == kArchX64) { + uint32_t rex = x86RexFromOpCodeAndOptions(opCode, options); + + rex += (opReg >> 3); // Rex.B (0x01). + + if (rex) { + rex |= kX86ByteRex; + opReg &= 0x7; + EMIT_BYTE(rex); + + if (x86RexIsInvalid(rex)) + goto _IllegalInst; + } + } + + // Instruction opcodes. + opCode += opReg; + EMIT_MM(opCode); + EMIT_OP(opCode); + + if (imLen != 0) + goto _EmitImm; + else + goto _EmitDone; + +_EmitX86R: + // Mandatory instruction prefix. + EMIT_PP(opCode); + + // Rex prefix (64-bit only). + if (Arch == kArchX64) { + uint32_t rex = x86RexFromOpCodeAndOptions(opCode, options); + + rex += static_cast(opReg & 0x08) >> 1; // Rex.R (0x04). + rex += static_cast(rmReg) >> 3; // Rex.B (0x01). + + if (rex) { + rex |= kX86ByteRex; + opReg &= 0x7; + rmReg &= 0x7; + EMIT_BYTE(rex); + + if (x86RexIsInvalid(rex)) + goto _IllegalInst; + } + } + + // Instruction opcodes. + EMIT_MM(opCode); + EMIT_OP(opCode); + + // ModR. + EMIT_BYTE(x86EncodeMod(3, opReg, static_cast(rmReg))); + + if (imLen != 0) + goto _EmitImm; + else + goto _EmitDone; + +_EmitX86M: + ASMJIT_ASSERT(rmMem != NULL); + ASMJIT_ASSERT(rmMem->getOp() == kOperandTypeMem); + + mBase = rmMem->getBase(); + mIndex = rmMem->getIndex(); + + // Size override prefix. + if (rmMem->hasBaseOrIndex() && rmMem->getMemType() != kMemTypeLabel) { + if (Arch == kArchX86) { + if (!rmMem->hasGpdBase()) + EMIT_BYTE(0x67); + } + else { + if (rmMem->hasGpdBase()) + EMIT_BYTE(0x67); + } + } + + // Segment override prefix. + if (rmMem->hasSegment()) { + EMIT_BYTE(x86SegmentPrefix[rmMem->getSegment()]); + } + + // Mandatory instruction prefix. + EMIT_PP(opCode); + + // Rex prefix (64-bit only). + if (Arch == kArchX64) { + uint32_t rex = x86RexFromOpCodeAndOptions(opCode, options); + + rex += static_cast(opReg & 8) >> 1; // Rex.R (0x04). + rex += static_cast(mIndex - 8 < 8) << 1; // Rex.X (0x02). + rex += static_cast(mBase - 8 < 8); // Rex.B (0x01). + + if (rex) { + rex |= kX86ByteRex; + opReg &= 0x7; + EMIT_BYTE(rex); + + if (x86RexIsInvalid(rex)) + goto _IllegalInst; + } + + mBase &= 0x7; + } + + // Instruction opcodes. + EMIT_MM(opCode); + EMIT_OP(opCode); + // ... Fall through ... + + // -------------------------------------------------------------------------- + // [Emit - SIB] + // -------------------------------------------------------------------------- + +_EmitSib: + dispOffset = rmMem->getDisplacement(); + if (rmMem->isBaseIndexType()) { + if (mIndex >= kInvalidReg) { + if (mBase == kX86RegIndexSp) { + if (dispOffset == 0) { + // [Esp/Rsp/R12]. + EMIT_BYTE(x86EncodeMod(0, opReg, 4)); + EMIT_BYTE(x86EncodeSib(0, 4, 4)); + } + else if (IntUtil::isInt8(dispOffset)) { + // [Esp/Rsp/R12 + Disp8]. + EMIT_BYTE(x86EncodeMod(1, opReg, 4)); + EMIT_BYTE(x86EncodeSib(0, 4, 4)); + EMIT_BYTE(static_cast(dispOffset)); + } + else { + // [Esp/Rsp/R12 + Disp32]. + EMIT_BYTE(x86EncodeMod(2, opReg, 4)); + EMIT_BYTE(x86EncodeSib(0, 4, 4)); + EMIT_DWORD(static_cast(dispOffset)); + } + } + else if (mBase != kX86RegIndexBp && dispOffset == 0) { + // [Base]. + EMIT_BYTE(x86EncodeMod(0, opReg, mBase)); + } + else if (IntUtil::isInt8(dispOffset)) { + // [Base + Disp8]. + EMIT_BYTE(x86EncodeMod(1, opReg, mBase)); + EMIT_BYTE(static_cast(dispOffset)); + } + else { + // [Base + Disp32]. + EMIT_BYTE(x86EncodeMod(2, opReg, mBase)); + EMIT_DWORD(static_cast(dispOffset)); + } + } + else { + uint32_t shift = rmMem->getShift(); + + // Esp/Rsp/R12 register can't be used as an index. + mIndex &= 0x7; + ASMJIT_ASSERT(mIndex != kX86RegIndexSp); + + if (mBase != kX86RegIndexBp && dispOffset == 0) { + // [Base + Index * Scale]. + EMIT_BYTE(x86EncodeMod(0, opReg, 4)); + EMIT_BYTE(x86EncodeSib(shift, mIndex, mBase)); + } + else if (IntUtil::isInt8(dispOffset)) { + // [Base + Index * Scale + Disp8]. + EMIT_BYTE(x86EncodeMod(1, opReg, 4)); + EMIT_BYTE(x86EncodeSib(shift, mIndex, mBase)); + EMIT_BYTE(static_cast(dispOffset)); + } + else { + // [Base + Index * Scale + Disp32]. + EMIT_BYTE(x86EncodeMod(2, opReg, 4)); + EMIT_BYTE(x86EncodeSib(shift, mIndex, mBase)); + EMIT_DWORD(static_cast(dispOffset)); + } + } + } + else if (Arch == kArchX86) { + if (mIndex >= kInvalidReg) { + // [Disp32]. + EMIT_BYTE(x86EncodeMod(0, opReg, 5)); + } + else { + // [Index * Scale + Disp32]. + uint32_t shift = rmMem->getShift(); + ASMJIT_ASSERT(mIndex != kX86RegIndexSp); + + EMIT_BYTE(x86EncodeMod(0, opReg, 4)); + EMIT_BYTE(x86EncodeSib(shift, mIndex, 5)); + } + + if (rmMem->getMemType() == kMemTypeLabel) { + // Relative->Absolute [x86 mode]. + label = self->getLabelData(rmMem->_vmem.base); + relocId = self->_relocList.getLength(); + + { + RelocData rd; + rd.type = kRelocRelToAbs; + rd.size = 4; + rd.from = static_cast((uintptr_t)(cursor - self->_buffer)); + rd.data = static_cast(dispOffset); + + if (self->_relocList.append(rd) != kErrorOk) + return self->setError(kErrorNoHeapMemory); + } + + if (label->offset != -1) { + // Bound label. + self->_relocList[relocId].data += static_cast(label->offset); + EMIT_DWORD(0); + } + else { + // Non-bound label. + dispOffset = -4 - imLen; + dispSize = 4; + goto _EmitDisplacement; + } + } + else { + // [Disp32]. + EMIT_DWORD(static_cast(dispOffset)); + } + } + else /* if (Arch === kArchX64) */ { + if (rmMem->getMemType() == kMemTypeLabel) { + // [RIP + Disp32]. + label = self->getLabelData(rmMem->_vmem.base); + + // Indexing is invalid. + if (mIndex < kInvalidReg) + goto _IllegalDisp; + + EMIT_BYTE(x86EncodeMod(0, opReg, 5)); + dispOffset -= (4 + imLen); + + if (label->offset != -1) { + // Bound label. + dispOffset += label->offset - static_cast((intptr_t)(cursor - self->_buffer)); + EMIT_DWORD(static_cast(dispOffset)); + } + else { + // Non-bound label. + dispSize = 4; + relocId = -1; + goto _EmitDisplacement; + } + } + else { + EMIT_BYTE(x86EncodeMod(0, opReg, 4)); + if (mIndex >= kInvalidReg) { + // [Disp32]. + EMIT_BYTE(x86EncodeSib(0, 4, 5)); + } + else { + // [Disp32 + Index * Scale]. + mIndex &= 0x7; + ASMJIT_ASSERT(mIndex != kX86RegIndexSp); + + uint32_t shift = rmMem->getShift(); + EMIT_BYTE(x86EncodeSib(shift, mIndex, 5)); + } + + EMIT_DWORD(static_cast(dispOffset)); + } + } + + if (imLen == 0) + goto _EmitDone; + + // -------------------------------------------------------------------------- + // [Emit - Imm] + // -------------------------------------------------------------------------- + +_EmitImm: + switch (imLen) { + case 1: EMIT_BYTE (imVal & 0x000000FF); break; + case 2: EMIT_WORD (imVal & 0x0000FFFF); break; + case 4: EMIT_DWORD(imVal & 0xFFFFFFFF); break; + case 8: EMIT_QWORD(imVal ); break; + + default: + ASMJIT_ASSERT(!"Reached"); + } + goto _EmitDone; + + // -------------------------------------------------------------------------- + // [Emit - Fpu] + // -------------------------------------------------------------------------- + +_EmitFpuOp: + // Mandatory instruction prefix. + EMIT_PP(opCode); + + // Instruction opcodes. + EMIT_OP(opCode >> 8); + EMIT_OP(opCode); + goto _EmitDone; + + // -------------------------------------------------------------------------- + // [Emit - Avx] + // -------------------------------------------------------------------------- + +#define EMIT_AVX_M \ + ASMJIT_ASSERT(rmMem != NULL); \ + ASMJIT_ASSERT(rmMem->getOp() == kOperandTypeMem); \ + \ + if (rmMem->hasSegment()) { \ + EMIT_BYTE(x86SegmentPrefix[rmMem->getSegment()]); \ + } \ + \ + mBase = rmMem->getBase(); \ + mIndex = rmMem->getIndex(); \ + \ + { \ + uint32_t vex_XvvvvLpp; \ + uint32_t vex_rxbmmmmm; \ + \ + vex_XvvvvLpp = (opCode >> (kX86InstOpCode_W_Shift - 7)) & 0x80; \ + vex_XvvvvLpp += (opCode >> (kX86InstOpCode_L_Shift - 2)) & 0x04; \ + vex_XvvvvLpp += (opCode >> (kX86InstOpCode_PP_Shift )) & 0x03; \ + vex_XvvvvLpp += (opReg >> (kVexVVVVShift - 3)); \ + \ + vex_rxbmmmmm = (opCode >> kX86InstOpCode_MM_Shift) & 0x0F; \ + vex_rxbmmmmm |= static_cast(mBase - 8 < 8) << 5; \ + vex_rxbmmmmm |= static_cast(mIndex - 8 < 8) << 6; \ + \ + if (vex_rxbmmmmm != 0x01 || vex_XvvvvLpp >= 0x80 || (options & kX86InstOptionVex3) != 0) { \ + vex_rxbmmmmm |= static_cast(opReg << 4) & 0x80; \ + vex_rxbmmmmm ^= 0xE0; \ + vex_XvvvvLpp ^= 0x78; \ + \ + EMIT_BYTE(kX86ByteVex3); \ + EMIT_BYTE(vex_rxbmmmmm); \ + EMIT_BYTE(vex_XvvvvLpp); \ + EMIT_OP(opCode); \ + } \ + else { \ + vex_XvvvvLpp |= static_cast(opReg << 4) & 0x80; \ + vex_XvvvvLpp ^= 0xF8; \ + \ + EMIT_BYTE(kX86ByteVex2); \ + EMIT_BYTE(vex_XvvvvLpp); \ + EMIT_OP(opCode); \ + } \ + } \ + \ + mBase &= 0x7; \ + opReg &= 0x7; + +_EmitAvxOp: + { + uint32_t vex_XvvvvLpp; + + vex_XvvvvLpp = (opCode >> (kX86InstOpCode_L_Shift - 2)) & 0x04; + vex_XvvvvLpp |= (opCode >> (kX86InstOpCode_PP_Shift)); + vex_XvvvvLpp |= 0xF8; + + // Encode 3-byte VEX prefix only if specified in options. + if ((options & kX86InstOptionVex3) != 0) { + uint32_t vex_rxbmmmmm = (opCode >> kX86InstOpCode_MM_Shift) | 0xE0; + + EMIT_BYTE(kX86ByteVex3); + EMIT_OP(vex_rxbmmmmm); + EMIT_OP(vex_XvvvvLpp); + EMIT_OP(opCode); + } + else { + EMIT_BYTE(kX86ByteVex2); + EMIT_OP(vex_XvvvvLpp); + EMIT_OP(opCode); + } + } + goto _EmitDone; + +_EmitAvxR: + { + uint32_t vex_XvvvvLpp; + uint32_t vex_rxbmmmmm; + + vex_XvvvvLpp = (opCode >> (kX86InstOpCode_W_Shift - 7)) & 0x80; + vex_XvvvvLpp += (opCode >> (kX86InstOpCode_L_Shift - 2)) & 0x04; + vex_XvvvvLpp += (opCode >> (kX86InstOpCode_PP_Shift )) & 0x03; + vex_XvvvvLpp += (opReg >> (kVexVVVVShift - 3)); + + vex_rxbmmmmm = (opCode >> kX86InstOpCode_MM_Shift) & 0x0F; + vex_rxbmmmmm |= (rmReg << 2) & 0x20; + + if (vex_rxbmmmmm != 0x01 || vex_XvvvvLpp >= 0x80 || (options & kX86InstOptionVex3) != 0) { + vex_rxbmmmmm |= static_cast(opReg & 0x08) << 4; + vex_rxbmmmmm ^= 0xE0; + vex_XvvvvLpp ^= 0x78; + + EMIT_BYTE(kX86ByteVex3); + EMIT_OP(vex_rxbmmmmm); + EMIT_OP(vex_XvvvvLpp); + EMIT_OP(opCode); + + rmReg &= 0x07; + } + else { + vex_XvvvvLpp += static_cast(opReg & 0x08) << 4; + vex_XvvvvLpp ^= 0xF8; + + EMIT_BYTE(kX86ByteVex2); + EMIT_OP(vex_XvvvvLpp); + EMIT_OP(opCode); + } + } + + EMIT_BYTE(x86EncodeMod(3, opReg, static_cast(rmReg))); + + if (imLen == 0) + goto _EmitDone; + + EMIT_BYTE(imVal & 0xFF); + goto _EmitDone; + +_EmitAvxM: + EMIT_AVX_M + goto _EmitSib; + +_EmitAvxV: + EMIT_AVX_M + + if (mIndex >= kInvalidReg) + goto _IllegalInst; + + if (Arch == kArchX64) + mIndex &= 0x7; + + dispOffset = rmMem->getDisplacement(); + if (rmMem->isBaseIndexType()) { + uint32_t shift = rmMem->getShift(); + + if (mBase != kX86RegIndexBp && dispOffset == 0) { + // [Base + Index * Scale]. + EMIT_BYTE(x86EncodeMod(0, opReg, 4)); + EMIT_BYTE(x86EncodeSib(shift, mIndex, mBase)); + } + else if (IntUtil::isInt8(dispOffset)) { + // [Base + Index * Scale + Disp8]. + EMIT_BYTE(x86EncodeMod(1, opReg, 4)); + EMIT_BYTE(x86EncodeSib(shift, mIndex, mBase)); + EMIT_BYTE(static_cast(dispOffset)); + } + else { + // [Base + Index * Scale + Disp32]. + EMIT_BYTE(x86EncodeMod(2, opReg, 4)); + EMIT_BYTE(x86EncodeSib(shift, mIndex, mBase)); + EMIT_DWORD(static_cast(dispOffset)); + } + } + else { + // [Index * Scale + Disp32]. + uint32_t shift = rmMem->getShift(); + + EMIT_BYTE(x86EncodeMod(0, opReg, 4)); + EMIT_BYTE(x86EncodeSib(shift, mIndex, 5)); + + if (rmMem->getMemType() == kMemTypeLabel) { + if (Arch == kArchX64) + goto _IllegalAddr; + + // Relative->Absolute [x86 mode]. + label = self->getLabelData(rmMem->_vmem.base); + relocId = self->_relocList.getLength(); + + { + RelocData rd; + rd.type = kRelocRelToAbs; + rd.size = 4; + rd.from = static_cast((uintptr_t)(cursor - self->_buffer)); + rd.data = static_cast(dispOffset); + + if (self->_relocList.append(rd) != kErrorOk) + return self->setError(kErrorNoHeapMemory); + } + + if (label->offset != -1) { + // Bound label. + self->_relocList[relocId].data += static_cast(label->offset); + EMIT_DWORD(0); + } + else { + // Non-bound label. + dispOffset = -4 - imLen; + dispSize = 4; + goto _EmitDisplacement; + } + } + else { + // [Disp32]. + EMIT_DWORD(static_cast(dispOffset)); + } + } + goto _EmitDone; + + // -------------------------------------------------------------------------- + // [Xop] + // -------------------------------------------------------------------------- + +#define EMIT_XOP_M \ + ASMJIT_ASSERT(rmMem != NULL); \ + ASMJIT_ASSERT(rmMem->getOp() == kOperandTypeMem); \ + \ + if (rmMem->hasSegment()) { \ + EMIT_BYTE(x86SegmentPrefix[rmMem->getSegment()]); \ + } \ + \ + mBase = rmMem->getBase(); \ + mIndex = rmMem->getIndex(); \ + \ + { \ + uint32_t vex_XvvvvLpp; \ + uint32_t vex_rxbmmmmm; \ + \ + vex_XvvvvLpp = (opCode >> (kX86InstOpCode_W_Shift - 7)) & 0x80; \ + vex_XvvvvLpp += (opCode >> (kX86InstOpCode_L_Shift - 2)) & 0x04; \ + vex_XvvvvLpp += (opCode >> (kX86InstOpCode_PP_Shift )) & 0x03; \ + vex_XvvvvLpp += (opReg >> (kVexVVVVShift - 3)); \ + \ + vex_rxbmmmmm = (opCode >> kX86InstOpCode_MM_Shift) & 0x0F; \ + vex_rxbmmmmm += static_cast(mBase - 8 < 8) << 5; \ + vex_rxbmmmmm += static_cast(mIndex - 8 < 8) << 6; \ + \ + vex_rxbmmmmm |= static_cast(opReg << 4) & 0x80; \ + vex_rxbmmmmm ^= 0xE0; \ + vex_XvvvvLpp ^= 0x78; \ + \ + EMIT_BYTE(kX86ByteXop3); \ + EMIT_BYTE(vex_rxbmmmmm); \ + EMIT_BYTE(vex_XvvvvLpp); \ + EMIT_OP(opCode); \ + } \ + \ + mBase &= 0x7; \ + opReg &= 0x7; + +_EmitXopR: + { + uint32_t xop_XvvvvLpp; + uint32_t xop_rxbmmmmm; + + xop_XvvvvLpp = (opCode >> (kX86InstOpCode_W_Shift - 7)) & 0x80; + xop_XvvvvLpp += (opCode >> (kX86InstOpCode_L_Shift - 2)) & 0x04; + xop_XvvvvLpp += (opCode >> (kX86InstOpCode_PP_Shift )) & 0x03; + xop_XvvvvLpp += (opReg >> (kVexVVVVShift - 3)); + + xop_rxbmmmmm = (opCode >> kX86InstOpCode_MM_Shift) & 0x0F; + xop_rxbmmmmm |= (rmReg << 2) & 0x20; + + xop_rxbmmmmm |= static_cast(opReg & 0x08) << 4; + xop_rxbmmmmm ^= 0xE0; + xop_XvvvvLpp ^= 0x78; + + EMIT_BYTE(kX86ByteXop3); + EMIT_OP(xop_rxbmmmmm); + EMIT_OP(xop_XvvvvLpp); + EMIT_OP(opCode); + + rmReg &= 0x07; + } + + EMIT_BYTE(x86EncodeMod(3, opReg, static_cast(rmReg))); + + if (imLen == 0) + goto _EmitDone; + + EMIT_BYTE(imVal & 0xFF); + goto _EmitDone; + +_EmitXopM: + EMIT_XOP_M + goto _EmitSib; + + // -------------------------------------------------------------------------- + // [Emit - Jump/Call to an Immediate] + // -------------------------------------------------------------------------- + + // 64-bit mode requires a trampoline if a relative displacement doesn't fit + // into a 32-bit address. Old version of AsmJit used to emit jump to a section + // which contained another jump followed by an address (it worked well for + // both `jmp` and `call`), but it required to reserve 14-bytes for a possible + // trampoline. + // + // Instead of using 5-byte `jmp/call` and reserving 14 bytes required by the + // trampoline, it's better to use 6-byte `jmp/call` (prefixing it with REX + // prefix) and to patch the `jmp/call` instruction to read the address from + // a memory in case the trampoline is needed. + // +_EmitJmpOrCallAbs: + { + RelocData rd; + rd.type = kRelocAbsToRel; + rd.size = 4; + rd.from = (intptr_t)(cursor - self->_buffer) + 1; + rd.data = static_cast(imVal); + + uint32_t trampolineSize = 0; + + if (Arch == kArchX64) { + Ptr baseAddress = self->getBaseAddress(); + + // If the base address of the output is known, it's possible to determine + // the need for a trampoline here. This saves possible REX prefix in + // 64-bit mode and prevents reserving space needed for an absolute address. + if (baseAddress == kNoBaseAddress || !x64IsRelative(rd.data, baseAddress + rd.from + 4)) { + // Emit REX prefix so the instruction can be patched later on. The REX + // prefix does nothing if not patched after, but allows to patch the + // instruction in case where the trampoline is needed. + rd.type = kRelocTrampoline; + rd.from++; + + EMIT_BYTE(kX86ByteRex); + trampolineSize = 8; + } + } + + // Both `jmp` and `call` instructions have a single-byte opcode and are + // followed by a 32-bit displacement. + EMIT_OP(opCode); + EMIT_DWORD(0); + + if (self->_relocList.append(rd) != kErrorOk) + return self->setError(kErrorNoHeapMemory); + + // Reserve space for a possible trampoline. + self->_trampolineSize += trampolineSize; + } + goto _EmitDone; + + // -------------------------------------------------------------------------- + // [Emit - Displacement] + // -------------------------------------------------------------------------- + +_EmitDisplacement: + { + ASMJIT_ASSERT(label->offset == -1); + ASMJIT_ASSERT(dispSize == 1 || dispSize == 4); + + // Chain with label. + LabelLink* link = self->_newLabelLink(); + link->prev = label->links; + link->offset = (intptr_t)(cursor - self->_buffer); + link->displacement = dispOffset; + link->relocId = relocId; + label->links = link; + + // Emit label size as dummy data. + if (dispSize == 1) + EMIT_BYTE(0x01); + else // if (dispSize == 4) + EMIT_DWORD(0x04040404); + + if (imLen != 0) + goto _EmitImm; + } + + // -------------------------------------------------------------------------- + // [Logging] + // -------------------------------------------------------------------------- + +_EmitDone: +#if !defined(ASMJIT_DISABLE_LOGGER) +# if defined(ASMJIT_DEBUG) + if (self->_logger || assertIllegal) { +# else + if (self->_logger) { +# endif // ASMJIT_DEBUG + StringBuilderT<512> sb; + uint32_t loggerOptions = 0; + + if (self->_logger) { + sb.appendString(self->_logger->getIndentation()); + loggerOptions = self->_logger->getOptions(); + } + + X86Assembler_dumpInstruction(sb, Arch, code, options, o0, o1, o2, o3, loggerOptions); + + if ((loggerOptions & (1 << kLoggerOptionBinaryForm)) != 0) + X86Assembler_dumpComment(sb, sb.getLength(), self->_cursor, (intptr_t)(cursor - self->_cursor), dispSize, imLen, self->_comment); + else + X86Assembler_dumpComment(sb, sb.getLength(), NULL, 0, 0, 0, self->_comment); + +# if defined(ASMJIT_DEBUG) + if (self->_logger) +# endif // ASMJIT_DEBUG + self->_logger->logString(kLoggerStyleDefault, sb.getData(), sb.getLength()); + +# if defined(ASMJIT_DEBUG) + // Raise an assertion failure, because this situation shouldn't happen. + if (assertIllegal) + assertionFailed(sb.getData(), __FILE__, __LINE__); +# endif // ASMJIT_DEBUG + } +#else +# if defined(ASMJIT_DEBUG) + ASMJIT_ASSERT(!assertIllegal); +# endif // ASMJIT_DEBUG +#endif // !ASMJIT_DISABLE_LOGGER + + self->_comment = NULL; + self->setCursor(cursor); + + return kErrorOk; + +_GrowBuffer: + ASMJIT_PROPAGATE_ERROR(self->_grow(16)); + + cursor = self->getCursor(); + goto _Prepare; +} + +Error X86Assembler::_emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, const Operand& o3) { +#if defined(ASMJIT_BUILD_X86) && !defined(ASMJIT_BUILD_X64) + return X86Assembler_emit(this, code, &o0, &o1, &o2, &o3); +#elif !defined(ASMJIT_BUILD_X86) && defined(ASMJIT_BUILD_X64) + return X86Assembler_emit(this, code, &o0, &o1, &o2, &o3); +#else + if (_arch == kArchX86) + return X86Assembler_emit(this, code, &o0, &o1, &o2, &o3); + else + return X86Assembler_emit(this, code, &o0, &o1, &o2, &o3); +#endif +} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64 diff --git a/third/Blackbone/src/3rd_party/AsmJit/x86/x86assembler.h b/third/Blackbone/src/3rd_party/AsmJit/x86/x86assembler.h new file mode 100644 index 0000000000000000000000000000000000000000..715eb73fea8f3eb055b86e84c06b8f87f648ccf1 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/x86/x86assembler.h @@ -0,0 +1,6680 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Guard] +#ifndef _ASMJIT_X86_X86ASSEMBLER_H +#define _ASMJIT_X86_X86ASSEMBLER_H + +// [Dependencies - AsmJit] +#include "../base/assembler.h" +#include "../x86/x86inst.h" +#include "../x86/x86operand.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +//! \addtogroup asmjit_x86_general +//! \{ + +// ============================================================================ +// [asmjit::X86Assembler] +// ============================================================================ + +// \internal +#define ASMJIT_X86_EMIT_OPTIONS(_Class_) \ + /*! Force short form of jmp/jcc instruction. */ \ + ASMJIT_INLINE _Class_& short_() { \ + _instOptions |= kInstOptionShortForm; \ + return *this; \ + } \ + \ + /*! Force long form of jmp/jcc instruction. */ \ + ASMJIT_INLINE _Class_& long_() { \ + _instOptions |= kInstOptionLongForm; \ + return *this; \ + } \ + \ + /*! Condition is likely to be taken (has only benefit on P4). */ \ + ASMJIT_INLINE _Class_& taken() { \ + _instOptions |= kInstOptionTaken; \ + return *this; \ + } \ + \ + /*! Condition is unlikely to be taken (has only benefit on P4). */ \ + ASMJIT_INLINE _Class_& notTaken() { \ + _instOptions |= kInstOptionNotTaken; \ + return *this; \ + } \ + \ + /*! Use LOCK prefix. */ \ + ASMJIT_INLINE _Class_& lock() { \ + _instOptions |= kX86InstOptionLock; \ + return *this; \ + } \ + \ + /*! Force REX prefix (X64). */ \ + ASMJIT_INLINE _Class_& rex() { \ + _instOptions |= kX86InstOptionRex; \ + return *this; \ + } \ + \ + /*! Force 3-byte VEX prefix (AVX+). */ \ + ASMJIT_INLINE _Class_& vex3() { \ + _instOptions |= kX86InstOptionVex3; \ + return *this; \ + } \ + \ + /*! Force 4-byte EVEX prefix (AVX512+). */ \ + ASMJIT_INLINE _Class_& evex() { \ + _instOptions |= kX86InstOptionEvex; \ + return *this; \ + } \ + \ + /*! Use zeroing instead of merging (AVX512+). */ \ + ASMJIT_INLINE _Class_& z() { \ + _instOptions |= kX86InstOptionEvexZero; \ + return *this; \ + } \ + \ + /*! Broadcast one element to all other elements (AVX512+). */ \ + ASMJIT_INLINE _Class_& _1ToN() { \ + _instOptions |= kX86InstOptionEvexOneN; \ + return *this; \ + } \ + \ + /*! Suppress all exceptions (AVX512+). */ \ + ASMJIT_INLINE _Class_& sae() { \ + _instOptions |= kX86InstOptionEvexSae; \ + return *this; \ + } \ + \ + /*! Static rounding mode `round-to-nearest` (even) and `SAE` (AVX512+). */ \ + ASMJIT_INLINE _Class_& rn_sae() { \ + _instOptions |= kX86InstOptionEvexRnSae; \ + return *this; \ + } \ + \ + /*! Static rounding mode `round-down` (toward -inf) and `SAE` (AVX512+). */ \ + ASMJIT_INLINE _Class_& rd_sae() { \ + _instOptions |= kX86InstOptionEvexRdSae; \ + return *this; \ + } \ + \ + /*! Static rounding mode `round-up` (toward +inf) and `SAE` (AVX512+). */ \ + ASMJIT_INLINE _Class_& ru_sae() { \ + _instOptions |= kX86InstOptionEvexRuSae; \ + return *this; \ + } \ + \ + /*! Static rounding mode `round-toward-zero` (truncate) and `SAE` (AVX512+). */ \ + ASMJIT_INLINE _Class_& rz_sae() { \ + _instOptions |= kX86InstOptionEvexRzSae; \ + return *this; \ + } + +//! X86/X64 assembler. +//! +//! Assembler is the main class in AsmJit that can encode instructions and their +//! operands to a binary stream runnable by CPU. It creates internal buffer +//! where the encodes instructions are stored and it contains intrinsics that +//! can be used to emit the code in a convenent way. Code generation is in +//! general safe, because the intrinsics uses method overloading so even the +//! code is emitted it can be checked by a C++ compiler. It's nearly impossible +//! to create invalid instruction, for example `mov [eax], [eax]`, because such +//! overload doesn't exist. +//! +//! Each call to an assembler intrinsic function emits instruction directly +//! to the binary stream. There are also runtime checks that prevent invalid +//! code to be emitted. It will assert in debug mode and put the `Assembler` +//! instance to an error state in production mode. +//! +//! Code Generation +//! --------------- +//! +//! To generate code is only needed to create instance of `Assembler` +//! and to use intrinsics. See example how to do that: +//! +//! ~~~ +//! // Use asmjit namespace. +//! using namespace asmjit; +//! using namespace asmjit::x86; +//! +//! // Create X86Assembler instance. +//! X86Assembler a; +//! +//! // Prolog. +//! a.push(ebp); +//! a.mov(ebp, esp); +//! +//! // Mov 1024 to EAX, EAX is also return value. +//! a.mov(eax, 1024); +//! +//! // Epilog. +//! a.mov(esp, ebp); +//! a.pop(ebp); +//! +//! // Return. +//! a.ret(); +//! ~~~ +//! +//! You can see that syntax is very close to Intel one. Only difference is that +//! you are calling functions that emit binary code for you. All registers are +//! in `asmjit::x86` namespace, so it's very comfortable to use it (look at the +//! `use namespace` section). Without importing `asmjit::x86` registers would +//! have to be written as `x86::eax`, `x86::esp`, and so on. +//! +//! There is also possibility to use memory addresses and immediates. Use +//! `ptr()`, `byte_ptr()`, `word_ptr()`, `dword_ptr()` and similar functions to +//! build a memory address operand. In most cases `ptr()` is enough, because an +//! information related to the operand size is needed only in rare cases, that +//! is an instruction without having any register operands, such as `inc [mem]`. +//! +//! for example, `a` is an `X86Assembler` instance: +//! +//! ~~~ +//! a.mov(ptr(eax), 0); // mov ptr [eax], 0 +//! a.mov(ptr(eax), edx); // mov ptr [eax], edx +//! ~~~ +//! +//! But it's also possible to create complex addresses offered by x86 architecture: +//! +//! ~~~ +//! // eax + ecx*x addresses +//! a.mov(ptr(eax, ecx, 0), 0); // mov ptr [eax + ecx], 0 +//! a.mov(ptr(eax, ecx, 1), 0); // mov ptr [eax + ecx * 2], 0 +//! a.mov(ptr(eax, ecx, 2), 0); // mov ptr [eax + ecx * 4], 0 +//! a.mov(ptr(eax, ecx, 3), 0); // mov ptr [eax + ecx * 8], 0 +//! // eax + ecx*x + disp addresses +//! a.mov(ptr(eax, ecx, 0, 4), 0); // mov ptr [eax + ecx + 4], 0 +//! a.mov(ptr(eax, ecx, 1, 8), 0); // mov ptr [eax + ecx * 2 + 8], 0 +//! a.mov(ptr(eax, ecx, 2, 12), 0); // mov ptr [eax + ecx * 4 + 12], 0 +//! a.mov(ptr(eax, ecx, 3, 16), 0); // mov ptr [eax + ecx * 8 + 16], 0 +//! ~~~ +//! +//! All addresses shown are using `x86::ptr()` to make memory operand. Some +//! assembler instructions using a single operand need to know the size of +//! the operand to avoid ambiguity. For example `a.inc(ptr(eax))` is ambiguous +//! and would cause a runtime error. This problem can be fixed by using memory +//! operand with size specified - `byte_ptr`, `word_ptr`, `dword_ptr`, see the +//! code below: +//! +//! ~~~ +//! // [byte] address. +//! a.inc(byte_ptr(eax)); // Inc byte ptr [eax]. +//! a.dec(byte_ptr(eax)); // Dec byte ptr [eax]. +//! // [word] address. +//! a.inc(word_ptr(eax)); // Inc word ptr [eax]. +//! a.dec(word_ptr(eax)); // Dec word ptr [eax]. +//! // [dword] address. +//! a.inc(dword_ptr(eax)); // Inc dword ptr [eax]. +//! a.dec(dword_ptr(eax)); // Dec dword ptr [eax]. +//! // [dword] address. +//! a.inc(dword_ptr(rax)); // Inc qword ptr [rax]. +//! a.dec(dword_ptr(rax)); // Dec qword ptr [rax]. +//! ~~~ +//! +//! Calling JIT Code +//! ---------------- +//! +//! After you are finished with emitting instructions, you can make your function +//! callable by using `Assembler::make()` method. This method will use memory +//! manager to allocate virtual memory and relocates generated code to it. The +//! memory is allocated through `Runtime` instance provided to `X86Assembler` +//! constructor. +//! +//! The size of the code generated can be retrieved by `getCodeSize()` and +//! `getOffset()` methods. The `getOffset()` method returns the current offset +//! (that is mostly equal to the final code size, if called after the code +//! generation) and `getCodeSize()` returns the final code size with possible +//! trampolines. The `takeCode()` method can be used to take the internal buffer +//! and reset the code generator, but the buffer returned has to be freed manually +//! in such case. +//! +//! Machine code can be executed only in memory that is marked executable. This +//! mark is usually not set for memory returned by a C/C++ `malloc()` function. +//! The `VMemUtil::alloc()` function can be used allocate a memory where the code +//! can be executed. Please note that `VMemUtil` is a low-level class that works +//! at memory page level. High level interface that is similar to malloc/free is +//! provided by `VMemMgr` class. +//! +//! The next example shows how to allocate memory where the code can be executed: +//! +//! ~~~ +//! using namespace asmjit; +//! +//! JitRuntime runtime; +//! X86Assembler a(&runtime); +//! +//! ... Code generation ... +//! +//! // The function prototype. +//! typedef void (*MyFunc)(); +//! +//! // Make the function. +//! MyFunc func = asmjit_cast(a.make()); +//! +//! // Call the function. +//! func(); +//! +//! // Release the function if not needed anymore. +//! runtime.release(func); +//! ~~~ +//! +//! This was a very primitive example showing how the generated code can be. +//! executed by using the foundation of classes AsmJit offers. In production +//! nobody is likely to generate a function that is only called once and freed +//! immediately after it's been called, however, the concept of releasing code +//! that is not needed anymore should be clear. +//! +//! Labels +//! ------ +//! +//! While generating assembler code, you will usually need to create complex +//! code with labels. Labels are fully supported and you can call `jmp` or +//! `je` (and similar) instructions to initialized or yet uninitialized label. +//! Each label expects to be bound into offset. To bind label to specific +//! offset, use `CodeGen::bind()` method. +//! +//! See next example that contains complete code that creates simple memory +//! copy function (in DWord entities). +//! +//! ~~~ +//! // Example: Usage of Label (32-bit code). +//! // +//! // Create simple DWord memory copy function: +//! // ASMJIT_STDCALL void copy32(uint32_t* dst, const uint32_t* src, size_t count); +//! using namespace asmjit; +//! +//! // Assembler instance. +//! JitRuntime runtime; +//! Assembler a(&runtime); +//! +//! // Constants. +//! const int arg_offset = 8; // Arguments offset (STDCALL EBP). +//! const int arg_size = 12; // Arguments size. +//! +//! // Labels. +//! Label L_Loop(a); +//! +//! // Prolog. +//! a.push(ebp); +//! a.mov(ebp, esp); +//! a.push(esi); +//! a.push(edi); +//! +//! // Fetch arguments +//! a.mov(esi, dword_ptr(ebp, arg_offset + 0)); // Get dst. +//! a.mov(edi, dword_ptr(ebp, arg_offset + 4)); // Get src. +//! a.mov(ecx, dword_ptr(ebp, arg_offset + 8)); // Get count. +//! +//! // Bind L_Loop label to here. +//! a.bind(L_Loop); +//! +//! Copy 4 bytes. +//! a.mov(eax, dword_ptr(esi)); +//! a.mov(dword_ptr(edi), eax); +//! +//! // Increment pointers. +//! a.add(esi, 4); +//! a.add(edi, 4); +//! +//! // Repeat loop until (--ecx != 0). +//! a.dec(ecx); +//! a.jz(L_Loop); +//! +//! // Epilog. +//! a.pop(edi); +//! a.pop(esi); +//! a.mov(esp, ebp); +//! a.pop(ebp); +//! +//! // Return: Pop the stack by `arg_size` as defined by `STDCALL` convention. +//! a.ret(arg_size); +//! ~~~ +//! +//! If you need more abstraction for generating assembler code and you want +//! to hide calling conventions between 32-bit and 64-bit operating systems, +//! look at `Compiler` class that is designed for higher level code +//! generation. +//! +//! Advanced Code Generation +//! ------------------------ +//! +//! This section describes some advanced generation features of `Assembler` +//! class which can be simply overlooked. The first thing that is very likely +//! needed is generic register support. In previous example the named registers +//! were used. AsmJit contains functions which can convert register index into +//! operand and back. +//! +//! Let's define function which can be used to generate some abstract code: +//! +//! ~~~ +//! // Simple function that generates dword copy. +//! void genCopyDWord(Assembler& a, const X86GpReg& dst, const X86GpReg& src, const X86GpReg& tmp) { +//! a.mov(tmp, dword_ptr(src)); +//! a.mov(dword_ptr(dst), tmp); +//! } +//! ~~~ +//! +//! This function can be called like `genCopyDWord(a, edi, esi, ebx)` or by +//! using existing `X86GpReg` instances. This abstraction allows to join more +//! code sections together without rewriting each to use specific registers. +//! You need to take care only about implicit registers which may be used by +//! several instructions (like mul, imul, div, idiv, shifting, etc...). +//! +//! Next, more advanced, but often needed technique is that you can build your +//! own registers allocator. X86 architecture contains 8 general purpose +//! registers, 8 Mm registers and 8 Xmm/Ymm/Zmm registers. X64 architecture +//! extends the count of Gp registers and Xmm/Ymm/Zmm registers to 16. AVX-512 +//! architecture extends Xmm/Ymm/Zmm SIMD registers to 32. +//! +//! To create a general purpose register operand from register index use +//! `gpb_lo()`, `gpb_hi()`, `gpw()`, `gpd()`, `gpq()`. To create registers of +//! other types there `fp()`, `mm()`, `k()`, `xmm()`, `ymm()` and `zmm()` +//! functions available that return a new register operand. +//! +//! \sa X86Compiler. +struct ASMJIT_VCLASS X86Assembler : public Assembler { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + ASMJIT_API X86Assembler(Runtime* runtime, uint32_t arch +#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64) + = kArchHost +#endif // ASMJIT_HOST_X86 || ASMJIT_HOST_X64 + ); + ASMJIT_API virtual ~X86Assembler(); + + // -------------------------------------------------------------------------- + // [Arch] + // -------------------------------------------------------------------------- + + //! Get count of registers of the current architecture and mode. + ASMJIT_INLINE const X86RegCount& getRegCount() const { + return _regCount; + } + + //! Get Gpd or Gpq register depending on the current architecture. + ASMJIT_INLINE X86GpReg gpz(uint32_t index) const { + return X86GpReg(zax, index); + } + + //! Create an architecture dependent intptr_t memory operand. + ASMJIT_INLINE X86Mem intptr_ptr(const X86GpReg& base, int32_t disp = 0) const { + return x86::ptr(base, disp, _regSize); + } + //! \overload + ASMJIT_INLINE X86Mem intptr_ptr(const X86GpReg& base, const X86GpReg& index, uint32_t shift = 0, int32_t disp = 0) const { + return x86::ptr(base, index, shift, disp, _regSize); + } + //! \overload + ASMJIT_INLINE X86Mem intptr_ptr(const Label& label, int32_t disp = 0) const { + return x86::ptr(label, disp, _regSize); + } + //! \overload + ASMJIT_INLINE X86Mem intptr_ptr(const Label& label, const X86GpReg& index, uint32_t shift, int32_t disp = 0) const { + return x86::ptr(label, index, shift, disp, _regSize); + } + //! \overload + ASMJIT_INLINE X86Mem intptr_ptr_abs(Ptr pAbs, int32_t disp = 0) const { + return x86::ptr_abs(pAbs, disp, _regSize); + } + //! \overload + ASMJIT_INLINE X86Mem intptr_ptr_abs(Ptr pAbs, const X86GpReg& index, uint32_t shift, int32_t disp = 0) const { + return x86::ptr_abs(pAbs, index, shift, disp, _regSize); + } + + ASMJIT_API Error setArch(uint32_t arch); + + // -------------------------------------------------------------------------- + // [Embed] + // -------------------------------------------------------------------------- + + //! Add 8-bit integer data to the instruction stream. + ASMJIT_INLINE void db(uint8_t x) { embed(&x, 1); } + //! Add 16-bit integer data to the instruction stream. + ASMJIT_INLINE void dw(uint16_t x) { embed(&x, 2); } + //! Add 32-bit integer data to the instruction stream. + ASMJIT_INLINE void dd(uint32_t x) { embed(&x, 4); } + //! Add 64-bit integer data to the instruction stream. + ASMJIT_INLINE void dq(uint64_t x) { embed(&x, 8); } + + //! Add 8-bit integer data to the instruction stream. + ASMJIT_INLINE void dint8(int8_t x) { embed(&x, sizeof(int8_t)); } + //! Add 8-bit integer data to the instruction stream. + ASMJIT_INLINE void duint8(uint8_t x) { embed(&x, sizeof(uint8_t)); } + + //! Add 16-bit integer data to the instruction stream. + ASMJIT_INLINE void dint16(int16_t x) { embed(&x, sizeof(int16_t)); } + //! Add 16-bit integer data to the instruction stream. + ASMJIT_INLINE void duint16(uint16_t x) { embed(&x, sizeof(uint16_t)); } + + //! Add 32-bit integer data to the instruction stream. + ASMJIT_INLINE void dint32(int32_t x) { embed(&x, sizeof(int32_t)); } + //! Add 32-bit integer data to the instruction stream. + ASMJIT_INLINE void duint32(uint32_t x) { embed(&x, sizeof(uint32_t)); } + + //! Add 64-bit integer data to the instruction stream. + ASMJIT_INLINE void dint64(int64_t x) { embed(&x, sizeof(int64_t)); } + //! Add 64-bit integer data to the instruction stream. + ASMJIT_INLINE void duint64(uint64_t x) { embed(&x, sizeof(uint64_t)); } + + //! Add float data to the instruction stream. + ASMJIT_INLINE void dfloat(float x) { embed(&x, sizeof(float)); } + //! Add double data to the instruction stream. + ASMJIT_INLINE void ddouble(double x) { embed(&x, sizeof(double)); } + + //! Add Mm data to the instruction stream. + ASMJIT_INLINE void dmm(const Vec64& x) { embed(&x, sizeof(Vec64)); } + //! Add Xmm data to the instruction stream. + ASMJIT_INLINE void dxmm(const Vec128& x) { embed(&x, sizeof(Vec128)); } + //! Add Ymm data to the instruction stream. + ASMJIT_INLINE void dymm(const Vec256& x) { embed(&x, sizeof(Vec256)); } + + //! Add data in a given structure instance to the instruction stream. + template + ASMJIT_INLINE void dstruct(const T& x) { embed(&x, static_cast(sizeof(T))); } + + //! Embed absolute label pointer (4 or 8 bytes). + ASMJIT_API Error embedLabel(const Label& op); + + // -------------------------------------------------------------------------- + // [Align] + // -------------------------------------------------------------------------- + + ASMJIT_API virtual Error align(uint32_t mode, uint32_t offset); + + // -------------------------------------------------------------------------- + // [Reloc] + // -------------------------------------------------------------------------- + + ASMJIT_API virtual size_t _relocCode(void* dst, Ptr baseAddress) const; + + // -------------------------------------------------------------------------- + // [Emit] + // -------------------------------------------------------------------------- + + ASMJIT_API virtual Error _emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, const Operand& o3); + + // ------------------------------------------------------------------------- + // [Options] + // ------------------------------------------------------------------------- + + ASMJIT_X86_EMIT_OPTIONS(X86Assembler) + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Count of registers depending on the current architecture. + X86RegCount _regCount; + + //! EAX or RAX register depending on the current architecture. + X86GpReg zax; + //! ECX or RCX register depending on the current architecture. + X86GpReg zcx; + //! EDX or RDX register depending on the current architecture. + X86GpReg zdx; + //! EBX or RBX register depending on the current architecture. + X86GpReg zbx; + //! ESP or RSP register depending on the current architecture. + X86GpReg zsp; + //! EBP or RBP register depending on the current architecture. + X86GpReg zbp; + //! ESI or RSI register depending on the current architecture. + X86GpReg zsi; + //! EDI or RDI register depending on the current architecture. + X86GpReg zdi; + + // -------------------------------------------------------------------------- + // [Emit] + // -------------------------------------------------------------------------- + +#define INST_0x(_Inst_, _Code_) \ + ASMJIT_INLINE Error _Inst_() { \ + return emit(_Code_); \ + } + +#define INST_1x(_Inst_, _Code_, _Op0_) \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0) { \ + return emit(_Code_, o0); \ + } + +#define INST_1x_(_Inst_, _Code_, _Op0_, _Cond_) \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0) { \ + ASMJIT_ASSERT(_Cond_); \ + return emit(_Code_, o0); \ + } + +#define INST_1i(_Inst_, _Code_, _Op0_) \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0) { \ + return emit(_Code_, o0); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(int o0) { \ + return emit(_Code_, o0); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(unsigned int o0) { \ + return emit(_Code_, static_cast(o0)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(int64_t o0) { \ + return emit(_Code_, static_cast(o0)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(uint64_t o0) { \ + return emit(_Code_, o0); \ + } + +#define INST_1cc(_Inst_, _Code_, _Translate_, _Op0_) \ + ASMJIT_INLINE Error _Inst_(uint32_t cc, const _Op0_& o0) { \ + return emit(_Translate_(cc), o0); \ + } \ + \ + ASMJIT_INLINE Error _Inst_##a(const _Op0_& o0) { return emit(_Code_##a, o0); } \ + ASMJIT_INLINE Error _Inst_##ae(const _Op0_& o0) { return emit(_Code_##ae, o0); } \ + ASMJIT_INLINE Error _Inst_##b(const _Op0_& o0) { return emit(_Code_##b, o0); } \ + ASMJIT_INLINE Error _Inst_##be(const _Op0_& o0) { return emit(_Code_##be, o0); } \ + ASMJIT_INLINE Error _Inst_##c(const _Op0_& o0) { return emit(_Code_##c, o0); } \ + ASMJIT_INLINE Error _Inst_##e(const _Op0_& o0) { return emit(_Code_##e, o0); } \ + ASMJIT_INLINE Error _Inst_##g(const _Op0_& o0) { return emit(_Code_##g, o0); } \ + ASMJIT_INLINE Error _Inst_##ge(const _Op0_& o0) { return emit(_Code_##ge, o0); } \ + ASMJIT_INLINE Error _Inst_##l(const _Op0_& o0) { return emit(_Code_##l, o0); } \ + ASMJIT_INLINE Error _Inst_##le(const _Op0_& o0) { return emit(_Code_##le, o0); } \ + ASMJIT_INLINE Error _Inst_##na(const _Op0_& o0) { return emit(_Code_##na, o0); } \ + ASMJIT_INLINE Error _Inst_##nae(const _Op0_& o0) { return emit(_Code_##nae, o0); } \ + ASMJIT_INLINE Error _Inst_##nb(const _Op0_& o0) { return emit(_Code_##nb, o0); } \ + ASMJIT_INLINE Error _Inst_##nbe(const _Op0_& o0) { return emit(_Code_##nbe, o0); } \ + ASMJIT_INLINE Error _Inst_##nc(const _Op0_& o0) { return emit(_Code_##nc, o0); } \ + ASMJIT_INLINE Error _Inst_##ne(const _Op0_& o0) { return emit(_Code_##ne, o0); } \ + ASMJIT_INLINE Error _Inst_##ng(const _Op0_& o0) { return emit(_Code_##ng, o0); } \ + ASMJIT_INLINE Error _Inst_##nge(const _Op0_& o0) { return emit(_Code_##nge, o0); } \ + ASMJIT_INLINE Error _Inst_##nl(const _Op0_& o0) { return emit(_Code_##nl, o0); } \ + ASMJIT_INLINE Error _Inst_##nle(const _Op0_& o0) { return emit(_Code_##nle, o0); } \ + ASMJIT_INLINE Error _Inst_##no(const _Op0_& o0) { return emit(_Code_##no, o0); } \ + ASMJIT_INLINE Error _Inst_##np(const _Op0_& o0) { return emit(_Code_##np, o0); } \ + ASMJIT_INLINE Error _Inst_##ns(const _Op0_& o0) { return emit(_Code_##ns, o0); } \ + ASMJIT_INLINE Error _Inst_##nz(const _Op0_& o0) { return emit(_Code_##nz, o0); } \ + ASMJIT_INLINE Error _Inst_##o(const _Op0_& o0) { return emit(_Code_##o, o0); } \ + ASMJIT_INLINE Error _Inst_##p(const _Op0_& o0) { return emit(_Code_##p, o0); } \ + ASMJIT_INLINE Error _Inst_##pe(const _Op0_& o0) { return emit(_Code_##pe, o0); } \ + ASMJIT_INLINE Error _Inst_##po(const _Op0_& o0) { return emit(_Code_##po, o0); } \ + ASMJIT_INLINE Error _Inst_##s(const _Op0_& o0) { return emit(_Code_##s, o0); } \ + ASMJIT_INLINE Error _Inst_##z(const _Op0_& o0) { return emit(_Code_##z, o0); } + +#define INST_2x(_Inst_, _Code_, _Op0_, _Op1_) \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1) { \ + return emit(_Code_, o0, o1); \ + } + +#define INST_2x_(_Inst_, _Code_, _Op0_, _Op1_, _Cond_) \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1) { \ + ASMJIT_ASSERT(_Cond_); \ + return emit(_Code_, o0, o1); \ + } + +#define INST_2i(_Inst_, _Code_, _Op0_, _Op1_) \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1) { \ + return emit(_Code_, o0, o1); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, int o1) { \ + return emit(_Code_, o0, o1); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, unsigned int o1) { \ + return emit(_Code_, o0, static_cast(o1)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, int64_t o1) { \ + return emit(_Code_, o0, static_cast(o1)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, uint64_t o1) { \ + return emit(_Code_, o0, o1); \ + } + +#define INST_2cc(_Inst_, _Code_, _Translate_, _Op0_, _Op1_) \ + ASMJIT_INLINE Error _Inst_(uint32_t cc, const _Op0_& o0, const _Op1_& o1) { \ + return emit(_Translate_(cc), o0, o1); \ + } \ + \ + ASMJIT_INLINE Error _Inst_##a(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##a, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##ae(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##ae, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##b(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##b, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##be(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##be, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##c(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##c, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##e(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##e, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##g(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##g, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##ge(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##ge, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##l(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##l, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##le(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##le, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##na(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##na, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##nae(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##nae, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##nb(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##nb, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##nbe(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##nbe, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##nc(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##nc, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##ne(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##ne, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##ng(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##ng, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##nge(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##nge, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##nl(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##nl, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##nle(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##nle, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##no(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##no, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##np(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##np, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##ns(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##ns, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##nz(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##nz, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##o(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##o, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##p(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##p, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##pe(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##pe, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##po(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##po, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##s(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##s, o0, o1); } \ + ASMJIT_INLINE Error _Inst_##z(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##z, o0, o1); } + +#define INST_3x(_Inst_, _Code_, _Op0_, _Op1_, _Op2_) \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2) { \ + return emit(_Code_, o0, o1, o2); \ + } + +#define INST_3x_(_Inst_, _Code_, _Op0_, _Op1_, _Op2_, _Cond_) \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2) { \ + ASMJIT_ASSERT(_Cond_); \ + return emit(_Code_, o0, o1, o2); \ + } + +#define INST_3i(_Inst_, _Code_, _Op0_, _Op1_, _Op2_) \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2) { \ + return emit(_Code_, o0, o1, o2); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, int o2) { \ + return emit(_Code_, o0, o1, o2); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, unsigned int o2) { \ + return emit(_Code_, o0, o1, static_cast(o2)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, int64_t o2) { \ + return emit(_Code_, o0, o1, static_cast(o2)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, uint64_t o2) { \ + return emit(_Code_, o0, o1, o2); \ + } + +#define INST_3ii(_Inst_, _Code_, _Op0_, _Op1_, _Op2_) \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2) { \ + return emit(_Code_, o0, o1, o2); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, int o1, int o2) { \ + Imm o1Imm(o1); \ + return emit(_Code_, o0, o1Imm, o2); \ + } \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, unsigned int o1, unsigned int o2) { \ + Imm o1Imm(o1); \ + return emit(_Code_, o0, o1Imm, static_cast(o2)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, int64_t o1, int64_t o2) { \ + Imm o1Imm(o1); \ + return emit(_Code_, o0, o1Imm, static_cast(o2)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, uint64_t o1, uint64_t o2) { \ + Imm o1Imm(o1); \ + return emit(_Code_, o0, o1Imm, o2); \ + } + +#define INST_4x(_Inst_, _Code_, _Op0_, _Op1_, _Op2_, _Op3_) \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2, const _Op3_& o3) { \ + return emit(_Code_, o0, o1, o2, o3); \ + } + +#define INST_4x_(_Inst_, _Code_, _Op0_, _Op1_, _Op2_, _Op3_, _Cond_) \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2, const _Op3_& o3) { \ + ASMJIT_ASSERT(_Cond_); \ + return emit(_Code_, o0, o1, o2, o3); \ + } + +#define INST_4i(_Inst_, _Code_, _Op0_, _Op1_, _Op2_, _Op3_) \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2, const _Op3_& o3) { \ + return emit(_Code_, o0, o1, o2, o3); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2, int o3) { \ + return emit(_Code_, o0, o1, o2, o3); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2, unsigned int o3) { \ + return emit(_Code_, o0, o1, o2, static_cast(o3)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2, int64_t o3) { \ + return emit(_Code_, o0, o1, o2, static_cast(o3)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2, uint64_t o3) { \ + return emit(_Code_, o0, o1, o2, o3); \ + } + +#define INST_4ii(_Inst_, _Code_, _Op0_, _Op1_, _Op2_, _Op3_) \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2, const _Op3_& o3) { \ + return emit(_Code_, o0, o1, o2, o3); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, int o2, int o3) { \ + Imm o2Imm(o2); \ + return emit(_Code_, o0, o1, o2Imm, o3); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, unsigned int o2, unsigned int o3) { \ + Imm o2Imm(o2); \ + return emit(_Code_, o0, o1, o2Imm, static_cast(o3)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, int64_t o2, int64_t o3) { \ + Imm o2Imm(o2); \ + return emit(_Code_, o0, o1, o2Imm, static_cast(o3)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE Error _Inst_(const _Op0_& o0, const _Op1_& o1, uint64_t o2, uint64_t o3) { \ + Imm o2Imm(o2); \ + return emit(_Code_, o0, o1, o2Imm, o3); \ + } + + // -------------------------------------------------------------------------- + // [X86/X64] + // -------------------------------------------------------------------------- + + //! Add with Carry. + INST_2x(adc, kX86InstIdAdc, X86GpReg, X86GpReg) + //! \overload + INST_2x(adc, kX86InstIdAdc, X86GpReg, X86Mem) + //! \overload + INST_2i(adc, kX86InstIdAdc, X86GpReg, Imm) + //! \overload + INST_2x(adc, kX86InstIdAdc, X86Mem, X86GpReg) + //! \overload + INST_2i(adc, kX86InstIdAdc, X86Mem, Imm) + + //! Add. + INST_2x(add, kX86InstIdAdd, X86GpReg, X86GpReg) + //! \overload + INST_2x(add, kX86InstIdAdd, X86GpReg, X86Mem) + //! \overload + INST_2i(add, kX86InstIdAdd, X86GpReg, Imm) + //! \overload + INST_2x(add, kX86InstIdAdd, X86Mem, X86GpReg) + //! \overload + INST_2i(add, kX86InstIdAdd, X86Mem, Imm) + + //! And. + INST_2x(and_, kX86InstIdAnd, X86GpReg, X86GpReg) + //! \overload + INST_2x(and_, kX86InstIdAnd, X86GpReg, X86Mem) + //! \overload + INST_2i(and_, kX86InstIdAnd, X86GpReg, Imm) + //! \overload + INST_2x(and_, kX86InstIdAnd, X86Mem, X86GpReg) + //! \overload + INST_2i(and_, kX86InstIdAnd, X86Mem, Imm) + + //! Bit scan forward. + INST_2x_(bsf, kX86InstIdBsf, X86GpReg, X86GpReg, !o0.isGpb()) + //! \overload + INST_2x_(bsf, kX86InstIdBsf, X86GpReg, X86Mem, !o0.isGpb()) + + //! Bit scan reverse. + INST_2x_(bsr, kX86InstIdBsr, X86GpReg, X86GpReg, !o0.isGpb()) + //! \overload + INST_2x_(bsr, kX86InstIdBsr, X86GpReg, X86Mem, !o0.isGpb()) + + //! Byte swap (32-bit or 64-bit registers only) (i486). + INST_1x_(bswap, kX86InstIdBswap, X86GpReg, o0.getSize() >= 4) + + //! Bit test. + INST_2x(bt, kX86InstIdBt, X86GpReg, X86GpReg) + //! \overload + INST_2i(bt, kX86InstIdBt, X86GpReg, Imm) + //! \overload + INST_2x(bt, kX86InstIdBt, X86Mem, X86GpReg) + //! \overload + INST_2i(bt, kX86InstIdBt, X86Mem, Imm) + + //! Bit test and complement. + INST_2x(btc, kX86InstIdBtc, X86GpReg, X86GpReg) + //! \overload + INST_2i(btc, kX86InstIdBtc, X86GpReg, Imm) + //! \overload + INST_2x(btc, kX86InstIdBtc, X86Mem, X86GpReg) + //! \overload + INST_2i(btc, kX86InstIdBtc, X86Mem, Imm) + + //! Bit test and reset. + INST_2x(btr, kX86InstIdBtr, X86GpReg, X86GpReg) + //! \overload + INST_2i(btr, kX86InstIdBtr, X86GpReg, Imm) + //! \overload + INST_2x(btr, kX86InstIdBtr, X86Mem, X86GpReg) + //! \overload + INST_2i(btr, kX86InstIdBtr, X86Mem, Imm) + + //! Bit test and set. + INST_2x(bts, kX86InstIdBts, X86GpReg, X86GpReg) + //! \overload + INST_2i(bts, kX86InstIdBts, X86GpReg, Imm) + //! \overload + INST_2x(bts, kX86InstIdBts, X86Mem, X86GpReg) + //! \overload + INST_2i(bts, kX86InstIdBts, X86Mem, Imm) + + //! Call. + INST_1x(call, kX86InstIdCall, X86GpReg) + //! \overload + INST_1x(call, kX86InstIdCall, X86Mem) + //! \overload + INST_1x(call, kX86InstIdCall, Label) + //! \overload + INST_1x(call, kX86InstIdCall, Imm) + //! \overload + ASMJIT_INLINE Error call(Ptr o0) { return call(Imm(o0)); } + + //! Clear carry flag. + INST_0x(clc, kX86InstIdClc) + //! Clear direction flag. + INST_0x(cld, kX86InstIdCld) + //! Complement carry flag. + INST_0x(cmc, kX86InstIdCmc) + + //! Convert BYTE to WORD (AX <- Sign Extend AL). + INST_0x(cbw, kX86InstIdCbw) + //! Convert DWORD to QWORD (EDX:EAX <- Sign Extend EAX). + INST_0x(cdq, kX86InstIdCdq) + //! Convert DWORD to QWORD (RAX <- Sign Extend EAX) (X64 Only). + INST_0x(cdqe, kX86InstIdCdqe) + //! Convert QWORD to OWORD (RDX:RAX <- Sign Extend RAX) (X64 Only). + INST_0x(cqo, kX86InstIdCqo) + //! Convert WORD to DWORD (DX:AX <- Sign Extend AX). + INST_0x(cwd, kX86InstIdCwd) + //! Convert WORD to DWORD (EAX <- Sign Extend AX). + INST_0x(cwde, kX86InstIdCwde) + + //! Conditional move. + INST_2cc(cmov, kX86InstIdCmov, X86Util::condToCmovcc, X86GpReg, X86GpReg) + //! Conditional move. + INST_2cc(cmov, kX86InstIdCmov, X86Util::condToCmovcc, X86GpReg, X86Mem) + + //! Compare two operands. + INST_2x(cmp, kX86InstIdCmp, X86GpReg, X86GpReg) + //! \overload + INST_2x(cmp, kX86InstIdCmp, X86GpReg, X86Mem) + //! \overload + INST_2i(cmp, kX86InstIdCmp, X86GpReg, Imm) + //! \overload + INST_2x(cmp, kX86InstIdCmp, X86Mem, X86GpReg) + //! \overload + INST_2i(cmp, kX86InstIdCmp, X86Mem, Imm) + + //! Compare BYTE in ES:[EDI/RDI] and DS:[ESI/RSI]. + INST_0x(cmpsb, kX86InstIdCmpsB) + //! Compare DWORD in ES:[EDI/RDI] and DS:[ESI/RSI]. + INST_0x(cmpsd, kX86InstIdCmpsD) + //! Compare QWORD in ES:[RDI] and DS:[RDI] (X64 Only). + INST_0x(cmpsq, kX86InstIdCmpsQ) + //! Compare WORD in ES:[EDI/RDI] and DS:[ESI/RSI]. + INST_0x(cmpsw, kX86InstIdCmpsW) + + //! Compare and exchange (i486). + INST_2x(cmpxchg, kX86InstIdCmpxchg, X86GpReg, X86GpReg) + //! \overload + INST_2x(cmpxchg, kX86InstIdCmpxchg, X86Mem, X86GpReg) + + //! Compare and exchange 128-bit value in RDX:RAX with the memory operand (X64 Only). + INST_1x(cmpxchg16b, kX86InstIdCmpxchg16b, X86Mem) + //! Compare and exchange 64-bit value in EDX:EAX with the memory operand (Pentium). + INST_1x(cmpxchg8b, kX86InstIdCmpxchg8b, X86Mem) + + //! CPU identification (i486). + INST_0x(cpuid, kX86InstIdCpuid) + + //! Decimal adjust AL after addition (X86 Only). + INST_0x(daa, kX86InstIdDaa) + //! Decimal adjust AL after subtraction (X86 Only). + INST_0x(das, kX86InstIdDas) + + //! Decrement by 1. + INST_1x(dec, kX86InstIdDec, X86GpReg) + //! \overload + INST_1x(dec, kX86InstIdDec, X86Mem) + + //! Unsigned divide (xDX:xAX <- xDX:xAX / o0). + INST_1x(div, kX86InstIdDiv, X86GpReg) + //! \overload + INST_1x(div, kX86InstIdDiv, X86Mem) + + //! Make stack frame for procedure parameters. + INST_2x(enter, kX86InstIdEnter, Imm, Imm) + + //! Signed divide (xDX:xAX <- xDX:xAX / op). + INST_1x(idiv, kX86InstIdIdiv, X86GpReg) + //! \overload + INST_1x(idiv, kX86InstIdIdiv, X86Mem) + + //! Signed multiply (xDX:xAX <- xAX * o0). + INST_1x(imul, kX86InstIdImul, X86GpReg) + //! \overload + INST_1x(imul, kX86InstIdImul, X86Mem) + + //! Signed multiply. + INST_2x(imul, kX86InstIdImul, X86GpReg, X86GpReg) + //! \overload + INST_2x(imul, kX86InstIdImul, X86GpReg, X86Mem) + //! \overload + INST_2i(imul, kX86InstIdImul, X86GpReg, Imm) + + //! Signed multiply. + INST_3i(imul, kX86InstIdImul, X86GpReg, X86GpReg, Imm) + //! \overload + INST_3i(imul, kX86InstIdImul, X86GpReg, X86Mem, Imm) + + //! Increment by 1. + INST_1x(inc, kX86InstIdInc, X86GpReg) + //! \overload + INST_1x(inc, kX86InstIdInc, X86Mem) + + //! Interrupt. + INST_1i(int_, kX86InstIdInt, Imm) + //! Interrupt 3 - trap to debugger. + ASMJIT_INLINE Error int3() { return int_(3); } + + //! Jump to `label` if condition `cc` is met. + INST_1cc(j, kX86InstIdJ, X86Util::condToJcc, Label) + + //! Short jump if CX/ECX/RCX is zero. + INST_2x_(jecxz, kX86InstIdJecxz, X86GpReg, Label, o0.getRegIndex() == kX86RegIndexCx) + + //! Jump. + INST_1x(jmp, kX86InstIdJmp, X86GpReg) + //! \overload + INST_1x(jmp, kX86InstIdJmp, X86Mem) + //! \overload + INST_1x(jmp, kX86InstIdJmp, Label) + //! \overload + INST_1x(jmp, kX86InstIdJmp, Imm) + //! \overload + ASMJIT_INLINE Error jmp(Ptr dst) { return jmp(Imm(dst)); } + + //! Load AH from flags. + INST_0x(lahf, kX86InstIdLahf) + + //! Load effective address + INST_2x(lea, kX86InstIdLea, X86GpReg, X86Mem) + + //! High level procedure exit. + INST_0x(leave, kX86InstIdLeave) + + //! Load BYTE from DS:[ESI/RSI] to AL. + INST_0x(lodsb, kX86InstIdLodsB) + //! Load DWORD from DS:[ESI/RSI] to EAX. + INST_0x(lodsd, kX86InstIdLodsD) + //! Load QWORD from DS:[RDI] to RAX (X64 Only). + INST_0x(lodsq, kX86InstIdLodsQ) + //! Load WORD from DS:[ESI/RSI] to AX. + INST_0x(lodsw, kX86InstIdLodsW) + + //! Move. + INST_2x(mov, kX86InstIdMov, X86GpReg, X86GpReg) + //! \overload + INST_2x(mov, kX86InstIdMov, X86GpReg, X86Mem) + //! \overload + INST_2i(mov, kX86InstIdMov, X86GpReg, Imm) + //! \overload + INST_2x(mov, kX86InstIdMov, X86Mem, X86GpReg) + //! \overload + INST_2i(mov, kX86InstIdMov, X86Mem, Imm) + + //! Move from segment register. + INST_2x(mov, kX86InstIdMov, X86GpReg, X86SegReg) + //! \overload + INST_2x(mov, kX86InstIdMov, X86Mem, X86SegReg) + //! Move to segment register. + INST_2x(mov, kX86InstIdMov, X86SegReg, X86GpReg) + //! \overload + INST_2x(mov, kX86InstIdMov, X86SegReg, X86Mem) + + //! Move (AL|AX|EAX|RAX <- absolute address in immediate). + INST_2x_(mov_ptr, kX86InstIdMovPtr, X86GpReg, Imm, o0.getRegIndex() == 0); + //! \overload + ASMJIT_INLINE Error mov_ptr(const X86GpReg& o0, Ptr o1) { + ASMJIT_ASSERT(o0.getRegIndex() == 0); + return emit(kX86InstIdMovPtr, o0, Imm(o1)); + } + + //! Move (absolute address in immediate <- AL|AX|EAX|RAX). + INST_2x_(mov_ptr, kX86InstIdMovPtr, Imm, X86GpReg, o1.getRegIndex() == 0); + //! \overload + ASMJIT_INLINE Error mov_ptr(Ptr o0, const X86GpReg& o1) { + ASMJIT_ASSERT(o1.getRegIndex() == 0); + return emit(kX86InstIdMovPtr, Imm(o0), o1); + } + + //! Move data after dwapping bytes (SSE3 - Atom). + INST_2x_(movbe, kX86InstIdMovbe, X86GpReg, X86Mem, !o0.isGpb()); + //! \overload + INST_2x_(movbe, kX86InstIdMovbe, X86Mem, X86GpReg, !o1.isGpb()); + + //! Move BYTE from DS:[ESI/RSI] to ES:[EDI/RDI]. + INST_0x(movsb, kX86InstIdMovsB) + //! Move DWORD from DS:[ESI/RSI] to ES:[EDI/RDI]. + INST_0x(movsd, kX86InstIdMovsD) + //! Move QWORD from DS:[RSI] to ES:[RDI] (X64 Only). + INST_0x(movsq, kX86InstIdMovsQ) + //! Move WORD from DS:[ESI/RSI] to ES:[EDI/RDI]. + INST_0x(movsw, kX86InstIdMovsW) + + //! Move with sign-extension. + INST_2x(movsx, kX86InstIdMovsx, X86GpReg, X86GpReg) + //! \overload + INST_2x(movsx, kX86InstIdMovsx, X86GpReg, X86Mem) + + //! Move DWORD to QWORD with sign-extension (X64 Only). + INST_2x(movsxd, kX86InstIdMovsxd, X86GpReg, X86GpReg) + //! \overload + INST_2x(movsxd, kX86InstIdMovsxd, X86GpReg, X86Mem) + + //! Move with zero-extension. + INST_2x(movzx, kX86InstIdMovzx, X86GpReg, X86GpReg) + //! \overload + INST_2x(movzx, kX86InstIdMovzx, X86GpReg, X86Mem) + + //! Unsigned multiply (xDX:xAX <- xAX * o0). + INST_1x(mul, kX86InstIdMul, X86GpReg) + //! \overload + INST_1x(mul, kX86InstIdMul, X86Mem) + + //! Two's complement negation. + INST_1x(neg, kX86InstIdNeg, X86GpReg) + //! \overload + INST_1x(neg, kX86InstIdNeg, X86Mem) + + //! No operation. + INST_0x(nop, kX86InstIdNop) + + //! One's complement negation. + INST_1x(not_, kX86InstIdNot, X86GpReg) + //! \overload + INST_1x(not_, kX86InstIdNot, X86Mem) + + //! Or. + INST_2x(or_, kX86InstIdOr, X86GpReg, X86GpReg) + //! \overload + INST_2x(or_, kX86InstIdOr, X86GpReg, X86Mem) + //! \overload + INST_2i(or_, kX86InstIdOr, X86GpReg, Imm) + //! \overload + INST_2x(or_, kX86InstIdOr, X86Mem, X86GpReg) + //! \overload + INST_2i(or_, kX86InstIdOr, X86Mem, Imm) + + //! Pop a value from the stack. + INST_1x_(pop, kX86InstIdPop, X86GpReg, o0.getSize() == 2 || o0.getSize() == _regSize) + //! \overload + INST_1x_(pop, kX86InstIdPop, X86Mem, o0.getSize() == 2 || o0.getSize() == _regSize) + + //! Pop a segment register from the stack. + //! + //! \note There is no instruction to pop a cs segment register. + INST_1x_(pop, kX86InstIdPop, X86SegReg, o0.getRegIndex() != kX86SegCs); + + //! Pop all Gp registers - EDI|ESI|EBP|Ign|EBX|EDX|ECX|EAX (X86 Only). + INST_0x(popa, kX86InstIdPopa) + + //! Pop stack into EFLAGS register (32-bit or 64-bit). + INST_0x(popf, kX86InstIdPopf) + + //! Push WORD or DWORD/QWORD on the stack. + INST_1x_(push, kX86InstIdPush, X86GpReg, o0.getSize() == 2 || o0.getSize() == _regSize) + //! Push WORD or DWORD/QWORD on the stack. + INST_1x_(push, kX86InstIdPush, X86Mem, o0.getSize() == 2 || o0.getSize() == _regSize) + //! Push segment register on the stack. + INST_1x(push, kX86InstIdPush, X86SegReg) + //! Push WORD or DWORD/QWORD on the stack. + INST_1i(push, kX86InstIdPush, Imm) + + //! Push all Gp registers - EAX|ECX|EDX|EBX|ESP|EBP|ESI|EDI (X86 Only). + INST_0x(pusha, kX86InstIdPusha) + + //! Push EFLAGS register (32-bit or 64-bit) on the stack. + INST_0x(pushf, kX86InstIdPushf) + + //! Rotate bits left. + //! + //! \note `o1` register can be only `cl`. + INST_2x(rcl, kX86InstIdRcl, X86GpReg, X86GpReg) + //! \overload + INST_2x(rcl, kX86InstIdRcl, X86Mem, X86GpReg) + //! Rotate bits left. + INST_2i(rcl, kX86InstIdRcl, X86GpReg, Imm) + //! \overload + INST_2i(rcl, kX86InstIdRcl, X86Mem, Imm) + + //! Rotate bits right. + //! + //! \note `o1` register can be only `cl`. + INST_2x(rcr, kX86InstIdRcr, X86GpReg, X86GpReg) + //! \overload + INST_2x(rcr, kX86InstIdRcr, X86Mem, X86GpReg) + //! Rotate bits right. + INST_2i(rcr, kX86InstIdRcr, X86GpReg, Imm) + //! \overload + INST_2i(rcr, kX86InstIdRcr, X86Mem, Imm) + + //! Read time-stamp counter (Pentium). + INST_0x(rdtsc, kX86InstIdRdtsc) + //! Read time-stamp counter and processor id (Pentium). + INST_0x(rdtscp, kX86InstIdRdtscp) + + //! Repeated load ECX/RCX BYTEs from DS:[ESI/RSI] to AL. + INST_0x(rep_lodsb, kX86InstIdRepLodsB) + //! Repeated load ECX/RCX DWORDs from DS:[ESI/RSI] to EAX. + INST_0x(rep_lodsd, kX86InstIdRepLodsD) + //! Repeated load ECX/RCX QWORDs from DS:[RDI] to RAX (X64 Only). + INST_0x(rep_lodsq, kX86InstIdRepLodsQ) + //! Repeated load ECX/RCX WORDs from DS:[ESI/RSI] to AX. + INST_0x(rep_lodsw, kX86InstIdRepLodsW) + + //! Repeated move ECX/RCX BYTEs from DS:[ESI/RSI] to ES:[EDI/RDI]. + INST_0x(rep_movsb, kX86InstIdRepMovsB) + //! Repeated move ECX/RCX DWORDs from DS:[ESI/RSI] to ES:[EDI/RDI]. + INST_0x(rep_movsd, kX86InstIdRepMovsD) + //! Repeated move ECX/RCX QWORDs from DS:[RSI] to ES:[RDI] (X64 Only). + INST_0x(rep_movsq, kX86InstIdRepMovsQ) + //! Repeated move ECX/RCX WORDs from DS:[ESI/RSI] to ES:[EDI/RDI]. + INST_0x(rep_movsw, kX86InstIdRepMovsW) + + //! Repeated fill ECX/RCX BYTEs at ES:[EDI/RDI] with AL. + INST_0x(rep_stosb, kX86InstIdRepStosB) + //! Repeated fill ECX/RCX DWORDs at ES:[EDI/RDI] with EAX. + INST_0x(rep_stosd, kX86InstIdRepStosD) + //! Repeated fill ECX/RCX QWORDs at ES:[RDI] with RAX (X64 Only). + INST_0x(rep_stosq, kX86InstIdRepStosQ) + //! Repeated fill ECX/RCX WORDs at ES:[EDI/RDI] with AX. + INST_0x(rep_stosw, kX86InstIdRepStosW) + + //! Repeated find non-AL BYTEs in ES:[EDI/RDI] and DS:[ESI/RSI]. + INST_0x(repe_cmpsb, kX86InstIdRepeCmpsB) + //! Repeated find non-EAX DWORDs in ES:[EDI/RDI] and DS:[ESI/RSI]. + INST_0x(repe_cmpsd, kX86InstIdRepeCmpsD) + //! Repeated find non-RAX QWORDs in ES:[RDI] and DS:[RDI] (X64 Only). + INST_0x(repe_cmpsq, kX86InstIdRepeCmpsQ) + //! Repeated find non-AX WORDs in ES:[EDI/RDI] and DS:[ESI/RSI]. + INST_0x(repe_cmpsw, kX86InstIdRepeCmpsW) + + //! Repeated find non-AL BYTE starting at ES:[EDI/RDI]. + INST_0x(repe_scasb, kX86InstIdRepeScasB) + //! Repeated find non-EAX DWORD starting at ES:[EDI/RDI]. + INST_0x(repe_scasd, kX86InstIdRepeScasD) + //! Repeated find non-RAX QWORD starting at ES:[RDI] (X64 Only). + INST_0x(repe_scasq, kX86InstIdRepeScasQ) + //! Repeated find non-AX WORD starting at ES:[EDI/RDI]. + INST_0x(repe_scasw, kX86InstIdRepeScasW) + + //! Repeated find AL BYTEs in ES:[EDI/RDI] and DS:[ESI/RSI]. + INST_0x(repne_cmpsb, kX86InstIdRepneCmpsB) + //! Repeated find EAX DWORDs in ES:[EDI/RDI] and DS:[ESI/RSI]. + INST_0x(repne_cmpsd, kX86InstIdRepneCmpsD) + //! Repeated find RAX QWORDs in ES:[RDI] and DS:[RDI] (X64 Only). + INST_0x(repne_cmpsq, kX86InstIdRepneCmpsQ) + //! Repeated find AX WORDs in ES:[EDI/RDI] and DS:[ESI/RSI]. + INST_0x(repne_cmpsw, kX86InstIdRepneCmpsW) + + //! Repeated find AL BYTEs starting at ES:[EDI/RDI]. + INST_0x(repne_scasb, kX86InstIdRepneScasB) + //! Repeated find EAX DWORDs starting at ES:[EDI/RDI]. + INST_0x(repne_scasd, kX86InstIdRepneScasD) + //! Repeated find RAX QWORDs starting at ES:[RDI] (X64 Only). + INST_0x(repne_scasq, kX86InstIdRepneScasQ) + //! Repeated find AX WORDs starting at ES:[EDI/RDI]. + INST_0x(repne_scasw, kX86InstIdRepneScasW) + + //! Return. + INST_0x(ret, kX86InstIdRet) + //! \overload + INST_1i(ret, kX86InstIdRet, Imm) + + //! Rotate bits left. + //! + //! \note `o1` register can be only `cl`. + INST_2x(rol, kX86InstIdRol, X86GpReg, X86GpReg) + //! \overload + INST_2x(rol, kX86InstIdRol, X86Mem, X86GpReg) + //! Rotate bits left. + INST_2i(rol, kX86InstIdRol, X86GpReg, Imm) + //! \overload + INST_2i(rol, kX86InstIdRol, X86Mem, Imm) + + //! Rotate bits right. + //! + //! \note `o1` register can be only `cl`. + INST_2x(ror, kX86InstIdRor, X86GpReg, X86GpReg) + //! \overload + INST_2x(ror, kX86InstIdRor, X86Mem, X86GpReg) + //! Rotate bits right. + INST_2i(ror, kX86InstIdRor, X86GpReg, Imm) + //! \overload + INST_2i(ror, kX86InstIdRor, X86Mem, Imm) + + //! Store AH into flags. + INST_0x(sahf, kX86InstIdSahf) + + //! Integer subtraction with borrow. + INST_2x(sbb, kX86InstIdSbb, X86GpReg, X86GpReg) + //! \overload + INST_2x(sbb, kX86InstIdSbb, X86GpReg, X86Mem) + //! \overload + INST_2i(sbb, kX86InstIdSbb, X86GpReg, Imm) + //! \overload + INST_2x(sbb, kX86InstIdSbb, X86Mem, X86GpReg) + //! \overload + INST_2i(sbb, kX86InstIdSbb, X86Mem, Imm) + + //! Shift bits left. + //! + //! \note `o1` register can be only `cl`. + INST_2x(sal, kX86InstIdSal, X86GpReg, X86GpReg) + //! \overload + INST_2x(sal, kX86InstIdSal, X86Mem, X86GpReg) + //! Shift bits left. + INST_2i(sal, kX86InstIdSal, X86GpReg, Imm) + //! \overload + INST_2i(sal, kX86InstIdSal, X86Mem, Imm) + + //! Shift bits right. + //! + //! \note `o1` register can be only `cl`. + INST_2x(sar, kX86InstIdSar, X86GpReg, X86GpReg) + //! \overload + INST_2x(sar, kX86InstIdSar, X86Mem, X86GpReg) + //! Shift bits right. + INST_2i(sar, kX86InstIdSar, X86GpReg, Imm) + //! \overload + INST_2i(sar, kX86InstIdSar, X86Mem, Imm) + + //! Find non-AL BYTE starting at ES:[EDI/RDI]. + INST_0x(scasb, kX86InstIdScasB) + //! Find non-EAX DWORD starting at ES:[EDI/RDI]. + INST_0x(scasd, kX86InstIdScasD) + //! Find non-rax QWORD starting at ES:[RDI] (X64 Only). + INST_0x(scasq, kX86InstIdScasQ) + //! Find non-AX WORD starting at ES:[EDI/RDI]. + INST_0x(scasw, kX86InstIdScasW) + + //! Set byte on condition. + INST_1cc(set, kX86InstIdSet, X86Util::condToSetcc, X86GpReg) + //! Set byte on condition. + INST_1cc(set, kX86InstIdSet, X86Util::condToSetcc, X86Mem) + + //! Shift bits left. + //! + //! \note `o1` register can be only `cl`. + INST_2x(shl, kX86InstIdShl, X86GpReg, X86GpReg) + //! \overload + INST_2x(shl, kX86InstIdShl, X86Mem, X86GpReg) + //! Shift bits left. + INST_2i(shl, kX86InstIdShl, X86GpReg, Imm) + //! \overload + INST_2i(shl, kX86InstIdShl, X86Mem, Imm) + + //! Shift bits right. + //! + //! \note `o1` register can be only `cl`. + INST_2x(shr, kX86InstIdShr, X86GpReg, X86GpReg) + //! \overload + INST_2x(shr, kX86InstIdShr, X86Mem, X86GpReg) + //! Shift bits right. + INST_2i(shr, kX86InstIdShr, X86GpReg, Imm) + //! \overload + INST_2i(shr, kX86InstIdShr, X86Mem, Imm) + + //! Double precision shift left. + //! + //! \note `o2` register can be only `cl` register. + INST_3x(shld, kX86InstIdShld, X86GpReg, X86GpReg, X86GpReg) + //! \overload + INST_3x(shld, kX86InstIdShld, X86Mem, X86GpReg, X86GpReg) + //! Double precision shift left. + INST_3i(shld, kX86InstIdShld, X86GpReg, X86GpReg, Imm) + //! \overload + INST_3i(shld, kX86InstIdShld, X86Mem, X86GpReg, Imm) + + //! Double precision shift right. + //! + //! \note `o2` register can be only `cl` register. + INST_3x(shrd, kX86InstIdShrd, X86GpReg, X86GpReg, X86GpReg) + //! \overload + INST_3x(shrd, kX86InstIdShrd, X86Mem, X86GpReg, X86GpReg) + //! Double precision shift right. + INST_3i(shrd, kX86InstIdShrd, X86GpReg, X86GpReg, Imm) + //! \overload + INST_3i(shrd, kX86InstIdShrd, X86Mem, X86GpReg, Imm) + + //! Set carry flag to 1. + INST_0x(stc, kX86InstIdStc) + //! Set direction flag to 1. + INST_0x(std, kX86InstIdStd) + + //! Fill BYTE at ES:[EDI/RDI] with AL. + INST_0x(stosb, kX86InstIdStosB) + //! Fill DWORD at ES:[EDI/RDI] with EAX. + INST_0x(stosd, kX86InstIdStosD) + //! Fill QWORD at ES:[RDI] with RAX (X64 Only). + INST_0x(stosq, kX86InstIdStosQ) + //! Fill WORD at ES:[EDI/RDI] with AX. + INST_0x(stosw, kX86InstIdStosW) + + //! Subtract. + INST_2x(sub, kX86InstIdSub, X86GpReg, X86GpReg) + //! \overload + INST_2x(sub, kX86InstIdSub, X86GpReg, X86Mem) + //! \overload + INST_2i(sub, kX86InstIdSub, X86GpReg, Imm) + //! \overload + INST_2x(sub, kX86InstIdSub, X86Mem, X86GpReg) + //! \overload + INST_2i(sub, kX86InstIdSub, X86Mem, Imm) + + //! Logical compare. + INST_2x(test, kX86InstIdTest, X86GpReg, X86GpReg) + //! \overload + INST_2i(test, kX86InstIdTest, X86GpReg, Imm) + //! \overload + INST_2x(test, kX86InstIdTest, X86Mem, X86GpReg) + //! \overload + INST_2i(test, kX86InstIdTest, X86Mem, Imm) + + //! Undefined instruction - Raise #UD exception. + INST_0x(ud2, kX86InstIdUd2) + + //! Exchange and Add. + INST_2x(xadd, kX86InstIdXadd, X86GpReg, X86GpReg) + //! \overload + INST_2x(xadd, kX86InstIdXadd, X86Mem, X86GpReg) + + //! Exchange register/memory with register. + INST_2x(xchg, kX86InstIdXchg, X86GpReg, X86GpReg) + //! \overload + INST_2x(xchg, kX86InstIdXchg, X86Mem, X86GpReg) + //! \overload + INST_2x(xchg, kX86InstIdXchg, X86GpReg, X86Mem) + + //! Xor. + INST_2x(xor_, kX86InstIdXor, X86GpReg, X86GpReg) + //! \overload + INST_2x(xor_, kX86InstIdXor, X86GpReg, X86Mem) + //! \overload + INST_2i(xor_, kX86InstIdXor, X86GpReg, Imm) + //! \overload + INST_2x(xor_, kX86InstIdXor, X86Mem, X86GpReg) + //! \overload + INST_2i(xor_, kX86InstIdXor, X86Mem, Imm) + + // -------------------------------------------------------------------------- + // [FPU] + // -------------------------------------------------------------------------- + + //! Compute `2^x - 1` - `fp0 = POW(2, fp0) - 1` (FPU). + INST_0x(f2xm1, kX86InstIdF2xm1) + //! Abs `fp0 = ABS(fp0)` (FPU). + INST_0x(fabs, kX86InstIdFabs) + + //! Add `o0 = o0 + o1` (one operand has to be `fp0`) (FPU). + INST_2x_(fadd, kX86InstIdFadd, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0) + //! Add `fp0 = fp0 + float_or_double[o0]` (FPU). + INST_1x(fadd, kX86InstIdFadd, X86Mem) + //! Add `o0 = o0 + fp0` and POP (FPU). + INST_1x(faddp, kX86InstIdFaddp, X86FpReg) + //! Add `fp1 = fp1 + fp0` and POP (FPU). + INST_0x(faddp, kX86InstIdFaddp) + + //! Load BCD from `[o0]` and PUSH (FPU). + INST_1x(fbld, kX86InstIdFbld, X86Mem) + //! Store BCD-Integer to `[o0]` and POP (FPU). + INST_1x(fbstp, kX86InstIdFbstp, X86Mem) + + //! Complement Sign `fp0 = -fp0` (FPU). + INST_0x(fchs, kX86InstIdFchs) + + //! Clear exceptions (FPU). + INST_0x(fclex, kX86InstIdFclex) + + //! Conditional move `if (CF=1) fp0 = o0` (FPU). + INST_1x(fcmovb, kX86InstIdFcmovb, X86FpReg) + //! Conditional move `if (CF|ZF=1) fp0 = o0` (FPU). + INST_1x(fcmovbe, kX86InstIdFcmovbe, X86FpReg) + //! Conditional move `if (ZF=1) fp0 = o0` (FPU). + INST_1x(fcmove, kX86InstIdFcmove, X86FpReg) + //! Conditional move `if (CF=0) fp0 = o0` (FPU). + INST_1x(fcmovnb, kX86InstIdFcmovnb, X86FpReg) + //! Conditional move `if (CF|ZF=0) fp0 = o0` (FPU). + INST_1x(fcmovnbe, kX86InstIdFcmovnbe, X86FpReg) + //! Conditional move `if (ZF=0) fp0 = o0` (FPU). + INST_1x(fcmovne, kX86InstIdFcmovne, X86FpReg) + //! Conditional move `if (PF=0) fp0 = o0` (FPU). + INST_1x(fcmovnu, kX86InstIdFcmovnu, X86FpReg) + //! Conditional move `if (PF=1) fp0 = o0` (FPU). + INST_1x(fcmovu, kX86InstIdFcmovu, X86FpReg) + + //! Compare `fp0` with `o0` (FPU). + INST_1x(fcom, kX86InstIdFcom, X86FpReg) + //! Compare `fp0` with `fp1` (FPU). + INST_0x(fcom, kX86InstIdFcom) + //! Compare `fp0` with `float_or_double[o0]` (FPU). + INST_1x(fcom, kX86InstIdFcom, X86Mem) + //! Compare `fp0` with `o0` and POP (FPU). + INST_1x(fcomp, kX86InstIdFcomp, X86FpReg) + //! Compare `fp0` with `fp1` and POP (FPU). + INST_0x(fcomp, kX86InstIdFcomp) + //! Compare `fp0` with `float_or_double[o0]` and POP (FPU). + INST_1x(fcomp, kX86InstIdFcomp, X86Mem) + //! Compare `fp0` with `fp1` and POP twice (FPU). + INST_0x(fcompp, kX86InstIdFcompp) + //! Compare `fp0` with `o0` and set EFLAGS (FPU). + INST_1x(fcomi, kX86InstIdFcomi, X86FpReg) + //! Compare `fp0` with `o0` and set EFLAGS and POP (FPU). + INST_1x(fcomip, kX86InstIdFcomip, X86FpReg) + + //! Cos `fp0 = cos(fp0)` (FPU). + INST_0x(fcos, kX86InstIdFcos) + + //! Decrement FPU stack pointer (FPU). + INST_0x(fdecstp, kX86InstIdFdecstp) + + //! Divide `o0 = o0 / o1` (one has to be `fp0`) (FPU). + INST_2x_(fdiv, kX86InstIdFdiv, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0) + //! Divide `fp0 = fp0 / float_or_double[o0]` (FPU). + INST_1x(fdiv, kX86InstIdFdiv, X86Mem) + //! Divide `o0 = o0 / fp0` and POP (FPU). + INST_1x(fdivp, kX86InstIdFdivp, X86FpReg) + //! Divide `fp1 = fp1 / fp0` and POP (FPU). + INST_0x(fdivp, kX86InstIdFdivp) + + //! Reverse divide `o0 = o1 / o0` (one has to be `fp0`) (FPU). + INST_2x_(fdivr, kX86InstIdFdivr, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0) + //! Reverse divide `fp0 = float_or_double[o0] / fp0` (FPU). + INST_1x(fdivr, kX86InstIdFdivr, X86Mem) + //! Reverse divide `o0 = fp0 / o0` and POP (FPU). + INST_1x(fdivrp, kX86InstIdFdivrp, X86FpReg) + //! Reverse divide `fp1 = fp0 / fp1` and POP (FPU). + INST_0x(fdivrp, kX86InstIdFdivrp) + + //! Free FP register (FPU). + INST_1x(ffree, kX86InstIdFfree, X86FpReg) + + //! Add `fp0 = fp0 + short_or_int[o0]` (FPU). + INST_1x_(fiadd, kX86InstIdFiadd, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + //! Compare `fp0` with `short_or_int[o0]` (FPU). + INST_1x_(ficom, kX86InstIdFicom, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + //! Compare `fp0` with `short_or_int[o0]` and POP (FPU). + INST_1x_(ficomp, kX86InstIdFicomp, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + //! Divide `fp0 = fp0 / short_or_int[o0]` (FPU). + INST_1x_(fidiv, kX86InstIdFidiv, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + //! Reverse divide `fp0 = short_or_int[o0] / fp0` (FPU). + INST_1x_(fidivr, kX86InstIdFidivr, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + + //! Load `short_or_int_or_long[o0]` and PUSH (FPU). + INST_1x_(fild, kX86InstIdFild, X86Mem, o0.getSize() == 2 || o0.getSize() == 4 || o0.getSize() == 8) + //! Multiply `fp0 *= short_or_int[o0]` (FPU). + INST_1x_(fimul, kX86InstIdFimul, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + + //! Increment FPU stack pointer (FPU). + INST_0x(fincstp, kX86InstIdFincstp) + //! Initialize FPU (FPU). + INST_0x(finit, kX86InstIdFinit) + + //! Subtract `fp0 = fp0 - short_or_int[o0]` (FPU). + INST_1x_(fisub, kX86InstIdFisub, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + //! Reverse subtract `fp0 = short_or_int[o0] - fp0` (FPU). + INST_1x_(fisubr, kX86InstIdFisubr, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + + //! Initialize FPU without checking for pending unmasked exceptions (FPU). + INST_0x(fninit, kX86InstIdFninit) + + //! Store `fp0` as `short_or_int[o0]` (FPU). + INST_1x_(fist, kX86InstIdFist, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + //! Store `fp0` as `short_or_int_or_long[o0]` and POP (FPU). + INST_1x_(fistp, kX86InstIdFistp, X86Mem, o0.getSize() == 2 || o0.getSize() == 4 || o0.getSize() == 8) + + //! Load `float_or_double_or_extended[o0]` and PUSH (FPU). + INST_1x_(fld, kX86InstIdFld, X86Mem, o0.getSize() == 4 || o0.getSize() == 8 || o0.getSize() == 10) + //! PUSH `o0` (FPU). + INST_1x(fld, kX86InstIdFld, X86FpReg) + + //! PUSH `1.0` (FPU). + INST_0x(fld1, kX86InstIdFld1) + //! PUSH `log2(10)` (FPU). + INST_0x(fldl2t, kX86InstIdFldl2t) + //! PUSH `log2(e)` (FPU). + INST_0x(fldl2e, kX86InstIdFldl2e) + //! PUSH `pi` (FPU). + INST_0x(fldpi, kX86InstIdFldpi) + //! PUSH `log10(2)` (FPU). + INST_0x(fldlg2, kX86InstIdFldlg2) + //! PUSH `ln(2)` (FPU). + INST_0x(fldln2, kX86InstIdFldln2) + //! PUSH `+0.0` (FPU). + INST_0x(fldz, kX86InstIdFldz) + + //! Load x87 FPU control word from `word_ptr[o0]` (FPU). + INST_1x(fldcw, kX86InstIdFldcw, X86Mem) + //! Load x87 FPU environment (14 or 28 bytes) from `[o0]` (FPU). + INST_1x(fldenv, kX86InstIdFldenv, X86Mem) + + //! Multiply `o0 = o0 * o1` (one has to be `fp0`) (FPU). + INST_2x_(fmul, kX86InstIdFmul, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0) + //! Multiply `fp0 = fp0 * float_or_double[o0]` (FPU). + INST_1x(fmul, kX86InstIdFmul, X86Mem) + //! Multiply `o0 = o0 * fp0` and POP (FPU). + INST_1x(fmulp, kX86InstIdFmulp, X86FpReg) + //! Multiply `fp1 = fp1 * fp0` and POP (FPU). + INST_0x(fmulp, kX86InstIdFmulp) + + //! Clear exceptions (FPU). + INST_0x(fnclex, kX86InstIdFnclex) + //! No operation (FPU). + INST_0x(fnop, kX86InstIdFnop) + //! Save FPU state to `[o0]` (FPU). + INST_1x(fnsave, kX86InstIdFnsave, X86Mem) + //! Store x87 FPU environment to `[o0]` (FPU). + INST_1x(fnstenv, kX86InstIdFnstenv, X86Mem) + //! Store x87 FPU control word to `[o0]` (FPU). + INST_1x(fnstcw, kX86InstIdFnstcw, X86Mem) + + //! Store x87 FPU status word to `o0` (AX) (FPU). + INST_1x_(fnstsw, kX86InstIdFnstsw, X86GpReg, o0.isRegCode(kX86RegTypeGpw, kX86RegIndexAx)) + //! Store x87 FPU status word to `word_ptr[o0]` (FPU). + INST_1x(fnstsw, kX86InstIdFnstsw, X86Mem) + + //! Partial Arctan `fp1 = atan2(fp1, fp0)` and POP (FPU). + INST_0x(fpatan, kX86InstIdFpatan) + //! Partial Remainder[Trunc] `fp1 = fp0 % fp1` and POP (FPU). + INST_0x(fprem, kX86InstIdFprem) + //! Partial Remainder[Round] `fp1 = fp0 % fp1` and POP (FPU). + INST_0x(fprem1, kX86InstIdFprem1) + //! Partial Tan `fp0 = tan(fp0)` and PUSH `1.0` (FPU). + INST_0x(fptan, kX86InstIdFptan) + //! Round `fp0 = round(fp0)` (FPU). + INST_0x(frndint, kX86InstIdFrndint) + + //! Restore FPU state from `[o0]` (94 or 108 bytes) (FPU). + INST_1x(frstor, kX86InstIdFrstor, X86Mem) + //! Save FPU state to `[o0]` (94 or 108 bytes) (FPU). + INST_1x(fsave, kX86InstIdFsave, X86Mem) + + //! Scale `fp0 = fp0 * pow(2, RoundTowardsZero(fp1))` (FPU). + INST_0x(fscale, kX86InstIdFscale) + //! Sin `fp0 = sin(fp0)` (FPU). + INST_0x(fsin, kX86InstIdFsin) + //! Sincos `fp0 = sin(fp0)` and PUSH `cos(fp0)` (FPU). + INST_0x(fsincos, kX86InstIdFsincos) + //! Square root `fp0 = sqrt(fp0)` (FPU). + INST_0x(fsqrt, kX86InstIdFsqrt) + + //! Store floating point value to `float_or_double[o0]` (FPU). + INST_1x_(fst, kX86InstIdFst, X86Mem, o0.getSize() == 4 || o0.getSize() == 8) + //! Copy `o0 = fp0` (FPU). + INST_1x(fst, kX86InstIdFst, X86FpReg) + //! Store floating point value to `float_or_double_or_extended[o0]` and POP (FPU). + INST_1x_(fstp, kX86InstIdFstp, X86Mem, o0.getSize() == 4 || o0.getSize() == 8 || o0.getSize() == 10) + //! Copy `o0 = fp0` and POP (FPU). + INST_1x(fstp, kX86InstIdFstp, X86FpReg) + + //! Store x87 FPU control word to `word_ptr[o0]` (FPU). + INST_1x(fstcw, kX86InstIdFstcw, X86Mem) + //! Store x87 FPU environment to `[o0]` (14 or 28 bytes) (FPU). + INST_1x(fstenv, kX86InstIdFstenv, X86Mem) + //! Store x87 FPU status word to `o0` (AX) (FPU). + INST_1x_(fstsw, kX86InstIdFstsw, X86GpReg, o0.getRegIndex() == kX86RegIndexAx) + //! Store x87 FPU status word to `word_ptr[o0]` (FPU). + INST_1x(fstsw, kX86InstIdFstsw, X86Mem) + + //! Subtract `o0 = o0 - o1` (one has to be `fp0`) (FPU). + INST_2x_(fsub, kX86InstIdFsub, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0) + //! Subtract `fp0 = fp0 - float_or_double[o0]` (FPU). + INST_1x_(fsub, kX86InstIdFsub, X86Mem, o0.getSize() == 4 || o0.getSize() == 8) + //! Subtract `o0 = o0 - fp0` and POP (FPU). + INST_1x(fsubp, kX86InstIdFsubp, X86FpReg) + //! Subtract `fp1 = fp1 - fp0` and POP (FPU). + INST_0x(fsubp, kX86InstIdFsubp) + + //! Reverse subtract `o0 = o1 - o0` (one has to be `fp0`) (FPU). + INST_2x_(fsubr, kX86InstIdFsubr, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0) + //! Reverse subtract `fp0 = fp0 - float_or_double[o0]` (FPU). + INST_1x_(fsubr, kX86InstIdFsubr, X86Mem, o0.getSize() == 4 || o0.getSize() == 8) + //! Reverse subtract `o0 = o0 - fp0` and POP (FPU). + INST_1x(fsubrp, kX86InstIdFsubrp, X86FpReg) + //! Reverse subtract `fp1 = fp1 - fp0` and POP (FPU). + INST_0x(fsubrp, kX86InstIdFsubrp) + + //! Compare `fp0` with `0.0` (FPU). + INST_0x(ftst, kX86InstIdFtst) + + //! Unordered compare `fp0` with `o0` (FPU). + INST_1x(fucom, kX86InstIdFucom, X86FpReg) + //! Unordered compare `fp0` with `fp1` (FPU). + INST_0x(fucom, kX86InstIdFucom) + //! Unordered compare `fp0` with `o0`, check for ordered values and set EFLAGS (FPU). + INST_1x(fucomi, kX86InstIdFucomi, X86FpReg) + //! Unordered compare `fp0` with `o0`, check for ordered values and set EFLAGS and POP (FPU). + INST_1x(fucomip, kX86InstIdFucomip, X86FpReg) + //! Unordered compare `fp0` with `o0` and POP (FPU). + INST_1x(fucomp, kX86InstIdFucomp, X86FpReg) + //! Unordered compare `fp0` with `fp1` and POP (FPU). + INST_0x(fucomp, kX86InstIdFucomp) + //! Unordered compare `fp0` with `fp1` and POP twice (FPU). + INST_0x(fucompp, kX86InstIdFucompp) + + INST_0x(fwait, kX86InstIdFwait) + + //! Examine fp0 (FPU). + INST_0x(fxam, kX86InstIdFxam) + //! Exchange `fp0` with `o0` (FPU). + INST_1x(fxch, kX86InstIdFxch, X86FpReg) + + //! Restore FP/MMX/SIMD extension states to `o0` (512 bytes) (FPU, MMX, SSE). + INST_1x(fxrstor, kX86InstIdFxrstor, X86Mem) + //! Store FP/MMX/SIMD extension states to `o0` (512 bytes) (FPU, MMX, SSE). + INST_1x(fxsave, kX86InstIdFxsave, X86Mem) + //! Extract `fp0 = exponent(fp0)` and PUSH `significant(fp0)` (FPU). + INST_0x(fxtract, kX86InstIdFxtract) + + //! Compute `fp1 = fp1 * log2(fp0)` and POP (FPU). + INST_0x(fyl2x, kX86InstIdFyl2x) + //! Compute `fp1 = fp1 * log2(fp0 + 1)` and POP (FPU). + INST_0x(fyl2xp1, kX86InstIdFyl2xp1) + + // -------------------------------------------------------------------------- + // [MMX] + // -------------------------------------------------------------------------- + + //! Move DWORD (MMX). + INST_2x(movd, kX86InstIdMovd, X86Mem, X86MmReg) + //! \overload + INST_2x(movd, kX86InstIdMovd, X86GpReg, X86MmReg) + //! \overload + INST_2x(movd, kX86InstIdMovd, X86MmReg, X86Mem) + //! \overload + INST_2x(movd, kX86InstIdMovd, X86MmReg, X86GpReg) + + //! Move QWORD (MMX). + INST_2x(movq, kX86InstIdMovq, X86MmReg, X86MmReg) + //! \overload + INST_2x(movq, kX86InstIdMovq, X86Mem, X86MmReg) + //! \overload + INST_2x(movq, kX86InstIdMovq, X86MmReg, X86Mem) + + //! Move QWORD (X64 Only). + INST_2x(movq, kX86InstIdMovq, X86GpReg, X86MmReg) + //! \overload + INST_2x(movq, kX86InstIdMovq, X86MmReg, X86GpReg) + + //! Pack DWORDs to WORDs with signed saturation (MMX). + INST_2x(packssdw, kX86InstIdPackssdw, X86MmReg, X86MmReg) + //! \overload + INST_2x(packssdw, kX86InstIdPackssdw, X86MmReg, X86Mem) + + //! Pack WORDs to BYTEs with signed saturation (MMX). + INST_2x(packsswb, kX86InstIdPacksswb, X86MmReg, X86MmReg) + //! \overload + INST_2x(packsswb, kX86InstIdPacksswb, X86MmReg, X86Mem) + + //! Pack WORDs to BYTEs with unsigned saturation (MMX). + INST_2x(packuswb, kX86InstIdPackuswb, X86MmReg, X86MmReg) + //! \overload + INST_2x(packuswb, kX86InstIdPackuswb, X86MmReg, X86Mem) + + //! Packed BYTE add (MMX). + INST_2x(paddb, kX86InstIdPaddb, X86MmReg, X86MmReg) + //! \overload + INST_2x(paddb, kX86InstIdPaddb, X86MmReg, X86Mem) + + //! Packed DWORD add (MMX). + INST_2x(paddd, kX86InstIdPaddd, X86MmReg, X86MmReg) + //! \overload + INST_2x(paddd, kX86InstIdPaddd, X86MmReg, X86Mem) + + //! Packed BYTE add with saturation (MMX). + INST_2x(paddsb, kX86InstIdPaddsb, X86MmReg, X86MmReg) + //! \overload + INST_2x(paddsb, kX86InstIdPaddsb, X86MmReg, X86Mem) + + //! Packed WORD add with saturation (MMX). + INST_2x(paddsw, kX86InstIdPaddsw, X86MmReg, X86MmReg) + //! \overload + INST_2x(paddsw, kX86InstIdPaddsw, X86MmReg, X86Mem) + + //! Packed BYTE add with unsigned saturation (MMX). + INST_2x(paddusb, kX86InstIdPaddusb, X86MmReg, X86MmReg) + //! \overload + INST_2x(paddusb, kX86InstIdPaddusb, X86MmReg, X86Mem) + + //! Packed WORD add with unsigned saturation (MMX). + INST_2x(paddusw, kX86InstIdPaddusw, X86MmReg, X86MmReg) + //! \overload + INST_2x(paddusw, kX86InstIdPaddusw, X86MmReg, X86Mem) + + //! Packed WORD add (MMX). + INST_2x(paddw, kX86InstIdPaddw, X86MmReg, X86MmReg) + //! \overload + INST_2x(paddw, kX86InstIdPaddw, X86MmReg, X86Mem) + + //! Packed bitwise and (MMX). + INST_2x(pand, kX86InstIdPand, X86MmReg, X86MmReg) + //! \overload + INST_2x(pand, kX86InstIdPand, X86MmReg, X86Mem) + + //! Packed bitwise and-not (MMX). + INST_2x(pandn, kX86InstIdPandn, X86MmReg, X86MmReg) + //! \overload + INST_2x(pandn, kX86InstIdPandn, X86MmReg, X86Mem) + + //! Packed BYTEs compare for equality (MMX). + INST_2x(pcmpeqb, kX86InstIdPcmpeqb, X86MmReg, X86MmReg) + //! \overload + INST_2x(pcmpeqb, kX86InstIdPcmpeqb, X86MmReg, X86Mem) + + //! Packed DWORDs compare for equality (MMX). + INST_2x(pcmpeqd, kX86InstIdPcmpeqd, X86MmReg, X86MmReg) + //! \overload + INST_2x(pcmpeqd, kX86InstIdPcmpeqd, X86MmReg, X86Mem) + + //! Packed WORDs compare for equality (MMX). + INST_2x(pcmpeqw, kX86InstIdPcmpeqw, X86MmReg, X86MmReg) + //! \overload + INST_2x(pcmpeqw, kX86InstIdPcmpeqw, X86MmReg, X86Mem) + + //! Packed BYTEs compare if greater than (MMX). + INST_2x(pcmpgtb, kX86InstIdPcmpgtb, X86MmReg, X86MmReg) + //! \overload + INST_2x(pcmpgtb, kX86InstIdPcmpgtb, X86MmReg, X86Mem) + + //! Packed DWORDs compare if greater than (MMX). + INST_2x(pcmpgtd, kX86InstIdPcmpgtd, X86MmReg, X86MmReg) + //! \overload + INST_2x(pcmpgtd, kX86InstIdPcmpgtd, X86MmReg, X86Mem) + + //! Packed WORDs compare if greater than (MMX). + INST_2x(pcmpgtw, kX86InstIdPcmpgtw, X86MmReg, X86MmReg) + //! \overload + INST_2x(pcmpgtw, kX86InstIdPcmpgtw, X86MmReg, X86Mem) + + //! Packed WORDs multiply high (MMX). + INST_2x(pmulhw, kX86InstIdPmulhw, X86MmReg, X86MmReg) + //! \overload + INST_2x(pmulhw, kX86InstIdPmulhw, X86MmReg, X86Mem) + + //! Packed WORDs multiply low (MMX). + INST_2x(pmullw, kX86InstIdPmullw, X86MmReg, X86MmReg) + //! \overload + INST_2x(pmullw, kX86InstIdPmullw, X86MmReg, X86Mem) + + //! Pakced bitwise or (MMX). + INST_2x(por, kX86InstIdPor, X86MmReg, X86MmReg) + //! \overload + INST_2x(por, kX86InstIdPor, X86MmReg, X86Mem) + + //! Packed WORD multiply and add to packed DWORD (MMX). + INST_2x(pmaddwd, kX86InstIdPmaddwd, X86MmReg, X86MmReg) + //! \overload + INST_2x(pmaddwd, kX86InstIdPmaddwd, X86MmReg, X86Mem) + + //! Packed DWORD shift left logical (MMX). + INST_2x(pslld, kX86InstIdPslld, X86MmReg, X86MmReg) + //! \overload + INST_2x(pslld, kX86InstIdPslld, X86MmReg, X86Mem) + //! \overload + INST_2i(pslld, kX86InstIdPslld, X86MmReg, Imm) + + //! Packed QWORD shift left logical (MMX). + INST_2x(psllq, kX86InstIdPsllq, X86MmReg, X86MmReg) + //! \overload + INST_2x(psllq, kX86InstIdPsllq, X86MmReg, X86Mem) + //! \overload + INST_2i(psllq, kX86InstIdPsllq, X86MmReg, Imm) + + //! Packed WORD shift left logical (MMX). + INST_2x(psllw, kX86InstIdPsllw, X86MmReg, X86MmReg) + //! \overload + INST_2x(psllw, kX86InstIdPsllw, X86MmReg, X86Mem) + //! \overload + INST_2i(psllw, kX86InstIdPsllw, X86MmReg, Imm) + + //! Packed DWORD shift right arithmetic (MMX). + INST_2x(psrad, kX86InstIdPsrad, X86MmReg, X86MmReg) + //! \overload + INST_2x(psrad, kX86InstIdPsrad, X86MmReg, X86Mem) + //! \overload + INST_2i(psrad, kX86InstIdPsrad, X86MmReg, Imm) + + //! Packed WORD shift right arithmetic (MMX). + INST_2x(psraw, kX86InstIdPsraw, X86MmReg, X86MmReg) + //! \overload + INST_2x(psraw, kX86InstIdPsraw, X86MmReg, X86Mem) + //! \overload + INST_2i(psraw, kX86InstIdPsraw, X86MmReg, Imm) + + //! Packed DWORD shift right logical (MMX). + INST_2x(psrld, kX86InstIdPsrld, X86MmReg, X86MmReg) + //! \overload + INST_2x(psrld, kX86InstIdPsrld, X86MmReg, X86Mem) + //! \overload + INST_2i(psrld, kX86InstIdPsrld, X86MmReg, Imm) + + //! Packed QWORD shift right logical (MMX). + INST_2x(psrlq, kX86InstIdPsrlq, X86MmReg, X86MmReg) + //! \overload + INST_2x(psrlq, kX86InstIdPsrlq, X86MmReg, X86Mem) + //! \overload + INST_2i(psrlq, kX86InstIdPsrlq, X86MmReg, Imm) + + //! Packed WORD shift right logical (MMX). + INST_2x(psrlw, kX86InstIdPsrlw, X86MmReg, X86MmReg) + //! \overload + INST_2x(psrlw, kX86InstIdPsrlw, X86MmReg, X86Mem) + //! \overload + INST_2i(psrlw, kX86InstIdPsrlw, X86MmReg, Imm) + + //! Packed BYTE subtract (MMX). + INST_2x(psubb, kX86InstIdPsubb, X86MmReg, X86MmReg) + //! \overload + INST_2x(psubb, kX86InstIdPsubb, X86MmReg, X86Mem) + + //! Packed DWORD subtract (MMX). + INST_2x(psubd, kX86InstIdPsubd, X86MmReg, X86MmReg) + //! \overload + INST_2x(psubd, kX86InstIdPsubd, X86MmReg, X86Mem) + + //! Packed BYTE subtract with saturation (MMX). + INST_2x(psubsb, kX86InstIdPsubsb, X86MmReg, X86MmReg) + //! \overload + INST_2x(psubsb, kX86InstIdPsubsb, X86MmReg, X86Mem) + + //! Packed WORD subtract with saturation (MMX). + INST_2x(psubsw, kX86InstIdPsubsw, X86MmReg, X86MmReg) + //! \overload + INST_2x(psubsw, kX86InstIdPsubsw, X86MmReg, X86Mem) + + //! Packed BYTE subtract with unsigned saturation (MMX). + INST_2x(psubusb, kX86InstIdPsubusb, X86MmReg, X86MmReg) + //! \overload + INST_2x(psubusb, kX86InstIdPsubusb, X86MmReg, X86Mem) + + //! Packed WORD subtract with unsigned saturation (MMX). + INST_2x(psubusw, kX86InstIdPsubusw, X86MmReg, X86MmReg) + //! \overload + INST_2x(psubusw, kX86InstIdPsubusw, X86MmReg, X86Mem) + + //! Packed WORD subtract (MMX). + INST_2x(psubw, kX86InstIdPsubw, X86MmReg, X86MmReg) + //! \overload + INST_2x(psubw, kX86InstIdPsubw, X86MmReg, X86Mem) + + //! Unpack high packed BYTEs to WORDs (MMX). + INST_2x(punpckhbw, kX86InstIdPunpckhbw, X86MmReg, X86MmReg) + //! \overload + INST_2x(punpckhbw, kX86InstIdPunpckhbw, X86MmReg, X86Mem) + + //! Unpack high packed DWORDs to QWORDs (MMX). + INST_2x(punpckhdq, kX86InstIdPunpckhdq, X86MmReg, X86MmReg) + //! \overload + INST_2x(punpckhdq, kX86InstIdPunpckhdq, X86MmReg, X86Mem) + + //! Unpack high packed WORDs to DWORDs (MMX). + INST_2x(punpckhwd, kX86InstIdPunpckhwd, X86MmReg, X86MmReg) + //! \overload + INST_2x(punpckhwd, kX86InstIdPunpckhwd, X86MmReg, X86Mem) + + //! Unpack low packed BYTEs to WORDs (MMX). + INST_2x(punpcklbw, kX86InstIdPunpcklbw, X86MmReg, X86MmReg) + //! \overload + INST_2x(punpcklbw, kX86InstIdPunpcklbw, X86MmReg, X86Mem) + + //! Unpack low packed DWORDs to QWORDs (MMX). + INST_2x(punpckldq, kX86InstIdPunpckldq, X86MmReg, X86MmReg) + //! \overload + INST_2x(punpckldq, kX86InstIdPunpckldq, X86MmReg, X86Mem) + + //! Unpack low packed WORDs to DWORDs (MMX). + INST_2x(punpcklwd, kX86InstIdPunpcklwd, X86MmReg, X86MmReg) + //! \overload + INST_2x(punpcklwd, kX86InstIdPunpcklwd, X86MmReg, X86Mem) + + //! Packed bitwise xor (MMX). + INST_2x(pxor, kX86InstIdPxor, X86MmReg, X86MmReg) + //! \overload + INST_2x(pxor, kX86InstIdPxor, X86MmReg, X86Mem) + + //! Empty MMX state. + INST_0x(emms, kX86InstIdEmms) + + // ------------------------------------------------------------------------- + // [3dNow] + // ------------------------------------------------------------------------- + + //! Packed SP-FP to DWORD convert (3dNow!). + INST_2x(pf2id, kX86InstIdPf2id, X86MmReg, X86MmReg) + //! \overload + INST_2x(pf2id, kX86InstIdPf2id, X86MmReg, X86Mem) + + //! Packed SP-FP to WORD convert (3dNow!). + INST_2x(pf2iw, kX86InstIdPf2iw, X86MmReg, X86MmReg) + //! \overload + INST_2x(pf2iw, kX86InstIdPf2iw, X86MmReg, X86Mem) + + //! Packed SP-FP accumulate (3dNow!). + INST_2x(pfacc, kX86InstIdPfacc, X86MmReg, X86MmReg) + //! \overload + INST_2x(pfacc, kX86InstIdPfacc, X86MmReg, X86Mem) + + //! Packed SP-FP addition (3dNow!). + INST_2x(pfadd, kX86InstIdPfadd, X86MmReg, X86MmReg) + //! \overload + INST_2x(pfadd, kX86InstIdPfadd, X86MmReg, X86Mem) + + //! Packed SP-FP compare - dst == src (3dNow!). + INST_2x(pfcmpeq, kX86InstIdPfcmpeq, X86MmReg, X86MmReg) + //! \overload + INST_2x(pfcmpeq, kX86InstIdPfcmpeq, X86MmReg, X86Mem) + + //! Packed SP-FP compare - dst >= src (3dNow!). + INST_2x(pfcmpge, kX86InstIdPfcmpge, X86MmReg, X86MmReg) + //! \overload + INST_2x(pfcmpge, kX86InstIdPfcmpge, X86MmReg, X86Mem) + + //! Packed SP-FP compare - dst > src (3dNow!). + INST_2x(pfcmpgt, kX86InstIdPfcmpgt, X86MmReg, X86MmReg) + //! \overload + INST_2x(pfcmpgt, kX86InstIdPfcmpgt, X86MmReg, X86Mem) + + //! Packed SP-FP maximum (3dNow!). + INST_2x(pfmax, kX86InstIdPfmax, X86MmReg, X86MmReg) + //! \overload + INST_2x(pfmax, kX86InstIdPfmax, X86MmReg, X86Mem) + + //! Packed SP-FP minimum (3dNow!). + INST_2x(pfmin, kX86InstIdPfmin, X86MmReg, X86MmReg) + //! \overload + INST_2x(pfmin, kX86InstIdPfmin, X86MmReg, X86Mem) + + //! Packed SP-FP multiply (3dNow!). + INST_2x(pfmul, kX86InstIdPfmul, X86MmReg, X86MmReg) + //! \overload + INST_2x(pfmul, kX86InstIdPfmul, X86MmReg, X86Mem) + + //! Packed SP-FP negative accumulate (3dNow!). + INST_2x(pfnacc, kX86InstIdPfnacc, X86MmReg, X86MmReg) + //! \overload + INST_2x(pfnacc, kX86InstIdPfnacc, X86MmReg, X86Mem) + + //! Packed SP-FP mixed accumulate (3dNow!). + INST_2x(pfpnacc, kX86InstIdPfpnacc, X86MmReg, X86MmReg) + //! \overload + INST_2x(pfpnacc, kX86InstIdPfpnacc, X86MmReg, X86Mem) + + //! Packed SP-FP reciprocal Approximation (3dNow!). + INST_2x(pfrcp, kX86InstIdPfrcp, X86MmReg, X86MmReg) + //! \overload + INST_2x(pfrcp, kX86InstIdPfrcp, X86MmReg, X86Mem) + + //! Packed SP-FP reciprocal, first iteration step (3dNow!). + INST_2x(pfrcpit1, kX86InstIdPfrcpit1, X86MmReg, X86MmReg) + //! \overload + INST_2x(pfrcpit1, kX86InstIdPfrcpit1, X86MmReg, X86Mem) + + //! Packed SP-FP reciprocal, second iteration step (3dNow!). + INST_2x(pfrcpit2, kX86InstIdPfrcpit2, X86MmReg, X86MmReg) + //! \overload + INST_2x(pfrcpit2, kX86InstIdPfrcpit2, X86MmReg, X86Mem) + + //! Packed SP-FP reciprocal square root, first iteration step (3dNow!). + INST_2x(pfrsqit1, kX86InstIdPfrsqit1, X86MmReg, X86MmReg) + //! \overload + INST_2x(pfrsqit1, kX86InstIdPfrsqit1, X86MmReg, X86Mem) + + //! Packed SP-FP reciprocal square root approximation (3dNow!). + INST_2x(pfrsqrt, kX86InstIdPfrsqrt, X86MmReg, X86MmReg) + //! \overload + INST_2x(pfrsqrt, kX86InstIdPfrsqrt, X86MmReg, X86Mem) + + //! Packed SP-FP subtract (3dNow!). + INST_2x(pfsub, kX86InstIdPfsub, X86MmReg, X86MmReg) + //! \overload + INST_2x(pfsub, kX86InstIdPfsub, X86MmReg, X86Mem) + + //! Packed SP-FP reverse subtract (3dNow!). + INST_2x(pfsubr, kX86InstIdPfsubr, X86MmReg, X86MmReg) + //! \overload + INST_2x(pfsubr, kX86InstIdPfsubr, X86MmReg, X86Mem) + + //! Packed DWORDs to SP-FP (3dNow!). + INST_2x(pi2fd, kX86InstIdPi2fd, X86MmReg, X86MmReg) + //! \overload + INST_2x(pi2fd, kX86InstIdPi2fd, X86MmReg, X86Mem) + + //! Packed WORDs to SP-FP (3dNow!). + INST_2x(pi2fw, kX86InstIdPi2fw, X86MmReg, X86MmReg) + //! \overload + INST_2x(pi2fw, kX86InstIdPi2fw, X86MmReg, X86Mem) + + //! Packed swap DWORDs (3dNow!) + INST_2x(pswapd, kX86InstIdPswapd, X86MmReg, X86MmReg) + //! \overload + INST_2x(pswapd, kX86InstIdPswapd, X86MmReg, X86Mem) + + //! Prefetch (3dNow!). + INST_1x(prefetch3dnow, kX86InstIdPrefetch3dNow, X86Mem) + + //! Prefetch and set cache to modified (3dNow!). + INST_1x(prefetchw3dnow, kX86InstIdPrefetchw3dNow, X86Mem) + + //! Faster EMMS (3dNow!). + INST_0x(femms, kX86InstIdFemms) + + // -------------------------------------------------------------------------- + // [SSE] + // -------------------------------------------------------------------------- + + //! Packed SP-FP add (SSE). + INST_2x(addps, kX86InstIdAddps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(addps, kX86InstIdAddps, X86XmmReg, X86Mem) + + //! Scalar SP-FP add (SSE). + INST_2x(addss, kX86InstIdAddss, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(addss, kX86InstIdAddss, X86XmmReg, X86Mem) + + //! Packed SP-FP bitwise and-not (SSE). + INST_2x(andnps, kX86InstIdAndnps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(andnps, kX86InstIdAndnps, X86XmmReg, X86Mem) + + //! Packed SP-FP bitwise and (SSE). + INST_2x(andps, kX86InstIdAndps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(andps, kX86InstIdAndps, X86XmmReg, X86Mem) + + //! Packed SP-FP compare (SSE). + INST_3i(cmpps, kX86InstIdCmpps, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(cmpps, kX86InstIdCmpps, X86XmmReg, X86Mem, Imm) + + //! Compare scalar SP-FP (SSE). + INST_3i(cmpss, kX86InstIdCmpss, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(cmpss, kX86InstIdCmpss, X86XmmReg, X86Mem, Imm) + + //! Scalar ordered SP-FP compare and set EFLAGS (SSE). + INST_2x(comiss, kX86InstIdComiss, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(comiss, kX86InstIdComiss, X86XmmReg, X86Mem) + + //! Packed signed INT32 to packed SP-FP conversion (SSE). + INST_2x(cvtpi2ps, kX86InstIdCvtpi2ps, X86XmmReg, X86MmReg) + //! \overload + INST_2x(cvtpi2ps, kX86InstIdCvtpi2ps, X86XmmReg, X86Mem) + + //! Packed SP-FP to packed INT32 conversion (SSE). + INST_2x(cvtps2pi, kX86InstIdCvtps2pi, X86MmReg, X86XmmReg) + //! \overload + INST_2x(cvtps2pi, kX86InstIdCvtps2pi, X86MmReg, X86Mem) + + //! Convert scalar INT32 to SP-FP (SSE). + INST_2x(cvtsi2ss, kX86InstIdCvtsi2ss, X86XmmReg, X86GpReg) + //! \overload + INST_2x(cvtsi2ss, kX86InstIdCvtsi2ss, X86XmmReg, X86Mem) + + //! Convert scalar SP-FP to INT32 (SSE). + INST_2x(cvtss2si, kX86InstIdCvtss2si, X86GpReg, X86XmmReg) + //! \overload + INST_2x(cvtss2si, kX86InstIdCvtss2si, X86GpReg, X86Mem) + + //! Convert with truncation packed SP-FP to packed INT32 (SSE). + INST_2x(cvttps2pi, kX86InstIdCvttps2pi, X86MmReg, X86XmmReg) + //! \overload + INST_2x(cvttps2pi, kX86InstIdCvttps2pi, X86MmReg, X86Mem) + + //! Convert with truncation scalar SP-FP to INT32 (SSE). + INST_2x(cvttss2si, kX86InstIdCvttss2si, X86GpReg, X86XmmReg) + //! \overload + INST_2x(cvttss2si, kX86InstIdCvttss2si, X86GpReg, X86Mem) + + //! Packed SP-FP divide (SSE). + INST_2x(divps, kX86InstIdDivps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(divps, kX86InstIdDivps, X86XmmReg, X86Mem) + + //! Scalar SP-FP divide (SSE). + INST_2x(divss, kX86InstIdDivss, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(divss, kX86InstIdDivss, X86XmmReg, X86Mem) + + //! Load streaming SIMD extension control/status (SSE). + INST_1x(ldmxcsr, kX86InstIdLdmxcsr, X86Mem) + + //! Byte mask write to DS:EDI/RDI (SSE). + INST_2x(maskmovq, kX86InstIdMaskmovq, X86MmReg, X86MmReg) + + //! Packed SP-FP maximum (SSE). + INST_2x(maxps, kX86InstIdMaxps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(maxps, kX86InstIdMaxps, X86XmmReg, X86Mem) + + //! Scalar SP-FP maximum (SSE). + INST_2x(maxss, kX86InstIdMaxss, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(maxss, kX86InstIdMaxss, X86XmmReg, X86Mem) + + //! Packed SP-FP minimum (SSE). + INST_2x(minps, kX86InstIdMinps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(minps, kX86InstIdMinps, X86XmmReg, X86Mem) + + //! Scalar SP-FP minimum (SSE). + INST_2x(minss, kX86InstIdMinss, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(minss, kX86InstIdMinss, X86XmmReg, X86Mem) + + //! Move aligned packed SP-FP (SSE). + INST_2x(movaps, kX86InstIdMovaps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(movaps, kX86InstIdMovaps, X86XmmReg, X86Mem) + //! Move aligned packed SP-FP (SSE). + INST_2x(movaps, kX86InstIdMovaps, X86Mem, X86XmmReg) + + //! Move DWORD. + INST_2x(movd, kX86InstIdMovd, X86Mem, X86XmmReg) + //! \overload + INST_2x(movd, kX86InstIdMovd, X86GpReg, X86XmmReg) + //! \overload + INST_2x(movd, kX86InstIdMovd, X86XmmReg, X86Mem) + //! \overload + INST_2x(movd, kX86InstIdMovd, X86XmmReg, X86GpReg) + + //! Move QWORD (SSE). + INST_2x(movq, kX86InstIdMovq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(movq, kX86InstIdMovq, X86Mem, X86XmmReg) + //! \overload + INST_2x(movq, kX86InstIdMovq, X86XmmReg, X86Mem) + + //! Move QWORD (X64 Only). + INST_2x(movq, kX86InstIdMovq, X86GpReg, X86XmmReg) + //! \overload + INST_2x(movq, kX86InstIdMovq, X86XmmReg, X86GpReg) + + //! Move QWORD using NT hint (SSE). + INST_2x(movntq, kX86InstIdMovntq, X86Mem, X86MmReg) + + //! Move high to low packed SP-FP (SSE). + INST_2x(movhlps, kX86InstIdMovhlps, X86XmmReg, X86XmmReg) + + //! Move high packed SP-FP (SSE). + INST_2x(movhps, kX86InstIdMovhps, X86XmmReg, X86Mem) + //! Move high packed SP-FP (SSE). + INST_2x(movhps, kX86InstIdMovhps, X86Mem, X86XmmReg) + + //! Move low to high packed SP-FP (SSE). + INST_2x(movlhps, kX86InstIdMovlhps, X86XmmReg, X86XmmReg) + + //! Move low packed SP-FP (SSE). + INST_2x(movlps, kX86InstIdMovlps, X86XmmReg, X86Mem) + //! Move low packed SP-FP (SSE). + INST_2x(movlps, kX86InstIdMovlps, X86Mem, X86XmmReg) + + //! Move aligned packed SP-FP using NT hint (SSE). + INST_2x(movntps, kX86InstIdMovntps, X86Mem, X86XmmReg) + + //! Move scalar SP-FP (SSE). + INST_2x(movss, kX86InstIdMovss, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(movss, kX86InstIdMovss, X86XmmReg, X86Mem) + //! \overload + INST_2x(movss, kX86InstIdMovss, X86Mem, X86XmmReg) + + //! Move unaligned packed SP-FP (SSE). + INST_2x(movups, kX86InstIdMovups, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(movups, kX86InstIdMovups, X86XmmReg, X86Mem) + //! \overload + INST_2x(movups, kX86InstIdMovups, X86Mem, X86XmmReg) + + //! Packed SP-FP multiply (SSE). + INST_2x(mulps, kX86InstIdMulps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(mulps, kX86InstIdMulps, X86XmmReg, X86Mem) + + //! Scalar SP-FP multiply (SSE). + INST_2x(mulss, kX86InstIdMulss, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(mulss, kX86InstIdMulss, X86XmmReg, X86Mem) + + //! Packed SP-FP bitwise or (SSE). + INST_2x(orps, kX86InstIdOrps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(orps, kX86InstIdOrps, X86XmmReg, X86Mem) + + //! Packed BYTE average (SSE). + INST_2x(pavgb, kX86InstIdPavgb, X86MmReg, X86MmReg) + //! \overload + INST_2x(pavgb, kX86InstIdPavgb, X86MmReg, X86Mem) + + //! Packed WORD average (SSE). + INST_2x(pavgw, kX86InstIdPavgw, X86MmReg, X86MmReg) + //! \overload + INST_2x(pavgw, kX86InstIdPavgw, X86MmReg, X86Mem) + + //! Extract WORD based on selector (SSE). + INST_3i(pextrw, kX86InstIdPextrw, X86GpReg, X86MmReg, Imm) + + //! Insert WORD based on selector (SSE). + INST_3i(pinsrw, kX86InstIdPinsrw, X86MmReg, X86GpReg, Imm) + //! \overload + INST_3i(pinsrw, kX86InstIdPinsrw, X86MmReg, X86Mem, Imm) + + //! Packed WORD maximum (SSE). + INST_2x(pmaxsw, kX86InstIdPmaxsw, X86MmReg, X86MmReg) + //! \overload + INST_2x(pmaxsw, kX86InstIdPmaxsw, X86MmReg, X86Mem) + + //! Packed BYTE unsigned maximum (SSE). + INST_2x(pmaxub, kX86InstIdPmaxub, X86MmReg, X86MmReg) + //! \overload + INST_2x(pmaxub, kX86InstIdPmaxub, X86MmReg, X86Mem) + + //! Packed WORD minimum (SSE). + INST_2x(pminsw, kX86InstIdPminsw, X86MmReg, X86MmReg) + //! \overload + INST_2x(pminsw, kX86InstIdPminsw, X86MmReg, X86Mem) + + //! Packed BYTE unsigned minimum (SSE). + INST_2x(pminub, kX86InstIdPminub, X86MmReg, X86MmReg) + //! \overload + INST_2x(pminub, kX86InstIdPminub, X86MmReg, X86Mem) + + //! Move Byte mask to integer (SSE). + INST_2x(pmovmskb, kX86InstIdPmovmskb, X86GpReg, X86MmReg) + + //! Packed WORD unsigned multiply high (SSE). + INST_2x(pmulhuw, kX86InstIdPmulhuw, X86MmReg, X86MmReg) + //! \overload + INST_2x(pmulhuw, kX86InstIdPmulhuw, X86MmReg, X86Mem) + + //! Packed WORD sum of absolute differences (SSE). + INST_2x(psadbw, kX86InstIdPsadbw, X86MmReg, X86MmReg) + //! \overload + INST_2x(psadbw, kX86InstIdPsadbw, X86MmReg, X86Mem) + + //! Packed WORD shuffle (SSE). + INST_3i(pshufw, kX86InstIdPshufw, X86MmReg, X86MmReg, Imm) + //! \overload + INST_3i(pshufw, kX86InstIdPshufw, X86MmReg, X86Mem, Imm) + + //! Packed SP-FP reciprocal (SSE). + INST_2x(rcpps, kX86InstIdRcpps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(rcpps, kX86InstIdRcpps, X86XmmReg, X86Mem) + + //! Scalar SP-FP reciprocal (SSE). + INST_2x(rcpss, kX86InstIdRcpss, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(rcpss, kX86InstIdRcpss, X86XmmReg, X86Mem) + + //! Prefetch (SSE). + INST_2i(prefetch, kX86InstIdPrefetch, X86Mem, Imm) + + //! Packed WORD sum of absolute differences (SSE). + INST_2x(psadbw, kX86InstIdPsadbw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psadbw, kX86InstIdPsadbw, X86XmmReg, X86Mem) + + //! Packed SP-FP square root reciprocal (SSE). + INST_2x(rsqrtps, kX86InstIdRsqrtps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(rsqrtps, kX86InstIdRsqrtps, X86XmmReg, X86Mem) + + //! Scalar SP-FP square root reciprocal (SSE). + INST_2x(rsqrtss, kX86InstIdRsqrtss, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(rsqrtss, kX86InstIdRsqrtss, X86XmmReg, X86Mem) + + //! Store fence (SSE). + INST_0x(sfence, kX86InstIdSfence) + + //! Shuffle SP-FP (SSE). + INST_3i(shufps, kX86InstIdShufps, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(shufps, kX86InstIdShufps, X86XmmReg, X86Mem, Imm) + + //! Packed SP-FP square root (SSE). + INST_2x(sqrtps, kX86InstIdSqrtps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(sqrtps, kX86InstIdSqrtps, X86XmmReg, X86Mem) + + //! Scalar SP-FP square root (SSE). + INST_2x(sqrtss, kX86InstIdSqrtss, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(sqrtss, kX86InstIdSqrtss, X86XmmReg, X86Mem) + + //! Store streaming SIMD extension control/status (SSE). + INST_1x(stmxcsr, kX86InstIdStmxcsr, X86Mem) + + //! Packed SP-FP subtract (SSE). + INST_2x(subps, kX86InstIdSubps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(subps, kX86InstIdSubps, X86XmmReg, X86Mem) + + //! Scalar SP-FP subtract (SSE). + INST_2x(subss, kX86InstIdSubss, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(subss, kX86InstIdSubss, X86XmmReg, X86Mem) + + //! Unordered scalar SP-FP compare and set EFLAGS (SSE). + INST_2x(ucomiss, kX86InstIdUcomiss, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(ucomiss, kX86InstIdUcomiss, X86XmmReg, X86Mem) + + //! Unpack high packed SP-FP data (SSE). + INST_2x(unpckhps, kX86InstIdUnpckhps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(unpckhps, kX86InstIdUnpckhps, X86XmmReg, X86Mem) + + //! Unpack low packed SP-FP data (SSE). + INST_2x(unpcklps, kX86InstIdUnpcklps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(unpcklps, kX86InstIdUnpcklps, X86XmmReg, X86Mem) + + //! Packed SP-FP bitwise xor (SSE). + INST_2x(xorps, kX86InstIdXorps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(xorps, kX86InstIdXorps, X86XmmReg, X86Mem) + + // -------------------------------------------------------------------------- + // [SSE2] + // -------------------------------------------------------------------------- + + //! Packed DP-FP add (SSE2). + INST_2x(addpd, kX86InstIdAddpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(addpd, kX86InstIdAddpd, X86XmmReg, X86Mem) + + //! Scalar DP-FP add (SSE2). + INST_2x(addsd, kX86InstIdAddsd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(addsd, kX86InstIdAddsd, X86XmmReg, X86Mem) + + //! Packed DP-FP bitwise and-not (SSE2). + INST_2x(andnpd, kX86InstIdAndnpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(andnpd, kX86InstIdAndnpd, X86XmmReg, X86Mem) + + //! Packed DP-FP bitwise and (SSE2). + INST_2x(andpd, kX86InstIdAndpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(andpd, kX86InstIdAndpd, X86XmmReg, X86Mem) + + //! Flush cache line (SSE2). + INST_1x(clflush, kX86InstIdClflush, X86Mem) + + //! Packed DP-FP compare (SSE2). + INST_3i(cmppd, kX86InstIdCmppd, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(cmppd, kX86InstIdCmppd, X86XmmReg, X86Mem, Imm) + + //! Scalar SP-FP compare (SSE2). + INST_3i(cmpsd, kX86InstIdCmpsd, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(cmpsd, kX86InstIdCmpsd, X86XmmReg, X86Mem, Imm) + + //! Scalar ordered DP-FP compare and set EFLAGS (SSE2). + INST_2x(comisd, kX86InstIdComisd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(comisd, kX86InstIdComisd, X86XmmReg, X86Mem) + + //! Convert packed QWORDs to packed DP-FP (SSE2). + INST_2x(cvtdq2pd, kX86InstIdCvtdq2pd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(cvtdq2pd, kX86InstIdCvtdq2pd, X86XmmReg, X86Mem) + + //! Convert packed QWORDs to packed SP-FP (SSE2). + INST_2x(cvtdq2ps, kX86InstIdCvtdq2ps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(cvtdq2ps, kX86InstIdCvtdq2ps, X86XmmReg, X86Mem) + + //! Convert packed DP-FP to packed DWORDs (SSE2). + INST_2x(cvtpd2dq, kX86InstIdCvtpd2dq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(cvtpd2dq, kX86InstIdCvtpd2dq, X86XmmReg, X86Mem) + + //! Convert packed DP-FP to packed DWORDs (SSE2). + INST_2x(cvtpd2pi, kX86InstIdCvtpd2pi, X86MmReg, X86XmmReg) + //! \overload + INST_2x(cvtpd2pi, kX86InstIdCvtpd2pi, X86MmReg, X86Mem) + + //! Convert packed DP-FP to packed SP-FP (SSE2). + INST_2x(cvtpd2ps, kX86InstIdCvtpd2ps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(cvtpd2ps, kX86InstIdCvtpd2ps, X86XmmReg, X86Mem) + + //! Convert packed DWORDs integers to packed DP-FP (SSE2). + INST_2x(cvtpi2pd, kX86InstIdCvtpi2pd, X86XmmReg, X86MmReg) + //! \overload + INST_2x(cvtpi2pd, kX86InstIdCvtpi2pd, X86XmmReg, X86Mem) + + //! Convert packed SP-FP to packed DWORDs (SSE2). + INST_2x(cvtps2dq, kX86InstIdCvtps2dq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(cvtps2dq, kX86InstIdCvtps2dq, X86XmmReg, X86Mem) + + //! Convert packed SP-FP to packed DP-FP (SSE2). + INST_2x(cvtps2pd, kX86InstIdCvtps2pd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(cvtps2pd, kX86InstIdCvtps2pd, X86XmmReg, X86Mem) + + //! Convert scalar DP-FP to DWORD integer (SSE2). + INST_2x(cvtsd2si, kX86InstIdCvtsd2si, X86GpReg, X86XmmReg) + //! \overload + INST_2x(cvtsd2si, kX86InstIdCvtsd2si, X86GpReg, X86Mem) + + //! Convert scalar DP-FP to scalar SP-FP (SSE2). + INST_2x(cvtsd2ss, kX86InstIdCvtsd2ss, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(cvtsd2ss, kX86InstIdCvtsd2ss, X86XmmReg, X86Mem) + + //! Convert DWORD integer to scalar DP-FP (SSE2). + INST_2x(cvtsi2sd, kX86InstIdCvtsi2sd, X86XmmReg, X86GpReg) + //! \overload + INST_2x(cvtsi2sd, kX86InstIdCvtsi2sd, X86XmmReg, X86Mem) + + //! Convert scalar SP-FP to DP-FP (SSE2). + INST_2x(cvtss2sd, kX86InstIdCvtss2sd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(cvtss2sd, kX86InstIdCvtss2sd, X86XmmReg, X86Mem) + + //! Convert with truncation packed DP-FP to packed DWORDs (SSE2). + INST_2x(cvttpd2pi, kX86InstIdCvttpd2pi, X86MmReg, X86XmmReg) + //! \overload + INST_2x(cvttpd2pi, kX86InstIdCvttpd2pi, X86MmReg, X86Mem) + + //! Convert with truncation packed DP-FP to packed DWORDs (SSE2). + INST_2x(cvttpd2dq, kX86InstIdCvttpd2dq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(cvttpd2dq, kX86InstIdCvttpd2dq, X86XmmReg, X86Mem) + + //! Convert with truncation packed SP-FP to packed DWORDs (SSE2). + INST_2x(cvttps2dq, kX86InstIdCvttps2dq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(cvttps2dq, kX86InstIdCvttps2dq, X86XmmReg, X86Mem) + + //! Convert with truncation scalar DP-FP to signed DWORDs (SSE2). + INST_2x(cvttsd2si, kX86InstIdCvttsd2si, X86GpReg, X86XmmReg) + //! \overload + INST_2x(cvttsd2si, kX86InstIdCvttsd2si, X86GpReg, X86Mem) + + //! Packed DP-FP divide (SSE2). + INST_2x(divpd, kX86InstIdDivpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(divpd, kX86InstIdDivpd, X86XmmReg, X86Mem) + + //! Scalar DP-FP divide (SSE2). + INST_2x(divsd, kX86InstIdDivsd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(divsd, kX86InstIdDivsd, X86XmmReg, X86Mem) + + //! Load fence (SSE2). + INST_0x(lfence, kX86InstIdLfence) + + //! Store selected bytes of OWORD to DS:EDI/RDI (SSE2). + INST_2x(maskmovdqu, kX86InstIdMaskmovdqu, X86XmmReg, X86XmmReg) + + //! Packed DP-FP maximum (SSE2). + INST_2x(maxpd, kX86InstIdMaxpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(maxpd, kX86InstIdMaxpd, X86XmmReg, X86Mem) + + //! Scalar DP-FP maximum (SSE2). + INST_2x(maxsd, kX86InstIdMaxsd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(maxsd, kX86InstIdMaxsd, X86XmmReg, X86Mem) + + //! Memory fence (SSE2). + INST_0x(mfence, kX86InstIdMfence) + + //! Packed DP-FP minimum (SSE2). + INST_2x(minpd, kX86InstIdMinpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(minpd, kX86InstIdMinpd, X86XmmReg, X86Mem) + + //! Scalar DP-FP minimum (SSE2). + INST_2x(minsd, kX86InstIdMinsd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(minsd, kX86InstIdMinsd, X86XmmReg, X86Mem) + + //! Move aligned OWORD (SSE2). + INST_2x(movdqa, kX86InstIdMovdqa, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(movdqa, kX86InstIdMovdqa, X86XmmReg, X86Mem) + //! \overload + INST_2x(movdqa, kX86InstIdMovdqa, X86Mem, X86XmmReg) + + //! Move unaligned OWORD (SSE2). + INST_2x(movdqu, kX86InstIdMovdqu, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(movdqu, kX86InstIdMovdqu, X86XmmReg, X86Mem) + //! \overload + INST_2x(movdqu, kX86InstIdMovdqu, X86Mem, X86XmmReg) + + //! Extract packed SP-FP sign mask (SSE2). + INST_2x(movmskps, kX86InstIdMovmskps, X86GpReg, X86XmmReg) + + //! Extract packed DP-FP sign mask (SSE2). + INST_2x(movmskpd, kX86InstIdMovmskpd, X86GpReg, X86XmmReg) + + //! Move scalar DP-FP (SSE2). + INST_2x(movsd, kX86InstIdMovsd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(movsd, kX86InstIdMovsd, X86XmmReg, X86Mem) + //! \overload + INST_2x(movsd, kX86InstIdMovsd, X86Mem, X86XmmReg) + + //! Move aligned packed DP-FP (SSE2). + INST_2x(movapd, kX86InstIdMovapd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(movapd, kX86InstIdMovapd, X86XmmReg, X86Mem) + //! \overload + INST_2x(movapd, kX86InstIdMovapd, X86Mem, X86XmmReg) + + //! Move QWORD from Xmm to Mm register (SSE2). + INST_2x(movdq2q, kX86InstIdMovdq2q, X86MmReg, X86XmmReg) + + //! Move QWORD from Mm to Xmm register (SSE2). + INST_2x(movq2dq, kX86InstIdMovq2dq, X86XmmReg, X86MmReg) + + //! Move high packed DP-FP (SSE2). + INST_2x(movhpd, kX86InstIdMovhpd, X86XmmReg, X86Mem) + //! \overload + INST_2x(movhpd, kX86InstIdMovhpd, X86Mem, X86XmmReg) + + //! Move low packed DP-FP (SSE2). + INST_2x(movlpd, kX86InstIdMovlpd, X86XmmReg, X86Mem) + //! \overload + INST_2x(movlpd, kX86InstIdMovlpd, X86Mem, X86XmmReg) + + //! Store OWORD using NT hint (SSE2). + INST_2x(movntdq, kX86InstIdMovntdq, X86Mem, X86XmmReg) + + //! Store DWORD using NT hint (SSE2). + INST_2x(movnti, kX86InstIdMovnti, X86Mem, X86GpReg) + + //! Store packed DP-FP using NT hint (SSE2). + INST_2x(movntpd, kX86InstIdMovntpd, X86Mem, X86XmmReg) + + //! Move unaligned packed DP-FP (SSE2). + INST_2x(movupd, kX86InstIdMovupd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(movupd, kX86InstIdMovupd, X86XmmReg, X86Mem) + //! \overload + INST_2x(movupd, kX86InstIdMovupd, X86Mem, X86XmmReg) + + //! Packed DP-FP multiply (SSE2). + INST_2x(mulpd, kX86InstIdMulpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(mulpd, kX86InstIdMulpd, X86XmmReg, X86Mem) + + //! Scalar DP-FP multiply (SSE2). + INST_2x(mulsd, kX86InstIdMulsd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(mulsd, kX86InstIdMulsd, X86XmmReg, X86Mem) + + //! Packed DP-FP bitwise or (SSE2). + INST_2x(orpd, kX86InstIdOrpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(orpd, kX86InstIdOrpd, X86XmmReg, X86Mem) + + //! Pack WORDs to BYTEs with signed saturation (SSE2). + INST_2x(packsswb, kX86InstIdPacksswb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(packsswb, kX86InstIdPacksswb, X86XmmReg, X86Mem) + + //! Pack DWORDs to WORDs with signed saturation (SSE2). + INST_2x(packssdw, kX86InstIdPackssdw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(packssdw, kX86InstIdPackssdw, X86XmmReg, X86Mem) + + //! Pack WORDs to BYTEs with unsigned saturation (SSE2). + INST_2x(packuswb, kX86InstIdPackuswb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(packuswb, kX86InstIdPackuswb, X86XmmReg, X86Mem) + + //! Packed BYTE Add (SSE2). + INST_2x(paddb, kX86InstIdPaddb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(paddb, kX86InstIdPaddb, X86XmmReg, X86Mem) + + //! Packed WORD add (SSE2). + INST_2x(paddw, kX86InstIdPaddw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(paddw, kX86InstIdPaddw, X86XmmReg, X86Mem) + + //! Packed DWORD add (SSE2). + INST_2x(paddd, kX86InstIdPaddd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(paddd, kX86InstIdPaddd, X86XmmReg, X86Mem) + + //! Packed QWORD add (SSE2). + INST_2x(paddq, kX86InstIdPaddq, X86MmReg, X86MmReg) + //! \overload + INST_2x(paddq, kX86InstIdPaddq, X86MmReg, X86Mem) + + //! Packed QWORD add (SSE2). + INST_2x(paddq, kX86InstIdPaddq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(paddq, kX86InstIdPaddq, X86XmmReg, X86Mem) + + //! Packed BYTE add with saturation (SSE2). + INST_2x(paddsb, kX86InstIdPaddsb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(paddsb, kX86InstIdPaddsb, X86XmmReg, X86Mem) + + //! Packed WORD add with saturation (SSE2). + INST_2x(paddsw, kX86InstIdPaddsw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(paddsw, kX86InstIdPaddsw, X86XmmReg, X86Mem) + + //! Packed BYTE add with unsigned saturation (SSE2). + INST_2x(paddusb, kX86InstIdPaddusb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(paddusb, kX86InstIdPaddusb, X86XmmReg, X86Mem) + + //! Packed WORD add with unsigned saturation (SSE2). + INST_2x(paddusw, kX86InstIdPaddusw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(paddusw, kX86InstIdPaddusw, X86XmmReg, X86Mem) + + //! Packed bitwise and (SSE2). + INST_2x(pand, kX86InstIdPand, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pand, kX86InstIdPand, X86XmmReg, X86Mem) + + //! Packed bitwise and-not (SSE2). + INST_2x(pandn, kX86InstIdPandn, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pandn, kX86InstIdPandn, X86XmmReg, X86Mem) + + //! Spin loop hint (SSE2). + INST_0x(pause, kX86InstIdPause) + + //! Packed BYTE average (SSE2). + INST_2x(pavgb, kX86InstIdPavgb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pavgb, kX86InstIdPavgb, X86XmmReg, X86Mem) + + //! Packed WORD average (SSE2). + INST_2x(pavgw, kX86InstIdPavgw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pavgw, kX86InstIdPavgw, X86XmmReg, X86Mem) + + //! Packed BYTE compare for equality (SSE2). + INST_2x(pcmpeqb, kX86InstIdPcmpeqb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pcmpeqb, kX86InstIdPcmpeqb, X86XmmReg, X86Mem) + + //! Packed WORD compare for equality (SSE2). + INST_2x(pcmpeqw, kX86InstIdPcmpeqw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pcmpeqw, kX86InstIdPcmpeqw, X86XmmReg, X86Mem) + + //! Packed DWORD compare for equality (SSE2). + INST_2x(pcmpeqd, kX86InstIdPcmpeqd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pcmpeqd, kX86InstIdPcmpeqd, X86XmmReg, X86Mem) + + //! Packed BYTE compare if greater than (SSE2). + INST_2x(pcmpgtb, kX86InstIdPcmpgtb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pcmpgtb, kX86InstIdPcmpgtb, X86XmmReg, X86Mem) + + //! Packed WORD compare if greater than (SSE2). + INST_2x(pcmpgtw, kX86InstIdPcmpgtw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pcmpgtw, kX86InstIdPcmpgtw, X86XmmReg, X86Mem) + + //! Packed DWORD compare if greater than (SSE2). + INST_2x(pcmpgtd, kX86InstIdPcmpgtd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pcmpgtd, kX86InstIdPcmpgtd, X86XmmReg, X86Mem) + + //! Extract WORD based on selector (SSE2). + INST_3i(pextrw, kX86InstIdPextrw, X86GpReg, X86XmmReg, Imm) + + //! Insert WORD based on selector (SSE2). + INST_3i(pinsrw, kX86InstIdPinsrw, X86XmmReg, X86GpReg, Imm) + //! \overload + INST_3i(pinsrw, kX86InstIdPinsrw, X86XmmReg, X86Mem, Imm) + + //! Packed WORD maximum (SSE2). + INST_2x(pmaxsw, kX86InstIdPmaxsw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmaxsw, kX86InstIdPmaxsw, X86XmmReg, X86Mem) + + //! Packed BYTE unsigned maximum (SSE2). + INST_2x(pmaxub, kX86InstIdPmaxub, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmaxub, kX86InstIdPmaxub, X86XmmReg, X86Mem) + + //! Packed WORD minimum (SSE2). + INST_2x(pminsw, kX86InstIdPminsw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pminsw, kX86InstIdPminsw, X86XmmReg, X86Mem) + + //! Packed BYTE unsigned minimum (SSE2). + INST_2x(pminub, kX86InstIdPminub, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pminub, kX86InstIdPminub, X86XmmReg, X86Mem) + + //! Move byte mask (SSE2). + INST_2x(pmovmskb, kX86InstIdPmovmskb, X86GpReg, X86XmmReg) + + //! Packed WORD multiply high (SSE2). + INST_2x(pmulhw, kX86InstIdPmulhw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmulhw, kX86InstIdPmulhw, X86XmmReg, X86Mem) + + //! Packed WORD unsigned multiply high (SSE2). + INST_2x(pmulhuw, kX86InstIdPmulhuw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmulhuw, kX86InstIdPmulhuw, X86XmmReg, X86Mem) + + //! Packed WORD multiply low (SSE2). + INST_2x(pmullw, kX86InstIdPmullw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmullw, kX86InstIdPmullw, X86XmmReg, X86Mem) + + //! Packed DWORD multiply to QWORD (SSE2). + INST_2x(pmuludq, kX86InstIdPmuludq, X86MmReg, X86MmReg) + //! \overload + INST_2x(pmuludq, kX86InstIdPmuludq, X86MmReg, X86Mem) + + //! Packed DWORD multiply to QWORD (SSE2). + INST_2x(pmuludq, kX86InstIdPmuludq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmuludq, kX86InstIdPmuludq, X86XmmReg, X86Mem) + + //! Packed bitwise or (SSE2). + INST_2x(por, kX86InstIdPor, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(por, kX86InstIdPor, X86XmmReg, X86Mem) + + //! Packed DWORD shift left logical (SSE2). + INST_2x(pslld, kX86InstIdPslld, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pslld, kX86InstIdPslld, X86XmmReg, X86Mem) + //! \overload + INST_2i(pslld, kX86InstIdPslld, X86XmmReg, Imm) + + //! Packed QWORD shift left logical (SSE2). + INST_2x(psllq, kX86InstIdPsllq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psllq, kX86InstIdPsllq, X86XmmReg, X86Mem) + //! \overload + INST_2i(psllq, kX86InstIdPsllq, X86XmmReg, Imm) + + //! Packed WORD shift left logical (SSE2). + INST_2x(psllw, kX86InstIdPsllw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psllw, kX86InstIdPsllw, X86XmmReg, X86Mem) + //! \overload + INST_2i(psllw, kX86InstIdPsllw, X86XmmReg, Imm) + + //! Packed OWORD shift left logical (SSE2). + INST_2i(pslldq, kX86InstIdPslldq, X86XmmReg, Imm) + + //! Packed DWORD shift right arithmetic (SSE2). + INST_2x(psrad, kX86InstIdPsrad, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psrad, kX86InstIdPsrad, X86XmmReg, X86Mem) + //! \overload + INST_2i(psrad, kX86InstIdPsrad, X86XmmReg, Imm) + + //! Packed WORD shift right arithmetic (SSE2). + INST_2x(psraw, kX86InstIdPsraw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psraw, kX86InstIdPsraw, X86XmmReg, X86Mem) + //! \overload + INST_2i(psraw, kX86InstIdPsraw, X86XmmReg, Imm) + + //! Packed BYTE subtract (SSE2). + INST_2x(psubb, kX86InstIdPsubb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psubb, kX86InstIdPsubb, X86XmmReg, X86Mem) + + //! Packed DWORD subtract (SSE2). + INST_2x(psubd, kX86InstIdPsubd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psubd, kX86InstIdPsubd, X86XmmReg, X86Mem) + + //! Packed QWORD subtract (SSE2). + INST_2x(psubq, kX86InstIdPsubq, X86MmReg, X86MmReg) + //! \overload + INST_2x(psubq, kX86InstIdPsubq, X86MmReg, X86Mem) + + //! Packed QWORD subtract (SSE2). + INST_2x(psubq, kX86InstIdPsubq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psubq, kX86InstIdPsubq, X86XmmReg, X86Mem) + + //! Packed WORD subtract (SSE2). + INST_2x(psubw, kX86InstIdPsubw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psubw, kX86InstIdPsubw, X86XmmReg, X86Mem) + + //! Packed WORD to DWORD multiply and add (SSE2). + INST_2x(pmaddwd, kX86InstIdPmaddwd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmaddwd, kX86InstIdPmaddwd, X86XmmReg, X86Mem) + + //! Packed DWORD shuffle (SSE2). + INST_3i(pshufd, kX86InstIdPshufd, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(pshufd, kX86InstIdPshufd, X86XmmReg, X86Mem, Imm) + + //! Packed WORD shuffle high (SSE2). + INST_3i(pshufhw, kX86InstIdPshufhw, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(pshufhw, kX86InstIdPshufhw, X86XmmReg, X86Mem, Imm) + + //! Packed WORD shuffle low (SSE2). + INST_3i(pshuflw, kX86InstIdPshuflw, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(pshuflw, kX86InstIdPshuflw, X86XmmReg, X86Mem, Imm) + + //! Packed DWORD shift right logical (SSE2). + INST_2x(psrld, kX86InstIdPsrld, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psrld, kX86InstIdPsrld, X86XmmReg, X86Mem) + //! \overload + INST_2i(psrld, kX86InstIdPsrld, X86XmmReg, Imm) + + //! Packed QWORD shift right logical (SSE2). + INST_2x(psrlq, kX86InstIdPsrlq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psrlq, kX86InstIdPsrlq, X86XmmReg, X86Mem) + //! \overload + INST_2i(psrlq, kX86InstIdPsrlq, X86XmmReg, Imm) + + //! Scalar OWORD shift right logical (SSE2). + INST_2i(psrldq, kX86InstIdPsrldq, X86XmmReg, Imm) + + //! Packed WORD shift right logical (SSE2). + INST_2x(psrlw, kX86InstIdPsrlw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psrlw, kX86InstIdPsrlw, X86XmmReg, X86Mem) + //! \overload + INST_2i(psrlw, kX86InstIdPsrlw, X86XmmReg, Imm) + + //! Packed BYTE subtract with saturation (SSE2). + INST_2x(psubsb, kX86InstIdPsubsb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psubsb, kX86InstIdPsubsb, X86XmmReg, X86Mem) + + //! Packed WORD subtract with saturation (SSE2). + INST_2x(psubsw, kX86InstIdPsubsw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psubsw, kX86InstIdPsubsw, X86XmmReg, X86Mem) + + //! Packed BYTE subtract with unsigned saturation (SSE2). + INST_2x(psubusb, kX86InstIdPsubusb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psubusb, kX86InstIdPsubusb, X86XmmReg, X86Mem) + + //! Packed WORD subtract with unsigned saturation (SSE2). + INST_2x(psubusw, kX86InstIdPsubusw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psubusw, kX86InstIdPsubusw, X86XmmReg, X86Mem) + + //! Unpack high packed BYTEs to WORDs (SSE2). + INST_2x(punpckhbw, kX86InstIdPunpckhbw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(punpckhbw, kX86InstIdPunpckhbw, X86XmmReg, X86Mem) + + //! Unpack high packed DWORDs to QWORDs (SSE2). + INST_2x(punpckhdq, kX86InstIdPunpckhdq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(punpckhdq, kX86InstIdPunpckhdq, X86XmmReg, X86Mem) + + //! Unpack high packed QWORDs to OWORD (SSE2). + INST_2x(punpckhqdq, kX86InstIdPunpckhqdq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(punpckhqdq, kX86InstIdPunpckhqdq, X86XmmReg, X86Mem) + + //! Unpack high packed WORDs to DWORDs (SSE2). + INST_2x(punpckhwd, kX86InstIdPunpckhwd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(punpckhwd, kX86InstIdPunpckhwd, X86XmmReg, X86Mem) + + //! Unpack low packed BYTEs to WORDs (SSE2). + INST_2x(punpcklbw, kX86InstIdPunpcklbw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(punpcklbw, kX86InstIdPunpcklbw, X86XmmReg, X86Mem) + + //! Unpack low packed DWORDs to QWORDs (SSE2). + INST_2x(punpckldq, kX86InstIdPunpckldq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(punpckldq, kX86InstIdPunpckldq, X86XmmReg, X86Mem) + + //! Unpack low packed QWORDs to OWORD (SSE2). + INST_2x(punpcklqdq, kX86InstIdPunpcklqdq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(punpcklqdq, kX86InstIdPunpcklqdq, X86XmmReg, X86Mem) + + //! Unpack low packed WORDs to DWORDs (SSE2). + INST_2x(punpcklwd, kX86InstIdPunpcklwd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(punpcklwd, kX86InstIdPunpcklwd, X86XmmReg, X86Mem) + + //! Packed bitwise xor (SSE2). + INST_2x(pxor, kX86InstIdPxor, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pxor, kX86InstIdPxor, X86XmmReg, X86Mem) + + //! Shuffle DP-FP (SSE2). + INST_3i(shufpd, kX86InstIdShufpd, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(shufpd, kX86InstIdShufpd, X86XmmReg, X86Mem, Imm) + + //! Packed DP-FP square root (SSE2). + INST_2x(sqrtpd, kX86InstIdSqrtpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(sqrtpd, kX86InstIdSqrtpd, X86XmmReg, X86Mem) + + //! Scalar DP-FP square root (SSE2). + INST_2x(sqrtsd, kX86InstIdSqrtsd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(sqrtsd, kX86InstIdSqrtsd, X86XmmReg, X86Mem) + + //! Packed DP-FP subtract (SSE2). + INST_2x(subpd, kX86InstIdSubpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(subpd, kX86InstIdSubpd, X86XmmReg, X86Mem) + + //! Scalar DP-FP subtract (SSE2). + INST_2x(subsd, kX86InstIdSubsd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(subsd, kX86InstIdSubsd, X86XmmReg, X86Mem) + + //! Scalar DP-FP unordered compare and set EFLAGS (SSE2). + INST_2x(ucomisd, kX86InstIdUcomisd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(ucomisd, kX86InstIdUcomisd, X86XmmReg, X86Mem) + + //! Unpack and interleave high packed DP-FP (SSE2). + INST_2x(unpckhpd, kX86InstIdUnpckhpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(unpckhpd, kX86InstIdUnpckhpd, X86XmmReg, X86Mem) + + //! Unpack and interleave low packed DP-FP (SSE2). + INST_2x(unpcklpd, kX86InstIdUnpcklpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(unpcklpd, kX86InstIdUnpcklpd, X86XmmReg, X86Mem) + + //! Packed DP-FP bitwise xor (SSE2). + INST_2x(xorpd, kX86InstIdXorpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(xorpd, kX86InstIdXorpd, X86XmmReg, X86Mem) + + // -------------------------------------------------------------------------- + // [SSE3] + // -------------------------------------------------------------------------- + + //! Packed DP-FP add/subtract (SSE3). + INST_2x(addsubpd, kX86InstIdAddsubpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(addsubpd, kX86InstIdAddsubpd, X86XmmReg, X86Mem) + + //! Packed SP-FP add/subtract (SSE3). + INST_2x(addsubps, kX86InstIdAddsubps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(addsubps, kX86InstIdAddsubps, X86XmmReg, X86Mem) + + //! Store truncated `fp0` to `short_or_int_or_long[o0]` and POP (FPU & SSE3). + INST_1x(fisttp, kX86InstIdFisttp, X86Mem) + + //! Packed DP-FP horizontal add (SSE3). + INST_2x(haddpd, kX86InstIdHaddpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(haddpd, kX86InstIdHaddpd, X86XmmReg, X86Mem) + + //! Packed SP-FP horizontal add (SSE3). + INST_2x(haddps, kX86InstIdHaddps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(haddps, kX86InstIdHaddps, X86XmmReg, X86Mem) + + //! Packed DP-FP horizontal subtract (SSE3). + INST_2x(hsubpd, kX86InstIdHsubpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(hsubpd, kX86InstIdHsubpd, X86XmmReg, X86Mem) + + //! Packed SP-FP horizontal subtract (SSE3). + INST_2x(hsubps, kX86InstIdHsubps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(hsubps, kX86InstIdHsubps, X86XmmReg, X86Mem) + + //! Load 128-bits unaligned (SSE3). + INST_2x(lddqu, kX86InstIdLddqu, X86XmmReg, X86Mem) + + //! Setup monitor address (SSE3). + INST_0x(monitor, kX86InstIdMonitor) + + //! Move one DP-FP and duplicate (SSE3). + INST_2x(movddup, kX86InstIdMovddup, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(movddup, kX86InstIdMovddup, X86XmmReg, X86Mem) + + //! Move packed SP-FP high and duplicate (SSE3). + INST_2x(movshdup, kX86InstIdMovshdup, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(movshdup, kX86InstIdMovshdup, X86XmmReg, X86Mem) + + //! Move packed SP-FP low and duplicate (SSE3). + INST_2x(movsldup, kX86InstIdMovsldup, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(movsldup, kX86InstIdMovsldup, X86XmmReg, X86Mem) + + //! Monitor wait (SSE3). + INST_0x(mwait, kX86InstIdMwait) + + // -------------------------------------------------------------------------- + // [SSSE3] + // -------------------------------------------------------------------------- + + //! Packed BYTE sign (SSSE3). + INST_2x(psignb, kX86InstIdPsignb, X86MmReg, X86MmReg) + //! \overload + INST_2x(psignb, kX86InstIdPsignb, X86MmReg, X86Mem) + + //! Packed BYTE sign (SSSE3). + INST_2x(psignb, kX86InstIdPsignb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psignb, kX86InstIdPsignb, X86XmmReg, X86Mem) + + //! Packed DWORD sign (SSSE3). + INST_2x(psignd, kX86InstIdPsignd, X86MmReg, X86MmReg) + //! \overload + INST_2x(psignd, kX86InstIdPsignd, X86MmReg, X86Mem) + + //! Packed DWORD sign (SSSE3). + INST_2x(psignd, kX86InstIdPsignd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psignd, kX86InstIdPsignd, X86XmmReg, X86Mem) + + //! Packed WORD sign (SSSE3). + INST_2x(psignw, kX86InstIdPsignw, X86MmReg, X86MmReg) + //! \overload + INST_2x(psignw, kX86InstIdPsignw, X86MmReg, X86Mem) + + //! Packed WORD sign (SSSE3). + INST_2x(psignw, kX86InstIdPsignw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(psignw, kX86InstIdPsignw, X86XmmReg, X86Mem) + + //! Packed DWORD horizontal add (SSSE3). + INST_2x(phaddd, kX86InstIdPhaddd, X86MmReg, X86MmReg) + //! \overload + INST_2x(phaddd, kX86InstIdPhaddd, X86MmReg, X86Mem) + + //! Packed DWORD horizontal add (SSSE3). + INST_2x(phaddd, kX86InstIdPhaddd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(phaddd, kX86InstIdPhaddd, X86XmmReg, X86Mem) + + //! Packed WORD horizontal add with saturation (SSSE3). + INST_2x(phaddsw, kX86InstIdPhaddsw, X86MmReg, X86MmReg) + //! \overload + INST_2x(phaddsw, kX86InstIdPhaddsw, X86MmReg, X86Mem) + + //! Packed WORD horizontal add with saturation (SSSE3). + INST_2x(phaddsw, kX86InstIdPhaddsw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(phaddsw, kX86InstIdPhaddsw, X86XmmReg, X86Mem) + + //! Packed WORD horizontal add (SSSE3). + INST_2x(phaddw, kX86InstIdPhaddw, X86MmReg, X86MmReg) + //! \overload + INST_2x(phaddw, kX86InstIdPhaddw, X86MmReg, X86Mem) + + //! Packed WORD horizontal add (SSSE3). + INST_2x(phaddw, kX86InstIdPhaddw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(phaddw, kX86InstIdPhaddw, X86XmmReg, X86Mem) + + //! Packed DWORD horizontal subtract (SSSE3). + INST_2x(phsubd, kX86InstIdPhsubd, X86MmReg, X86MmReg) + //! \overload + INST_2x(phsubd, kX86InstIdPhsubd, X86MmReg, X86Mem) + + //! Packed DWORD horizontal subtract (SSSE3). + INST_2x(phsubd, kX86InstIdPhsubd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(phsubd, kX86InstIdPhsubd, X86XmmReg, X86Mem) + + //! Packed WORD horizontal subtract with saturation (SSSE3). + INST_2x(phsubsw, kX86InstIdPhsubsw, X86MmReg, X86MmReg) + //! \overload + INST_2x(phsubsw, kX86InstIdPhsubsw, X86MmReg, X86Mem) + + //! Packed WORD horizontal subtract with saturation (SSSE3). + INST_2x(phsubsw, kX86InstIdPhsubsw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(phsubsw, kX86InstIdPhsubsw, X86XmmReg, X86Mem) + + //! Packed WORD horizontal subtract (SSSE3). + INST_2x(phsubw, kX86InstIdPhsubw, X86MmReg, X86MmReg) + //! \overload + INST_2x(phsubw, kX86InstIdPhsubw, X86MmReg, X86Mem) + + //! Packed WORD horizontal subtract (SSSE3). + INST_2x(phsubw, kX86InstIdPhsubw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(phsubw, kX86InstIdPhsubw, X86XmmReg, X86Mem) + + //! Packed multiply and add signed and unsigned bytes (SSSE3). + INST_2x(pmaddubsw, kX86InstIdPmaddubsw, X86MmReg, X86MmReg) + //! \overload + INST_2x(pmaddubsw, kX86InstIdPmaddubsw, X86MmReg, X86Mem) + + //! Packed multiply and add signed and unsigned bytes (SSSE3). + INST_2x(pmaddubsw, kX86InstIdPmaddubsw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmaddubsw, kX86InstIdPmaddubsw, X86XmmReg, X86Mem) + + //! Packed BYTE absolute value (SSSE3). + INST_2x(pabsb, kX86InstIdPabsb, X86MmReg, X86MmReg) + //! \overload + INST_2x(pabsb, kX86InstIdPabsb, X86MmReg, X86Mem) + + //! Packed BYTE absolute value (SSSE3). + INST_2x(pabsb, kX86InstIdPabsb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pabsb, kX86InstIdPabsb, X86XmmReg, X86Mem) + + //! Packed DWORD absolute value (SSSE3). + INST_2x(pabsd, kX86InstIdPabsd, X86MmReg, X86MmReg) + //! \overload + INST_2x(pabsd, kX86InstIdPabsd, X86MmReg, X86Mem) + + //! Packed DWORD absolute value (SSSE3). + INST_2x(pabsd, kX86InstIdPabsd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pabsd, kX86InstIdPabsd, X86XmmReg, X86Mem) + + //! Packed WORD absolute value (SSSE3). + INST_2x(pabsw, kX86InstIdPabsw, X86MmReg, X86MmReg) + //! \overload + INST_2x(pabsw, kX86InstIdPabsw, X86MmReg, X86Mem) + + //! Packed WORD absolute value (SSSE3). + INST_2x(pabsw, kX86InstIdPabsw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pabsw, kX86InstIdPabsw, X86XmmReg, X86Mem) + + //! Packed WORD multiply high, round and scale (SSSE3). + INST_2x(pmulhrsw, kX86InstIdPmulhrsw, X86MmReg, X86MmReg) + //! \overload + INST_2x(pmulhrsw, kX86InstIdPmulhrsw, X86MmReg, X86Mem) + + //! Packed WORD multiply high, round and scale (SSSE3). + INST_2x(pmulhrsw, kX86InstIdPmulhrsw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmulhrsw, kX86InstIdPmulhrsw, X86XmmReg, X86Mem) + + //! Packed BYTE shuffle (SSSE3). + INST_2x(pshufb, kX86InstIdPshufb, X86MmReg, X86MmReg) + //! \overload + INST_2x(pshufb, kX86InstIdPshufb, X86MmReg, X86Mem) + + //! Packed BYTE shuffle (SSSE3). + INST_2x(pshufb, kX86InstIdPshufb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pshufb, kX86InstIdPshufb, X86XmmReg, X86Mem) + + //! Packed align right (SSSE3). + INST_3i(palignr, kX86InstIdPalignr, X86MmReg, X86MmReg, Imm) + //! \overload + INST_3i(palignr, kX86InstIdPalignr, X86MmReg, X86Mem, Imm) + + //! Packed align right (SSSE3). + INST_3i(palignr, kX86InstIdPalignr, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(palignr, kX86InstIdPalignr, X86XmmReg, X86Mem, Imm) + + // -------------------------------------------------------------------------- + // [SSE4.1] + // -------------------------------------------------------------------------- + + //! Packed DP-FP blend (SSE4.1). + INST_3i(blendpd, kX86InstIdBlendpd, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(blendpd, kX86InstIdBlendpd, X86XmmReg, X86Mem, Imm) + + //! Packed SP-FP blend (SSE4.1). + INST_3i(blendps, kX86InstIdBlendps, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(blendps, kX86InstIdBlendps, X86XmmReg, X86Mem, Imm) + + //! Packed DP-FP variable blend (SSE4.1). + INST_2x(blendvpd, kX86InstIdBlendvpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(blendvpd, kX86InstIdBlendvpd, X86XmmReg, X86Mem) + + //! Packed SP-FP variable blend (SSE4.1). + INST_2x(blendvps, kX86InstIdBlendvps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(blendvps, kX86InstIdBlendvps, X86XmmReg, X86Mem) + + //! Packed DP-FP dot product (SSE4.1). + INST_3i(dppd, kX86InstIdDppd, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(dppd, kX86InstIdDppd, X86XmmReg, X86Mem, Imm) + + //! Packed SP-FP dot product (SSE4.1). + INST_3i(dpps, kX86InstIdDpps, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(dpps, kX86InstIdDpps, X86XmmReg, X86Mem, Imm) + + //! Extract SP-FP based on selector (SSE4.1). + INST_3i(extractps, kX86InstIdExtractps, X86GpReg, X86XmmReg, Imm) + //! \overload + INST_3i(extractps, kX86InstIdExtractps, X86Mem, X86XmmReg, Imm) + + //! Insert SP-FP based on selector (SSE4.1). + INST_3i(insertps, kX86InstIdInsertps, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(insertps, kX86InstIdInsertps, X86XmmReg, X86Mem, Imm) + + //! Load OWORD aligned using NT hint (SSE4.1). + INST_2x(movntdqa, kX86InstIdMovntdqa, X86XmmReg, X86Mem) + + //! Packed WORD sums of absolute difference (SSE4.1). + INST_3i(mpsadbw, kX86InstIdMpsadbw, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(mpsadbw, kX86InstIdMpsadbw, X86XmmReg, X86Mem, Imm) + + //! Pack DWORDs to WORDs with unsigned saturation (SSE4.1). + INST_2x(packusdw, kX86InstIdPackusdw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(packusdw, kX86InstIdPackusdw, X86XmmReg, X86Mem) + + //! Packed BYTE variable blend (SSE4.1). + INST_2x(pblendvb, kX86InstIdPblendvb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pblendvb, kX86InstIdPblendvb, X86XmmReg, X86Mem) + + //! Packed WORD blend (SSE4.1). + INST_3i(pblendw, kX86InstIdPblendw, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(pblendw, kX86InstIdPblendw, X86XmmReg, X86Mem, Imm) + + //! Packed QWORD compare for equality (SSE4.1). + INST_2x(pcmpeqq, kX86InstIdPcmpeqq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pcmpeqq, kX86InstIdPcmpeqq, X86XmmReg, X86Mem) + + //! Extract BYTE based on selector (SSE4.1). + INST_3i(pextrb, kX86InstIdPextrb, X86GpReg, X86XmmReg, Imm) + //! \overload + INST_3i(pextrb, kX86InstIdPextrb, X86Mem, X86XmmReg, Imm) + + //! Extract DWORD based on selector (SSE4.1). + INST_3i(pextrd, kX86InstIdPextrd, X86GpReg, X86XmmReg, Imm) + //! \overload + INST_3i(pextrd, kX86InstIdPextrd, X86Mem, X86XmmReg, Imm) + + //! Extract QWORD based on selector (SSE4.1). + INST_3i(pextrq, kX86InstIdPextrq, X86GpReg, X86XmmReg, Imm) + //! \overload + INST_3i(pextrq, kX86InstIdPextrq, X86Mem, X86XmmReg, Imm) + + //! Extract WORD based on selector (SSE4.1). + INST_3i(pextrw, kX86InstIdPextrw, X86Mem, X86XmmReg, Imm) + + //! Packed WORD horizontal minimum (SSE4.1). + INST_2x(phminposuw, kX86InstIdPhminposuw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(phminposuw, kX86InstIdPhminposuw, X86XmmReg, X86Mem) + + //! Insert BYTE based on selector (SSE4.1). + INST_3i(pinsrb, kX86InstIdPinsrb, X86XmmReg, X86GpReg, Imm) + //! \overload + INST_3i(pinsrb, kX86InstIdPinsrb, X86XmmReg, X86Mem, Imm) + + //! Insert DWORD based on selector (SSE4.1). + INST_3i(pinsrd, kX86InstIdPinsrd, X86XmmReg, X86GpReg, Imm) + //! \overload + INST_3i(pinsrd, kX86InstIdPinsrd, X86XmmReg, X86Mem, Imm) + + //! Insert QWORD based on selector (SSE4.1). + INST_3i(pinsrq, kX86InstIdPinsrq, X86XmmReg, X86GpReg, Imm) + //! \overload + INST_3i(pinsrq, kX86InstIdPinsrq, X86XmmReg, X86Mem, Imm) + + //! Packed BYTE maximum (SSE4.1). + INST_2x(pmaxsb, kX86InstIdPmaxsb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmaxsb, kX86InstIdPmaxsb, X86XmmReg, X86Mem) + + //! Packed DWORD maximum (SSE4.1). + INST_2x(pmaxsd, kX86InstIdPmaxsd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmaxsd, kX86InstIdPmaxsd, X86XmmReg, X86Mem) + + //! Packed DWORD unsigned maximum (SSE4.1). + INST_2x(pmaxud, kX86InstIdPmaxud, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmaxud,kX86InstIdPmaxud , X86XmmReg, X86Mem) + + //! Packed WORD unsigned maximum (SSE4.1). + INST_2x(pmaxuw, kX86InstIdPmaxuw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmaxuw, kX86InstIdPmaxuw, X86XmmReg, X86Mem) + + //! Packed BYTE minimum (SSE4.1). + INST_2x(pminsb, kX86InstIdPminsb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pminsb, kX86InstIdPminsb, X86XmmReg, X86Mem) + + //! Packed DWORD minimum (SSE4.1). + INST_2x(pminsd, kX86InstIdPminsd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pminsd, kX86InstIdPminsd, X86XmmReg, X86Mem) + + //! Packed WORD unsigned minimum (SSE4.1). + INST_2x(pminuw, kX86InstIdPminuw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pminuw, kX86InstIdPminuw, X86XmmReg, X86Mem) + + //! Packed DWORD unsigned minimum (SSE4.1). + INST_2x(pminud, kX86InstIdPminud, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pminud, kX86InstIdPminud, X86XmmReg, X86Mem) + + //! BYTE to DWORD with sign extend (SSE4.1). + INST_2x(pmovsxbd, kX86InstIdPmovsxbd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmovsxbd, kX86InstIdPmovsxbd, X86XmmReg, X86Mem) + + //! Packed BYTE to QWORD with sign extend (SSE4.1). + INST_2x(pmovsxbq, kX86InstIdPmovsxbq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmovsxbq, kX86InstIdPmovsxbq, X86XmmReg, X86Mem) + + //! Packed BYTE to WORD with sign extend (SSE4.1). + INST_2x(pmovsxbw, kX86InstIdPmovsxbw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmovsxbw, kX86InstIdPmovsxbw, X86XmmReg, X86Mem) + + //! Packed DWORD to QWORD with sign extend (SSE4.1). + INST_2x(pmovsxdq, kX86InstIdPmovsxdq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmovsxdq, kX86InstIdPmovsxdq, X86XmmReg, X86Mem) + + //! Packed WORD to DWORD with sign extend (SSE4.1). + INST_2x(pmovsxwd, kX86InstIdPmovsxwd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmovsxwd, kX86InstIdPmovsxwd, X86XmmReg, X86Mem) + + //! Packed WORD to QWORD with sign extend (SSE4.1). + INST_2x(pmovsxwq, kX86InstIdPmovsxwq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmovsxwq, kX86InstIdPmovsxwq, X86XmmReg, X86Mem) + + //! BYTE to DWORD with zero extend (SSE4.1). + INST_2x(pmovzxbd, kX86InstIdPmovzxbd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmovzxbd, kX86InstIdPmovzxbd, X86XmmReg, X86Mem) + + //! Packed BYTE to QWORD with zero extend (SSE4.1). + INST_2x(pmovzxbq, kX86InstIdPmovzxbq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmovzxbq, kX86InstIdPmovzxbq, X86XmmReg, X86Mem) + + //! BYTE to WORD with zero extend (SSE4.1). + INST_2x(pmovzxbw, kX86InstIdPmovzxbw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmovzxbw, kX86InstIdPmovzxbw, X86XmmReg, X86Mem) + + //! Packed DWORD to QWORD with zero extend (SSE4.1). + INST_2x(pmovzxdq, kX86InstIdPmovzxdq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmovzxdq, kX86InstIdPmovzxdq, X86XmmReg, X86Mem) + + //! Packed WORD to DWORD with zero extend (SSE4.1). + INST_2x(pmovzxwd, kX86InstIdPmovzxwd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmovzxwd, kX86InstIdPmovzxwd, X86XmmReg, X86Mem) + + //! Packed WORD to QWORD with zero extend (SSE4.1). + INST_2x(pmovzxwq, kX86InstIdPmovzxwq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmovzxwq, kX86InstIdPmovzxwq, X86XmmReg, X86Mem) + + //! Packed DWORD to QWORD multiply (SSE4.1). + INST_2x(pmuldq, kX86InstIdPmuldq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmuldq, kX86InstIdPmuldq, X86XmmReg, X86Mem) + + //! Packed DWORD multiply low (SSE4.1). + INST_2x(pmulld, kX86InstIdPmulld, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pmulld, kX86InstIdPmulld, X86XmmReg, X86Mem) + + //! Logical compare (SSE4.1). + INST_2x(ptest, kX86InstIdPtest, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(ptest, kX86InstIdPtest, X86XmmReg, X86Mem) + + //! Packed DP-FP round (SSE4.1). + INST_3i(roundpd, kX86InstIdRoundpd, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(roundpd, kX86InstIdRoundpd, X86XmmReg, X86Mem, Imm) + + //! Packed SP-FP round (SSE4.1). + INST_3i(roundps, kX86InstIdRoundps, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(roundps, kX86InstIdRoundps, X86XmmReg, X86Mem, Imm) + + //! Scalar DP-FP round (SSE4.1). + INST_3i(roundsd, kX86InstIdRoundsd, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(roundsd, kX86InstIdRoundsd, X86XmmReg, X86Mem, Imm) + + //! Scalar SP-FP round (SSE4.1). + INST_3i(roundss, kX86InstIdRoundss, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(roundss, kX86InstIdRoundss, X86XmmReg, X86Mem, Imm) + + // -------------------------------------------------------------------------- + // [SSE4.2] + // -------------------------------------------------------------------------- + + //! Accumulate crc32 value (polynomial 0x11EDC6F41) (SSE4.2). + INST_2x_(crc32, kX86InstIdCrc32, X86GpReg, X86GpReg, o0.isRegType(kX86RegTypeGpd) || o0.isRegType(kX86RegTypeGpq)) + //! \overload + INST_2x_(crc32, kX86InstIdCrc32, X86GpReg, X86Mem, o0.isRegType(kX86RegTypeGpd) || o0.isRegType(kX86RegTypeGpq)) + + //! Packed compare explicit length strings, return index (SSE4.2). + INST_3i(pcmpestri, kX86InstIdPcmpestri, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(pcmpestri, kX86InstIdPcmpestri, X86XmmReg, X86Mem, Imm) + + //! Packed compare explicit length strings, return mask (SSE4.2). + INST_3i(pcmpestrm, kX86InstIdPcmpestrm, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(pcmpestrm, kX86InstIdPcmpestrm, X86XmmReg, X86Mem, Imm) + + //! Packed compare implicit length strings, return index (SSE4.2). + INST_3i(pcmpistri, kX86InstIdPcmpistri, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(pcmpistri, kX86InstIdPcmpistri, X86XmmReg, X86Mem, Imm) + + //! Packed compare implicit length strings, return mask (SSE4.2). + INST_3i(pcmpistrm, kX86InstIdPcmpistrm, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(pcmpistrm, kX86InstIdPcmpistrm, X86XmmReg, X86Mem, Imm) + + //! Packed QWORD compare if greater than (SSE4.2). + INST_2x(pcmpgtq, kX86InstIdPcmpgtq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(pcmpgtq, kX86InstIdPcmpgtq, X86XmmReg, X86Mem) + + // -------------------------------------------------------------------------- + // [SSE4a] + // -------------------------------------------------------------------------- + + //! Extract Field (SSE4a). + INST_2x(extrq, kX86InstIdExtrq, X86XmmReg, X86XmmReg) + //! Extract Field (SSE4a). + INST_3ii(extrq, kX86InstIdExtrq, X86XmmReg, Imm, Imm) + + //! Insert Field (SSE4a). + INST_2x(insertq, kX86InstIdInsertq, X86XmmReg, X86XmmReg) + //! Insert Field (SSE4a). + INST_4ii(insertq, kX86InstIdInsertq, X86XmmReg, X86XmmReg, Imm, Imm) + + //! Move Non-Temporal Scalar DP-FP (SSE4a). + INST_2x(movntsd, kX86InstIdMovntsd, X86Mem, X86XmmReg) + //! Move Non-Temporal Scalar SP-FP (SSE4a). + INST_2x(movntss, kX86InstIdMovntss, X86Mem, X86XmmReg) + + // -------------------------------------------------------------------------- + // [POPCNT] + // -------------------------------------------------------------------------- + + //! Return the count of number of bits set to 1 (POPCNT). + INST_2x_(popcnt, kX86InstIdPopcnt, X86GpReg, X86GpReg, !o0.isGpb() && o0.getRegType() == o1.getRegType()) + //! \overload + INST_2x_(popcnt, kX86InstIdPopcnt, X86GpReg, X86Mem, !o0.isGpb()) + + // -------------------------------------------------------------------------- + // [LZCNT] + // -------------------------------------------------------------------------- + + //! Count the number of leading zero bits (LZCNT). + INST_2x(lzcnt, kX86InstIdLzcnt, X86GpReg, X86GpReg) + //! \overload + INST_2x(lzcnt, kX86InstIdLzcnt, X86GpReg, X86Mem) + + // -------------------------------------------------------------------------- + // [AESNI] + // -------------------------------------------------------------------------- + + //! Perform a single round of the AES decryption flow (AESNI). + INST_2x(aesdec, kX86InstIdAesdec, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(aesdec, kX86InstIdAesdec, X86XmmReg, X86Mem) + + //! Perform the last round of the AES decryption flow (AESNI). + INST_2x(aesdeclast, kX86InstIdAesdeclast, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(aesdeclast, kX86InstIdAesdeclast, X86XmmReg, X86Mem) + + //! Perform a single round of the AES encryption flow (AESNI). + INST_2x(aesenc, kX86InstIdAesenc, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(aesenc, kX86InstIdAesenc, X86XmmReg, X86Mem) + + //! Perform the last round of the AES encryption flow (AESNI). + INST_2x(aesenclast, kX86InstIdAesenclast, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(aesenclast, kX86InstIdAesenclast, X86XmmReg, X86Mem) + + //! Perform the InvMixColumns transformation (AESNI). + INST_2x(aesimc, kX86InstIdAesimc, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(aesimc, kX86InstIdAesimc, X86XmmReg, X86Mem) + + //! Assist in expanding the AES cipher key (AESNI). + INST_3i(aeskeygenassist, kX86InstIdAeskeygenassist, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(aeskeygenassist, kX86InstIdAeskeygenassist, X86XmmReg, X86Mem, Imm) + + // -------------------------------------------------------------------------- + // [PCLMULQDQ] + // -------------------------------------------------------------------------- + + //! Packed QWORD to OWORD carry-less multiply (PCLMULQDQ). + INST_3i(pclmulqdq, kX86InstIdPclmulqdq, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(pclmulqdq, kX86InstIdPclmulqdq, X86XmmReg, X86Mem, Imm) + + // -------------------------------------------------------------------------- + // [XSAVE] + // -------------------------------------------------------------------------- + + //! Restore Processor Extended States specified by `EDX:EAX` (XSAVE). + INST_1x(xrstor, kX86InstIdXrstor, X86Mem) + //! Restore Processor Extended States specified by `EDX:EAX` (XSAVE&X64). + INST_1x(xrstor64, kX86InstIdXrstor64, X86Mem) + + //! Save Processor Extended States specified by `EDX:EAX` (XSAVE). + INST_1x(xsave, kX86InstIdXsave, X86Mem) + //! Save Processor Extended States specified by `EDX:EAX` (XSAVE&X64). + INST_1x(xsave64, kX86InstIdXsave64, X86Mem) + + //! Save Processor Extended States specified by `EDX:EAX` (Optimized) (XSAVEOPT). + INST_1x(xsaveopt, kX86InstIdXsave, X86Mem) + //! Save Processor Extended States specified by `EDX:EAX` (Optimized) (XSAVEOPT&X64). + INST_1x(xsaveopt64, kX86InstIdXsave64, X86Mem) + + //! Get XCR - `EDX:EAX <- XCR[ECX]` (XSAVE). + INST_0x(xgetbv, kX86InstIdXgetbv) + //! Set XCR - `XCR[ECX] <- EDX:EAX` (XSAVE). + INST_0x(xsetbv, kX86InstIdXsetbv) + + // -------------------------------------------------------------------------- + // [AVX] + // -------------------------------------------------------------------------- + + //! Packed DP-FP add (AVX). + INST_3x(vaddpd, kX86InstIdVaddpd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vaddpd, kX86InstIdVaddpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vaddpd, kX86InstIdVaddpd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vaddpd, kX86InstIdVaddpd, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed SP-FP add (AVX). + INST_3x(vaddps, kX86InstIdVaddps, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vaddps, kX86InstIdVaddps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vaddps, kX86InstIdVaddps, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vaddps, kX86InstIdVaddps, X86YmmReg, X86YmmReg, X86Mem) + + //! Scalar DP-FP add (AVX) + INST_3x(vaddsd, kX86InstIdVaddsd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vaddsd, kX86InstIdVaddsd, X86XmmReg, X86XmmReg, X86Mem) + + //! Scalar SP-FP add (AVX) + INST_3x(vaddss, kX86InstIdVaddss, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vaddss, kX86InstIdVaddss, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DP-FP add/subtract (AVX). + INST_3x(vaddsubpd, kX86InstIdVaddsubpd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vaddsubpd, kX86InstIdVaddsubpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vaddsubpd, kX86InstIdVaddsubpd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vaddsubpd, kX86InstIdVaddsubpd, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed SP-FP add/subtract (AVX). + INST_3x(vaddsubps, kX86InstIdVaddsubps, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vaddsubps, kX86InstIdVaddsubps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vaddsubps, kX86InstIdVaddsubps, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vaddsubps, kX86InstIdVaddsubps, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed DP-FP bitwise and (AVX). + INST_3x(vandpd, kX86InstIdVandpd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vandpd, kX86InstIdVandpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vandpd, kX86InstIdVandpd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vandpd, kX86InstIdVandpd, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed SP-FP bitwise and (AVX). + INST_3x(vandps, kX86InstIdVandps, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vandps, kX86InstIdVandps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vandps, kX86InstIdVandps, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vandps, kX86InstIdVandps, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed DP-FP bitwise and-not (AVX). + INST_3x(vandnpd, kX86InstIdVandnpd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vandnpd, kX86InstIdVandnpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vandnpd, kX86InstIdVandnpd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vandnpd, kX86InstIdVandnpd, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed SP-FP bitwise and-not (AVX). + INST_3x(vandnps, kX86InstIdVandnps, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vandnps, kX86InstIdVandnps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vandnps, kX86InstIdVandnps, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vandnps, kX86InstIdVandnps, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed DP-FP blend (AVX). + INST_4i(vblendpd, kX86InstIdVblendpd, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vblendpd, kX86InstIdVblendpd, X86XmmReg, X86XmmReg, X86Mem, Imm) + //! \overload + INST_4i(vblendpd, kX86InstIdVblendpd, X86YmmReg, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_4i(vblendpd, kX86InstIdVblendpd, X86YmmReg, X86YmmReg, X86Mem, Imm) + + //! Packed SP-FP blend (AVX). + INST_4i(vblendps, kX86InstIdVblendps, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vblendps, kX86InstIdVblendps, X86XmmReg, X86XmmReg, X86Mem, Imm) + //! \overload + INST_4i(vblendps, kX86InstIdVblendps, X86YmmReg, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_4i(vblendps, kX86InstIdVblendps, X86YmmReg, X86YmmReg, X86Mem, Imm) + + //! Packed DP-FP variable blend (AVX). + INST_4x(vblendvpd, kX86InstIdVblendvpd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_4x(vblendvpd, kX86InstIdVblendvpd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + //! \overload + INST_4x(vblendvpd, kX86InstIdVblendvpd, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_4x(vblendvpd, kX86InstIdVblendvpd, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + + //! Packed SP-FP variable blend (AVX). + INST_4x(vblendvps, kX86InstIdVblendvps, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_4x(vblendvps, kX86InstIdVblendvps, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + //! \overload + INST_4x(vblendvps, kX86InstIdVblendvps, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_4x(vblendvps, kX86InstIdVblendvps, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + + //! Broadcast 128-bits of FP data in `o1` to low and high 128-bits in `o0` (AVX). + INST_2x(vbroadcastf128, kX86InstIdVbroadcastf128, X86YmmReg, X86Mem) + //! Broadcast DP-FP element in `o1` to four locations in `o0` (AVX). + INST_2x(vbroadcastsd, kX86InstIdVbroadcastsd, X86YmmReg, X86Mem) + //! Broadcast SP-FP element in `o1` to four locations in `o0` (AVX). + INST_2x(vbroadcastss, kX86InstIdVbroadcastss, X86XmmReg, X86Mem) + //! Broadcast SP-FP element in `o1` to eight locations in `o0` (AVX). + INST_2x(vbroadcastss, kX86InstIdVbroadcastss, X86YmmReg, X86Mem) + + //! Packed DP-FP compare (AVX). + INST_4i(vcmppd, kX86InstIdVcmppd, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vcmppd, kX86InstIdVcmppd, X86XmmReg, X86XmmReg, X86Mem, Imm) + //! \overload + INST_4i(vcmppd, kX86InstIdVcmppd, X86YmmReg, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_4i(vcmppd, kX86InstIdVcmppd, X86YmmReg, X86YmmReg, X86Mem, Imm) + + //! Packed SP-FP compare (AVX). + INST_4i(vcmpps, kX86InstIdVcmpps, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vcmpps, kX86InstIdVcmpps, X86XmmReg, X86XmmReg, X86Mem, Imm) + //! \overload + INST_4i(vcmpps, kX86InstIdVcmpps, X86YmmReg, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_4i(vcmpps, kX86InstIdVcmpps, X86YmmReg, X86YmmReg, X86Mem, Imm) + + //! Scalar DP-FP compare (AVX). + INST_4i(vcmpsd, kX86InstIdVcmpsd, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vcmpsd, kX86InstIdVcmpsd, X86XmmReg, X86XmmReg, X86Mem, Imm) + + //! Scalar SP-FP compare (AVX). + INST_4i(vcmpss, kX86InstIdVcmpss, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vcmpss, kX86InstIdVcmpss, X86XmmReg, X86XmmReg, X86Mem, Imm) + + //! Scalar DP-FP ordered compare and set EFLAGS (AVX). + INST_2x(vcomisd, kX86InstIdVcomisd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vcomisd, kX86InstIdVcomisd, X86XmmReg, X86Mem) + + //! Scalar SP-FP ordered compare and set EFLAGS (AVX). + INST_2x(vcomiss, kX86InstIdVcomiss, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vcomiss, kX86InstIdVcomiss, X86XmmReg, X86Mem) + + //! Convert packed QWORDs to packed DP-FP (AVX). + INST_2x(vcvtdq2pd, kX86InstIdVcvtdq2pd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vcvtdq2pd, kX86InstIdVcvtdq2pd, X86XmmReg, X86Mem) + //! \overload + INST_2x(vcvtdq2pd, kX86InstIdVcvtdq2pd, X86YmmReg, X86XmmReg) + //! \overload + INST_2x(vcvtdq2pd, kX86InstIdVcvtdq2pd, X86YmmReg, X86Mem) + + //! Convert packed QWORDs to packed SP-FP (AVX). + INST_2x(vcvtdq2ps, kX86InstIdVcvtdq2ps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vcvtdq2ps, kX86InstIdVcvtdq2ps, X86XmmReg, X86Mem) + //! \overload + INST_2x(vcvtdq2ps, kX86InstIdVcvtdq2ps, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vcvtdq2ps, kX86InstIdVcvtdq2ps, X86YmmReg, X86Mem) + + //! Convert packed DP-FP to packed DWORDs (AVX). + INST_2x(vcvtpd2dq, kX86InstIdVcvtpd2dq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vcvtpd2dq, kX86InstIdVcvtpd2dq, X86XmmReg, X86YmmReg) + //! \overload + INST_2x(vcvtpd2dq, kX86InstIdVcvtpd2dq, X86XmmReg, X86Mem) + + //! Convert packed DP-FP to packed SP-FP (AVX). + INST_2x(vcvtpd2ps, kX86InstIdVcvtpd2ps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vcvtpd2ps, kX86InstIdVcvtpd2ps, X86XmmReg, X86YmmReg) + //! \overload + INST_2x(vcvtpd2ps, kX86InstIdVcvtpd2ps, X86XmmReg, X86Mem) + + //! Convert packed SP-FP to packed DWORDs (AVX). + INST_2x(vcvtps2dq, kX86InstIdVcvtps2dq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vcvtps2dq, kX86InstIdVcvtps2dq, X86XmmReg, X86Mem) + //! \overload + INST_2x(vcvtps2dq, kX86InstIdVcvtps2dq, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vcvtps2dq, kX86InstIdVcvtps2dq, X86YmmReg, X86Mem) + + //! Convert packed SP-FP to packed DP-FP (AVX). + INST_2x(vcvtps2pd, kX86InstIdVcvtps2pd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vcvtps2pd, kX86InstIdVcvtps2pd, X86XmmReg, X86Mem) + //! \overload + INST_2x(vcvtps2pd, kX86InstIdVcvtps2pd, X86YmmReg, X86XmmReg) + //! \overload + INST_2x(vcvtps2pd, kX86InstIdVcvtps2pd, X86YmmReg, X86Mem) + + //! Convert scalar DP-FP to DWORD (AVX). + INST_2x(vcvtsd2si, kX86InstIdVcvtsd2si, X86GpReg, X86XmmReg) + //! \overload + INST_2x(vcvtsd2si, kX86InstIdVcvtsd2si, X86GpReg, X86Mem) + + //! Convert scalar DP-FP to scalar SP-FP (AVX). + INST_3x(vcvtsd2ss, kX86InstIdVcvtsd2ss, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vcvtsd2ss, kX86InstIdVcvtsd2ss, X86XmmReg, X86XmmReg, X86Mem) + + //! Convert DWORD integer to scalar DP-FP (AVX). + INST_3x(vcvtsi2sd, kX86InstIdVcvtsi2sd, X86XmmReg, X86XmmReg, X86GpReg) + //! \overload + INST_3x(vcvtsi2sd, kX86InstIdVcvtsi2sd, X86XmmReg, X86XmmReg, X86Mem) + + //! Convert scalar INT32 to SP-FP (AVX). + INST_3x(vcvtsi2ss, kX86InstIdVcvtsi2ss, X86XmmReg, X86XmmReg, X86GpReg) + //! \overload + INST_3x(vcvtsi2ss, kX86InstIdVcvtsi2ss, X86XmmReg, X86XmmReg, X86Mem) + + //! Convert scalar SP-FP to DP-FP (AVX). + INST_3x(vcvtss2sd, kX86InstIdVcvtss2sd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vcvtss2sd, kX86InstIdVcvtss2sd, X86XmmReg, X86XmmReg, X86Mem) + + //! Convert scalar SP-FP to INT32 (AVX). + INST_2x(vcvtss2si, kX86InstIdVcvtss2si, X86GpReg, X86XmmReg) + //! \overload + INST_2x(vcvtss2si, kX86InstIdVcvtss2si, X86GpReg, X86Mem) + + //! Convert with truncation packed DP-FP to packed DWORDs (AVX). + INST_2x(vcvttpd2dq, kX86InstIdVcvttpd2dq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vcvttpd2dq, kX86InstIdVcvttpd2dq, X86XmmReg, X86YmmReg) + //! \overload + INST_2x(vcvttpd2dq, kX86InstIdVcvttpd2dq, X86XmmReg, X86Mem) + + //! Convert with truncation packed SP-FP to packed DWORDs (AVX). + INST_2x(vcvttps2dq, kX86InstIdVcvttps2dq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vcvttps2dq, kX86InstIdVcvttps2dq, X86XmmReg, X86Mem) + //! \overload + INST_2x(vcvttps2dq, kX86InstIdVcvttps2dq, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vcvttps2dq, kX86InstIdVcvttps2dq, X86YmmReg, X86Mem) + + //! Convert with truncation scalar DP-FP to INT32 (AVX). + INST_2x(vcvttsd2si, kX86InstIdVcvttsd2si, X86GpReg, X86XmmReg) + //! \overload + INST_2x(vcvttsd2si, kX86InstIdVcvttsd2si, X86GpReg, X86Mem) + + //! Convert with truncation scalar SP-FP to INT32 (AVX). + INST_2x(vcvttss2si, kX86InstIdVcvttss2si, X86GpReg, X86XmmReg) + //! \overload + INST_2x(vcvttss2si, kX86InstIdVcvttss2si, X86GpReg, X86Mem) + + //! Packed DP-FP divide (AVX). + INST_3x(vdivpd, kX86InstIdVdivpd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vdivpd, kX86InstIdVdivpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vdivpd, kX86InstIdVdivpd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vdivpd, kX86InstIdVdivpd, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed SP-FP divide (AVX). + INST_3x(vdivps, kX86InstIdVdivps, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vdivps, kX86InstIdVdivps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vdivps, kX86InstIdVdivps, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vdivps, kX86InstIdVdivps, X86YmmReg, X86YmmReg, X86Mem) + + //! Scalar DP-FP divide (AVX). + INST_3x(vdivsd, kX86InstIdVdivsd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vdivsd, kX86InstIdVdivsd, X86XmmReg, X86XmmReg, X86Mem) + + //! Scalar SP-FP divide (AVX). + INST_3x(vdivss, kX86InstIdVdivss, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vdivss, kX86InstIdVdivss, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DP-FP dot product (AVX). + INST_4i(vdppd, kX86InstIdVdppd, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vdppd, kX86InstIdVdppd, X86XmmReg, X86XmmReg, X86Mem, Imm) + + //! Packed SP-FP dot product (AVX). + INST_4i(vdpps, kX86InstIdVdpps, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vdpps, kX86InstIdVdpps, X86XmmReg, X86XmmReg, X86Mem, Imm) + //! \overload + INST_4i(vdpps, kX86InstIdVdpps, X86YmmReg, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_4i(vdpps, kX86InstIdVdpps, X86YmmReg, X86YmmReg, X86Mem, Imm) + + //! Extract 128 bits of packed FP data from `o1` and store results in `o0` (AVX). + INST_3i(vextractf128, kX86InstIdVextractf128, X86XmmReg, X86YmmReg, Imm) + //! \overload + INST_3i(vextractf128, kX86InstIdVextractf128, X86Mem, X86YmmReg, Imm) + + //! Extract SP-FP based on selector (AVX). + INST_3i(vextractps, kX86InstIdVextractps, X86GpReg, X86XmmReg, Imm) + //! \overload + INST_3i(vextractps, kX86InstIdVextractps, X86Mem, X86XmmReg, Imm) + + //! Packed DP-FP horizontal add (AVX). + INST_3x(vhaddpd, kX86InstIdVhaddpd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vhaddpd, kX86InstIdVhaddpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vhaddpd, kX86InstIdVhaddpd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vhaddpd, kX86InstIdVhaddpd, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed SP-FP horizontal add (AVX). + INST_3x(vhaddps, kX86InstIdVhaddps, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vhaddps, kX86InstIdVhaddps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vhaddps, kX86InstIdVhaddps, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vhaddps, kX86InstIdVhaddps, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed DP-FP horizontal subtract (AVX). + INST_3x(vhsubpd, kX86InstIdVhsubpd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vhsubpd, kX86InstIdVhsubpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vhsubpd, kX86InstIdVhsubpd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vhsubpd, kX86InstIdVhsubpd, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed SP-FP horizontal subtract (AVX). + INST_3x(vhsubps, kX86InstIdVhsubps, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vhsubps, kX86InstIdVhsubps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vhsubps, kX86InstIdVhsubps, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vhsubps, kX86InstIdVhsubps, X86YmmReg, X86YmmReg, X86Mem) + + //! Insert 128-bit of packed FP data based on selector (AVX). + INST_4i(vinsertf128, kX86InstIdVinsertf128, X86YmmReg, X86YmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vinsertf128, kX86InstIdVinsertf128, X86YmmReg, X86YmmReg, X86Mem, Imm) + + //! Insert SP-FP based on selector (AVX). + INST_4i(vinsertps, kX86InstIdVinsertps, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vinsertps, kX86InstIdVinsertps, X86XmmReg, X86XmmReg, X86Mem, Imm) + + //! Load 128-bits unaligned (AVX). + INST_2x(vlddqu, kX86InstIdVlddqu, X86XmmReg, X86Mem) + //! Load 256-bits unaligned (AVX). + INST_2x(vlddqu, kX86InstIdVlddqu, X86YmmReg, X86Mem) + + //! Load streaming SIMD extension control/status (AVX). + INST_1x(vldmxcsr, kX86InstIdVldmxcsr, X86Mem) + + //! Store selected bytes of OWORD to DS:EDI/RDI (AVX). + INST_2x(vmaskmovdqu, kX86InstIdVmaskmovdqu, X86XmmReg, X86XmmReg) + + //! Conditionally load packed DP-FP from `o2` using mask in `o1 and store in `o0` (AVX). + INST_3x(vmaskmovpd, kX86InstIdVmaskmovpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vmaskmovpd, kX86InstIdVmaskmovpd, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vmaskmovpd, kX86InstIdVmaskmovpd, X86Mem, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vmaskmovpd, kX86InstIdVmaskmovpd, X86Mem, X86YmmReg, X86YmmReg) + + //! Conditionally load packed SP-FP from `o2` using mask in `o1 and store in `o0` (AVX). + INST_3x(vmaskmovps, kX86InstIdVmaskmovps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vmaskmovps, kX86InstIdVmaskmovps, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vmaskmovps, kX86InstIdVmaskmovps, X86Mem, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vmaskmovps, kX86InstIdVmaskmovps, X86Mem, X86YmmReg, X86YmmReg) + + //! Packed DP-FP maximum (AVX). + INST_3x(vmaxpd, kX86InstIdVmaxpd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vmaxpd, kX86InstIdVmaxpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vmaxpd, kX86InstIdVmaxpd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vmaxpd, kX86InstIdVmaxpd, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed SP-FP maximum (AVX). + INST_3x(vmaxps, kX86InstIdVmaxps, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vmaxps, kX86InstIdVmaxps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vmaxps, kX86InstIdVmaxps, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vmaxps, kX86InstIdVmaxps, X86YmmReg, X86YmmReg, X86Mem) + + //! Scalar DP-FP maximum (AVX). + INST_3x(vmaxsd, kX86InstIdVmaxsd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vmaxsd, kX86InstIdVmaxsd, X86XmmReg, X86XmmReg, X86Mem) + + //! Scalar SP-FP maximum (AVX). + INST_3x(vmaxss, kX86InstIdVmaxss, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vmaxss, kX86InstIdVmaxss, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DP-FP minimum (AVX). + INST_3x(vminpd, kX86InstIdVminpd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vminpd, kX86InstIdVminpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vminpd, kX86InstIdVminpd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vminpd, kX86InstIdVminpd, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed SP-FP minimum (AVX). + INST_3x(vminps, kX86InstIdVminps, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vminps, kX86InstIdVminps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vminps, kX86InstIdVminps, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vminps, kX86InstIdVminps, X86YmmReg, X86YmmReg, X86Mem) + + //! Scalar DP-FP minimum (AVX). + INST_3x(vminsd, kX86InstIdVminsd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vminsd, kX86InstIdVminsd, X86XmmReg, X86XmmReg, X86Mem) + + //! Scalar SP-FP minimum (AVX). + INST_3x(vminss, kX86InstIdVminss, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vminss, kX86InstIdVminss, X86XmmReg, X86XmmReg, X86Mem) + + //! Move 128-bits of aligned packed DP-FP (AVX). + INST_2x(vmovapd, kX86InstIdVmovapd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vmovapd, kX86InstIdVmovapd, X86XmmReg, X86Mem) + //! \overload + INST_2x(vmovapd, kX86InstIdVmovapd, X86Mem, X86XmmReg) + //! Move 256-bits of aligned packed DP-FP (AVX). + INST_2x(vmovapd, kX86InstIdVmovapd, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vmovapd, kX86InstIdVmovapd, X86YmmReg, X86Mem) + //! \overload + INST_2x(vmovapd, kX86InstIdVmovapd, X86Mem, X86YmmReg) + + //! Move 128-bits of aligned packed SP-FP (AVX). + INST_2x(vmovaps, kX86InstIdVmovaps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vmovaps, kX86InstIdVmovaps, X86XmmReg, X86Mem) + //! \overload + INST_2x(vmovaps, kX86InstIdVmovaps, X86Mem, X86XmmReg) + //! Move 256-bits of aligned packed SP-FP (AVX). + INST_2x(vmovaps, kX86InstIdVmovaps, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vmovaps, kX86InstIdVmovaps, X86YmmReg, X86Mem) + //! \overload + INST_2x(vmovaps, kX86InstIdVmovaps, X86Mem, X86YmmReg) + + //! Move DWORD (AVX). + INST_2x(vmovd, kX86InstIdVmovd, X86XmmReg, X86GpReg) + //! \overload + INST_2x(vmovd, kX86InstIdVmovd, X86XmmReg, X86Mem) + //! \overload + INST_2x(vmovd, kX86InstIdVmovd, X86GpReg, X86XmmReg) + //! \overload + INST_2x(vmovd, kX86InstIdVmovd, X86Mem, X86XmmReg) + + //! Move QWORD (AVX). + INST_2x(vmovq, kX86InstIdVmovq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vmovq, kX86InstIdVmovq, X86XmmReg, X86Mem) + //! \overload + INST_2x(vmovq, kX86InstIdVmovq, X86Mem, X86XmmReg) + + //! Move QWORD (AVX and X64 Only). + INST_2x(vmovq, kX86InstIdVmovq, X86XmmReg, X86GpReg) + //! \overload + INST_2x(vmovq, kX86InstIdVmovq, X86GpReg, X86XmmReg) + + //! Move one DP-FP and duplicate (AVX). + INST_2x(vmovddup, kX86InstIdVmovddup, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vmovddup, kX86InstIdVmovddup, X86XmmReg, X86Mem) + //! \overload + INST_2x(vmovddup, kX86InstIdVmovddup, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vmovddup, kX86InstIdVmovddup, X86YmmReg, X86Mem) + + //! Move 128-bits aligned (AVX). + INST_2x(vmovdqa, kX86InstIdVmovdqa, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vmovdqa, kX86InstIdVmovdqa, X86XmmReg, X86Mem) + //! \overload + INST_2x(vmovdqa, kX86InstIdVmovdqa, X86Mem, X86XmmReg) + //! Move 256-bits aligned (AVX). + INST_2x(vmovdqa, kX86InstIdVmovdqa, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vmovdqa, kX86InstIdVmovdqa, X86YmmReg, X86Mem) + //! \overload + INST_2x(vmovdqa, kX86InstIdVmovdqa, X86Mem, X86YmmReg) + + //! Move 128-bits unaligned (AVX). + INST_2x(vmovdqu, kX86InstIdVmovdqu, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vmovdqu, kX86InstIdVmovdqu, X86XmmReg, X86Mem) + //! \overload + INST_2x(vmovdqu, kX86InstIdVmovdqu, X86Mem, X86XmmReg) + //! Move 256-bits unaligned (AVX). + INST_2x(vmovdqu, kX86InstIdVmovdqu, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vmovdqu, kX86InstIdVmovdqu, X86YmmReg, X86Mem) + //! \overload + INST_2x(vmovdqu, kX86InstIdVmovdqu, X86Mem, X86YmmReg) + + //! High to low packed SP-FP (AVX). + INST_3x(vmovhlps, kX86InstIdVmovhlps, X86XmmReg, X86XmmReg, X86XmmReg) + + //! Move high packed DP-FP (AVX). + INST_3x(vmovhpd, kX86InstIdVmovhpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_2x(vmovhpd, kX86InstIdVmovhpd, X86Mem, X86XmmReg) + + //! Move high packed SP-FP (AVX). + INST_3x(vmovhps, kX86InstIdVmovhps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_2x(vmovhps, kX86InstIdVmovhps, X86Mem, X86XmmReg) + + //! Move low to high packed SP-FP (AVX). + INST_3x(vmovlhps, kX86InstIdVmovlhps, X86XmmReg, X86XmmReg, X86XmmReg) + + //! Move low packed DP-FP (AVX). + INST_3x(vmovlpd, kX86InstIdVmovlpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_2x(vmovlpd, kX86InstIdVmovlpd, X86Mem, X86XmmReg) + + //! Move low packed SP-FP (AVX). + INST_3x(vmovlps, kX86InstIdVmovlps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_2x(vmovlps, kX86InstIdVmovlps, X86Mem, X86XmmReg) + + //! Extract packed DP-FP sign mask (AVX). + INST_2x(vmovmskpd, kX86InstIdVmovmskpd, X86GpReg, X86XmmReg) + //! \overload + INST_2x(vmovmskpd, kX86InstIdVmovmskpd, X86GpReg, X86YmmReg) + + //! Extract packed SP-FP sign mask (AVX). + INST_2x(vmovmskps, kX86InstIdVmovmskps, X86GpReg, X86XmmReg) + //! \overload + INST_2x(vmovmskps, kX86InstIdVmovmskps, X86GpReg, X86YmmReg) + + //! Store 128-bits using NT hint (AVX). + INST_2x(vmovntdq, kX86InstIdVmovntdq, X86Mem, X86XmmReg) + //! Store 256-bits using NT hint (AVX). + INST_2x(vmovntdq, kX86InstIdVmovntdq, X86Mem, X86YmmReg) + + //! Store 128-bits aligned using NT hint (AVX). + INST_2x(vmovntdqa, kX86InstIdVmovntdqa, X86XmmReg, X86Mem) + + //! Store packed DP-FP (128-bits) using NT hint (AVX). + INST_2x(vmovntpd, kX86InstIdVmovntpd, X86Mem, X86XmmReg) + //! Store packed DP-FP (256-bits) using NT hint (AVX). + INST_2x(vmovntpd, kX86InstIdVmovntpd, X86Mem, X86YmmReg) + + //! Store packed SP-FP (128-bits) using NT hint (AVX). + INST_2x(vmovntps, kX86InstIdVmovntps, X86Mem, X86XmmReg) + //! Store packed SP-FP (256-bits) using NT hint (AVX). + INST_2x(vmovntps, kX86InstIdVmovntps, X86Mem, X86YmmReg) + + //! Move scalar DP-FP (AVX). + INST_3x(vmovsd, kX86InstIdVmovsd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vmovsd, kX86InstIdVmovsd, X86XmmReg, X86Mem) + //! \overload + INST_2x(vmovsd, kX86InstIdVmovsd, X86Mem, X86XmmReg) + + //! Move packed SP-FP high and duplicate (AVX). + INST_2x(vmovshdup, kX86InstIdVmovshdup, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vmovshdup, kX86InstIdVmovshdup, X86XmmReg, X86Mem) + //! \overload + INST_2x(vmovshdup, kX86InstIdVmovshdup, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vmovshdup, kX86InstIdVmovshdup, X86YmmReg, X86Mem) + + //! Move packed SP-FP low and duplicate (AVX). + INST_2x(vmovsldup, kX86InstIdVmovsldup, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vmovsldup, kX86InstIdVmovsldup, X86XmmReg, X86Mem) + //! \overload + INST_2x(vmovsldup, kX86InstIdVmovsldup, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vmovsldup, kX86InstIdVmovsldup, X86YmmReg, X86Mem) + + //! Move scalar SP-FP (AVX). + INST_3x(vmovss, kX86InstIdVmovss, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vmovss, kX86InstIdVmovss, X86XmmReg, X86Mem) + //! \overload + INST_2x(vmovss, kX86InstIdVmovss, X86Mem, X86XmmReg) + + //! Move 128-bits of unaligned packed DP-FP (AVX). + INST_2x(vmovupd, kX86InstIdVmovupd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vmovupd, kX86InstIdVmovupd, X86XmmReg, X86Mem) + //! \overload + INST_2x(vmovupd, kX86InstIdVmovupd, X86Mem, X86XmmReg) + //! Move 256-bits of unaligned packed DP-FP (AVX). + INST_2x(vmovupd, kX86InstIdVmovupd, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vmovupd, kX86InstIdVmovupd, X86YmmReg, X86Mem) + //! \overload + INST_2x(vmovupd, kX86InstIdVmovupd, X86Mem, X86YmmReg) + + //! Move 128-bits of unaligned packed SP-FP (AVX). + INST_2x(vmovups, kX86InstIdVmovups, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vmovups, kX86InstIdVmovups, X86XmmReg, X86Mem) + //! \overload + INST_2x(vmovups, kX86InstIdVmovups, X86Mem, X86XmmReg) + //! Move 256-bits of unaligned packed SP-FP (AVX). + INST_2x(vmovups, kX86InstIdVmovups, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vmovups, kX86InstIdVmovups, X86YmmReg, X86Mem) + //! \overload + INST_2x(vmovups, kX86InstIdVmovups, X86Mem, X86YmmReg) + + //! Packed WORD sums of absolute difference (AVX). + INST_4i(vmpsadbw, kX86InstIdVmpsadbw, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vmpsadbw, kX86InstIdVmpsadbw, X86XmmReg, X86XmmReg, X86Mem, Imm) + + //! Packed DP-FP multiply (AVX). + INST_3x(vmulpd, kX86InstIdVmulpd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vmulpd, kX86InstIdVmulpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vmulpd, kX86InstIdVmulpd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vmulpd, kX86InstIdVmulpd, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed SP-FP multiply (AVX). + INST_3x(vmulps, kX86InstIdVmulps, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vmulps, kX86InstIdVmulps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vmulps, kX86InstIdVmulps, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vmulps, kX86InstIdVmulps, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed SP-FP multiply (AVX). + INST_3x(vmulsd, kX86InstIdVmulsd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vmulsd, kX86InstIdVmulsd, X86XmmReg, X86XmmReg, X86Mem) + + //! Scalar SP-FP multiply (AVX). + INST_3x(vmulss, kX86InstIdVmulss, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vmulss, kX86InstIdVmulss, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DP-FP bitwise or (AVX). + INST_3x(vorpd, kX86InstIdVorpd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vorpd, kX86InstIdVorpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vorpd, kX86InstIdVorpd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vorpd, kX86InstIdVorpd, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed SP-FP bitwise or (AVX). + INST_3x(vorps, kX86InstIdVorps, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vorps, kX86InstIdVorps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vorps, kX86InstIdVorps, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vorps, kX86InstIdVorps, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed BYTE absolute value (AVX). + INST_2x(vpabsb, kX86InstIdVpabsb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpabsb, kX86InstIdVpabsb, X86XmmReg, X86Mem) + + //! Packed DWORD absolute value (AVX). + INST_2x(vpabsd, kX86InstIdVpabsd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpabsd, kX86InstIdVpabsd, X86XmmReg, X86Mem) + + //! Packed WORD absolute value (AVX). + INST_2x(vpabsw, kX86InstIdVpabsw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpabsw, kX86InstIdVpabsw, X86XmmReg, X86Mem) + + //! Pack DWORDs to WORDs with signed saturation (AVX). + INST_3x(vpackssdw, kX86InstIdVpackssdw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpackssdw, kX86InstIdVpackssdw, X86XmmReg, X86XmmReg, X86Mem) + + //! Pack WORDs to BYTEs with signed saturation (AVX). + INST_3x(vpacksswb, kX86InstIdVpacksswb, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpacksswb, kX86InstIdVpacksswb, X86XmmReg, X86XmmReg, X86Mem) + + //! Pack DWORDs to WORDs with unsigned saturation (AVX). + INST_3x(vpackusdw, kX86InstIdVpackusdw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpackusdw, kX86InstIdVpackusdw, X86XmmReg, X86XmmReg, X86Mem) + + //! Pack WORDs to BYTEs with unsigned saturation (AVX). + INST_3x(vpackuswb, kX86InstIdVpackuswb, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpackuswb, kX86InstIdVpackuswb, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed BYTE add (AVX). + INST_3x(vpaddb, kX86InstIdVpaddb, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpaddb, kX86InstIdVpaddb, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DWORD add (AVX). + INST_3x(vpaddd, kX86InstIdVpaddd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpaddd, kX86InstIdVpaddd, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed QWORD add (AVX). + INST_3x(vpaddq, kX86InstIdVpaddq, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpaddq, kX86InstIdVpaddq, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD add (AVX). + INST_3x(vpaddw, kX86InstIdVpaddw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpaddw, kX86InstIdVpaddw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed BYTE add with saturation (AVX). + INST_3x(vpaddsb, kX86InstIdVpaddsb, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpaddsb, kX86InstIdVpaddsb, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD add with saturation (AVX). + INST_3x(vpaddsw, kX86InstIdVpaddsw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpaddsw, kX86InstIdVpaddsw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed BYTE add with unsigned saturation (AVX). + INST_3x(vpaddusb, kX86InstIdVpaddusb, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpaddusb, kX86InstIdVpaddusb, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD add with unsigned saturation (AVX). + INST_3x(vpaddusw, kX86InstIdVpaddusw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpaddusw, kX86InstIdVpaddusw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed align right (AVX). + INST_4i(vpalignr, kX86InstIdVpalignr, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vpalignr, kX86InstIdVpalignr, X86XmmReg, X86XmmReg, X86Mem, Imm) + + //! Packed bitwise and (AVX). + INST_3x(vpand, kX86InstIdVpand, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpand, kX86InstIdVpand, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed bitwise and-not (AVX). + INST_3x(vpandn, kX86InstIdVpandn, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpandn, kX86InstIdVpandn, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed BYTE average (AVX). + INST_3x(vpavgb, kX86InstIdVpavgb, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpavgb, kX86InstIdVpavgb, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD average (AVX). + INST_3x(vpavgw, kX86InstIdVpavgw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpavgw, kX86InstIdVpavgw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed BYTE variable blend (AVX). + INST_4x(vpblendvb, kX86InstIdVpblendvb, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_4x(vpblendvb, kX86InstIdVpblendvb, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + + //! Packed WORD blend (AVX). + INST_4i(vpblendw, kX86InstIdVpblendw, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vpblendw, kX86InstIdVpblendw, X86XmmReg, X86XmmReg, X86Mem, Imm) + + //! Packed BYTEs compare for equality (AVX). + INST_3x(vpcmpeqb, kX86InstIdVpcmpeqb, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpcmpeqb, kX86InstIdVpcmpeqb, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DWORDs compare for equality (AVX). + INST_3x(vpcmpeqd, kX86InstIdVpcmpeqd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpcmpeqd, kX86InstIdVpcmpeqd, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed QWORDs compare for equality (AVX). + INST_3x(vpcmpeqq, kX86InstIdVpcmpeqq, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpcmpeqq, kX86InstIdVpcmpeqq, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORDs compare for equality (AVX). + INST_3x(vpcmpeqw, kX86InstIdVpcmpeqw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpcmpeqw, kX86InstIdVpcmpeqw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed BYTEs compare if greater than (AVX). + INST_3x(vpcmpgtb, kX86InstIdVpcmpgtb, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpcmpgtb, kX86InstIdVpcmpgtb, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DWORDs compare if greater than (AVX). + INST_3x(vpcmpgtd, kX86InstIdVpcmpgtd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpcmpgtd, kX86InstIdVpcmpgtd, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed QWORDs compare if greater than (AVX). + INST_3x(vpcmpgtq, kX86InstIdVpcmpgtq, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpcmpgtq, kX86InstIdVpcmpgtq, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORDs compare if greater than (AVX). + INST_3x(vpcmpgtw, kX86InstIdVpcmpgtw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpcmpgtw, kX86InstIdVpcmpgtw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed compare explicit length strings, return index (AVX). + INST_3i(vpcmpestri, kX86InstIdVpcmpestri, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(vpcmpestri, kX86InstIdVpcmpestri, X86XmmReg, X86Mem, Imm) + + //! Packed compare explicit length strings, return mask (AVX). + INST_3i(vpcmpestrm, kX86InstIdVpcmpestrm, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(vpcmpestrm, kX86InstIdVpcmpestrm, X86XmmReg, X86Mem, Imm) + + //! Packed compare implicit length strings, return index (AVX). + INST_3i(vpcmpistri, kX86InstIdVpcmpistri, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(vpcmpistri, kX86InstIdVpcmpistri, X86XmmReg, X86Mem, Imm) + + //! Packed compare implicit length strings, return mask (AVX). + INST_3i(vpcmpistrm, kX86InstIdVpcmpistrm, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(vpcmpistrm, kX86InstIdVpcmpistrm, X86XmmReg, X86Mem, Imm) + + //! Packed DP-FP permute (AVX). + INST_3x(vpermilpd, kX86InstIdVpermilpd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpermilpd, kX86InstIdVpermilpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vpermilpd, kX86InstIdVpermilpd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpermilpd, kX86InstIdVpermilpd, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3i(vpermilpd, kX86InstIdVpermilpd, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(vpermilpd, kX86InstIdVpermilpd, X86XmmReg, X86Mem, Imm) + //! \overload + INST_3i(vpermilpd, kX86InstIdVpermilpd, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_3i(vpermilpd, kX86InstIdVpermilpd, X86YmmReg, X86Mem, Imm) + + //! Packed SP-FP permute (AVX). + INST_3x(vpermilps, kX86InstIdVpermilps, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpermilps, kX86InstIdVpermilps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vpermilps, kX86InstIdVpermilps, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpermilps, kX86InstIdVpermilps, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3i(vpermilps, kX86InstIdVpermilps, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(vpermilps, kX86InstIdVpermilps, X86XmmReg, X86Mem, Imm) + //! \overload + INST_3i(vpermilps, kX86InstIdVpermilps, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_3i(vpermilps, kX86InstIdVpermilps, X86YmmReg, X86Mem, Imm) + + //! Packed 128-bit FP permute (AVX). + INST_4i(vperm2f128, kX86InstIdVperm2f128, X86YmmReg, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_4i(vperm2f128, kX86InstIdVperm2f128, X86YmmReg, X86YmmReg, X86Mem, Imm) + + //! Extract BYTE (AVX). + INST_3i(vpextrb, kX86InstIdVpextrb, X86GpReg, X86XmmReg, Imm) + //! \overload + INST_3i(vpextrb, kX86InstIdVpextrb, X86Mem, X86XmmReg, Imm) + + //! Extract DWORD (AVX). + INST_3i(vpextrd, kX86InstIdVpextrd, X86GpReg, X86XmmReg, Imm) + //! \overload + INST_3i(vpextrd, kX86InstIdVpextrd, X86Mem, X86XmmReg, Imm) + + //! Extract QWORD (AVX and X64 Only). + INST_3i(vpextrq, kX86InstIdVpextrq, X86GpReg, X86XmmReg, Imm) + //! \overload + INST_3i(vpextrq, kX86InstIdVpextrq, X86Mem, X86XmmReg, Imm) + + //! Extract WORD (AVX). + INST_3i(vpextrw, kX86InstIdVpextrw, X86GpReg, X86XmmReg, Imm) + //! \overload + INST_3i(vpextrw, kX86InstIdVpextrw, X86Mem, X86XmmReg, Imm) + + //! Packed DWORD horizontal add (AVX). + INST_3x(vphaddd, kX86InstIdVphaddd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vphaddd, kX86InstIdVphaddd, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD horizontal add with saturation (AVX). + INST_3x(vphaddsw, kX86InstIdVphaddsw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vphaddsw, kX86InstIdVphaddsw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD horizontal add (AVX). + INST_3x(vphaddw, kX86InstIdVphaddw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vphaddw, kX86InstIdVphaddw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD horizontal minimum (AVX). + INST_2x(vphminposuw, kX86InstIdVphminposuw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vphminposuw, kX86InstIdVphminposuw, X86XmmReg, X86Mem) + + //! Packed DWORD horizontal subtract (AVX). + INST_3x(vphsubd, kX86InstIdVphsubd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vphsubd, kX86InstIdVphsubd, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD horizontal subtract with saturation (AVX). + INST_3x(vphsubsw, kX86InstIdVphsubsw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vphsubsw, kX86InstIdVphsubsw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD horizontal subtract (AVX). + INST_3x(vphsubw, kX86InstIdVphsubw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vphsubw, kX86InstIdVphsubw, X86XmmReg, X86XmmReg, X86Mem) + + //! Insert BYTE based on selector (AVX). + INST_4i(vpinsrb, kX86InstIdVpinsrb, X86XmmReg, X86XmmReg, X86GpReg, Imm) + //! \overload + INST_4i(vpinsrb, kX86InstIdVpinsrb, X86XmmReg, X86XmmReg, X86Mem, Imm) + + //! Insert DWORD based on selector (AVX). + INST_4i(vpinsrd, kX86InstIdVpinsrd, X86XmmReg, X86XmmReg, X86GpReg, Imm) + //! \overload + INST_4i(vpinsrd, kX86InstIdVpinsrd, X86XmmReg, X86XmmReg, X86Mem, Imm) + + //! Insert QWORD based on selector (AVX and X64 Only). + INST_4i(vpinsrq, kX86InstIdVpinsrq, X86XmmReg, X86XmmReg, X86GpReg, Imm) + //! \overload + INST_4i(vpinsrq, kX86InstIdVpinsrq, X86XmmReg, X86XmmReg, X86Mem, Imm) + + //! Insert WORD based on selector (AVX). + INST_4i(vpinsrw, kX86InstIdVpinsrw, X86XmmReg, X86XmmReg, X86GpReg, Imm) + //! \overload + INST_4i(vpinsrw, kX86InstIdVpinsrw, X86XmmReg, X86XmmReg, X86Mem, Imm) + + //! Packed multiply and add signed and unsigned bytes (AVX). + INST_3x(vpmaddubsw, kX86InstIdVpmaddubsw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpmaddubsw, kX86InstIdVpmaddubsw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD multiply and add to packed DWORD (AVX). + INST_3x(vpmaddwd, kX86InstIdVpmaddwd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpmaddwd, kX86InstIdVpmaddwd, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed BYTE maximum (AVX). + INST_3x(vpmaxsb, kX86InstIdVpmaxsb, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpmaxsb, kX86InstIdVpmaxsb, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DWORD maximum (AVX). + INST_3x(vpmaxsd, kX86InstIdVpmaxsd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpmaxsd, kX86InstIdVpmaxsd, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD maximum (AVX). + INST_3x(vpmaxsw, kX86InstIdVpmaxsw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpmaxsw, kX86InstIdVpmaxsw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed BYTE unsigned maximum (AVX). + INST_3x(vpmaxub, kX86InstIdVpmaxub, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpmaxub, kX86InstIdVpmaxub, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DWORD unsigned maximum (AVX). + INST_3x(vpmaxud, kX86InstIdVpmaxud, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpmaxud, kX86InstIdVpmaxud, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD unsigned maximum (AVX). + INST_3x(vpmaxuw, kX86InstIdVpmaxuw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpmaxuw, kX86InstIdVpmaxuw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed BYTE minimum (AVX). + INST_3x(vpminsb, kX86InstIdVpminsb, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpminsb, kX86InstIdVpminsb, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DWORD minimum (AVX). + INST_3x(vpminsd, kX86InstIdVpminsd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpminsd, kX86InstIdVpminsd, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD minimum (AVX). + INST_3x(vpminsw, kX86InstIdVpminsw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpminsw, kX86InstIdVpminsw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed BYTE unsigned minimum (AVX). + INST_3x(vpminub, kX86InstIdVpminub, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpminub, kX86InstIdVpminub, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DWORD unsigned minimum (AVX). + INST_3x(vpminud, kX86InstIdVpminud, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpminud, kX86InstIdVpminud, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD unsigned minimum (AVX). + INST_3x(vpminuw, kX86InstIdVpminuw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpminuw, kX86InstIdVpminuw, X86XmmReg, X86XmmReg, X86Mem) + + //! Move Byte mask to integer (AVX). + INST_2x(vpmovmskb, kX86InstIdVpmovmskb, X86GpReg, X86XmmReg) + + //! BYTE to DWORD with sign extend (AVX). + INST_2x(vpmovsxbd, kX86InstIdVpmovsxbd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpmovsxbd, kX86InstIdVpmovsxbd, X86XmmReg, X86Mem) + + //! Packed BYTE to QWORD with sign extend (AVX). + INST_2x(vpmovsxbq, kX86InstIdVpmovsxbq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpmovsxbq, kX86InstIdVpmovsxbq, X86XmmReg, X86Mem) + + //! Packed BYTE to WORD with sign extend (AVX). + INST_2x(vpmovsxbw, kX86InstIdVpmovsxbw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpmovsxbw, kX86InstIdVpmovsxbw, X86XmmReg, X86Mem) + + //! Packed DWORD to QWORD with sign extend (AVX). + INST_2x(vpmovsxdq, kX86InstIdVpmovsxdq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpmovsxdq, kX86InstIdVpmovsxdq, X86XmmReg, X86Mem) + + //! Packed WORD to DWORD with sign extend (AVX). + INST_2x(vpmovsxwd, kX86InstIdVpmovsxwd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpmovsxwd, kX86InstIdVpmovsxwd, X86XmmReg, X86Mem) + + //! Packed WORD to QWORD with sign extend (AVX). + INST_2x(vpmovsxwq, kX86InstIdVpmovsxwq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpmovsxwq, kX86InstIdVpmovsxwq, X86XmmReg, X86Mem) + + //! BYTE to DWORD with zero extend (AVX). + INST_2x(vpmovzxbd, kX86InstIdVpmovzxbd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpmovzxbd, kX86InstIdVpmovzxbd, X86XmmReg, X86Mem) + + //! Packed BYTE to QWORD with zero extend (AVX). + INST_2x(vpmovzxbq, kX86InstIdVpmovzxbq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpmovzxbq, kX86InstIdVpmovzxbq, X86XmmReg, X86Mem) + + //! BYTE to WORD with zero extend (AVX). + INST_2x(vpmovzxbw, kX86InstIdVpmovzxbw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpmovzxbw, kX86InstIdVpmovzxbw, X86XmmReg, X86Mem) + + //! Packed DWORD to QWORD with zero extend (AVX). + INST_2x(vpmovzxdq, kX86InstIdVpmovzxdq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpmovzxdq, kX86InstIdVpmovzxdq, X86XmmReg, X86Mem) + + //! Packed WORD to DWORD with zero extend (AVX). + INST_2x(vpmovzxwd, kX86InstIdVpmovzxwd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpmovzxwd, kX86InstIdVpmovzxwd, X86XmmReg, X86Mem) + + //! Packed WORD to QWORD with zero extend (AVX). + INST_2x(vpmovzxwq, kX86InstIdVpmovzxwq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpmovzxwq, kX86InstIdVpmovzxwq, X86XmmReg, X86Mem) + + //! Packed DWORD to QWORD multiply (AVX). + INST_3x(vpmuldq, kX86InstIdVpmuldq, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpmuldq, kX86InstIdVpmuldq, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD multiply high, round and scale (AVX). + INST_3x(vpmulhrsw, kX86InstIdVpmulhrsw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpmulhrsw, kX86InstIdVpmulhrsw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD unsigned multiply high (AVX). + INST_3x(vpmulhuw, kX86InstIdVpmulhuw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpmulhuw, kX86InstIdVpmulhuw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD multiply high (AVX). + INST_3x(vpmulhw, kX86InstIdVpmulhw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpmulhw, kX86InstIdVpmulhw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DWORD multiply low (AVX). + INST_3x(vpmulld, kX86InstIdVpmulld, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpmulld, kX86InstIdVpmulld, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORDs multiply low (AVX). + INST_3x(vpmullw, kX86InstIdVpmullw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpmullw, kX86InstIdVpmullw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DWORD multiply to QWORD (AVX). + INST_3x(vpmuludq, kX86InstIdVpmuludq, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpmuludq, kX86InstIdVpmuludq, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed bitwise or (AVX). + INST_3x(vpor, kX86InstIdVpor, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpor, kX86InstIdVpor, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD sum of absolute differences (AVX). + INST_3x(vpsadbw, kX86InstIdVpsadbw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsadbw, kX86InstIdVpsadbw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed BYTE shuffle (AVX). + INST_3x(vpshufb, kX86InstIdVpshufb, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpshufb, kX86InstIdVpshufb, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DWORD shuffle (AVX). + INST_3i(vpshufd, kX86InstIdVpshufd, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(vpshufd, kX86InstIdVpshufd, X86XmmReg, X86Mem, Imm) + + //! Packed WORD shuffle high (AVX). + INST_3i(vpshufhw, kX86InstIdVpshufhw, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(vpshufhw, kX86InstIdVpshufhw, X86XmmReg, X86Mem, Imm) + + //! Packed WORD shuffle low (AVX). + INST_3i(vpshuflw, kX86InstIdVpshuflw, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(vpshuflw, kX86InstIdVpshuflw, X86XmmReg, X86Mem, Imm) + + //! Packed BYTE sign (AVX). + INST_3x(vpsignb, kX86InstIdVpsignb, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsignb, kX86InstIdVpsignb, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DWORD sign (AVX). + INST_3x(vpsignd, kX86InstIdVpsignd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsignd, kX86InstIdVpsignd, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD sign (AVX). + INST_3x(vpsignw, kX86InstIdVpsignw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsignw, kX86InstIdVpsignw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DWORD shift left logical (AVX). + INST_3x(vpslld, kX86InstIdVpslld, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpslld, kX86InstIdVpslld, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3i(vpslld, kX86InstIdVpslld, X86XmmReg, X86XmmReg, Imm) + + //! Packed OWORD shift left logical (AVX). + INST_3i(vpslldq, kX86InstIdVpslldq, X86XmmReg, X86XmmReg, Imm) + + //! Packed QWORD shift left logical (AVX). + INST_3x(vpsllq, kX86InstIdVpsllq, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsllq, kX86InstIdVpsllq, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3i(vpsllq, kX86InstIdVpsllq, X86XmmReg, X86XmmReg, Imm) + + //! Packed WORD shift left logical (AVX). + INST_3x(vpsllw, kX86InstIdVpsllw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsllw, kX86InstIdVpsllw, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3i(vpsllw, kX86InstIdVpsllw, X86XmmReg, X86XmmReg, Imm) + + //! Packed DWORD shift right arithmetic (AVX). + INST_3x(vpsrad, kX86InstIdVpsrad, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsrad, kX86InstIdVpsrad, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3i(vpsrad, kX86InstIdVpsrad, X86XmmReg, X86XmmReg, Imm) + + //! Packed WORD shift right arithmetic (AVX). + INST_3x(vpsraw, kX86InstIdVpsraw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsraw, kX86InstIdVpsraw, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3i(vpsraw, kX86InstIdVpsraw, X86XmmReg, X86XmmReg, Imm) + + //! Packed DWORD shift right logical (AVX). + INST_3x(vpsrld, kX86InstIdVpsrld, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsrld, kX86InstIdVpsrld, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3i(vpsrld, kX86InstIdVpsrld, X86XmmReg, X86XmmReg, Imm) + + //! Scalar OWORD shift right logical (AVX). + INST_3i(vpsrldq, kX86InstIdVpsrldq, X86XmmReg, X86XmmReg, Imm) + + //! Packed QWORD shift right logical (AVX). + INST_3x(vpsrlq, kX86InstIdVpsrlq, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsrlq, kX86InstIdVpsrlq, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3i(vpsrlq, kX86InstIdVpsrlq, X86XmmReg, X86XmmReg, Imm) + + //! Packed WORD shift right logical (AVX). + INST_3x(vpsrlw, kX86InstIdVpsrlw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsrlw, kX86InstIdVpsrlw, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3i(vpsrlw, kX86InstIdVpsrlw, X86XmmReg, X86XmmReg, Imm) + + //! Packed BYTE subtract (AVX). + INST_3x(vpsubb, kX86InstIdVpsubb, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsubb, kX86InstIdVpsubb, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DWORD subtract (AVX). + INST_3x(vpsubd, kX86InstIdVpsubd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsubd, kX86InstIdVpsubd, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed QWORD subtract (AVX). + INST_3x(vpsubq, kX86InstIdVpsubq, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsubq, kX86InstIdVpsubq, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD subtract (AVX). + INST_3x(vpsubw, kX86InstIdVpsubw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsubw, kX86InstIdVpsubw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed BYTE subtract with saturation (AVX). + INST_3x(vpsubsb, kX86InstIdVpsubsb, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsubsb, kX86InstIdVpsubsb, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD subtract with saturation (AVX). + INST_3x(vpsubsw, kX86InstIdVpsubsw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsubsw, kX86InstIdVpsubsw, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed BYTE subtract with unsigned saturation (AVX). + INST_3x(vpsubusb, kX86InstIdVpsubusb, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsubusb, kX86InstIdVpsubusb, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed WORD subtract with unsigned saturation (AVX). + INST_3x(vpsubusw, kX86InstIdVpsubusw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpsubusw, kX86InstIdVpsubusw, X86XmmReg, X86XmmReg, X86Mem) + + //! Logical compare (AVX). + INST_2x(vptest, kX86InstIdVptest, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vptest, kX86InstIdVptest, X86XmmReg, X86Mem) + //! \overload + INST_2x(vptest, kX86InstIdVptest, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vptest, kX86InstIdVptest, X86YmmReg, X86Mem) + + //! Unpack high packed BYTEs to WORDs (AVX). + INST_3x(vpunpckhbw, kX86InstIdVpunpckhbw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpunpckhbw, kX86InstIdVpunpckhbw, X86XmmReg, X86XmmReg, X86Mem) + + //! Unpack high packed DWORDs to QWORDs (AVX). + INST_3x(vpunpckhdq, kX86InstIdVpunpckhdq, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpunpckhdq, kX86InstIdVpunpckhdq, X86XmmReg, X86XmmReg, X86Mem) + + //! Unpack high packed QWORDs to OWORD (AVX). + INST_3x(vpunpckhqdq, kX86InstIdVpunpckhqdq, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpunpckhqdq, kX86InstIdVpunpckhqdq, X86XmmReg, X86XmmReg, X86Mem) + + //! Unpack high packed WORDs to DWORDs (AVX). + INST_3x(vpunpckhwd, kX86InstIdVpunpckhwd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpunpckhwd, kX86InstIdVpunpckhwd, X86XmmReg, X86XmmReg, X86Mem) + + //! Unpack low packed BYTEs to WORDs (AVX). + INST_3x(vpunpcklbw, kX86InstIdVpunpcklbw, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpunpcklbw, kX86InstIdVpunpcklbw, X86XmmReg, X86XmmReg, X86Mem) + + //! Unpack low packed DWORDs to QWORDs (AVX). + INST_3x(vpunpckldq, kX86InstIdVpunpckldq, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpunpckldq, kX86InstIdVpunpckldq, X86XmmReg, X86XmmReg, X86Mem) + + //! Unpack low packed QWORDs to OWORD (AVX). + INST_3x(vpunpcklqdq, kX86InstIdVpunpcklqdq, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpunpcklqdq, kX86InstIdVpunpcklqdq, X86XmmReg, X86XmmReg, X86Mem) + + //! Unpack low packed WORDs to DWORDs (AVX). + INST_3x(vpunpcklwd, kX86InstIdVpunpcklwd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpunpcklwd, kX86InstIdVpunpcklwd, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed bitwise xor (AVX). + INST_3x(vpxor, kX86InstIdVpxor, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vpxor, kX86InstIdVpxor, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed SP-FP reciprocal (AVX). + INST_2x(vrcpps, kX86InstIdVrcpps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vrcpps, kX86InstIdVrcpps, X86XmmReg, X86Mem) + //! \overload + INST_2x(vrcpps, kX86InstIdVrcpps, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vrcpps, kX86InstIdVrcpps, X86YmmReg, X86Mem) + + //! Scalar SP-FP reciprocal (AVX). + INST_3x(vrcpss, kX86InstIdVrcpss, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vrcpss, kX86InstIdVrcpss, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed SP-FP square root reciprocal (AVX). + INST_2x(vrsqrtps, kX86InstIdVrsqrtps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vrsqrtps, kX86InstIdVrsqrtps, X86XmmReg, X86Mem) + //! \overload + INST_2x(vrsqrtps, kX86InstIdVrsqrtps, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vrsqrtps, kX86InstIdVrsqrtps, X86YmmReg, X86Mem) + + //! Scalar SP-FP square root reciprocal (AVX). + INST_3x(vrsqrtss, kX86InstIdVrsqrtss, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vrsqrtss, kX86InstIdVrsqrtss, X86XmmReg, X86XmmReg, X86Mem) + + //! Packed DP-FP round (AVX). + INST_3i(vroundpd, kX86InstIdVroundpd, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(vroundpd, kX86InstIdVroundpd, X86XmmReg, X86Mem, Imm) + //! \overload + INST_3i(vroundpd, kX86InstIdVroundpd, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_3i(vroundpd, kX86InstIdVroundpd, X86YmmReg, X86Mem, Imm) + + //! Packed SP-FP round (AVX). + INST_3i(vroundps, kX86InstIdVroundps, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(vroundps, kX86InstIdVroundps, X86XmmReg, X86Mem, Imm) + //! \overload + INST_3i(vroundps, kX86InstIdVroundps, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_3i(vroundps, kX86InstIdVroundps, X86YmmReg, X86Mem, Imm) + + //! Scalar DP-FP round (AVX). + INST_4i(vroundsd, kX86InstIdVroundsd, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vroundsd, kX86InstIdVroundsd, X86XmmReg, X86XmmReg, X86Mem, Imm) + + //! Scalar SP-FP round (AVX). + INST_4i(vroundss, kX86InstIdVroundss, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vroundss, kX86InstIdVroundss, X86XmmReg, X86XmmReg, X86Mem, Imm) + + //! Shuffle DP-FP (AVX). + INST_4i(vshufpd, kX86InstIdVshufpd, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vshufpd, kX86InstIdVshufpd, X86XmmReg, X86XmmReg, X86Mem, Imm) + //! \overload + INST_4i(vshufpd, kX86InstIdVshufpd, X86YmmReg, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_4i(vshufpd, kX86InstIdVshufpd, X86YmmReg, X86YmmReg, X86Mem, Imm) + + //! Shuffle SP-FP (AVX). + INST_4i(vshufps, kX86InstIdVshufps, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vshufps, kX86InstIdVshufps, X86XmmReg, X86XmmReg, X86Mem, Imm) + //! \overload + INST_4i(vshufps, kX86InstIdVshufps, X86YmmReg, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_4i(vshufps, kX86InstIdVshufps, X86YmmReg, X86YmmReg, X86Mem, Imm) + + //! Packed DP-FP square root (AVX). + INST_2x(vsqrtpd, kX86InstIdVsqrtpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vsqrtpd, kX86InstIdVsqrtpd, X86XmmReg, X86Mem) + //! \overload + INST_2x(vsqrtpd, kX86InstIdVsqrtpd, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vsqrtpd, kX86InstIdVsqrtpd, X86YmmReg, X86Mem) + + //! Packed SP-FP square root (AVX). + INST_2x(vsqrtps, kX86InstIdVsqrtps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vsqrtps, kX86InstIdVsqrtps, X86XmmReg, X86Mem) + //! \overload + INST_2x(vsqrtps, kX86InstIdVsqrtps, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vsqrtps, kX86InstIdVsqrtps, X86YmmReg, X86Mem) + + //! Scalar DP-FP square root (AVX). + INST_3x(vsqrtsd, kX86InstIdVsqrtsd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vsqrtsd, kX86InstIdVsqrtsd, X86XmmReg, X86XmmReg, X86Mem) + + //! Scalar SP-FP square root (AVX). + INST_3x(vsqrtss, kX86InstIdVsqrtss, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vsqrtss, kX86InstIdVsqrtss, X86XmmReg, X86XmmReg, X86Mem) + + //! Store streaming SIMD extension control/status (AVX). + INST_1x(vstmxcsr, kX86InstIdVstmxcsr, X86Mem) + + //! Packed DP-FP subtract (AVX). + INST_3x(vsubpd, kX86InstIdVsubpd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vsubpd, kX86InstIdVsubpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vsubpd, kX86InstIdVsubpd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vsubpd, kX86InstIdVsubpd, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed SP-FP subtract (AVX). + INST_3x(vsubps, kX86InstIdVsubps, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vsubps, kX86InstIdVsubps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vsubps, kX86InstIdVsubps, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vsubps, kX86InstIdVsubps, X86YmmReg, X86YmmReg, X86Mem) + + //! Scalar DP-FP subtract (AVX). + INST_3x(vsubsd, kX86InstIdVsubsd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vsubsd, kX86InstIdVsubsd, X86XmmReg, X86XmmReg, X86Mem) + + //! Scalar SP-FP subtract (AVX). + INST_3x(vsubss, kX86InstIdVsubss, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vsubss, kX86InstIdVsubss, X86XmmReg, X86XmmReg, X86Mem) + + //! Logical compare DP-FP (AVX). + INST_2x(vtestpd, kX86InstIdVtestpd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vtestpd, kX86InstIdVtestpd, X86XmmReg, X86Mem) + //! \overload + INST_2x(vtestpd, kX86InstIdVtestpd, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vtestpd, kX86InstIdVtestpd, X86YmmReg, X86Mem) + + //! Logical compare SP-FP (AVX). + INST_2x(vtestps, kX86InstIdVtestps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vtestps, kX86InstIdVtestps, X86XmmReg, X86Mem) + //! \overload + INST_2x(vtestps, kX86InstIdVtestps, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vtestps, kX86InstIdVtestps, X86YmmReg, X86Mem) + + //! Scalar DP-FP unordered compare and set EFLAGS (AVX). + INST_2x(vucomisd, kX86InstIdVucomisd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vucomisd, kX86InstIdVucomisd, X86XmmReg, X86Mem) + + //! Unordered scalar SP-FP compare and set EFLAGS (AVX). + INST_2x(vucomiss, kX86InstIdVucomiss, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vucomiss, kX86InstIdVucomiss, X86XmmReg, X86Mem) + + //! Unpack and interleave high packed DP-FP (AVX). + INST_3x(vunpckhpd, kX86InstIdVunpckhpd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vunpckhpd, kX86InstIdVunpckhpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vunpckhpd, kX86InstIdVunpckhpd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vunpckhpd, kX86InstIdVunpckhpd, X86YmmReg, X86YmmReg, X86Mem) + + //! Unpack high packed SP-FP data (AVX). + INST_3x(vunpckhps, kX86InstIdVunpckhps, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vunpckhps, kX86InstIdVunpckhps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vunpckhps, kX86InstIdVunpckhps, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vunpckhps, kX86InstIdVunpckhps, X86YmmReg, X86YmmReg, X86Mem) + + //! Unpack and interleave low packed DP-FP (AVX). + INST_3x(vunpcklpd, kX86InstIdVunpcklpd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vunpcklpd, kX86InstIdVunpcklpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vunpcklpd, kX86InstIdVunpcklpd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vunpcklpd, kX86InstIdVunpcklpd, X86YmmReg, X86YmmReg, X86Mem) + + //! Unpack low packed SP-FP data (AVX). + INST_3x(vunpcklps, kX86InstIdVunpcklps, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vunpcklps, kX86InstIdVunpcklps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vunpcklps, kX86InstIdVunpcklps, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vunpcklps, kX86InstIdVunpcklps, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed DP-FP bitwise xor (AVX). + INST_3x(vxorpd, kX86InstIdVxorpd, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vxorpd, kX86InstIdVxorpd, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vxorpd, kX86InstIdVxorpd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vxorpd, kX86InstIdVxorpd, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed SP-FP bitwise xor (AVX). + INST_3x(vxorps, kX86InstIdVxorps, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vxorps, kX86InstIdVxorps, X86XmmReg, X86XmmReg, X86Mem) + //! \overload + INST_3x(vxorps, kX86InstIdVxorps, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vxorps, kX86InstIdVxorps, X86YmmReg, X86YmmReg, X86Mem) + + //! Zero all Ymm registers. + INST_0x(vzeroall, kX86InstIdVzeroall) + //! Zero upper 128-bits of all Ymm registers. + INST_0x(vzeroupper, kX86InstIdVzeroupper) + + // -------------------------------------------------------------------------- + // [AVX+AESNI] + // -------------------------------------------------------------------------- + + //! Perform a single round of the AES decryption flow (AVX+AESNI). + INST_3x(vaesdec, kX86InstIdVaesdec, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vaesdec, kX86InstIdVaesdec, X86XmmReg, X86XmmReg, X86Mem) + + //! Perform the last round of the AES decryption flow (AVX+AESNI). + INST_3x(vaesdeclast, kX86InstIdVaesdeclast, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vaesdeclast, kX86InstIdVaesdeclast, X86XmmReg, X86XmmReg, X86Mem) + + //! Perform a single round of the AES encryption flow (AVX+AESNI). + INST_3x(vaesenc, kX86InstIdVaesenc, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vaesenc, kX86InstIdVaesenc, X86XmmReg, X86XmmReg, X86Mem) + + //! Perform the last round of the AES encryption flow (AVX+AESNI). + INST_3x(vaesenclast, kX86InstIdVaesenclast, X86XmmReg, X86XmmReg, X86XmmReg) + //! \overload + INST_3x(vaesenclast, kX86InstIdVaesenclast, X86XmmReg, X86XmmReg, X86Mem) + + //! Perform the InvMixColumns transformation (AVX+AESNI). + INST_2x(vaesimc, kX86InstIdVaesimc, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vaesimc, kX86InstIdVaesimc, X86XmmReg, X86Mem) + + //! Assist in expanding the AES cipher key (AVX+AESNI). + INST_3i(vaeskeygenassist, kX86InstIdVaeskeygenassist, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(vaeskeygenassist, kX86InstIdVaeskeygenassist, X86XmmReg, X86Mem, Imm) + + // -------------------------------------------------------------------------- + // [AVX+PCLMULQDQ] + // -------------------------------------------------------------------------- + + //! Carry-less multiplication QWORD (AVX+PCLMULQDQ). + INST_4i(vpclmulqdq, kX86InstIdVpclmulqdq, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vpclmulqdq, kX86InstIdVpclmulqdq, X86XmmReg, X86XmmReg, X86Mem, Imm) + + // -------------------------------------------------------------------------- + // [AVX2] + // -------------------------------------------------------------------------- + + //! Broadcast low 128-bit element in `o1` to `o0` (AVX2). + INST_2x(vbroadcasti128, kX86InstIdVbroadcasti128, X86YmmReg, X86Mem) + //! Broadcast low DP-FP element in `o1` to `o0` (AVX2). + INST_2x(vbroadcastsd, kX86InstIdVbroadcastsd, X86YmmReg, X86XmmReg) + //! Broadcast low SP-FP element in `o1` to `o0` (AVX2). + INST_2x(vbroadcastss, kX86InstIdVbroadcastss, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vbroadcastss, kX86InstIdVbroadcastss, X86YmmReg, X86XmmReg) + + //! Extract 128-bit element from `o1` to `o0` based on selector (AVX2). + INST_3i(vextracti128, kX86InstIdVextracti128, X86XmmReg, X86YmmReg, Imm) + //! \overload + INST_3i(vextracti128, kX86InstIdVextracti128, X86Mem, X86YmmReg, Imm) + + //! Gather DP-FP from DWORD indicies specified in `o1`s VSIB (AVX2). + INST_3x(vgatherdpd, kX86InstIdVgatherdpd, X86XmmReg, X86Mem, X86XmmReg) + //! \overload + INST_3x(vgatherdpd, kX86InstIdVgatherdpd, X86YmmReg, X86Mem, X86YmmReg) + + //! Gather SP-FP from DWORD indicies specified in `o1`s VSIB (AVX2). + INST_3x(vgatherdps, kX86InstIdVgatherdps, X86XmmReg, X86Mem, X86XmmReg) + //! \overload + INST_3x(vgatherdps, kX86InstIdVgatherdps, X86YmmReg, X86Mem, X86YmmReg) + + //! Gather DP-FP from QWORD indicies specified in `o1`s VSIB (AVX2). + INST_3x(vgatherqpd, kX86InstIdVgatherqpd, X86XmmReg, X86Mem, X86XmmReg) + //! \overload + INST_3x(vgatherqpd, kX86InstIdVgatherqpd, X86YmmReg, X86Mem, X86YmmReg) + + //! Gather SP-FP from QWORD indicies specified in `o1`s VSIB (AVX2). + INST_3x(vgatherqps, kX86InstIdVgatherqps, X86XmmReg, X86Mem, X86XmmReg) + + //! Insert 128-bit of packed data based on selector (AVX2). + INST_4i(vinserti128, kX86InstIdVinserti128, X86YmmReg, X86YmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vinserti128, kX86InstIdVinserti128, X86YmmReg, X86YmmReg, X86Mem, Imm) + + //! Load 256-bits aligned using NT hint (AVX2). + INST_2x(vmovntdqa, kX86InstIdVmovntdqa, X86YmmReg, X86Mem) + + //! Packed WORD sums of absolute difference (AVX2). + INST_4i(vmpsadbw, kX86InstIdVmpsadbw, X86YmmReg, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_4i(vmpsadbw, kX86InstIdVmpsadbw, X86YmmReg, X86YmmReg, X86Mem, Imm) + + //! Packed BYTE absolute value (AVX2). + INST_2x(vpabsb, kX86InstIdVpabsb, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vpabsb, kX86InstIdVpabsb, X86YmmReg, X86Mem) + + //! Packed DWORD absolute value (AVX2). + INST_2x(vpabsd, kX86InstIdVpabsd, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vpabsd, kX86InstIdVpabsd, X86YmmReg, X86Mem) + + //! Packed WORD absolute value (AVX2). + INST_2x(vpabsw, kX86InstIdVpabsw, X86YmmReg, X86YmmReg) + //! \overload + INST_2x(vpabsw, kX86InstIdVpabsw, X86YmmReg, X86Mem) + + //! Pack DWORDs to WORDs with signed saturation (AVX2). + INST_3x(vpackssdw, kX86InstIdVpackssdw, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpackssdw, kX86InstIdVpackssdw, X86YmmReg, X86YmmReg, X86Mem) + + //! Pack WORDs to BYTEs with signed saturation (AVX2). + INST_3x(vpacksswb, kX86InstIdVpacksswb, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpacksswb, kX86InstIdVpacksswb, X86YmmReg, X86YmmReg, X86Mem) + + //! Pack DWORDs to WORDs with unsigned saturation (AVX2). + INST_3x(vpackusdw, kX86InstIdVpackusdw, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpackusdw, kX86InstIdVpackusdw, X86YmmReg, X86YmmReg, X86Mem) + + //! Pack WORDs to BYTEs with unsigned saturation (AVX2). + INST_3x(vpackuswb, kX86InstIdVpackuswb, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpackuswb, kX86InstIdVpackuswb, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed BYTE add (AVX2). + INST_3x(vpaddb, kX86InstIdVpaddb, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpaddb, kX86InstIdVpaddb, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed DWORD add (AVX2). + INST_3x(vpaddd, kX86InstIdVpaddd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpaddd, kX86InstIdVpaddd, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed QDWORD add (AVX2). + INST_3x(vpaddq, kX86InstIdVpaddq, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpaddq, kX86InstIdVpaddq, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed WORD add (AVX2). + INST_3x(vpaddw, kX86InstIdVpaddw, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpaddw, kX86InstIdVpaddw, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed BYTE add with saturation (AVX2). + INST_3x(vpaddsb, kX86InstIdVpaddsb, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpaddsb, kX86InstIdVpaddsb, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed WORD add with saturation (AVX2). + INST_3x(vpaddsw, kX86InstIdVpaddsw, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpaddsw, kX86InstIdVpaddsw, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed BYTE add with unsigned saturation (AVX2). + INST_3x(vpaddusb, kX86InstIdVpaddusb, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpaddusb, kX86InstIdVpaddusb, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed WORD add with unsigned saturation (AVX2). + INST_3x(vpaddusw, kX86InstIdVpaddusw, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpaddusw, kX86InstIdVpaddusw, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed align right (AVX2). + INST_4i(vpalignr, kX86InstIdVpalignr, X86YmmReg, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_4i(vpalignr, kX86InstIdVpalignr, X86YmmReg, X86YmmReg, X86Mem, Imm) + + //! Packed bitwise and (AVX2). + INST_3x(vpand, kX86InstIdVpand, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpand, kX86InstIdVpand, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed bitwise and-not (AVX2). + INST_3x(vpandn, kX86InstIdVpandn, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpandn, kX86InstIdVpandn, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed BYTE average (AVX2). + INST_3x(vpavgb, kX86InstIdVpavgb, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpavgb, kX86InstIdVpavgb, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed WORD average (AVX2). + INST_3x(vpavgw, kX86InstIdVpavgw, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpavgw, kX86InstIdVpavgw, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed DWORD blend (AVX2). + INST_4i(vpblendd, kX86InstIdVpblendd, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_4i(vpblendd, kX86InstIdVpblendd, X86XmmReg, X86XmmReg, X86Mem, Imm) + //! \overload + INST_4i(vpblendd, kX86InstIdVpblendd, X86YmmReg, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_4i(vpblendd, kX86InstIdVpblendd, X86YmmReg, X86YmmReg, X86Mem, Imm) + + //! Packed DWORD variable blend (AVX2). + INST_4x(vpblendvb, kX86InstIdVpblendvb, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_4x(vpblendvb, kX86InstIdVpblendvb, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + + //! Packed WORD blend (AVX2). + INST_4i(vpblendw, kX86InstIdVpblendw, X86YmmReg, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_4i(vpblendw, kX86InstIdVpblendw, X86YmmReg, X86YmmReg, X86Mem, Imm) + + //! Broadcast BYTE from `o1` to 128-bits in `o0` (AVX2). + INST_2x(vpbroadcastb, kX86InstIdVpbroadcastb, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpbroadcastb, kX86InstIdVpbroadcastb, X86XmmReg, X86Mem) + //! Broadcast BYTE from `o1` to 256-bits in `o0` (AVX2). + INST_2x(vpbroadcastb, kX86InstIdVpbroadcastb, X86YmmReg, X86XmmReg) + //! \overload + INST_2x(vpbroadcastb, kX86InstIdVpbroadcastb, X86YmmReg, X86Mem) + + //! Broadcast DWORD from `o1` to 128-bits in `o0` (AVX2). + INST_2x(vpbroadcastd, kX86InstIdVpbroadcastd, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpbroadcastd, kX86InstIdVpbroadcastd, X86XmmReg, X86Mem) + //! Broadcast DWORD from `o1` to 256-bits in `o0` (AVX2). + INST_2x(vpbroadcastd, kX86InstIdVpbroadcastd, X86YmmReg, X86XmmReg) + //! \overload + INST_2x(vpbroadcastd, kX86InstIdVpbroadcastd, X86YmmReg, X86Mem) + + //! Broadcast QWORD from `o1` to 128-bits in `o0` (AVX2). + INST_2x(vpbroadcastq, kX86InstIdVpbroadcastq, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpbroadcastq, kX86InstIdVpbroadcastq, X86XmmReg, X86Mem) + //! Broadcast QWORD from `o1` to 256-bits in `o0` (AVX2). + INST_2x(vpbroadcastq, kX86InstIdVpbroadcastq, X86YmmReg, X86XmmReg) + //! \overload + INST_2x(vpbroadcastq, kX86InstIdVpbroadcastq, X86YmmReg, X86Mem) + + //! Broadcast WORD from `o1` to 128-bits in `o0` (AVX2). + INST_2x(vpbroadcastw, kX86InstIdVpbroadcastw, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vpbroadcastw, kX86InstIdVpbroadcastw, X86XmmReg, X86Mem) + //! Broadcast WORD from `o1` to 256-bits in `o0` (AVX2). + INST_2x(vpbroadcastw, kX86InstIdVpbroadcastw, X86YmmReg, X86XmmReg) + //! \overload + INST_2x(vpbroadcastw, kX86InstIdVpbroadcastw, X86YmmReg, X86Mem) + + //! Packed BYTEs compare for equality (AVX2). + INST_3x(vpcmpeqb, kX86InstIdVpcmpeqb, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpcmpeqb, kX86InstIdVpcmpeqb, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed DWORDs compare for equality (AVX2). + INST_3x(vpcmpeqd, kX86InstIdVpcmpeqd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpcmpeqd, kX86InstIdVpcmpeqd, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed QWORDs compare for equality (AVX2). + INST_3x(vpcmpeqq, kX86InstIdVpcmpeqq, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpcmpeqq, kX86InstIdVpcmpeqq, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed WORDs compare for equality (AVX2). + INST_3x(vpcmpeqw, kX86InstIdVpcmpeqw, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpcmpeqw, kX86InstIdVpcmpeqw, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed BYTEs compare if greater than (AVX2). + INST_3x(vpcmpgtb, kX86InstIdVpcmpgtb, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpcmpgtb, kX86InstIdVpcmpgtb, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed DWORDs compare if greater than (AVX2). + INST_3x(vpcmpgtd, kX86InstIdVpcmpgtd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpcmpgtd, kX86InstIdVpcmpgtd, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed QWORDs compare if greater than (AVX2). + INST_3x(vpcmpgtq, kX86InstIdVpcmpgtq, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpcmpgtq, kX86InstIdVpcmpgtq, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed WORDs compare if greater than (AVX2). + INST_3x(vpcmpgtw, kX86InstIdVpcmpgtw, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpcmpgtw, kX86InstIdVpcmpgtw, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed OWORD permute (AVX2). + INST_4i(vperm2i128, kX86InstIdVperm2i128, X86YmmReg, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_4i(vperm2i128, kX86InstIdVperm2i128, X86YmmReg, X86YmmReg, X86Mem, Imm) + + //! Packed DWORD permute (AVX2). + INST_3x(vpermd, kX86InstIdVpermd, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpermd, kX86InstIdVpermd, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed DP-FP permute (AVX2). + INST_3i(vpermpd, kX86InstIdVpermpd, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_3i(vpermpd, kX86InstIdVpermpd, X86YmmReg, X86Mem, Imm) + + //! Packed SP-FP permute (AVX2). + INST_3x(vpermps, kX86InstIdVpermps, X86YmmReg, X86YmmReg, X86YmmReg) + //! \overload + INST_3x(vpermps, kX86InstIdVpermps, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed QWORD permute (AVX2). + INST_3i(vpermq, kX86InstIdVpermq, X86YmmReg, X86YmmReg, Imm) + //! \overload + INST_3i(vpermq, kX86InstIdVpermq, X86YmmReg, X86Mem, Imm) + + INST_3x(vpgatherdd, kX86InstIdVpgatherdd, X86XmmReg, X86Mem, X86XmmReg) + INST_3x(vpgatherdd, kX86InstIdVpgatherdd, X86YmmReg, X86Mem, X86YmmReg) + + INST_3x(vpgatherdq, kX86InstIdVpgatherdq, X86XmmReg, X86Mem, X86XmmReg) + INST_3x(vpgatherdq, kX86InstIdVpgatherdq, X86YmmReg, X86Mem, X86YmmReg) + + INST_3x(vpgatherqd, kX86InstIdVpgatherqd, X86XmmReg, X86Mem, X86XmmReg) + + INST_3x(vpgatherqq, kX86InstIdVpgatherqq, X86XmmReg, X86Mem, X86XmmReg) + INST_3x(vpgatherqq, kX86InstIdVpgatherqq, X86YmmReg, X86Mem, X86YmmReg) + + //! Packed DWORD horizontal add (AVX2). + INST_3x(vphaddd, kX86InstIdVphaddd, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vphaddd, kX86InstIdVphaddd, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD horizontal add with saturation (AVX2). + INST_3x(vphaddsw, kX86InstIdVphaddsw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vphaddsw, kX86InstIdVphaddsw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD horizontal add (AVX2). + INST_3x(vphaddw, kX86InstIdVphaddw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vphaddw, kX86InstIdVphaddw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed DWORD horizontal subtract (AVX2). + INST_3x(vphsubd, kX86InstIdVphsubd, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vphsubd, kX86InstIdVphsubd, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD horizontal subtract with saturation (AVX2). + INST_3x(vphsubsw, kX86InstIdVphsubsw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vphsubsw, kX86InstIdVphsubsw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD horizontal subtract (AVX2). + INST_3x(vphsubw, kX86InstIdVphsubw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vphsubw, kX86InstIdVphsubw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Move Byte mask to integer (AVX2). + INST_2x(vpmovmskb, kX86InstIdVpmovmskb, X86GpReg, X86YmmReg) + + //! BYTE to DWORD with sign extend (AVX). + INST_2x(vpmovsxbd, kX86InstIdVpmovsxbd, X86YmmReg, X86Mem) + //! \overload + INST_2x(vpmovsxbd, kX86InstIdVpmovsxbd, X86YmmReg, X86XmmReg) + + //! Packed BYTE to QWORD with sign extend (AVX2). + INST_2x(vpmovsxbq, kX86InstIdVpmovsxbq, X86YmmReg, X86Mem) + //! \overload + INST_2x(vpmovsxbq, kX86InstIdVpmovsxbq, X86YmmReg, X86XmmReg) + + //! Packed BYTE to WORD with sign extend (AVX2). + INST_2x(vpmovsxbw, kX86InstIdVpmovsxbw, X86YmmReg, X86Mem) + //! \overload + INST_2x(vpmovsxbw, kX86InstIdVpmovsxbw, X86YmmReg, X86XmmReg) + + //! Packed DWORD to QWORD with sign extend (AVX2). + INST_2x(vpmovsxdq, kX86InstIdVpmovsxdq, X86YmmReg, X86Mem) + //! \overload + INST_2x(vpmovsxdq, kX86InstIdVpmovsxdq, X86YmmReg, X86XmmReg) + + //! Packed WORD to DWORD with sign extend (AVX2). + INST_2x(vpmovsxwd, kX86InstIdVpmovsxwd, X86YmmReg, X86Mem) + //! \overload + INST_2x(vpmovsxwd, kX86InstIdVpmovsxwd, X86YmmReg, X86XmmReg) + + //! Packed WORD to QWORD with sign extend (AVX2). + INST_2x(vpmovsxwq, kX86InstIdVpmovsxwq, X86YmmReg, X86Mem) + //! \overload + INST_2x(vpmovsxwq, kX86InstIdVpmovsxwq, X86YmmReg, X86XmmReg) + + //! BYTE to DWORD with zero extend (AVX2). + INST_2x(vpmovzxbd, kX86InstIdVpmovzxbd, X86YmmReg, X86Mem) + //! \overload + INST_2x(vpmovzxbd, kX86InstIdVpmovzxbd, X86YmmReg, X86XmmReg) + + //! Packed BYTE to QWORD with zero extend (AVX2). + INST_2x(vpmovzxbq, kX86InstIdVpmovzxbq, X86YmmReg, X86Mem) + //! \overload + INST_2x(vpmovzxbq, kX86InstIdVpmovzxbq, X86YmmReg, X86XmmReg) + + //! BYTE to WORD with zero extend (AVX2). + INST_2x(vpmovzxbw, kX86InstIdVpmovzxbw, X86YmmReg, X86Mem) + //! \overload + INST_2x(vpmovzxbw, kX86InstIdVpmovzxbw, X86YmmReg, X86XmmReg) + + //! Packed DWORD to QWORD with zero extend (AVX2). + INST_2x(vpmovzxdq, kX86InstIdVpmovzxdq, X86YmmReg, X86Mem) + //! \overload + INST_2x(vpmovzxdq, kX86InstIdVpmovzxdq, X86YmmReg, X86XmmReg) + + //! Packed WORD to DWORD with zero extend (AVX2). + INST_2x(vpmovzxwd, kX86InstIdVpmovzxwd, X86YmmReg, X86Mem) + //! \overload + INST_2x(vpmovzxwd, kX86InstIdVpmovzxwd, X86YmmReg, X86XmmReg) + + //! Packed WORD to QWORD with zero extend (AVX2). + INST_2x(vpmovzxwq, kX86InstIdVpmovzxwq, X86YmmReg, X86Mem) + //! \overload + INST_2x(vpmovzxwq, kX86InstIdVpmovzxwq, X86YmmReg, X86XmmReg) + + //! Packed multiply and add signed and unsigned bytes (AVX2). + INST_3x(vpmaddubsw, kX86InstIdVpmaddubsw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpmaddubsw, kX86InstIdVpmaddubsw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD multiply and add to packed DWORD (AVX2). + INST_3x(vpmaddwd, kX86InstIdVpmaddwd, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpmaddwd, kX86InstIdVpmaddwd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vpmaskmovd, kX86InstIdVpmaskmovd, X86Mem, X86XmmReg, X86XmmReg) + INST_3x(vpmaskmovd, kX86InstIdVpmaskmovd, X86Mem, X86YmmReg, X86YmmReg) + INST_3x(vpmaskmovd, kX86InstIdVpmaskmovd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vpmaskmovd, kX86InstIdVpmaskmovd, X86YmmReg, X86YmmReg, X86Mem) + + INST_3x(vpmaskmovq, kX86InstIdVpmaskmovq, X86Mem, X86XmmReg, X86XmmReg) + INST_3x(vpmaskmovq, kX86InstIdVpmaskmovq, X86Mem, X86YmmReg, X86YmmReg) + INST_3x(vpmaskmovq, kX86InstIdVpmaskmovq, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vpmaskmovq, kX86InstIdVpmaskmovq, X86YmmReg, X86YmmReg, X86Mem) + + //! Packed BYTE maximum (AVX2). + INST_3x(vpmaxsb, kX86InstIdVpmaxsb, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpmaxsb, kX86InstIdVpmaxsb, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed DWORD maximum (AVX2). + INST_3x(vpmaxsd, kX86InstIdVpmaxsd, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpmaxsd, kX86InstIdVpmaxsd, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD maximum (AVX2). + INST_3x(vpmaxsw, kX86InstIdVpmaxsw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpmaxsw, kX86InstIdVpmaxsw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed BYTE unsigned maximum (AVX2). + INST_3x(vpmaxub, kX86InstIdVpmaxub, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpmaxub, kX86InstIdVpmaxub, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed DWORD unsigned maximum (AVX2). + INST_3x(vpmaxud, kX86InstIdVpmaxud, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpmaxud, kX86InstIdVpmaxud, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD unsigned maximum (AVX2). + INST_3x(vpmaxuw, kX86InstIdVpmaxuw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpmaxuw, kX86InstIdVpmaxuw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed BYTE minimum (AVX2). + INST_3x(vpminsb, kX86InstIdVpminsb, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpminsb, kX86InstIdVpminsb, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed DWORD minimum (AVX2). + INST_3x(vpminsd, kX86InstIdVpminsd, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpminsd, kX86InstIdVpminsd, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD minimum (AVX2). + INST_3x(vpminsw, kX86InstIdVpminsw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpminsw, kX86InstIdVpminsw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed BYTE unsigned minimum (AVX2). + INST_3x(vpminub, kX86InstIdVpminub, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpminub, kX86InstIdVpminub, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed DWORD unsigned minimum (AVX2). + INST_3x(vpminud, kX86InstIdVpminud, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpminud, kX86InstIdVpminud, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD unsigned minimum (AVX2). + INST_3x(vpminuw, kX86InstIdVpminuw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpminuw, kX86InstIdVpminuw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed DWORD to QWORD multiply (AVX2). + INST_3x(vpmuldq, kX86InstIdVpmuldq, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpmuldq, kX86InstIdVpmuldq, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD multiply high, round and scale (AVX2). + INST_3x(vpmulhrsw, kX86InstIdVpmulhrsw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpmulhrsw, kX86InstIdVpmulhrsw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD unsigned multiply high (AVX2). + INST_3x(vpmulhuw, kX86InstIdVpmulhuw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpmulhuw, kX86InstIdVpmulhuw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD multiply high (AVX2). + INST_3x(vpmulhw, kX86InstIdVpmulhw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpmulhw, kX86InstIdVpmulhw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed DWORD multiply low (AVX2). + INST_3x(vpmulld, kX86InstIdVpmulld, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpmulld, kX86InstIdVpmulld, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORDs multiply low (AVX2). + INST_3x(vpmullw, kX86InstIdVpmullw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpmullw, kX86InstIdVpmullw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed DWORD multiply to QWORD (AVX2). + INST_3x(vpmuludq, kX86InstIdVpmuludq, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpmuludq, kX86InstIdVpmuludq, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed bitwise or (AVX2). + INST_3x(vpor, kX86InstIdVpor, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpor, kX86InstIdVpor, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD sum of absolute differences (AVX2). + INST_3x(vpsadbw, kX86InstIdVpsadbw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsadbw, kX86InstIdVpsadbw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed BYTE shuffle (AVX2). + INST_3x(vpshufb, kX86InstIdVpshufb, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpshufb, kX86InstIdVpshufb, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed DWORD shuffle (AVX2). + INST_3i(vpshufd, kX86InstIdVpshufd, X86YmmReg, X86Mem, Imm) + //! \overload + INST_3i(vpshufd, kX86InstIdVpshufd, X86YmmReg, X86YmmReg, Imm) + + //! Packed WORD shuffle high (AVX2). + INST_3i(vpshufhw, kX86InstIdVpshufhw, X86YmmReg, X86Mem, Imm) + //! \overload + INST_3i(vpshufhw, kX86InstIdVpshufhw, X86YmmReg, X86YmmReg, Imm) + + //! Packed WORD shuffle low (AVX2). + INST_3i(vpshuflw, kX86InstIdVpshuflw, X86YmmReg, X86Mem, Imm) + //! \overload + INST_3i(vpshuflw, kX86InstIdVpshuflw, X86YmmReg, X86YmmReg, Imm) + + //! Packed BYTE sign (AVX2). + INST_3x(vpsignb, kX86InstIdVpsignb, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsignb, kX86InstIdVpsignb, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed DWORD sign (AVX2). + INST_3x(vpsignd, kX86InstIdVpsignd, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsignd, kX86InstIdVpsignd, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD sign (AVX2). + INST_3x(vpsignw, kX86InstIdVpsignw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsignw, kX86InstIdVpsignw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed DWORD shift left logical (AVX2). + INST_3x(vpslld, kX86InstIdVpslld, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpslld, kX86InstIdVpslld, X86YmmReg, X86YmmReg, X86XmmReg) + //! \overload + INST_3i(vpslld, kX86InstIdVpslld, X86YmmReg, X86YmmReg, Imm) + + //! Packed OWORD shift left logical (AVX2). + INST_3i(vpslldq, kX86InstIdVpslldq, X86YmmReg, X86YmmReg, Imm) + + //! Packed QWORD shift left logical (AVX2). + INST_3x(vpsllq, kX86InstIdVpsllq, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsllq, kX86InstIdVpsllq, X86YmmReg, X86YmmReg, X86XmmReg) + //! \overload + INST_3i(vpsllq, kX86InstIdVpsllq, X86YmmReg, X86YmmReg, Imm) + + INST_3x(vpsllvd, kX86InstIdVpsllvd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vpsllvd, kX86InstIdVpsllvd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vpsllvd, kX86InstIdVpsllvd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vpsllvd, kX86InstIdVpsllvd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vpsllvq, kX86InstIdVpsllvq, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vpsllvq, kX86InstIdVpsllvq, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vpsllvq, kX86InstIdVpsllvq, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vpsllvq, kX86InstIdVpsllvq, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD shift left logical (AVX2). + INST_3x(vpsllw, kX86InstIdVpsllw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsllw, kX86InstIdVpsllw, X86YmmReg, X86YmmReg, X86XmmReg) + //! Packed WORD shift left logical (AVX2). + INST_3i(vpsllw, kX86InstIdVpsllw, X86YmmReg, X86YmmReg, Imm) + + //! Packed DWORD shift right arithmetic (AVX2). + INST_3x(vpsrad, kX86InstIdVpsrad, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsrad, kX86InstIdVpsrad, X86YmmReg, X86YmmReg, X86XmmReg) + //! \overload + INST_3i(vpsrad, kX86InstIdVpsrad, X86YmmReg, X86YmmReg, Imm) + + INST_3x(vpsravd, kX86InstIdVpsravd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vpsravd, kX86InstIdVpsravd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vpsravd, kX86InstIdVpsravd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vpsravd, kX86InstIdVpsravd, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD shift right arithmetic (AVX2). + INST_3x(vpsraw, kX86InstIdVpsraw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsraw, kX86InstIdVpsraw, X86YmmReg, X86YmmReg, X86XmmReg) + //! \overload + INST_3i(vpsraw, kX86InstIdVpsraw, X86YmmReg, X86YmmReg, Imm) + + //! Packed DWORD shift right logical (AVX2). + INST_3x(vpsrld, kX86InstIdVpsrld, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsrld, kX86InstIdVpsrld, X86YmmReg, X86YmmReg, X86XmmReg) + //! \overload + INST_3i(vpsrld, kX86InstIdVpsrld, X86YmmReg, X86YmmReg, Imm) + + //! Scalar OWORD shift right logical (AVX2). + INST_3i(vpsrldq, kX86InstIdVpsrldq, X86YmmReg, X86YmmReg, Imm) + + //! Packed QWORD shift right logical (AVX2). + INST_3x(vpsrlq, kX86InstIdVpsrlq, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsrlq, kX86InstIdVpsrlq, X86YmmReg, X86YmmReg, X86XmmReg) + //! \overload + INST_3i(vpsrlq, kX86InstIdVpsrlq, X86YmmReg, X86YmmReg, Imm) + + INST_3x(vpsrlvd, kX86InstIdVpsrlvd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vpsrlvd, kX86InstIdVpsrlvd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vpsrlvd, kX86InstIdVpsrlvd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vpsrlvd, kX86InstIdVpsrlvd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vpsrlvq, kX86InstIdVpsrlvq, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vpsrlvq, kX86InstIdVpsrlvq, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vpsrlvq, kX86InstIdVpsrlvq, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vpsrlvq, kX86InstIdVpsrlvq, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD shift right logical (AVX2). + INST_3x(vpsrlw, kX86InstIdVpsrlw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsrlw, kX86InstIdVpsrlw, X86YmmReg, X86YmmReg, X86XmmReg) + //! \overload + INST_3i(vpsrlw, kX86InstIdVpsrlw, X86YmmReg, X86YmmReg, Imm) + + //! Packed BYTE subtract (AVX2). + INST_3x(vpsubb, kX86InstIdVpsubb, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vpsubb, kX86InstIdVpsubb, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed DWORD subtract (AVX2). + INST_3x(vpsubd, kX86InstIdVpsubd, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsubd, kX86InstIdVpsubd, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed QWORD subtract (AVX2). + INST_3x(vpsubq, kX86InstIdVpsubq, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsubq, kX86InstIdVpsubq, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed BYTE subtract with saturation (AVX2). + INST_3x(vpsubsb, kX86InstIdVpsubsb, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsubsb, kX86InstIdVpsubsb, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD subtract with saturation (AVX2). + INST_3x(vpsubsw, kX86InstIdVpsubsw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsubsw, kX86InstIdVpsubsw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed BYTE subtract with unsigned saturation (AVX2). + INST_3x(vpsubusb, kX86InstIdVpsubusb, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsubusb, kX86InstIdVpsubusb, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD subtract with unsigned saturation (AVX2). + INST_3x(vpsubusw, kX86InstIdVpsubusw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsubusw, kX86InstIdVpsubusw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed WORD subtract (AVX2). + INST_3x(vpsubw, kX86InstIdVpsubw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpsubw, kX86InstIdVpsubw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Unpack high packed BYTEs to WORDs (AVX2). + INST_3x(vpunpckhbw, kX86InstIdVpunpckhbw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpunpckhbw, kX86InstIdVpunpckhbw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Unpack high packed DWORDs to QWORDs (AVX2). + INST_3x(vpunpckhdq, kX86InstIdVpunpckhdq, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpunpckhdq, kX86InstIdVpunpckhdq, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Unpack high packed QWORDs to OWORD (AVX2). + INST_3x(vpunpckhqdq, kX86InstIdVpunpckhqdq, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpunpckhqdq, kX86InstIdVpunpckhqdq, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Unpack high packed WORDs to DWORDs (AVX2). + INST_3x(vpunpckhwd, kX86InstIdVpunpckhwd, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpunpckhwd, kX86InstIdVpunpckhwd, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Unpack low packed BYTEs to WORDs (AVX2). + INST_3x(vpunpcklbw, kX86InstIdVpunpcklbw, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpunpcklbw, kX86InstIdVpunpcklbw, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Unpack low packed DWORDs to QWORDs (AVX2). + INST_3x(vpunpckldq, kX86InstIdVpunpckldq, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpunpckldq, kX86InstIdVpunpckldq, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Unpack low packed QWORDs to OWORD (AVX2). + INST_3x(vpunpcklqdq, kX86InstIdVpunpcklqdq, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpunpcklqdq, kX86InstIdVpunpcklqdq, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Unpack low packed WORDs to DWORDs (AVX2). + INST_3x(vpunpcklwd, kX86InstIdVpunpcklwd, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpunpcklwd, kX86InstIdVpunpcklwd, X86YmmReg, X86YmmReg, X86YmmReg) + + //! Packed bitwise xor (AVX2). + INST_3x(vpxor, kX86InstIdVpxor, X86YmmReg, X86YmmReg, X86Mem) + //! \overload + INST_3x(vpxor, kX86InstIdVpxor, X86YmmReg, X86YmmReg, X86YmmReg) + + // -------------------------------------------------------------------------- + // [FMA3] + // -------------------------------------------------------------------------- + + INST_3x(vfmadd132pd, kX86InstIdVfmadd132pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmadd132pd, kX86InstIdVfmadd132pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmadd132pd, kX86InstIdVfmadd132pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmadd132pd, kX86InstIdVfmadd132pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmadd132ps, kX86InstIdVfmadd132ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmadd132ps, kX86InstIdVfmadd132ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmadd132ps, kX86InstIdVfmadd132ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmadd132ps, kX86InstIdVfmadd132ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmadd132sd, kX86InstIdVfmadd132sd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmadd132sd, kX86InstIdVfmadd132sd, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfmadd132ss, kX86InstIdVfmadd132ss, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmadd132ss, kX86InstIdVfmadd132ss, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfmadd213pd, kX86InstIdVfmadd213pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmadd213pd, kX86InstIdVfmadd213pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmadd213pd, kX86InstIdVfmadd213pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmadd213pd, kX86InstIdVfmadd213pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmadd213ps, kX86InstIdVfmadd213ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmadd213ps, kX86InstIdVfmadd213ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmadd213ps, kX86InstIdVfmadd213ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmadd213ps, kX86InstIdVfmadd213ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmadd213sd, kX86InstIdVfmadd213sd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmadd213sd, kX86InstIdVfmadd213sd, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfmadd213ss, kX86InstIdVfmadd213ss, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmadd213ss, kX86InstIdVfmadd213ss, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfmadd231pd, kX86InstIdVfmadd231pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmadd231pd, kX86InstIdVfmadd231pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmadd231pd, kX86InstIdVfmadd231pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmadd231pd, kX86InstIdVfmadd231pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmadd231ps, kX86InstIdVfmadd231ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmadd231ps, kX86InstIdVfmadd231ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmadd231ps, kX86InstIdVfmadd231ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmadd231ps, kX86InstIdVfmadd231ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmadd231sd, kX86InstIdVfmadd231sd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmadd231sd, kX86InstIdVfmadd231sd, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfmadd231ss, kX86InstIdVfmadd231ss, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmadd231ss, kX86InstIdVfmadd231ss, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfmaddsub132pd, kX86InstIdVfmaddsub132pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmaddsub132pd, kX86InstIdVfmaddsub132pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmaddsub132pd, kX86InstIdVfmaddsub132pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmaddsub132pd, kX86InstIdVfmaddsub132pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmaddsub132ps, kX86InstIdVfmaddsub132ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmaddsub132ps, kX86InstIdVfmaddsub132ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmaddsub132ps, kX86InstIdVfmaddsub132ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmaddsub132ps, kX86InstIdVfmaddsub132ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmaddsub213pd, kX86InstIdVfmaddsub213pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmaddsub213pd, kX86InstIdVfmaddsub213pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmaddsub213pd, kX86InstIdVfmaddsub213pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmaddsub213pd, kX86InstIdVfmaddsub213pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmaddsub213ps, kX86InstIdVfmaddsub213ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmaddsub213ps, kX86InstIdVfmaddsub213ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmaddsub213ps, kX86InstIdVfmaddsub213ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmaddsub213ps, kX86InstIdVfmaddsub213ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmaddsub231pd, kX86InstIdVfmaddsub231pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmaddsub231pd, kX86InstIdVfmaddsub231pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmaddsub231pd, kX86InstIdVfmaddsub231pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmaddsub231pd, kX86InstIdVfmaddsub231pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmaddsub231ps, kX86InstIdVfmaddsub231ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmaddsub231ps, kX86InstIdVfmaddsub231ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmaddsub231ps, kX86InstIdVfmaddsub231ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmaddsub231ps, kX86InstIdVfmaddsub231ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmsub132pd, kX86InstIdVfmsub132pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsub132pd, kX86InstIdVfmsub132pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmsub132pd, kX86InstIdVfmsub132pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmsub132pd, kX86InstIdVfmsub132pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmsub132ps, kX86InstIdVfmsub132ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsub132ps, kX86InstIdVfmsub132ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmsub132ps, kX86InstIdVfmsub132ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmsub132ps, kX86InstIdVfmsub132ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmsub132sd, kX86InstIdVfmsub132sd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsub132sd, kX86InstIdVfmsub132sd, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfmsub132ss, kX86InstIdVfmsub132ss, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsub132ss, kX86InstIdVfmsub132ss, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfmsub213pd, kX86InstIdVfmsub213pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsub213pd, kX86InstIdVfmsub213pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmsub213pd, kX86InstIdVfmsub213pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmsub213pd, kX86InstIdVfmsub213pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmsub213ps, kX86InstIdVfmsub213ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsub213ps, kX86InstIdVfmsub213ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmsub213ps, kX86InstIdVfmsub213ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmsub213ps, kX86InstIdVfmsub213ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmsub213sd, kX86InstIdVfmsub213sd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsub213sd, kX86InstIdVfmsub213sd, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfmsub213ss, kX86InstIdVfmsub213ss, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsub213ss, kX86InstIdVfmsub213ss, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfmsub231pd, kX86InstIdVfmsub231pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsub231pd, kX86InstIdVfmsub231pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmsub231pd, kX86InstIdVfmsub231pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmsub231pd, kX86InstIdVfmsub231pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmsub231ps, kX86InstIdVfmsub231ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsub231ps, kX86InstIdVfmsub231ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmsub231ps, kX86InstIdVfmsub231ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmsub231ps, kX86InstIdVfmsub231ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmsub231sd, kX86InstIdVfmsub231sd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsub231sd, kX86InstIdVfmsub231sd, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfmsub231ss, kX86InstIdVfmsub231ss, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsub231ss, kX86InstIdVfmsub231ss, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfmsubadd132pd, kX86InstIdVfmsubadd132pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsubadd132pd, kX86InstIdVfmsubadd132pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmsubadd132pd, kX86InstIdVfmsubadd132pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmsubadd132pd, kX86InstIdVfmsubadd132pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmsubadd132ps, kX86InstIdVfmsubadd132ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsubadd132ps, kX86InstIdVfmsubadd132ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmsubadd132ps, kX86InstIdVfmsubadd132ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmsubadd132ps, kX86InstIdVfmsubadd132ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmsubadd213pd, kX86InstIdVfmsubadd213pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsubadd213pd, kX86InstIdVfmsubadd213pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmsubadd213pd, kX86InstIdVfmsubadd213pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmsubadd213pd, kX86InstIdVfmsubadd213pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmsubadd213ps, kX86InstIdVfmsubadd213ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsubadd213ps, kX86InstIdVfmsubadd213ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmsubadd213ps, kX86InstIdVfmsubadd213ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmsubadd213ps, kX86InstIdVfmsubadd213ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmsubadd231pd, kX86InstIdVfmsubadd231pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsubadd231pd, kX86InstIdVfmsubadd231pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmsubadd231pd, kX86InstIdVfmsubadd231pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmsubadd231pd, kX86InstIdVfmsubadd231pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfmsubadd231ps, kX86InstIdVfmsubadd231ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfmsubadd231ps, kX86InstIdVfmsubadd231ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfmsubadd231ps, kX86InstIdVfmsubadd231ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfmsubadd231ps, kX86InstIdVfmsubadd231ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfnmadd132pd, kX86InstIdVfnmadd132pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmadd132pd, kX86InstIdVfnmadd132pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfnmadd132pd, kX86InstIdVfnmadd132pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfnmadd132pd, kX86InstIdVfnmadd132pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfnmadd132ps, kX86InstIdVfnmadd132ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmadd132ps, kX86InstIdVfnmadd132ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfnmadd132ps, kX86InstIdVfnmadd132ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfnmadd132ps, kX86InstIdVfnmadd132ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfnmadd132sd, kX86InstIdVfnmadd132sd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmadd132sd, kX86InstIdVfnmadd132sd, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfnmadd132ss, kX86InstIdVfnmadd132ss, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmadd132ss, kX86InstIdVfnmadd132ss, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfnmadd213pd, kX86InstIdVfnmadd213pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmadd213pd, kX86InstIdVfnmadd213pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfnmadd213pd, kX86InstIdVfnmadd213pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfnmadd213pd, kX86InstIdVfnmadd213pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfnmadd213ps, kX86InstIdVfnmadd213ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmadd213ps, kX86InstIdVfnmadd213ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfnmadd213ps, kX86InstIdVfnmadd213ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfnmadd213ps, kX86InstIdVfnmadd213ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfnmadd213sd, kX86InstIdVfnmadd213sd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmadd213sd, kX86InstIdVfnmadd213sd, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfnmadd213ss, kX86InstIdVfnmadd213ss, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmadd213ss, kX86InstIdVfnmadd213ss, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfnmadd231pd, kX86InstIdVfnmadd231pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmadd231pd, kX86InstIdVfnmadd231pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfnmadd231pd, kX86InstIdVfnmadd231pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfnmadd231pd, kX86InstIdVfnmadd231pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfnmadd231ps, kX86InstIdVfnmadd231ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmadd231ps, kX86InstIdVfnmadd231ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfnmadd231ps, kX86InstIdVfnmadd231ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfnmadd231ps, kX86InstIdVfnmadd231ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfnmadd231sd, kX86InstIdVfnmadd231sd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmadd231sd, kX86InstIdVfnmadd231sd, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfnmadd231ss, kX86InstIdVfnmadd231ss, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmadd231ss, kX86InstIdVfnmadd231ss, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfnmsub132pd, kX86InstIdVfnmsub132pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmsub132pd, kX86InstIdVfnmsub132pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfnmsub132pd, kX86InstIdVfnmsub132pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfnmsub132pd, kX86InstIdVfnmsub132pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfnmsub132ps, kX86InstIdVfnmsub132ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmsub132ps, kX86InstIdVfnmsub132ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfnmsub132ps, kX86InstIdVfnmsub132ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfnmsub132ps, kX86InstIdVfnmsub132ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfnmsub132sd, kX86InstIdVfnmsub132sd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmsub132sd, kX86InstIdVfnmsub132sd, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfnmsub132ss, kX86InstIdVfnmsub132ss, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmsub132ss, kX86InstIdVfnmsub132ss, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfnmsub213pd, kX86InstIdVfnmsub213pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmsub213pd, kX86InstIdVfnmsub213pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfnmsub213pd, kX86InstIdVfnmsub213pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfnmsub213pd, kX86InstIdVfnmsub213pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfnmsub213ps, kX86InstIdVfnmsub213ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmsub213ps, kX86InstIdVfnmsub213ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfnmsub213ps, kX86InstIdVfnmsub213ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfnmsub213ps, kX86InstIdVfnmsub213ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfnmsub213sd, kX86InstIdVfnmsub213sd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmsub213sd, kX86InstIdVfnmsub213sd, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfnmsub213ss, kX86InstIdVfnmsub213ss, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmsub213ss, kX86InstIdVfnmsub213ss, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfnmsub231pd, kX86InstIdVfnmsub231pd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmsub231pd, kX86InstIdVfnmsub231pd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfnmsub231pd, kX86InstIdVfnmsub231pd, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfnmsub231pd, kX86InstIdVfnmsub231pd, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfnmsub231ps, kX86InstIdVfnmsub231ps, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmsub231ps, kX86InstIdVfnmsub231ps, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vfnmsub231ps, kX86InstIdVfnmsub231ps, X86YmmReg, X86YmmReg, X86Mem) + INST_3x(vfnmsub231ps, kX86InstIdVfnmsub231ps, X86YmmReg, X86YmmReg, X86YmmReg) + + INST_3x(vfnmsub231sd, kX86InstIdVfnmsub231sd, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmsub231sd, kX86InstIdVfnmsub231sd, X86XmmReg, X86XmmReg, X86XmmReg) + + INST_3x(vfnmsub231ss, kX86InstIdVfnmsub231ss, X86XmmReg, X86XmmReg, X86Mem) + INST_3x(vfnmsub231ss, kX86InstIdVfnmsub231ss, X86XmmReg, X86XmmReg, X86XmmReg) + + // -------------------------------------------------------------------------- + // [FMA4] + // -------------------------------------------------------------------------- + + INST_4x(vfmaddpd, kX86InstIdVfmaddpd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfmaddpd, kX86InstIdVfmaddpd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfmaddpd, kX86InstIdVfmaddpd, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + INST_4x(vfmaddpd, kX86InstIdVfmaddpd, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + INST_4x(vfmaddpd, kX86InstIdVfmaddpd, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + INST_4x(vfmaddpd, kX86InstIdVfmaddpd, X86YmmReg, X86YmmReg, X86YmmReg, X86Mem) + + INST_4x(vfmaddps, kX86InstIdVfmaddps, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfmaddps, kX86InstIdVfmaddps, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfmaddps, kX86InstIdVfmaddps, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + INST_4x(vfmaddps, kX86InstIdVfmaddps, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + INST_4x(vfmaddps, kX86InstIdVfmaddps, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + INST_4x(vfmaddps, kX86InstIdVfmaddps, X86YmmReg, X86YmmReg, X86YmmReg, X86Mem) + + INST_4x(vfmaddsd, kX86InstIdVfmaddsd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfmaddsd, kX86InstIdVfmaddsd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfmaddsd, kX86InstIdVfmaddsd, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + + INST_4x(vfmaddss, kX86InstIdVfmaddss, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfmaddss, kX86InstIdVfmaddss, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfmaddss, kX86InstIdVfmaddss, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + + INST_4x(vfmaddsubpd, kX86InstIdVfmaddsubpd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfmaddsubpd, kX86InstIdVfmaddsubpd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfmaddsubpd, kX86InstIdVfmaddsubpd, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + INST_4x(vfmaddsubpd, kX86InstIdVfmaddsubpd, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + INST_4x(vfmaddsubpd, kX86InstIdVfmaddsubpd, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + INST_4x(vfmaddsubpd, kX86InstIdVfmaddsubpd, X86YmmReg, X86YmmReg, X86YmmReg, X86Mem) + + INST_4x(vfmaddsubps, kX86InstIdVfmaddsubps, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfmaddsubps, kX86InstIdVfmaddsubps, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfmaddsubps, kX86InstIdVfmaddsubps, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + INST_4x(vfmaddsubps, kX86InstIdVfmaddsubps, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + INST_4x(vfmaddsubps, kX86InstIdVfmaddsubps, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + INST_4x(vfmaddsubps, kX86InstIdVfmaddsubps, X86YmmReg, X86YmmReg, X86YmmReg, X86Mem) + + INST_4x(vfmsubaddpd, kX86InstIdVfmsubaddpd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfmsubaddpd, kX86InstIdVfmsubaddpd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfmsubaddpd, kX86InstIdVfmsubaddpd, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + INST_4x(vfmsubaddpd, kX86InstIdVfmsubaddpd, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + INST_4x(vfmsubaddpd, kX86InstIdVfmsubaddpd, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + INST_4x(vfmsubaddpd, kX86InstIdVfmsubaddpd, X86YmmReg, X86YmmReg, X86YmmReg, X86Mem) + + INST_4x(vfmsubaddps, kX86InstIdVfmsubaddps, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfmsubaddps, kX86InstIdVfmsubaddps, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfmsubaddps, kX86InstIdVfmsubaddps, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + INST_4x(vfmsubaddps, kX86InstIdVfmsubaddps, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + INST_4x(vfmsubaddps, kX86InstIdVfmsubaddps, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + INST_4x(vfmsubaddps, kX86InstIdVfmsubaddps, X86YmmReg, X86YmmReg, X86YmmReg, X86Mem) + + INST_4x(vfmsubpd, kX86InstIdVfmsubpd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfmsubpd, kX86InstIdVfmsubpd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfmsubpd, kX86InstIdVfmsubpd, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + INST_4x(vfmsubpd, kX86InstIdVfmsubpd, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + INST_4x(vfmsubpd, kX86InstIdVfmsubpd, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + INST_4x(vfmsubpd, kX86InstIdVfmsubpd, X86YmmReg, X86YmmReg, X86YmmReg, X86Mem) + + INST_4x(vfmsubps, kX86InstIdVfmsubps, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfmsubps, kX86InstIdVfmsubps, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfmsubps, kX86InstIdVfmsubps, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + INST_4x(vfmsubps, kX86InstIdVfmsubps, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + INST_4x(vfmsubps, kX86InstIdVfmsubps, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + INST_4x(vfmsubps, kX86InstIdVfmsubps, X86YmmReg, X86YmmReg, X86YmmReg, X86Mem) + + INST_4x(vfmsubsd, kX86InstIdVfmsubsd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfmsubsd, kX86InstIdVfmsubsd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfmsubsd, kX86InstIdVfmsubsd, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + + INST_4x(vfmsubss, kX86InstIdVfmsubss, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfmsubss, kX86InstIdVfmsubss, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfmsubss, kX86InstIdVfmsubss, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + + INST_4x(vfnmaddpd, kX86InstIdVfnmaddpd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfnmaddpd, kX86InstIdVfnmaddpd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfnmaddpd, kX86InstIdVfnmaddpd, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + INST_4x(vfnmaddpd, kX86InstIdVfnmaddpd, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + INST_4x(vfnmaddpd, kX86InstIdVfnmaddpd, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + INST_4x(vfnmaddpd, kX86InstIdVfnmaddpd, X86YmmReg, X86YmmReg, X86YmmReg, X86Mem) + + INST_4x(vfnmaddps, kX86InstIdVfnmaddps, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfnmaddps, kX86InstIdVfnmaddps, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfnmaddps, kX86InstIdVfnmaddps, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + INST_4x(vfnmaddps, kX86InstIdVfnmaddps, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + INST_4x(vfnmaddps, kX86InstIdVfnmaddps, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + INST_4x(vfnmaddps, kX86InstIdVfnmaddps, X86YmmReg, X86YmmReg, X86YmmReg, X86Mem) + + INST_4x(vfnmaddsd, kX86InstIdVfnmaddsd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfnmaddsd, kX86InstIdVfnmaddsd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfnmaddsd, kX86InstIdVfnmaddsd, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + + INST_4x(vfnmaddss, kX86InstIdVfnmaddss, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfnmaddss, kX86InstIdVfnmaddss, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfnmaddss, kX86InstIdVfnmaddss, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + + INST_4x(vfnmsubpd, kX86InstIdVfnmsubpd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfnmsubpd, kX86InstIdVfnmsubpd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfnmsubpd, kX86InstIdVfnmsubpd, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + INST_4x(vfnmsubpd, kX86InstIdVfnmsubpd, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + INST_4x(vfnmsubpd, kX86InstIdVfnmsubpd, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + INST_4x(vfnmsubpd, kX86InstIdVfnmsubpd, X86YmmReg, X86YmmReg, X86YmmReg, X86Mem) + + INST_4x(vfnmsubps, kX86InstIdVfnmsubps, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfnmsubps, kX86InstIdVfnmsubps, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfnmsubps, kX86InstIdVfnmsubps, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + INST_4x(vfnmsubps, kX86InstIdVfnmsubps, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + INST_4x(vfnmsubps, kX86InstIdVfnmsubps, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + INST_4x(vfnmsubps, kX86InstIdVfnmsubps, X86YmmReg, X86YmmReg, X86YmmReg, X86Mem) + + INST_4x(vfnmsubsd, kX86InstIdVfnmsubsd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfnmsubsd, kX86InstIdVfnmsubsd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfnmsubsd, kX86InstIdVfnmsubsd, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + + INST_4x(vfnmsubss, kX86InstIdVfnmsubss, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vfnmsubss, kX86InstIdVfnmsubss, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vfnmsubss, kX86InstIdVfnmsubss, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + + // -------------------------------------------------------------------------- + // [XOP] + // -------------------------------------------------------------------------- + + INST_2x(vfrczpd, kX86InstIdVfrczpd, X86XmmReg, X86XmmReg) + INST_2x(vfrczpd, kX86InstIdVfrczpd, X86XmmReg, X86Mem) + INST_2x(vfrczpd, kX86InstIdVfrczpd, X86YmmReg, X86YmmReg) + INST_2x(vfrczpd, kX86InstIdVfrczpd, X86YmmReg, X86Mem) + + INST_2x(vfrczps, kX86InstIdVfrczps, X86XmmReg, X86XmmReg) + INST_2x(vfrczps, kX86InstIdVfrczps, X86XmmReg, X86Mem) + INST_2x(vfrczps, kX86InstIdVfrczps, X86YmmReg, X86YmmReg) + INST_2x(vfrczps, kX86InstIdVfrczps, X86YmmReg, X86Mem) + + INST_2x(vfrczsd, kX86InstIdVfrczsd, X86XmmReg, X86XmmReg) + INST_2x(vfrczsd, kX86InstIdVfrczsd, X86XmmReg, X86Mem) + + INST_2x(vfrczss, kX86InstIdVfrczss, X86XmmReg, X86XmmReg) + INST_2x(vfrczss, kX86InstIdVfrczss, X86XmmReg, X86Mem) + + INST_4x(vpcmov, kX86InstIdVpcmov, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vpcmov, kX86InstIdVpcmov, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vpcmov, kX86InstIdVpcmov, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + INST_4x(vpcmov, kX86InstIdVpcmov, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + INST_4x(vpcmov, kX86InstIdVpcmov, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + INST_4x(vpcmov, kX86InstIdVpcmov, X86YmmReg, X86YmmReg, X86YmmReg, X86Mem) + + INST_4i(vpcomb, kX86InstIdVpcomb, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + INST_4i(vpcomb, kX86InstIdVpcomb, X86XmmReg, X86XmmReg, X86Mem, Imm) + INST_4i(vpcomd, kX86InstIdVpcomd, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + INST_4i(vpcomd, kX86InstIdVpcomd, X86XmmReg, X86XmmReg, X86Mem, Imm) + INST_4i(vpcomq, kX86InstIdVpcomq, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + INST_4i(vpcomq, kX86InstIdVpcomq, X86XmmReg, X86XmmReg, X86Mem, Imm) + INST_4i(vpcomw, kX86InstIdVpcomw, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + INST_4i(vpcomw, kX86InstIdVpcomw, X86XmmReg, X86XmmReg, X86Mem, Imm) + + INST_4i(vpcomub, kX86InstIdVpcomub, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + INST_4i(vpcomub, kX86InstIdVpcomub, X86XmmReg, X86XmmReg, X86Mem, Imm) + INST_4i(vpcomud, kX86InstIdVpcomud, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + INST_4i(vpcomud, kX86InstIdVpcomud, X86XmmReg, X86XmmReg, X86Mem, Imm) + INST_4i(vpcomuq, kX86InstIdVpcomuq, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + INST_4i(vpcomuq, kX86InstIdVpcomuq, X86XmmReg, X86XmmReg, X86Mem, Imm) + INST_4i(vpcomuw, kX86InstIdVpcomuw, X86XmmReg, X86XmmReg, X86XmmReg, Imm) + INST_4i(vpcomuw, kX86InstIdVpcomuw, X86XmmReg, X86XmmReg, X86Mem, Imm) + + INST_4x(vpermil2pd, kX86InstIdVpermil2pd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vpermil2pd, kX86InstIdVpermil2pd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vpermil2pd, kX86InstIdVpermil2pd, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + INST_4x(vpermil2pd, kX86InstIdVpermil2pd, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + INST_4x(vpermil2pd, kX86InstIdVpermil2pd, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + INST_4x(vpermil2pd, kX86InstIdVpermil2pd, X86YmmReg, X86YmmReg, X86YmmReg, X86Mem) + + INST_4x(vpermil2ps, kX86InstIdVpermil2ps, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vpermil2ps, kX86InstIdVpermil2ps, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vpermil2ps, kX86InstIdVpermil2ps, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + INST_4x(vpermil2ps, kX86InstIdVpermil2ps, X86YmmReg, X86YmmReg, X86YmmReg, X86YmmReg) + INST_4x(vpermil2ps, kX86InstIdVpermil2ps, X86YmmReg, X86YmmReg, X86Mem, X86YmmReg) + INST_4x(vpermil2ps, kX86InstIdVpermil2ps, X86YmmReg, X86YmmReg, X86YmmReg, X86Mem) + + INST_2x(vphaddbd, kX86InstIdVphaddbd, X86XmmReg, X86XmmReg) + INST_2x(vphaddbd, kX86InstIdVphaddbd, X86XmmReg, X86Mem) + INST_2x(vphaddbq, kX86InstIdVphaddbq, X86XmmReg, X86XmmReg) + INST_2x(vphaddbq, kX86InstIdVphaddbq, X86XmmReg, X86Mem) + INST_2x(vphaddbw, kX86InstIdVphaddbw, X86XmmReg, X86XmmReg) + INST_2x(vphaddbw, kX86InstIdVphaddbw, X86XmmReg, X86Mem) + INST_2x(vphadddq, kX86InstIdVphadddq, X86XmmReg, X86XmmReg) + INST_2x(vphadddq, kX86InstIdVphadddq, X86XmmReg, X86Mem) + INST_2x(vphaddwd, kX86InstIdVphaddwd, X86XmmReg, X86XmmReg) + INST_2x(vphaddwd, kX86InstIdVphaddwd, X86XmmReg, X86Mem) + INST_2x(vphaddwq, kX86InstIdVphaddwq, X86XmmReg, X86XmmReg) + INST_2x(vphaddwq, kX86InstIdVphaddwq, X86XmmReg, X86Mem) + + INST_2x(vphaddubd, kX86InstIdVphaddubd, X86XmmReg, X86XmmReg) + INST_2x(vphaddubd, kX86InstIdVphaddubd, X86XmmReg, X86Mem) + INST_2x(vphaddubq, kX86InstIdVphaddubq, X86XmmReg, X86XmmReg) + INST_2x(vphaddubq, kX86InstIdVphaddubq, X86XmmReg, X86Mem) + INST_2x(vphaddubw, kX86InstIdVphaddubw, X86XmmReg, X86XmmReg) + INST_2x(vphaddubw, kX86InstIdVphaddubw, X86XmmReg, X86Mem) + INST_2x(vphaddudq, kX86InstIdVphaddudq, X86XmmReg, X86XmmReg) + INST_2x(vphaddudq, kX86InstIdVphaddudq, X86XmmReg, X86Mem) + INST_2x(vphadduwd, kX86InstIdVphadduwd, X86XmmReg, X86XmmReg) + INST_2x(vphadduwd, kX86InstIdVphadduwd, X86XmmReg, X86Mem) + INST_2x(vphadduwq, kX86InstIdVphadduwq, X86XmmReg, X86XmmReg) + INST_2x(vphadduwq, kX86InstIdVphadduwq, X86XmmReg, X86Mem) + + INST_2x(vphsubbw, kX86InstIdVphsubbw, X86XmmReg, X86XmmReg) + INST_2x(vphsubbw, kX86InstIdVphsubbw, X86XmmReg, X86Mem) + INST_2x(vphsubdq, kX86InstIdVphsubdq, X86XmmReg, X86XmmReg) + INST_2x(vphsubdq, kX86InstIdVphsubdq, X86XmmReg, X86Mem) + INST_2x(vphsubwd, kX86InstIdVphsubwd, X86XmmReg, X86XmmReg) + INST_2x(vphsubwd, kX86InstIdVphsubwd, X86XmmReg, X86Mem) + + INST_4x(vpmacsdd, kX86InstIdVpmacsdd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vpmacsdd, kX86InstIdVpmacsdd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vpmacsdqh, kX86InstIdVpmacsdqh, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vpmacsdqh, kX86InstIdVpmacsdqh, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vpmacsdql, kX86InstIdVpmacsdql, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vpmacsdql, kX86InstIdVpmacsdql, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vpmacswd, kX86InstIdVpmacswd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vpmacswd, kX86InstIdVpmacswd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vpmacsww, kX86InstIdVpmacsww, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vpmacsww, kX86InstIdVpmacsww, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + + INST_4x(vpmacssdd, kX86InstIdVpmacssdd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vpmacssdd, kX86InstIdVpmacssdd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vpmacssdqh, kX86InstIdVpmacssdqh, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vpmacssdqh, kX86InstIdVpmacssdqh, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vpmacssdql, kX86InstIdVpmacssdql, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vpmacssdql, kX86InstIdVpmacssdql, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vpmacsswd, kX86InstIdVpmacsswd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vpmacsswd, kX86InstIdVpmacsswd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vpmacssww, kX86InstIdVpmacssww, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vpmacssww, kX86InstIdVpmacssww, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + + INST_4x(vpmadcsswd, kX86InstIdVpmadcsswd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vpmadcsswd, kX86InstIdVpmadcsswd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + + INST_4x(vpmadcswd, kX86InstIdVpmadcswd, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vpmadcswd, kX86InstIdVpmadcswd, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + + INST_4x(vpperm, kX86InstIdVpperm, X86XmmReg, X86XmmReg, X86XmmReg, X86XmmReg) + INST_4x(vpperm, kX86InstIdVpperm, X86XmmReg, X86XmmReg, X86Mem, X86XmmReg) + INST_4x(vpperm, kX86InstIdVpperm, X86XmmReg, X86XmmReg, X86XmmReg, X86Mem) + + INST_3x(vprotb, kX86InstIdVprotb, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vprotb, kX86InstIdVprotb, X86XmmReg, X86Mem, X86XmmReg) + INST_3x(vprotb, kX86InstIdVprotb, X86XmmReg, X86XmmReg, X86Mem) + INST_3i(vprotb, kX86InstIdVprotb, X86XmmReg, X86XmmReg, Imm) + INST_3i(vprotb, kX86InstIdVprotb, X86XmmReg, X86Mem, Imm) + + INST_3x(vprotd, kX86InstIdVprotd, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vprotd, kX86InstIdVprotd, X86XmmReg, X86Mem, X86XmmReg) + INST_3x(vprotd, kX86InstIdVprotd, X86XmmReg, X86XmmReg, X86Mem) + INST_3i(vprotd, kX86InstIdVprotd, X86XmmReg, X86XmmReg, Imm) + INST_3i(vprotd, kX86InstIdVprotd, X86XmmReg, X86Mem, Imm) + + INST_3x(vprotq, kX86InstIdVprotq, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vprotq, kX86InstIdVprotq, X86XmmReg, X86Mem, X86XmmReg) + INST_3x(vprotq, kX86InstIdVprotq, X86XmmReg, X86XmmReg, X86Mem) + INST_3i(vprotq, kX86InstIdVprotq, X86XmmReg, X86XmmReg, Imm) + INST_3i(vprotq, kX86InstIdVprotq, X86XmmReg, X86Mem, Imm) + + INST_3x(vprotw, kX86InstIdVprotw, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vprotw, kX86InstIdVprotw, X86XmmReg, X86Mem, X86XmmReg) + INST_3x(vprotw, kX86InstIdVprotw, X86XmmReg, X86XmmReg, X86Mem) + INST_3i(vprotw, kX86InstIdVprotw, X86XmmReg, X86XmmReg, Imm) + INST_3i(vprotw, kX86InstIdVprotw, X86XmmReg, X86Mem, Imm) + + INST_3x(vpshab, kX86InstIdVpshab, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vpshab, kX86InstIdVpshab, X86XmmReg, X86Mem, X86XmmReg) + INST_3x(vpshab, kX86InstIdVpshab, X86XmmReg, X86XmmReg, X86Mem) + + INST_3x(vpshad, kX86InstIdVpshad, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vpshad, kX86InstIdVpshad, X86XmmReg, X86Mem, X86XmmReg) + INST_3x(vpshad, kX86InstIdVpshad, X86XmmReg, X86XmmReg, X86Mem) + + INST_3x(vpshaq, kX86InstIdVpshaq, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vpshaq, kX86InstIdVpshaq, X86XmmReg, X86Mem, X86XmmReg) + INST_3x(vpshaq, kX86InstIdVpshaq, X86XmmReg, X86XmmReg, X86Mem) + + INST_3x(vpshaw, kX86InstIdVpshaw, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vpshaw, kX86InstIdVpshaw, X86XmmReg, X86Mem, X86XmmReg) + INST_3x(vpshaw, kX86InstIdVpshaw, X86XmmReg, X86XmmReg, X86Mem) + + INST_3x(vpshlb, kX86InstIdVpshlb, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vpshlb, kX86InstIdVpshlb, X86XmmReg, X86Mem, X86XmmReg) + INST_3x(vpshlb, kX86InstIdVpshlb, X86XmmReg, X86XmmReg, X86Mem) + + INST_3x(vpshld, kX86InstIdVpshld, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vpshld, kX86InstIdVpshld, X86XmmReg, X86Mem, X86XmmReg) + INST_3x(vpshld, kX86InstIdVpshld, X86XmmReg, X86XmmReg, X86Mem) + + INST_3x(vpshlq, kX86InstIdVpshlq, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vpshlq, kX86InstIdVpshlq, X86XmmReg, X86Mem, X86XmmReg) + INST_3x(vpshlq, kX86InstIdVpshlq, X86XmmReg, X86XmmReg, X86Mem) + + INST_3x(vpshlw, kX86InstIdVpshlw, X86XmmReg, X86XmmReg, X86XmmReg) + INST_3x(vpshlw, kX86InstIdVpshlw, X86XmmReg, X86Mem, X86XmmReg) + INST_3x(vpshlw, kX86InstIdVpshlw, X86XmmReg, X86XmmReg, X86Mem) + + // -------------------------------------------------------------------------- + // [BMI] + // -------------------------------------------------------------------------- + + //! Bitwise and-not (BMI). + INST_3x(andn, kX86InstIdAndn, X86GpReg, X86GpReg, X86GpReg) + //! \overload + INST_3x(andn, kX86InstIdAndn, X86GpReg, X86GpReg, X86Mem) + + //! Bit field extract (BMI). + INST_3x(bextr, kX86InstIdBextr, X86GpReg, X86GpReg, X86GpReg) + //! \overload + INST_3x(bextr, kX86InstIdBextr, X86GpReg, X86Mem, X86GpReg) + + //! Extract lower set isolated bit (BMI). + INST_2x(blsi, kX86InstIdBlsi, X86GpReg, X86GpReg) + //! \overload + INST_2x(blsi, kX86InstIdBlsi, X86GpReg, X86Mem) + + //! Get mask up to lowest set bit (BMI). + INST_2x(blsmsk, kX86InstIdBlsmsk, X86GpReg, X86GpReg) + //! \overload + INST_2x(blsmsk, kX86InstIdBlsmsk, X86GpReg, X86Mem) + + //! Reset lowest set bit (BMI). + INST_2x(blsr, kX86InstIdBlsr, X86GpReg, X86GpReg) + //! \overload + INST_2x(blsr, kX86InstIdBlsr, X86GpReg, X86Mem) + + //! Count the number of trailing zero bits (BMI). + INST_2x(tzcnt, kX86InstIdTzcnt, X86GpReg, X86GpReg) + //! \overload + INST_2x(tzcnt, kX86InstIdTzcnt, X86GpReg, X86Mem) + + // -------------------------------------------------------------------------- + // [BMI2] + // -------------------------------------------------------------------------- + + //! Zero high bits starting with specified bit position (BMI2). + INST_3x(bzhi, kX86InstIdBzhi, X86GpReg, X86GpReg, X86GpReg) + //! \overload + INST_3x(bzhi, kX86InstIdBzhi, X86GpReg, X86Mem, X86GpReg) + + //! Unsigned multiply without affecting flags (BMI2). + INST_3x(mulx, kX86InstIdMulx, X86GpReg, X86GpReg, X86GpReg) + //! \overload + INST_3x(mulx, kX86InstIdMulx, X86GpReg, X86GpReg, X86Mem) + + //! Parallel bits deposit (BMI2). + INST_3x(pdep, kX86InstIdPdep, X86GpReg, X86GpReg, X86GpReg) + //! \overload + INST_3x(pdep, kX86InstIdPdep, X86GpReg, X86GpReg, X86Mem) + + //! Parallel bits extract (BMI2). + INST_3x(pext, kX86InstIdPext, X86GpReg, X86GpReg, X86GpReg) + //! \overload + INST_3x(pext, kX86InstIdPext, X86GpReg, X86GpReg, X86Mem) + + //! Rotate right without affecting flags (BMI2). + INST_3i(rorx, kX86InstIdRorx, X86GpReg, X86GpReg, Imm) + //! \overload + INST_3i(rorx, kX86InstIdRorx, X86GpReg, X86Mem, Imm) + + //! Shift arithmetic right without affecting flags (BMI2). + INST_3x(sarx, kX86InstIdSarx, X86GpReg, X86GpReg, X86GpReg) + //! \overload + INST_3x(sarx, kX86InstIdSarx, X86GpReg, X86Mem, X86GpReg) + + //! Shift logical left without affecting flags (BMI2). + INST_3x(shlx, kX86InstIdShlx, X86GpReg, X86GpReg, X86GpReg) + //! \overload + INST_3x(shlx, kX86InstIdShlx, X86GpReg, X86Mem, X86GpReg) + + //! Shift logical right without affecting flags (BMI2). + INST_3x(shrx, kX86InstIdShrx, X86GpReg, X86GpReg, X86GpReg) + //! \overload + INST_3x(shrx, kX86InstIdShrx, X86GpReg, X86Mem, X86GpReg) + + // -------------------------------------------------------------------------- + // [RDRAND] + // -------------------------------------------------------------------------- + + //! Store a random number in destination register (RDRAND). + //! + //! Please do not use this instruction in cryptographic software. The result + //! doesn't necessarily have to be random, which may cause a major security + //! hole in the software. + INST_1x(rdrand, kX86InstIdRdrand, X86GpReg) + + // -------------------------------------------------------------------------- + // [F16C] + // -------------------------------------------------------------------------- + + //! Convert packed HP-FP to SP-FP. + INST_2x(vcvtph2ps, kX86InstIdVcvtph2ps, X86XmmReg, X86XmmReg) + //! \overload + INST_2x(vcvtph2ps, kX86InstIdVcvtph2ps, X86XmmReg, X86Mem) + //! \overload + INST_2x(vcvtph2ps, kX86InstIdVcvtph2ps, X86YmmReg, X86XmmReg) + //! \overload + INST_2x(vcvtph2ps, kX86InstIdVcvtph2ps, X86YmmReg, X86Mem) + + //! Convert packed SP-FP to HP-FP. + INST_3i(vcvtps2ph, kX86InstIdVcvtps2ph, X86XmmReg, X86XmmReg, Imm) + //! \overload + INST_3i(vcvtps2ph, kX86InstIdVcvtps2ph, X86Mem, X86XmmReg, Imm) + //! \overload + INST_3i(vcvtps2ph, kX86InstIdVcvtps2ph, X86XmmReg, X86YmmReg, Imm) + //! \overload + INST_3i(vcvtps2ph, kX86InstIdVcvtps2ph, X86Mem, X86YmmReg, Imm) + + // -------------------------------------------------------------------------- + // [FSGSBASE] + // -------------------------------------------------------------------------- + + INST_1x(rdfsbase, kX86InstIdRdfsbase, X86GpReg) + INST_1x(rdgsbase, kX86InstIdRdgsbase, X86GpReg) + INST_1x(wrfsbase, kX86InstIdWrfsbase, X86GpReg) + INST_1x(wrgsbase, kX86InstIdWrgsbase, X86GpReg) + +#undef INST_0x + +#undef INST_1x +#undef INST_1x_ +#undef INST_1i +#undef INST_1cc + +#undef INST_2x +#undef INST_2x_ +#undef INST_2i +#undef INST_2cc + +#undef INST_3x +#undef INST_3x_ +#undef INST_3i +#undef INST_3ii + +#undef INST_4x +#undef INST_4x_ +#undef INST_4i +#undef INST_4ii +}; + +//! \} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // _ASMJIT_X86_X86ASSEMBLER_H diff --git a/third/Blackbone/src/3rd_party/AsmJit/x86/x86compiler.cpp b/third/Blackbone/src/3rd_party/AsmJit/x86/x86compiler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..424188aa817c27589a58e5f735c5d486a90fa45d --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/x86/x86compiler.cpp @@ -0,0 +1,1398 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Guard] +#include "../build.h" +#if !defined(ASMJIT_DISABLE_COMPILER) && (defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64)) + +// [Dependencies - AsmJit] +#include "../base/intutil.h" +#include "../base/string.h" +#include "../x86/x86assembler.h" +#include "../x86/x86compiler.h" +#include "../x86/x86context_p.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [Debug] +// ============================================================================ + +#if !defined(ASMJIT_DEBUG) +#define ASMJIT_ASSERT_UNINITIALIZED(op) \ + do {} while(0) +#else +#define ASMJIT_ASSERT_UNINITIALIZED(op) \ + do { \ + if (op.isVar() || op.isLabel()) { \ + ASMJIT_ASSERT(op.getId() != kInvalidValue); \ + } \ + } while(0) +#endif + +// ============================================================================ +// [asmjit::X86VarInfo] +// ============================================================================ + +#define C(_Class_) kX86RegClass##_Class_ +#define D(_Desc_) kVarFlag##_Desc_ + +const X86VarInfo _x86VarInfo[] = { + /* 00: kVarTypeInt8 */ { kX86RegTypeGpbLo, 1 , C(Gp) , 0 , "gpb" }, + /* 01: kVarTypeUInt8 */ { kX86RegTypeGpbLo, 1 , C(Gp) , 0 , "gpb" }, + /* 02: kVarTypeInt16 */ { kX86RegTypeGpw , 2 , C(Gp) , 0 , "gpw" }, + /* 03: kVarTypeUInt16 */ { kX86RegTypeGpw , 2 , C(Gp) , 0 , "gpw" }, + /* 04: kVarTypeInt32 */ { kX86RegTypeGpd , 4 , C(Gp) , 0 , "gpd" }, + /* 05: kVarTypeUInt32 */ { kX86RegTypeGpd , 4 , C(Gp) , 0 , "gpd" }, + /* 06: kVarTypeInt64 */ { kX86RegTypeGpq , 8 , C(Gp) , 0 , "gpq" }, + /* 07: kVarTypeUInt64 */ { kX86RegTypeGpq , 8 , C(Gp) , 0 , "gpq" }, + /* 08: kVarTypeIntPtr */ { 0 , 0 , C(Gp) , 0 , "" }, // Remapped. + /* 09: kVarTypeUIntPtr */ { 0 , 0 , C(Gp) , 0 , "" }, // Remapped. + /* 10: kVarTypeFp32 */ { kX86RegTypeFp , 4 , C(Fp) , D(Sp) , "fp" }, + /* 11: kVarTypeFp64 */ { kX86RegTypeFp , 8 , C(Fp) , D(Dp) , "fp" }, + /* 12: kX86VarTypeMm */ { kX86RegTypeMm , 8 , C(Mm) , 0 , "mm" }, + /* 13: kX86VarTypeK */ { kX86RegTypeK , 8 , C(K) , 0 , "k" }, + /* 14: kX86VarTypeXmm */ { kX86RegTypeXmm , 16, C(Xyz), 0 , "xmm" }, + /* 15: kX86VarTypeXmmSs */ { kX86RegTypeXmm , 4 , C(Xyz), D(Sp) , "xmm" }, + /* 16: kX86VarTypeXmmPs */ { kX86RegTypeXmm , 16, C(Xyz), D(Sp) | D(Packed), "xmm" }, + /* 17: kX86VarTypeXmmSd */ { kX86RegTypeXmm , 8 , C(Xyz), D(Dp) , "xmm" }, + /* 18: kX86VarTypeXmmPd */ { kX86RegTypeXmm , 16, C(Xyz), D(Dp) | D(Packed), "xmm" }, + /* 19: kX86VarTypeYmm */ { kX86RegTypeYmm , 32, C(Xyz), 0 , "ymm" }, + /* 20: kX86VarTypeYmmPs */ { kX86RegTypeYmm , 32, C(Xyz), D(Sp) | D(Packed), "ymm" }, + /* 21: kX86VarTypeYmmPd */ { kX86RegTypeYmm , 32, C(Xyz), D(Dp) | D(Packed), "ymm" }, + /* 22: kX86VarTypeZmm */ { kX86RegTypeZmm , 64, C(Xyz), 0 , "zmm" }, + /* 23: kX86VarTypeZmmPs */ { kX86RegTypeZmm , 64, C(Xyz), D(Sp) | D(Packed), "zmm" }, + /* 24: kX86VarTypeZmmPd */ { kX86RegTypeZmm , 64, C(Xyz), D(Dp) | D(Packed), "zmm" } +}; + +#undef D +#undef C + +#if defined(ASMJIT_BUILD_X86) +const uint8_t _x86VarMapping[kX86VarTypeCount] = { + /* 00: kVarTypeInt8 */ kVarTypeInt8, + /* 01: kVarTypeUInt8 */ kVarTypeUInt8, + /* 02: kVarTypeInt16 */ kVarTypeInt16, + /* 03: kVarTypeUInt16 */ kVarTypeUInt16, + /* 04: kVarTypeInt32 */ kVarTypeInt32, + /* 05: kVarTypeUInt32 */ kVarTypeUInt32, + /* 06: kVarTypeInt64 */ kInvalidVar, // Invalid in 32-bit mode. + /* 07: kVarTypeUInt64 */ kInvalidVar, // Invalid in 32-bit mode. + /* 08: kVarTypeIntPtr */ kVarTypeInt32, // Remapped to Int32. + /* 09: kVarTypeUIntPtr */ kVarTypeUInt32, // Remapped to UInt32. + /* 10: kVarTypeFp32 */ kVarTypeFp32, + /* 11: kVarTypeFp64 */ kVarTypeFp64, + /* 12: kX86VarTypeMm */ kX86VarTypeMm, + /* 13: kX86VarTypeK */ kX86VarTypeK, + /* 14: kX86VarTypeXmm */ kX86VarTypeXmm, + /* 15: kX86VarTypeXmmSs */ kX86VarTypeXmmSs, + /* 16: kX86VarTypeXmmPs */ kX86VarTypeXmmPs, + /* 17: kX86VarTypeXmmSd */ kX86VarTypeXmmSd, + /* 18: kX86VarTypeXmmPd */ kX86VarTypeXmmPd, + /* 19: kX86VarTypeYmm */ kX86VarTypeYmm, + /* 20: kX86VarTypeYmmPs */ kX86VarTypeYmmPs, + /* 21: kX86VarTypeYmmPd */ kX86VarTypeYmmPd, + /* 22: kX86VarTypeZmm */ kX86VarTypeZmm, + /* 23: kX86VarTypeZmmPs */ kX86VarTypeZmmPs, + /* 24: kX86VarTypeZmmPd */ kX86VarTypeZmmPd +}; +#endif // ASMJIT_BUILD_X86 + +#if defined(ASMJIT_BUILD_X64) +const uint8_t _x64VarMapping[kX86VarTypeCount] = { + /* 00: kVarTypeInt8 */ kVarTypeInt8, + /* 01: kVarTypeUInt8 */ kVarTypeUInt8, + /* 02: kVarTypeInt16 */ kVarTypeInt16, + /* 03: kVarTypeUInt16 */ kVarTypeUInt16, + /* 04: kVarTypeInt32 */ kVarTypeInt32, + /* 05: kVarTypeUInt32 */ kVarTypeUInt32, + /* 06: kVarTypeInt64 */ kVarTypeInt64, + /* 07: kVarTypeUInt64 */ kVarTypeUInt64, + /* 08: kVarTypeIntPtr */ kVarTypeInt64, // Remapped to Int64. + /* 09: kVarTypeUIntPtr */ kVarTypeUInt64, // Remapped to UInt64. + /* 10: kVarTypeFp32 */ kVarTypeFp32, + /* 11: kVarTypeFp64 */ kVarTypeFp64, + /* 12: kX86VarTypeMm */ kX86VarTypeMm, + /* 13: kX86VarTypeK */ kX86VarTypeK, + /* 14: kX86VarTypeXmm */ kX86VarTypeXmm, + /* 15: kX86VarTypeXmmSs */ kX86VarTypeXmmSs, + /* 16: kX86VarTypeXmmPs */ kX86VarTypeXmmPs, + /* 17: kX86VarTypeXmmSd */ kX86VarTypeXmmSd, + /* 18: kX86VarTypeXmmPd */ kX86VarTypeXmmPd, + /* 19: kX86VarTypeYmm */ kX86VarTypeYmm, + /* 20: kX86VarTypeYmmPs */ kX86VarTypeYmmPs, + /* 21: kX86VarTypeYmmPd */ kX86VarTypeYmmPd, + /* 22: kX86VarTypeZmm */ kX86VarTypeZmm, + /* 23: kX86VarTypeZmmPs */ kX86VarTypeZmmPs, + /* 24: kX86VarTypeZmmPd */ kX86VarTypeZmmPd +}; +#endif // ASMJIT_BUILD_X64 + +// ============================================================================ +// [asmjit::X86FuncDecl - Helpers] +// ============================================================================ + +static ASMJIT_INLINE bool x86ArgIsInt(uint32_t aType) { + ASMJIT_ASSERT(aType < kX86VarTypeCount); + return IntUtil::inInterval(aType, _kVarTypeIntStart, _kVarTypeIntEnd); +} + +static ASMJIT_INLINE bool x86ArgIsFp(uint32_t aType) { + ASMJIT_ASSERT(aType < kX86VarTypeCount); + return IntUtil::inInterval(aType, _kVarTypeFpStart, _kVarTypeFpEnd); +} + +static ASMJIT_INLINE uint32_t x86ArgTypeToXmmType(uint32_t aType) { + if (aType == kVarTypeFp32) + return kX86VarTypeXmmSs; + if (aType == kVarTypeFp64) + return kX86VarTypeXmmSd; + return aType; +} + +//! Get an architecture from calling convention. +//! +//! Returns `kArchX86` or `kArchX64` depending on `conv`. +static ASMJIT_INLINE uint32_t x86GetArchFromCConv(uint32_t conv) { + return IntUtil::inInterval(conv, kX86FuncConvW64, kX86FuncConvU64) ? kArchX64 : kArchX86; +} + +// ============================================================================ +// [asmjit::X86FuncDecl - SetPrototype] +// ============================================================================ + +#define R(_Index_) kX86RegIndex##_Index_ +static uint32_t X86FuncDecl_initConv(X86FuncDecl* self, uint32_t arch, uint32_t conv) { + // Setup defaults. + self->_argStackSize = 0; + self->_redZoneSize = 0; + self->_spillZoneSize = 0; + + self->_convention = static_cast(conv); + self->_calleePopsStack = false; + self->_direction = kFuncDirRtl; + + self->_passed.reset(); + self->_preserved.reset(); + + ::memset(self->_passedOrderGp, kInvalidReg, ASMJIT_ARRAY_SIZE(self->_passedOrderGp)); + ::memset(self->_passedOrderXmm, kInvalidReg, ASMJIT_ARRAY_SIZE(self->_passedOrderXmm)); + + // -------------------------------------------------------------------------- + // [X86 Support] + // -------------------------------------------------------------------------- + +#if defined(ASMJIT_BUILD_X86) + if (arch == kArchX86) { + self->_preserved.set(kX86RegClassGp, IntUtil::mask(R(Bx), R(Sp), R(Bp), R(Si), R(Di))); + + switch (conv) { + case kX86FuncConvCDecl: + break; + + case kX86FuncConvStdCall: + self->_calleePopsStack = true; + break; + + case kX86FuncConvMsThisCall: + self->_calleePopsStack = true; + self->_passed.set(kX86RegClassGp, IntUtil::mask(R(Cx))); + self->_passedOrderGp[0] = R(Cx); + break; + + case kX86FuncConvMsFastCall: + self->_calleePopsStack = true; + self->_passed.set(kX86RegClassGp, IntUtil::mask(R(Cx), R(Cx))); + self->_passedOrderGp[0] = R(Cx); + self->_passedOrderGp[1] = R(Dx); + break; + + case kX86FuncConvBorlandFastCall: + self->_calleePopsStack = true; + self->_direction = kFuncDirLtr; + self->_passed.set(kX86RegClassGp, IntUtil::mask(R(Ax), R(Dx), R(Cx))); + self->_passedOrderGp[0] = R(Ax); + self->_passedOrderGp[1] = R(Dx); + self->_passedOrderGp[2] = R(Cx); + break; + + case kX86FuncConvGccFastCall: + self->_calleePopsStack = true; + self->_passed.set(kX86RegClassGp, IntUtil::mask(R(Cx), R(Dx))); + self->_passedOrderGp[0] = R(Cx); + self->_passedOrderGp[1] = R(Dx); + break; + + case kX86FuncConvGccRegParm1: + self->_passed.set(kX86RegClassGp, IntUtil::mask(R(Ax))); + self->_passedOrderGp[0] = R(Ax); + break; + + case kX86FuncConvGccRegParm2: + self->_passed.set(kX86RegClassGp, IntUtil::mask(R(Ax), R(Dx))); + self->_passedOrderGp[0] = R(Ax); + self->_passedOrderGp[1] = R(Dx); + break; + + case kX86FuncConvGccRegParm3: + self->_passed.set(kX86RegClassGp, IntUtil::mask(R(Ax), R(Dx), R(Cx))); + self->_passedOrderGp[0] = R(Ax); + self->_passedOrderGp[1] = R(Dx); + self->_passedOrderGp[2] = R(Cx); + break; + + default: + ASMJIT_ASSERT(!"Reached"); + } + + return kErrorOk; + } +#endif // ASMJIT_BUILD_X86 + + // -------------------------------------------------------------------------- + // [X64 Support] + // -------------------------------------------------------------------------- + +#if defined(ASMJIT_BUILD_X64) + switch (conv) { + case kX86FuncConvW64: + self->_spillZoneSize = 32; + + self->_passed.set(kX86RegClassGp, IntUtil::mask(R(Cx), R(Dx), 8, 9)); + self->_passedOrderGp[0] = R(Cx); + self->_passedOrderGp[1] = R(Dx); + self->_passedOrderGp[2] = 8; + self->_passedOrderGp[3] = 9; + + self->_passed.set(kX86RegClassXyz, IntUtil::mask(0, 1, 2, 3)); + self->_passedOrderXmm[0] = 0; + self->_passedOrderXmm[1] = 1; + self->_passedOrderXmm[2] = 2; + self->_passedOrderXmm[3] = 3; + + self->_preserved.set(kX86RegClassGp , IntUtil::mask(R(Bx), R(Sp), R(Bp), R(Si), R(Di), 12, 13, 14, 15)); + self->_preserved.set(kX86RegClassXyz, IntUtil::mask(6, 7, 8, 9, 10, 11, 12, 13, 14, 15)); + break; + + case kX86FuncConvU64: + self->_redZoneSize = 128; + + self->_passed.set(kX86RegClassGp, IntUtil::mask(R(Di), R(Si), R(Dx), R(Cx), 8, 9)); + self->_passedOrderGp[0] = R(Di); + self->_passedOrderGp[1] = R(Si); + self->_passedOrderGp[2] = R(Dx); + self->_passedOrderGp[3] = R(Cx); + self->_passedOrderGp[4] = 8; + self->_passedOrderGp[5] = 9; + + self->_passed.set(kX86RegClassXyz, IntUtil::mask(0, 1, 2, 3, 4, 5, 6, 7)); + self->_passedOrderXmm[0] = 0; + self->_passedOrderXmm[1] = 1; + self->_passedOrderXmm[2] = 2; + self->_passedOrderXmm[3] = 3; + self->_passedOrderXmm[4] = 4; + self->_passedOrderXmm[5] = 5; + self->_passedOrderXmm[6] = 6; + self->_passedOrderXmm[7] = 7; + + self->_preserved.set(kX86RegClassGp, IntUtil::mask(R(Bx), R(Sp), R(Bp), 12, 13, 14, 15)); + break; + + default: + ASMJIT_ASSERT(!"Reached"); + } +#endif // ASMJIT_BUILD_X64 + + return kErrorOk; +} +#undef R + +static Error X86FuncDecl_initFunc(X86FuncDecl* self, uint32_t arch, + uint32_t ret, const uint32_t* argList, uint32_t argCount) { + + ASMJIT_ASSERT(argCount <= kFuncArgCount); + + uint32_t conv = self->_convention; + uint32_t regSize = (arch == kArchX86) ? 4 : 8; + + int32_t i = 0; + int32_t gpPos = 0; + int32_t xmmPos = 0; + int32_t stackOffset = 0; + + const uint8_t* varMapping; + +#if defined(ASMJIT_BUILD_X86) + if (arch == kArchX86) + varMapping = _x86VarMapping; +#endif // ASMJIT_BUILD_X86 + +#if defined(ASMJIT_BUILD_X64) + if (arch == kArchX64) + varMapping = _x64VarMapping; +#endif // ASMJIT_BUILD_X64 + + self->_argCount = static_cast(argCount); + self->_retCount = 0; + + for (i = 0; i < static_cast(argCount); i++) { + FuncInOut& arg = self->getArg(i); + arg._varType = static_cast(varMapping[argList[i]]); + arg._regIndex = kInvalidReg; + arg._stackOffset = kFuncStackInvalid; + } + + for (; i < kFuncArgCount; i++) { + self->_argList[i].reset(); + } + + self->_retList[0].reset(); + self->_retList[1].reset(); + self->_argStackSize = 0; + self->_used.reset(); + + if (ret != kInvalidVar) { + ret = varMapping[ret]; + switch (ret) { + case kVarTypeInt64: + case kVarTypeUInt64: + // 64-bit value is returned in EDX:EAX on x86. +#if defined(ASMJIT_BUILD_X86) + if (arch == kArchX86) { + self->_retCount = 2; + self->_retList[0]._varType = kVarTypeUInt32; + self->_retList[0]._regIndex = kX86RegIndexAx; + self->_retList[1]._varType = static_cast(ret - 2); + self->_retList[1]._regIndex = kX86RegIndexDx; + } +#endif // ASMJIT_BUILD_X86 + // ... Fall through ... + + case kVarTypeInt8: + case kVarTypeUInt8: + case kVarTypeInt16: + case kVarTypeUInt16: + case kVarTypeInt32: + case kVarTypeUInt32: + self->_retCount = 1; + self->_retList[0]._varType = static_cast(ret); + self->_retList[0]._regIndex = kX86RegIndexAx; + break; + + case kX86VarTypeMm: + self->_retCount = 1; + self->_retList[0]._varType = static_cast(ret); + self->_retList[0]._regIndex = 0; + break; + + case kVarTypeFp32: + self->_retCount = 1; + if (arch == kArchX86) { + self->_retList[0]._varType = kVarTypeFp32; + self->_retList[0]._regIndex = 0; + } + else { + self->_retList[0]._varType = kX86VarTypeXmmSs; + self->_retList[0]._regIndex = 0; + } + break; + + case kVarTypeFp64: + self->_retCount = 1; + if (arch == kArchX86) { + self->_retList[0]._varType = kVarTypeFp64; + self->_retList[0]._regIndex = 0; + } + else { + self->_retList[0]._varType = kX86VarTypeXmmSd; + self->_retList[0]._regIndex = 0; + break; + } + break; + + case kX86VarTypeXmm: + case kX86VarTypeXmmSs: + case kX86VarTypeXmmSd: + case kX86VarTypeXmmPs: + case kX86VarTypeXmmPd: + self->_retCount = 1; + self->_retList[0]._varType = static_cast(ret); + self->_retList[0]._regIndex = 0; + break; + } + } + + if (self->_argCount == 0) + return kErrorOk; + +#if defined(ASMJIT_BUILD_X86) + if (arch == kArchX86) { + // Register arguments (Integer), always left-to-right. + for (i = 0; i != static_cast(argCount); i++) { + FuncInOut& arg = self->getArg(i); + uint32_t varType = varMapping[arg.getVarType()]; + + if (!x86ArgIsInt(varType) || gpPos >= ASMJIT_ARRAY_SIZE(self->_passedOrderGp)) + continue; + + if (self->_passedOrderGp[gpPos] == kInvalidReg) + continue; + + arg._regIndex = self->_passedOrderGp[gpPos++]; + self->_used.or_(kX86RegClassGp, IntUtil::mask(arg.getRegIndex())); + } + + // Stack arguments. + int32_t iStart = static_cast(argCount - 1); + int32_t iEnd = -1; + int32_t iStep = -1; + + if (self->_direction == kFuncDirLtr) { + iStart = 0; + iEnd = static_cast(argCount); + iStep = 1; + } + + for (i = iStart; i != iEnd; i += iStep) { + FuncInOut& arg = self->getArg(i); + uint32_t varType = varMapping[arg.getVarType()]; + + if (arg.hasRegIndex()) + continue; + + if (x86ArgIsInt(varType)) { + stackOffset -= 4; + arg._stackOffset = static_cast(stackOffset); + } + else if (x86ArgIsFp(varType)) { + int32_t size = static_cast(_x86VarInfo[varType].getSize()); + stackOffset -= size; + arg._stackOffset = static_cast(stackOffset); + } + } + } +#endif // ASMJIT_BUILD_X86 + +#if defined(ASMJIT_BUILD_X64) + if (arch == kArchX64) { + if (conv == kX86FuncConvW64) { + int32_t argMax = IntUtil::iMin(argCount, 4); + + // Register arguments (Gp/Xmm), always left-to-right. + for (i = 0; i != argMax; i++) { + FuncInOut& arg = self->getArg(i); + uint32_t varType = varMapping[arg.getVarType()]; + + if (x86ArgIsInt(varType) && i < ASMJIT_ARRAY_SIZE(self->_passedOrderGp)) { + arg._regIndex = self->_passedOrderGp[i]; + self->_used.or_(kX86RegClassGp, IntUtil::mask(arg.getRegIndex())); + continue; + } + + if (x86ArgIsFp(varType) && i < ASMJIT_ARRAY_SIZE(self->_passedOrderXmm)) { + arg._varType = static_cast(x86ArgTypeToXmmType(varType)); + arg._regIndex = self->_passedOrderXmm[i]; + self->_used.or_(kX86RegClassXyz, IntUtil::mask(arg.getRegIndex())); + } + } + + // Stack arguments (always right-to-left). + for (i = argCount - 1; i != -1; i--) { + FuncInOut& arg = self->getArg(i); + uint32_t varType = varMapping[arg.getVarType()]; + + if (arg.hasRegIndex()) + continue; + + if (x86ArgIsInt(varType)) { + stackOffset -= 8; // Always 8 bytes. + arg._stackOffset = stackOffset; + } + else if (x86ArgIsFp(varType)) { + stackOffset -= 8; // Always 8 bytes (float/double). + arg._stackOffset = stackOffset; + } + } + + // 32 bytes shadow space (X64W calling convention specific). + stackOffset -= 4 * 8; + } + else { + // Register arguments (Gp), always left-to-right. + for (i = 0; i != static_cast(argCount); i++) { + FuncInOut& arg = self->getArg(i); + uint32_t varType = varMapping[arg.getVarType()]; + + if (!x86ArgIsInt(varType) || gpPos >= ASMJIT_ARRAY_SIZE(self->_passedOrderGp)) + continue; + + if (self->_passedOrderGp[gpPos] == kInvalidReg) + continue; + + arg._regIndex = self->_passedOrderGp[gpPos++]; + self->_used.or_(kX86RegClassGp, IntUtil::mask(arg.getRegIndex())); + } + + // Register arguments (Xmm), always left-to-right. + for (i = 0; i != static_cast(argCount); i++) { + FuncInOut& arg = self->getArg(i); + uint32_t varType = varMapping[arg.getVarType()]; + + if (x86ArgIsFp(varType)) { + arg._varType = static_cast(x86ArgTypeToXmmType(varType)); + arg._regIndex = self->_passedOrderXmm[xmmPos++]; + self->_used.or_(kX86RegClassXyz, IntUtil::mask(arg.getRegIndex())); + } + } + + // Stack arguments. + for (i = argCount - 1; i != -1; i--) { + FuncInOut& arg = self->getArg(i); + uint32_t varType = varMapping[arg.getVarType()]; + + if (arg.hasRegIndex()) + continue; + + if (x86ArgIsInt(varType)) { + stackOffset -= 8; + arg._stackOffset = static_cast(stackOffset); + } + else if (x86ArgIsFp(varType)) { + int32_t size = static_cast(_x86VarInfo[varType].getSize()); + + stackOffset -= size; + arg._stackOffset = static_cast(stackOffset); + } + } + } + } +#endif // ASMJIT_BUILD_X64 + + // Modify the stack offset, thus in result all parameters would have positive + // non-zero stack offset. + for (i = 0; i < static_cast(argCount); i++) { + FuncInOut& arg = self->getArg(i); + if (!arg.hasRegIndex()) { + arg._stackOffset += static_cast(static_cast(regSize) - stackOffset); + } + } + + self->_argStackSize = static_cast(-stackOffset); + return kErrorOk; +} + +Error X86FuncDecl::setPrototype(uint32_t conv, const FuncPrototype& p) { + if (conv == kFuncConvNone || conv >= _kX86FuncConvCount) + return kErrorInvalidArgument; + + if (p.getArgCount() > kFuncArgCount) + return kErrorInvalidArgument; + + // Validate that the required convention is supported by the current asmjit + // configuration, if only one target is compiled. + uint32_t arch = x86GetArchFromCConv(conv); +#if defined(ASMJIT_BUILD_X86) && !defined(ASMJIT_BUILD_X64) + if (arch == kArchX64) + return kErrorInvalidState; +#endif // ASMJIT_BUILD_X86 && !ASMJIT_BUILD_X64 + +#if !defined(ASMJIT_BUILD_X86) && defined(ASMJIT_BUILD_X64) + if (arch == kArchX86) + return kErrorInvalidState; +#endif // !ASMJIT_BUILD_X86 && ASMJIT_BUILD_X64 + + ASMJIT_PROPAGATE_ERROR(X86FuncDecl_initConv(this, arch, conv)); + ASMJIT_PROPAGATE_ERROR(X86FuncDecl_initFunc(this, arch, p.getRet(), p.getArgList(), p.getArgCount())); + + return kErrorOk; +} + +// ============================================================================ +// [asmjit::X86FuncDecl - Reset] +// ============================================================================ + +void X86FuncDecl::reset() { + uint32_t i; + + _convention = kFuncConvNone; + _calleePopsStack = false; + _direction = kFuncDirRtl; + _reserved0 = 0; + + _argCount = 0; + _retCount = 0; + + _argStackSize = 0; + _redZoneSize = 0; + _spillZoneSize = 0; + + for (i = 0; i < ASMJIT_ARRAY_SIZE(_argList); i++) { + _argList[i].reset(); + } + + _retList[0].reset(); + _retList[1].reset(); + + _used.reset(); + _passed.reset(); + _preserved.reset(); + + ::memset(_passedOrderGp, kInvalidReg, ASMJIT_ARRAY_SIZE(_passedOrderGp)); + ::memset(_passedOrderXmm, kInvalidReg, ASMJIT_ARRAY_SIZE(_passedOrderXmm)); +} + +// ============================================================================ +// [asmjit::X86CallNode - Prototype] +// ============================================================================ + +Error X86CallNode::setPrototype(uint32_t conv, const FuncPrototype& p) { + return _x86Decl.setPrototype(conv, p); +} + +// ============================================================================ +// [asmjit::X86CallNode - Arg / Ret] +// ============================================================================ + +bool X86CallNode::_setArg(uint32_t i, const Operand& op) { + if ((i & ~kFuncArgHi) >= _x86Decl.getArgCount()) + return false; + + _args[i] = op; + return true; +} + +bool X86CallNode::_setRet(uint32_t i, const Operand& op) { + if (i >= 2) + return false; + + _ret[i] = op; + return true; +} + +// ============================================================================ +// [asmjit::X86Compiler - Helpers (Private)] +// ============================================================================ + +static Error X86Compiler_emitConstPool(X86Compiler* self, + Label& label, ConstPool& pool) { + + if (label.getId() == kInvalidValue) + return kErrorOk; + + self->align(kAlignData, static_cast(pool.getAlignment())); + self->bind(label); + + EmbedNode* embedNode = self->embed(NULL, static_cast(pool.getSize())); + if (embedNode == NULL) + return kErrorNoHeapMemory; + + pool.fill(embedNode->getData()); + pool.reset(); + label.reset(); + + return kErrorOk; +} + +// ============================================================================ +// [asmjit::X86Compiler - Construction / Destruction] +// ============================================================================ + +X86Compiler::X86Compiler(Runtime* runtime, uint32_t arch) : + Compiler(runtime), + zax(NoInit), + zcx(NoInit), + zdx(NoInit), + zbx(NoInit), + zsp(NoInit), + zbp(NoInit), + zsi(NoInit), + zdi(NoInit) { + + setArch(arch); +} + +X86Compiler::~X86Compiler() {} + +// ============================================================================ +// [asmjit::X86Compiler - Arch] +// ============================================================================ + +Error X86Compiler::setArch(uint32_t arch) { +#if defined(ASMJIT_BUILD_X86) + if (arch == kArchX86) { + _arch = kArchX86; + _regSize = 4; + + _regCount.reset(); + _regCount._gp = 8; + _regCount._mm = 8; + _regCount._k = 8; + _regCount._xyz = 8; + + zax = x86::eax; + zcx = x86::ecx; + zdx = x86::edx; + zbx = x86::ebx; + zsp = x86::esp; + zbp = x86::ebp; + zsi = x86::esi; + zdi = x86::edi; + + _targetVarMapping = _x86VarMapping; + return kErrorOk; + } +#endif // ASMJIT_BUILD_X86 + +#if defined(ASMJIT_BUILD_X64) + if (arch == kArchX64) { + _arch = kArchX64; + _regSize = 8; + + _regCount.reset(); + _regCount._gp = 16; + _regCount._mm = 8; + _regCount._k = 8; + _regCount._xyz = 16; + + zax = x86::rax; + zcx = x86::rcx; + zdx = x86::rdx; + zbx = x86::rbx; + zsp = x86::rsp; + zbp = x86::rbp; + zsi = x86::rsi; + zdi = x86::rdi; + + _targetVarMapping = _x64VarMapping; + return kErrorOk; + } +#endif // ASMJIT_BUILD_X64 + + ASMJIT_ASSERT(!"Reached"); + return kErrorInvalidArgument; +} + +// ============================================================================ +// [asmjit::X86Compiler - Inst] +// ============================================================================ + +//! Get compiler instruction item size without operands assigned. +static ASMJIT_INLINE size_t X86Compiler_getInstSize(uint32_t code) { + return IntUtil::inInterval(code, _kX86InstIdJbegin, _kX86InstIdJend) ? sizeof(JumpNode) : sizeof(InstNode); +} + +static InstNode* X86Compiler_newInst(X86Compiler* self, void* p, uint32_t code, uint32_t options, Operand* opList, uint32_t opCount) { + if (IntUtil::inInterval(code, _kX86InstIdJbegin, _kX86InstIdJend)) { + JumpNode* node = new(p) JumpNode(self, code, options, opList, opCount); + TargetNode* jTarget = self->getTargetById(opList[0].getId()); + + node->orFlags(code == kX86InstIdJmp ? kNodeFlagIsJmp | kNodeFlagIsTaken : kNodeFlagIsJcc); + node->_target = jTarget; + node->_jumpNext = static_cast(jTarget->_from); + + jTarget->_from = node; + jTarget->addNumRefs(); + + // The 'jmp' is always taken, conditional jump can contain hint, we detect it. + if (code == kX86InstIdJmp) + node->orFlags(kNodeFlagIsTaken); + else if (options & kInstOptionTaken) + node->orFlags(kNodeFlagIsTaken); + + node->addOptions(options); + return node; + } + else { + InstNode* node = new(p) InstNode(self, code, options, opList, opCount); + node->addOptions(options); + return node; + } +} + +InstNode* X86Compiler::newInst(uint32_t code) { + size_t size = X86Compiler_getInstSize(code); + InstNode* inst = static_cast(_baseZone.alloc(size)); + + if (inst == NULL) + goto _NoMemory; + + return X86Compiler_newInst(this, inst, code, getInstOptionsAndReset(), NULL, 0); + +_NoMemory: + setError(kErrorNoHeapMemory); + return NULL; +} + +InstNode* X86Compiler::newInst(uint32_t code, const Operand& o0) { + size_t size = X86Compiler_getInstSize(code); + InstNode* inst = static_cast(_baseZone.alloc(size + 1 * sizeof(Operand))); + + if (inst == NULL) + goto _NoMemory; + + { + Operand* opList = reinterpret_cast(reinterpret_cast(inst) + size); + opList[0] = o0; + ASMJIT_ASSERT_UNINITIALIZED(o0); + return X86Compiler_newInst(this, inst, code, getInstOptionsAndReset(), opList, 1); + } + +_NoMemory: + setError(kErrorNoHeapMemory); + return NULL; +} + +InstNode* X86Compiler::newInst(uint32_t code, const Operand& o0, const Operand& o1) { + size_t size = X86Compiler_getInstSize(code); + InstNode* inst = static_cast(_baseZone.alloc(size + 2 * sizeof(Operand))); + + if (inst == NULL) + goto _NoMemory; + + { + Operand* opList = reinterpret_cast(reinterpret_cast(inst) + size); + opList[0] = o0; + opList[1] = o1; + ASMJIT_ASSERT_UNINITIALIZED(o0); + ASMJIT_ASSERT_UNINITIALIZED(o1); + return X86Compiler_newInst(this, inst, code, getInstOptionsAndReset(), opList, 2); + } + +_NoMemory: + setError(kErrorNoHeapMemory); + return NULL; +} + +InstNode* X86Compiler::newInst(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2) { + size_t size = X86Compiler_getInstSize(code); + InstNode* inst = static_cast(_baseZone.alloc(size + 3 * sizeof(Operand))); + + if (inst == NULL) + goto _NoMemory; + + { + Operand* opList = reinterpret_cast(reinterpret_cast(inst) + size); + opList[0] = o0; + opList[1] = o1; + opList[2] = o2; + ASMJIT_ASSERT_UNINITIALIZED(o0); + ASMJIT_ASSERT_UNINITIALIZED(o1); + ASMJIT_ASSERT_UNINITIALIZED(o2); + return X86Compiler_newInst(this, inst, code, getInstOptionsAndReset(), opList, 3); + } + +_NoMemory: + setError(kErrorNoHeapMemory); + return NULL; +} + +InstNode* X86Compiler::newInst(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, const Operand& o3) { + size_t size = X86Compiler_getInstSize(code); + InstNode* inst = static_cast(_baseZone.alloc(size + 4 * sizeof(Operand))); + + if (inst == NULL) + goto _NoMemory; + + { + Operand* opList = reinterpret_cast(reinterpret_cast(inst) + size); + opList[0] = o0; + opList[1] = o1; + opList[2] = o2; + opList[3] = o3; + ASMJIT_ASSERT_UNINITIALIZED(o0); + ASMJIT_ASSERT_UNINITIALIZED(o1); + ASMJIT_ASSERT_UNINITIALIZED(o2); + ASMJIT_ASSERT_UNINITIALIZED(o3); + return X86Compiler_newInst(this, inst, code, getInstOptionsAndReset(), opList, 4); + } + +_NoMemory: + setError(kErrorNoHeapMemory); + return NULL; +} + +InstNode* X86Compiler::newInst(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, const Operand& o3, const Operand& o4) { + size_t size = X86Compiler_getInstSize(code); + InstNode* inst = static_cast(_baseZone.alloc(size + 5 * sizeof(Operand))); + + if (inst == NULL) + goto _NoMemory; + + { + Operand* opList = reinterpret_cast(reinterpret_cast(inst) + size); + opList[0] = o0; + opList[1] = o1; + opList[2] = o2; + opList[3] = o3; + opList[4] = o4; + ASMJIT_ASSERT_UNINITIALIZED(o0); + ASMJIT_ASSERT_UNINITIALIZED(o1); + ASMJIT_ASSERT_UNINITIALIZED(o2); + ASMJIT_ASSERT_UNINITIALIZED(o3); + ASMJIT_ASSERT_UNINITIALIZED(o4); + return X86Compiler_newInst(this, inst, code, getInstOptionsAndReset(), opList, 5); + } + +_NoMemory: + setError(kErrorNoHeapMemory); + return NULL; +} + +InstNode* X86Compiler::emit(uint32_t code) { + InstNode* node = newInst(code); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +InstNode* X86Compiler::emit(uint32_t code, const Operand& o0) { + InstNode* node = newInst(code, o0); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +InstNode* X86Compiler::emit(uint32_t code, const Operand& o0, const Operand& o1){ + InstNode* node = newInst(code, o0, o1); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +InstNode* X86Compiler::emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2) { + InstNode* node = newInst(code, o0, o1, o2); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +InstNode* X86Compiler::emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, const Operand& o3){ + InstNode* node = newInst(code, o0, o1, o2, o3); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +InstNode* X86Compiler::emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, const Operand& o3, const Operand& o4) { + InstNode* node = newInst(code, o0, o1, o2, o3, o4); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +InstNode* X86Compiler::emit(uint32_t code, int o0_) { + Imm o0(o0_); + InstNode* node = newInst(code, o0); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +InstNode* X86Compiler::emit(uint32_t code, uint64_t o0_) { + Imm o0(o0_); + InstNode* node = newInst(code, o0); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +InstNode* X86Compiler::emit(uint32_t code, const Operand& o0, int o1_) { + Imm o1(o1_); + InstNode* node = newInst(code, o0, o1); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +InstNode* X86Compiler::emit(uint32_t code, const Operand& o0, uint64_t o1_) { + Imm o1(o1_); + InstNode* node = newInst(code, o0, o1); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +InstNode* X86Compiler::emit(uint32_t code, const Operand& o0, const Operand& o1, int o2_) { + Imm o2(o2_); + InstNode* node = newInst(code, o0, o1, o2); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +InstNode* X86Compiler::emit(uint32_t code, const Operand& o0, const Operand& o1, uint64_t o2_) { + Imm o2(o2_); + InstNode* node = newInst(code, o0, o1, o2); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +InstNode* X86Compiler::emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, int o3_) { + Imm o3(o3_); + InstNode* node = newInst(code, o0, o1, o2, o3); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +InstNode* X86Compiler::emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, uint64_t o3_) { + Imm o3(o3_); + InstNode* node = newInst(code, o0, o1, o2, o3); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +// ============================================================================ +// [asmjit::X86Compiler - Func] +// ============================================================================ + +X86FuncNode* X86Compiler::newFunc(uint32_t conv, const FuncPrototype& p) { + X86FuncNode* func = newNode(); + Error error; + + if (func == NULL) + goto _NoMemory; + + // Create helper nodes. + func->_entryNode = newTarget(); + func->_exitNode = newTarget(); + func->_end = newNode(); + + if (func->_entryNode == NULL || func->_exitNode == NULL || func->_end == NULL) + goto _NoMemory; + + // Emit push/pop sequence by default. + func->_funcHints |= IntUtil::mask(kX86FuncHintPushPop); + + // Function prototype. + if ((error = func->_x86Decl.setPrototype(conv, p)) != kErrorOk) { + setError(error); + return NULL; + } + + // Function arguments stack size. Since function requires _argStackSize to be + // set, we have to copy it from X86FuncDecl. + func->_argStackSize = func->_x86Decl.getArgStackSize(); + func->_redZoneSize = static_cast(func->_x86Decl.getRedZoneSize()); + func->_spillZoneSize = static_cast(func->_x86Decl.getSpillZoneSize()); + + // Expected/Required stack alignment. + func->_expectedStackAlignment = getRuntime()->getStackAlignment(); + func->_requiredStackAlignment = 0; + + // Allocate space for function arguments. + func->_argList = NULL; + if (func->getArgCount() != 0) { + func->_argList = _baseZone.allocT(func->getArgCount() * sizeof(VarData*)); + if (func->_argList == NULL) + goto _NoMemory; + ::memset(func->_argList, 0, func->getArgCount() * sizeof(VarData*)); + } + + return func; + +_NoMemory: + setError(kErrorNoHeapMemory); + return NULL; +} + +X86FuncNode* X86Compiler::addFunc(uint32_t conv, const FuncPrototype& p) { + X86FuncNode* func = newFunc(conv, p); + + if (func == NULL) { + setError(kErrorNoHeapMemory); + return NULL; + } + + ASMJIT_ASSERT(_func == NULL); + _func = func; + + addNode(func); + addNode(func->getEntryNode()); + + return func; +} + +EndNode* X86Compiler::endFunc() { + X86FuncNode* func = getFunc(); + ASMJIT_ASSERT(func != NULL); + + // App function exit / epilog marker. + addNode(func->getExitNode()); + + // Add local constant pool at the end of the function (if exist). + X86Compiler_emitConstPool(this, _localConstPoolLabel, _localConstPool); + + // Add function end marker. + addNode(func->getEnd()); + + // Finalize... + func->addFuncFlags(kFuncFlagIsFinished); + _func = NULL; + + return func->getEnd(); +} + +// ============================================================================ +// [asmjit::X86Compiler - Ret] +// ============================================================================ + +RetNode* X86Compiler::newRet(const Operand& o0, const Operand& o1) { + RetNode* node = newNode(o0, o1); + if (node == NULL) + goto _NoMemory; + return node; + +_NoMemory: + setError(kErrorNoHeapMemory); + return NULL; +} + +RetNode* X86Compiler::addRet(const Operand& o0, const Operand& o1) { + RetNode* node = newRet(o0, o1); + if (node == NULL) + return node; + return static_cast(addNode(node)); +} + +// ============================================================================ +// [asmjit::X86Compiler - Call] +// ============================================================================ + +X86CallNode* X86Compiler::newCall(const Operand& o0, uint32_t conv, const FuncPrototype& p) { + X86CallNode* node = newNode(o0); + Error error; + uint32_t nArgs; + + if (node == NULL) + goto _NoMemory; + + if ((error = node->_x86Decl.setPrototype(conv, p)) != kErrorOk) { + setError(error); + return NULL; + } + + // If there are no arguments skip the allocation. + if ((nArgs = p.getArgCount()) == 0) + return node; + + node->_args = static_cast(_baseZone.alloc(nArgs * sizeof(Operand))); + if (node->_args == NULL) + goto _NoMemory; + + ::memset(node->_args, 0, nArgs * sizeof(Operand)); + return node; + +_NoMemory: + setError(kErrorNoHeapMemory); + return NULL; +} + +X86CallNode* X86Compiler::addCall(const Operand& o0, uint32_t conv, const FuncPrototype& p) { + X86CallNode* node = newCall(o0, conv, p); + if (node == NULL) + return NULL; + return static_cast(addNode(node)); +} + +// ============================================================================ +// [asmjit::X86Compiler - Vars] +// ============================================================================ + +Error X86Compiler::setArg(uint32_t argIndex, Var& var) { + X86FuncNode* func = getFunc(); + + if (func == NULL) + return kErrorInvalidArgument; + + if (!isVarValid(var)) + return kErrorInvalidState; + + VarData* vd = getVd(var); + func->setArg(argIndex, vd); + + return kErrorOk; +} + +Error X86Compiler::_newVar(Var* var, uint32_t vType, const char* name) { + ASMJIT_ASSERT(vType < kX86VarTypeCount); + + vType = _targetVarMapping[vType]; + ASMJIT_ASSERT(vType != kInvalidVar); + + // There is not ASSERT in release mode and this should be checked. + if (vType == kInvalidVar) { + static_cast(var)->reset(); + return kErrorInvalidArgument; + } + + const X86VarInfo& vInfo = _x86VarInfo[vType]; + VarData* vd = _newVd(vType, vInfo.getSize(), vInfo.getClass(), name); + + if (vd == NULL) { + static_cast(var)->reset(); + return getError(); + } + + var->_init_packed_op_sz_w0_id(kOperandTypeVar, vd->getSize(), vInfo.getReg() << 8, vd->getId()); + var->_vreg.vType = vType; + return kErrorOk; +} + +// ============================================================================ +// [asmjit::X86Compiler - Stack] +// ============================================================================ + +Error X86Compiler::_newStack(BaseMem* mem, uint32_t size, uint32_t alignment, const char* name) { + if (size == 0) + return kErrorInvalidArgument; + + if (alignment > 64) + alignment = 64; + + VarData* vd = _newVd(kInvalidVar, size, kInvalidReg, name); + if (vd == NULL) { + static_cast(mem)->reset(); + return getError(); + } + + vd->_isStack = true; + vd->_alignment = static_cast(alignment); + + static_cast(mem)->_init(kMemTypeStackIndex, vd->getId(), 0, 0); + return kErrorOk; +} + +// ============================================================================ +// [asmjit::X86Compiler - Const] +// ============================================================================ + +Error X86Compiler::_newConst(BaseMem* mem, uint32_t scope, const void* data, size_t size) { + Error error = kErrorOk; + size_t offset; + + Label* dstLabel; + ConstPool* dstPool; + + if (scope == kConstScopeLocal) { + dstLabel = &_localConstPoolLabel; + dstPool = &_localConstPool; + } + else if (scope == kConstScopeGlobal) { + dstLabel = &_globalConstPoolLabel; + dstPool = &_globalConstPool; + } + else { + error = kErrorInvalidArgument; + goto _OnError; + } + + error = dstPool->add(data, size, offset); + if (error != kErrorOk) + goto _OnError; + + if (dstLabel->getId() == kInvalidValue) { + error = _newLabel(dstLabel); + if (error != kErrorOk) + goto _OnError; + } + + *static_cast(mem) = x86::ptr(*dstLabel, static_cast(offset), static_cast(size)); + return kErrorOk; + +_OnError: + return error; +} + +// ============================================================================ +// [asmjit::X86Compiler - Make] +// ============================================================================ + +void* X86Compiler::make() { + Assembler* assembler = getAssembler(); + if (assembler == NULL) { + setError(kErrorNoHeapMemory); + return NULL; + } + + Error error = serialize(assembler); + if (error != kErrorOk) { + setError(error); + return NULL; + } + + void* result = assembler->make(); + return result; +} + +// ============================================================================ +// [asmjit::X86Compiler - Assembler] +// ============================================================================ + +Assembler* X86Compiler::_newAssembler() { + return new(std::nothrow) X86Assembler(_runtime, _arch); +} + +// ============================================================================ +// [asmjit::X86Compiler - Serialize] +// ============================================================================ + +Error X86Compiler::serialize(Assembler* assembler) { + // Flush the global constant pool. + X86Compiler_emitConstPool(this, _globalConstPoolLabel, _globalConstPool); + + if (_firstNode == NULL) + return kErrorOk; + + X86Context context(this); + Error error = kErrorOk; + + Node* node = _firstNode; + Node* start; + + // Find function and use the context to translate/emit. + do { + start = node; + + if (node->getType() == kNodeTypeFunc) { + node = static_cast(start)->getEnd(); + error = context.compile(static_cast(start)); + + if (error != kErrorOk) + goto _Error; + } + + do { + node = node->getNext(); + } while (node != NULL && node->getType() != kNodeTypeFunc); + + error = context.serialize(assembler, start, node); + if (error != kErrorOk) + goto _Error; + context.cleanup(); + } while (node != NULL); + return kErrorOk; + +_Error: + context.cleanup(); + return error; +} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // !ASMJIT_DISABLE_COMPILER && (ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64) diff --git a/third/Blackbone/src/3rd_party/AsmJit/x86/x86compiler.h b/third/Blackbone/src/3rd_party/AsmJit/x86/x86compiler.h new file mode 100644 index 0000000000000000000000000000000000000000..56dda3a9bf81a02c214b77609adfa438db96ba39 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/x86/x86compiler.h @@ -0,0 +1,5626 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Guard] +#ifndef _ASMJIT_X86_X86COMPILER_H +#define _ASMJIT_X86_X86COMPILER_H + +#include "../build.h" +#if !defined(ASMJIT_DISABLE_COMPILER) + +// [Dependencies - AsmJit] +#include "../base/compiler.h" +#include "../base/vectypes.h" +#include "../x86/x86assembler.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [Forward Declarations] +// ============================================================================ + +struct X86CallNode; +struct X86FuncNode; +struct X86VarState; + +//! \addtogroup asmjit_x86_compiler +//! \{ + +// ============================================================================ +// [asmjit::k86VarType] +// ============================================================================ + +//! X86/X64 variable type. +ASMJIT_ENUM(kX86VarType) { + //! Variable is SP-FP (x87). + kX86VarTypeFp32 = kVarTypeFp32, + //! Variable is DP-FP (x87). + kX86VarTypeFp64 = kVarTypeFp64, + + //! Variable is Mm (MMX). + kX86VarTypeMm = 12, + + //! Variable is K (AVX512+) + kX86VarTypeK, + + //! Variable is Xmm (SSE+). + kX86VarTypeXmm, + //! Variable is a scalar Xmm SP-FP number. + kX86VarTypeXmmSs, + //! Variable is a packed Xmm SP-FP number (4 floats). + kX86VarTypeXmmPs, + //! Variable is a scalar Xmm DP-FP number. + kX86VarTypeXmmSd, + //! Variable is a packed Xmm DP-FP number (2 doubles). + kX86VarTypeXmmPd, + + //! Variable is Ymm (AVX+). + kX86VarTypeYmm, + //! Variable is a packed Ymm SP-FP number (8 floats). + kX86VarTypeYmmPs, + //! Variable is a packed Ymm DP-FP number (4 doubles). + kX86VarTypeYmmPd, + + //! Variable is Zmm (AVX512+). + kX86VarTypeZmm, + //! Variable is a packed Zmm SP-FP number (16 floats). + kX86VarTypeZmmPs, + //! Variable is a packed Zmm DP-FP number (8 doubles). + kX86VarTypeZmmPd, + + //! Count of variable types. + kX86VarTypeCount, + + //! \internal + //! \{ + _kX86VarTypeMmStart = kX86VarTypeMm, + _kX86VarTypeMmEnd = kX86VarTypeMm, + + _kX86VarTypeXmmStart = kX86VarTypeXmm, + _kX86VarTypeXmmEnd = kX86VarTypeXmmPd, + + _kX86VarTypeYmmStart = kX86VarTypeYmm, + _kX86VarTypeYmmEnd = kX86VarTypeYmmPd, + + _kX86VarTypeZmmStart = kX86VarTypeZmm, + _kX86VarTypeZmmEnd = kX86VarTypeZmmPd + //! \} +}; + +// ============================================================================ +// [asmjit::kX86VarAttr] +// ============================================================================ + +//! X86/X64 VarAttr flags. +ASMJIT_ENUM(kX86VarAttr) { + kX86VarAttrGpbLo = 0x10000000, + kX86VarAttrGpbHi = 0x20000000 +}; + +// ============================================================================ +// [asmjit::kX86FuncConv] +// ============================================================================ + +//! X86 function calling conventions. +//! +//! Calling convention is scheme how function arguments are passed into +//! function and how functions returns values. In assembler programming +//! it's needed to always comply with function calling conventions, because +//! even small inconsistency can cause undefined behavior or crash. +//! +//! List of calling conventions for 32-bit x86 mode: +//! - `kX86FuncConvCDecl` - Calling convention for C runtime. +//! - `kX86FuncConvStdCall` - Calling convention for WinAPI functions. +//! - `kX86FuncConvMsThisCall` - Calling convention for C++ members under +//! Windows (produced by MSVC and all MSVC compatible compilers). +//! - `kX86FuncConvMsFastCall` - Fastest calling convention that can be used +//! by MSVC compiler. +//! - `kX86FuncConvBorlandFastCall` - Borland fastcall convention. +//! - `kX86FuncConvGccFastCall` - GCC fastcall convention (2 register arguments). +//! - `kX86FuncConvGccRegParm1` - GCC regparm(1) convention. +//! - `kX86FuncConvGccRegParm2` - GCC regparm(2) convention. +//! - `kX86FuncConvGccRegParm3` - GCC regparm(3) convention. +//! +//! List of calling conventions for 64-bit x86 mode (x64): +//! - `kX86FuncConvW64` - Windows 64-bit calling convention (WIN64 ABI). +//! - `kX86FuncConvU64` - Unix 64-bit calling convention (AMD64 ABI). +//! +//! There is also `kFuncConvHost` that is defined to fit the host calling +//! convention. +//! +//! These types are used together with `Compiler::addFunc()` method. +ASMJIT_ENUM(kX86FuncConv) { + // -------------------------------------------------------------------------- + // [X64] + // -------------------------------------------------------------------------- + + //! X64 calling convention for Windows platform (WIN64 ABI). + //! + //! For first four arguments are used these registers: + //! - 1. 32/64-bit integer or floating point argument - rcx/xmm0 + //! - 2. 32/64-bit integer or floating point argument - rdx/xmm1 + //! - 3. 32/64-bit integer or floating point argument - r8/xmm2 + //! - 4. 32/64-bit integer or floating point argument - r9/xmm3 + //! + //! Note first four arguments here means arguments at positions from 1 to 4 + //! (included). For example if second argument is not passed in register then + //! rdx/xmm1 register is unused. + //! + //! All other arguments are pushed on the stack in right-to-left direction. + //! Stack is aligned by 16 bytes. There is 32-byte shadow space on the stack + //! that can be used to save up to four 64-bit registers (probably designed to + //! be used to save first four arguments passed in registers). + //! + //! Arguments direction: + //! - Right to Left (except for first 4 parameters that's in registers) + //! + //! Stack is cleaned by: + //! - Caller. + //! + //! Return value: + //! - Integer types - Rax register. + //! - Floating points - Xmm0 register. + //! + //! Stack is always aligned by 16 bytes. + //! + //! More information about this calling convention can be found on MSDN: + //! http://msdn.microsoft.com/en-us/library/9b372w95.aspx . + kX86FuncConvW64 = 1, + + //! X64 calling convention for Unix platforms (AMD64 ABI). + //! + //! First six 32 or 64-bit integer arguments are passed in rdi, rsi, rdx, + //! rcx, r8, r9 registers. First eight floating point or Xmm arguments + //! are passed in xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 registers. + //! This means that in registers can be transferred up to 14 arguments total. + //! + //! There is also RED ZONE below the stack pointer that can be used for + //! temporary storage. The red zone is the space from [rsp-128] to [rsp-8]. + //! + //! Arguments direction: + //! - Right to Left (Except for arguments passed in registers). + //! + //! Stack is cleaned by: + //! - Caller. + //! + //! Return value: + //! - Integer types - Rax register. + //! - Floating points - Xmm0 register. + //! + //! Stack is always aligned by 16 bytes. + kX86FuncConvU64 = 2, + + // -------------------------------------------------------------------------- + // [X86] + // -------------------------------------------------------------------------- + + //! Cdecl calling convention (used by C runtime). + //! + //! Compatible across MSVC and GCC. + //! + //! Arguments direction: + //! - Right to Left + //! + //! Stack is cleaned by: + //! - Caller. + kX86FuncConvCDecl = 3, + + //! Stdcall calling convention (used by WinAPI). + //! + //! Compatible across MSVC and GCC. + //! + //! Arguments direction: + //! - Right to Left + //! + //! Stack is cleaned by: + //! - Callee. + //! + //! Return value: + //! - Integer types - EAX:EDX registers. + //! - Floating points - fp0 register. + kX86FuncConvStdCall = 4, + + //! MSVC specific calling convention used by MSVC/Intel compilers + //! for struct/class methods. + //! + //! This is MSVC (and Intel) only calling convention used in Windows + //! world for C++ class methods. Implicit 'this' pointer is stored in + //! ECX register instead of storing it on the stack. + //! + //! Arguments direction: + //! - Right to Left (except this pointer in ECX) + //! + //! Stack is cleaned by: + //! - Callee. + //! + //! Return value: + //! - Integer types - EAX:EDX registers. + //! - Floating points - fp0 register. + //! + //! C++ class methods that have variable count of arguments uses different + //! calling convention called cdecl. + //! + //! \note This calling convention is always used by MSVC for class methods, + //! it's implicit and there is no way how to override it. + kX86FuncConvMsThisCall = 5, + + //! MSVC specific fastcall. + //! + //! Two first parameters (evaluated from left-to-right) are in ECX:EDX + //! registers, all others on the stack in right-to-left order. + //! + //! Arguments direction: + //! - Right to Left (except to first two integer arguments in ECX:EDX) + //! + //! Stack is cleaned by: + //! - Callee. + //! + //! Return value: + //! - Integer types - EAX:EDX registers. + //! - Floating points - fp0 register. + //! + //! \note This calling convention differs to GCC one in stack cleaning + //! mechanism. + kX86FuncConvMsFastCall = 6, + + //! Borland specific fastcall with 2 parameters in registers. + //! + //! Two first parameters (evaluated from left-to-right) are in ECX:EDX + //! registers, all others on the stack in left-to-right order. + //! + //! Arguments direction: + //! - Left to Right (except to first two integer arguments in ECX:EDX) + //! + //! Stack is cleaned by: + //! - Callee. + //! + //! Return value: + //! - Integer types - EAX:EDX registers. + //! - Floating points - fp0 register. + //! + //! \note Arguments on the stack are in left-to-right order that differs + //! to other fastcall conventions used in different compilers. + kX86FuncConvBorlandFastCall = 7, + + //! GCC specific fastcall convention. + //! + //! Two first parameters (evaluated from left-to-right) are in ECX:EDX + //! registers, all others on the stack in right-to-left order. + //! + //! Arguments direction: + //! - Right to Left (except to first two integer arguments in ECX:EDX) + //! + //! Stack is cleaned by: + //! - Callee. + //! + //! Return value: + //! - Integer types - EAX:EDX registers. + //! - Floating points - fp0 register. + //! + //! \note This calling convention should be compatible with `kX86FuncConvMsFastCall`. + kX86FuncConvGccFastCall = 8, + + //! GCC specific regparm(1) convention. + //! + //! The first parameter (evaluated from left-to-right) is in EAX register, + //! all others on the stack in right-to-left order. + //! + //! Arguments direction: + //! - Right to Left (except to first one integer argument in EAX) + //! + //! Stack is cleaned by: + //! - Caller. + //! + //! Return value: + //! - Integer types - EAX:EDX registers. + //! - Floating points - fp0 register. + kX86FuncConvGccRegParm1 = 9, + + //! GCC specific regparm(2) convention. + //! + //! Two first parameters (evaluated from left-to-right) are in EAX:EDX + //! registers, all others on the stack in right-to-left order. + //! + //! Arguments direction: + //! - Right to Left (except to first two integer arguments in EAX:EDX) + //! + //! Stack is cleaned by: + //! - Caller. + //! + //! Return value: + //! - Integer types - EAX:EDX registers. + //! - Floating points - fp0 register. + kX86FuncConvGccRegParm2 = 10, + + //! GCC specific fastcall with 3 parameters in registers. + //! + //! Three first parameters (evaluated from left-to-right) are in + //! EAX:EDX:ECX registers, all others on the stack in right-to-left order. + //! + //! Arguments direction: + //! - Right to Left (except to first three integer arguments in EAX:EDX:ECX) + //! + //! Stack is cleaned by: + //! - Caller. + //! + //! Return value: + //! - Integer types - EAX:EDX registers. + //! - Floating points - fp0 register. + kX86FuncConvGccRegParm3 = 11, + + //! \internal + //! + //! Count of function calling conventions. + _kX86FuncConvCount = 12 +}; + +#if !defined(ASMJIT_DOCGEN) +// X86/X64 Host Support - documented in base/compiler.h. +#if defined(ASMJIT_HOST_X86) +enum { + // X86. + kFuncConvHost = kX86FuncConvCDecl, + kFuncConvHostCDecl = kX86FuncConvCDecl, + kFuncConvHostStdCall = kX86FuncConvStdCall, +#if defined(_MSC_VER) + kFuncConvHostFastCall = kX86FuncConvMsFastCall +#elif defined(__GNUC__) + kFuncConvHostFastCall = kX86FuncConvGccFastCall +#elif defined(__BORLANDC__) + kFuncConvHostFastCall = kX86FuncConvBorlandFastCall +#else +#error "kFuncConvHostFastCall not determined." +#endif +}; +#endif // ASMJIT_HOST_X86 + +#if defined(ASMJIT_HOST_X64) +enum { +#if defined(ASMJIT_OS_WINDOWS) + kFuncConvHost = kX86FuncConvW64, +#else + kFuncConvHost = kX86FuncConvU64, +#endif + kFuncConvHostCDecl = kFuncConvHost, + kFuncConvHostStdCall = kFuncConvHost, + kFuncConvHostFastCall = kFuncConvHost +}; +#endif // ASMJIT_HOST_X64 +#endif // !ASMJIT_DOCGEN + +// ============================================================================ +// [asmjit::kX86FuncHint] +// ============================================================================ + +//! X86 function hints. +ASMJIT_ENUM(kX86FuncHint) { + //! Use push/pop sequences instead of mov sequences in function prolog + //! and epilog. + kX86FuncHintPushPop = 16, + //! Add emms instruction to the function epilog. + kX86FuncHintEmms = 17, + //! Add sfence instruction to the function epilog. + kX86FuncHintSFence = 18, + //! Add lfence instruction to the function epilog. + kX86FuncHintLFence = 19 +}; + +// ============================================================================ +// [asmjit::kX86FuncFlags] +// ============================================================================ + +//! X86 function flags. +ASMJIT_ENUM(kX86FuncFlags) { + //! Whether to emit register load/save sequence using push/pop pairs. + kX86FuncFlagPushPop = 0x00010000, + + //! Whether to emit `enter` instead of three instructions in case + //! that the function is not naked or misaligned. + kX86FuncFlagEnter = 0x00020000, + + //! Whether to emit `leave` instead of two instructions in case + //! that the function is not naked or misaligned. + kX86FuncFlagLeave = 0x00040000, + + //! Whether it's required to move arguments to a new stack location, + //! because of manual aligning. + kX86FuncFlagMoveArgs = 0x00080000, + + //! Whether to emit `emms` instruction in epilog (auto-detected). + kX86FuncFlagEmms = 0x01000000, + + //! Whether to emit `sfence` instruction in epilog (auto-detected). + //! + //! `kX86FuncFlagSFence` with `kX86FuncFlagLFence` results in emitting `mfence`. + kX86FuncFlagSFence = 0x02000000, + + //! Whether to emit `lfence` instruction in epilog (auto-detected). + //! + //! `kX86FuncFlagSFence` with `kX86FuncFlagLFence` results in emitting `mfence`. + kX86FuncFlagLFence = 0x04000000 +}; + +// ============================================================================ +// [asmjit::X86VarInfo] +// ============================================================================ + +//! \internal +//! +//! X86 variable information. +struct X86VarInfo { + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get register type, see `kX86RegType`. + ASMJIT_INLINE uint32_t getReg() const { return _reg; } + //! Get register size in bytes. + ASMJIT_INLINE uint32_t getSize() const { return _size; } + //! Get variable class, see `kRegClass`. + ASMJIT_INLINE uint32_t getClass() const { return _class; } + //! Get variable description, see `kVarFlag`. + ASMJIT_INLINE uint32_t getDesc() const { return _desc; } + //! Get variable type name. + ASMJIT_INLINE const char* getName() const { return _name; } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Register type, see `kX86RegType`. + uint8_t _reg; + //! Register size in bytes. + uint8_t _size; + //! Register class, see `kRegClass`. + uint8_t _class; + //! Variable flags, see `kVarFlag`. + uint8_t _desc; + //! Variable type name. + char _name[4]; +}; + +//! \internal +ASMJIT_VAR const X86VarInfo _x86VarInfo[]; + +#if defined(ASMJIT_BUILD_X86) +//! \internal +//! +//! Mapping of x86 variables into their real IDs. +//! +//! This mapping translates the following: +//! - `kVarTypeInt64` to `kInvalidVar`. +//! - `kVarTypeUInt64` to `kInvalidVar`. +//! - `kVarTypeIntPtr` to `kVarTypeInt32`. +//! - `kVarTypeUIntPtr` to `kVarTypeUInt32`. +ASMJIT_VAR const uint8_t _x86VarMapping[kX86VarTypeCount]; +#endif // ASMJIT_BUILD_X86 + +#if defined(ASMJIT_BUILD_X64) +//! \internal +//! +//! Mapping of x64 variables into their real IDs. +//! +//! This mapping translates the following: +//! - `kVarTypeIntPtr` to `kVarTypeInt64`. +//! - `kVarTypeUIntPtr` to `kVarTypeUInt64`. +ASMJIT_VAR const uint8_t _x64VarMapping[kX86VarTypeCount]; +#endif // ASMJIT_BUILD_X64 + +// ============================================================================ +// [asmjit::X86Var] +// ============================================================================ + +//! Base class for all X86 variables. +struct X86Var : public Var { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE X86Var() : Var(NoInit) { + reset(); + } + + ASMJIT_INLINE X86Var(const X86Var& other) : Var(other) {} + + explicit ASMJIT_INLINE X86Var(const _NoInit&) : Var(NoInit) {} + + // -------------------------------------------------------------------------- + // [X86Var Specific] + // -------------------------------------------------------------------------- + + //! Clone X86Var operand. + ASMJIT_INLINE X86Var clone() const { + return X86Var(*this); + } + + // -------------------------------------------------------------------------- + // [Type] + // -------------------------------------------------------------------------- + + //! Get register type. + ASMJIT_INLINE uint32_t getRegType() const { return _vreg.type; } + //! Get variable type. + ASMJIT_INLINE uint32_t getVarType() const { return _vreg.vType; } + + //! Get whether the variable is Gp register. + ASMJIT_INLINE bool isGp() const { return _vreg.type <= kX86RegTypeGpq; } + //! Get whether the variable is Gpb (8-bit) register. + ASMJIT_INLINE bool isGpb() const { return _vreg.type <= kX86RegTypeGpbHi; } + //! Get whether the variable is Gpb-lo (8-bit) register. + ASMJIT_INLINE bool isGpbLo() const { return _vreg.type == kX86RegTypeGpbLo; } + //! Get whether the variable is Gpb-hi (8-bit) register. + ASMJIT_INLINE bool isGpbHi() const { return _vreg.type == kX86RegTypeGpbHi; } + //! Get whether the variable is Gpw (16-bit) register. + ASMJIT_INLINE bool isGpw() const { return _vreg.type == kX86RegTypeGpw; } + //! Get whether the variable is Gpd (32-bit) register. + ASMJIT_INLINE bool isGpd() const { return _vreg.type == kX86RegTypeGpd; } + //! Get whether the variable is Gpq (64-bit) register. + ASMJIT_INLINE bool isGpq() const { return _vreg.type == kX86RegTypeGpq; } + + //! Get whether the variable is Mm (64-bit) register. + ASMJIT_INLINE bool isMm() const { return _vreg.type == kX86RegTypeMm; } + //! Get whether the variable is K (64-bit) register. + ASMJIT_INLINE bool isK() const { return _vreg.type == kX86RegTypeK; } + + //! Get whether the variable is Xmm (128-bit) register. + ASMJIT_INLINE bool isXmm() const { return _vreg.type == kX86RegTypeXmm; } + //! Get whether the variable is Ymm (256-bit) register. + ASMJIT_INLINE bool isYmm() const { return _vreg.type == kX86RegTypeYmm; } + //! Get whether the variable is Zmm (512-bit) register. + ASMJIT_INLINE bool isZmm() const { return _vreg.type == kX86RegTypeZmm; } + + // -------------------------------------------------------------------------- + // [Memory Cast] + // -------------------------------------------------------------------------- + + //! Cast this variable to a memory operand. + //! + //! \note Size of operand depends on native variable type, you can use other + //! variants if you want specific one. + ASMJIT_INLINE X86Mem m(int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, disp, getSize()); + } + + //! \overload + ASMJIT_INLINE X86Mem m(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, getSize()); + } + + //! Cast this variable to 8-bit memory operand. + ASMJIT_INLINE X86Mem m8(int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, disp, 1); + } + + //! \overload + ASMJIT_INLINE X86Mem m8(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, 1); + } + + //! Cast this variable to 16-bit memory operand. + ASMJIT_INLINE X86Mem m16(int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, disp, 2); + } + + //! \overload + ASMJIT_INLINE X86Mem m16(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, 2); + } + + //! Cast this variable to 32-bit memory operand. + ASMJIT_INLINE X86Mem m32(int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, disp, 4); + } + + //! \overload + ASMJIT_INLINE X86Mem m32(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, 4); + } + + //! Cast this variable to 64-bit memory operand. + ASMJIT_INLINE X86Mem m64(int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, disp, 8); + } + + //! \overload + ASMJIT_INLINE X86Mem m64(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, 8); + } + + //! Cast this variable to 80-bit memory operand (long double). + ASMJIT_INLINE X86Mem m80(int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, disp, 10); + } + + //! \overload + ASMJIT_INLINE X86Mem m80(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, 10); + } + + //! Cast this variable to 128-bit memory operand. + ASMJIT_INLINE X86Mem m128(int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, disp, 16); + } + + //! \overload + ASMJIT_INLINE X86Mem m128(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, 16); + } + + //! Cast this variable to 256-bit memory operand. + ASMJIT_INLINE X86Mem m256(int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, disp, 32); + } + + //! \overload + ASMJIT_INLINE X86Mem m256(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, 32); + } + + //! Cast this variable to 256-bit memory operand. + ASMJIT_INLINE X86Mem m512(int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, disp, 64); + } + + //! \overload + ASMJIT_INLINE X86Mem m512(const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) const { + return X86Mem(Init, kMemTypeStackIndex, *this, index, shift, disp, 64); + } + + // -------------------------------------------------------------------------- + // [Operator Overload] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE X86Var& operator=(const X86Var& other) { + _copy(other); + return *this; + } + + ASMJIT_INLINE bool operator==(const X86Var& other) const { + return _packed[0] == other._packed[0]; + } + + ASMJIT_INLINE bool operator!=(const X86Var& other) const { + return _packed[0] != other._packed[0]; + } + + // -------------------------------------------------------------------------- + // [Private] + // -------------------------------------------------------------------------- + +protected: + ASMJIT_INLINE X86Var(const X86Var& other, uint32_t reg, uint32_t size) : Var(NoInit) { + _init_packed_op_sz_w0_id(kOperandTypeVar, size, (reg << 8) + other._vreg.index, other._base.id); + _vreg.vType = other._vreg.vType; + } +}; + +// ============================================================================ +// [asmjit::X86GpVar] +// ============================================================================ + +//! Gp variable. +struct X86GpVar : public X86Var { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new uninitialized `X86GpVar` instance. + ASMJIT_INLINE X86GpVar() : X86Var() {} + + //! Create a new initialized `X86GpVar` instance. + ASMJIT_INLINE X86GpVar(Compiler& c, uint32_t type = kVarTypeIntPtr, const char* name = NULL) : X86Var(NoInit) { + c._newVar(this, type, name); + } + + //! Create a clone of `other`. + ASMJIT_INLINE X86GpVar(const X86GpVar& other) : X86Var(other) {} + + //! Create a new uninitialized `X86GpVar` instance (internal). + explicit ASMJIT_INLINE X86GpVar(const _NoInit&) : X86Var(NoInit) {} + + // -------------------------------------------------------------------------- + // [X86GpVar Specific] + // -------------------------------------------------------------------------- + + //! Clone X86GpVar operand. + ASMJIT_INLINE X86GpVar clone() const { + return X86GpVar(*this); + } + + //! Reset X86GpVar operand. + ASMJIT_INLINE void reset() { + X86Var::reset(); + } + + // -------------------------------------------------------------------------- + // [X86GpVar Cast] + // -------------------------------------------------------------------------- + + //! Cast this variable to 8-bit (LO) part of variable + ASMJIT_INLINE X86GpVar r8() const { return X86GpVar(*this, kX86RegTypeGpbLo, 1); } + //! Cast this variable to 8-bit (LO) part of variable + ASMJIT_INLINE X86GpVar r8Lo() const { return X86GpVar(*this, kX86RegTypeGpbLo, 1); } + //! Cast this variable to 8-bit (HI) part of variable + ASMJIT_INLINE X86GpVar r8Hi() const { return X86GpVar(*this, kX86RegTypeGpbHi, 1); } + + //! Cast this variable to 16-bit part of variable + ASMJIT_INLINE X86GpVar r16() const { return X86GpVar(*this, kX86RegTypeGpw, 2); } + //! Cast this variable to 32-bit part of variable + ASMJIT_INLINE X86GpVar r32() const { return X86GpVar(*this, kX86RegTypeGpd, 4); } + //! Cast this variable to 64-bit part of variable + ASMJIT_INLINE X86GpVar r64() const { return X86GpVar(*this, kX86RegTypeGpq, 8); } + + // -------------------------------------------------------------------------- + // [Operator Overload] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE X86GpVar& operator=(const X86GpVar& other) { _copy(other); return *this; } + + ASMJIT_INLINE bool operator==(const X86GpVar& other) const { return X86Var::operator==(other); } + ASMJIT_INLINE bool operator!=(const X86GpVar& other) const { return X86Var::operator!=(other); } + + // -------------------------------------------------------------------------- + // [Private] + // -------------------------------------------------------------------------- + +protected: + ASMJIT_INLINE X86GpVar(const X86GpVar& other, uint32_t reg, uint32_t size) : X86Var(other, reg, size) {} +}; + +// ============================================================================ +// [asmjit::X86MmVar] +// ============================================================================ + +//! Mm variable. +struct X86MmVar : public X86Var { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new uninitialized `X86MmVar` instance. + ASMJIT_INLINE X86MmVar() : X86Var() {} + //! Create a new initialized `X86MmVar` instance. + ASMJIT_INLINE X86MmVar(Compiler& c, uint32_t type = kX86VarTypeMm, const char* name = NULL) : X86Var(NoInit) { + c._newVar(this, type, name); + } + + //! Create a clone of `other`. + ASMJIT_INLINE X86MmVar(const X86MmVar& other) : X86Var(other) {} + + //! Create a new uninitialized `X86MmVar` instance (internal). + explicit ASMJIT_INLINE X86MmVar(const _NoInit&) : X86Var(NoInit) {} + + // -------------------------------------------------------------------------- + // [X86MmVar Specific] + // -------------------------------------------------------------------------- + + //! Clone X86MmVar operand. + ASMJIT_INLINE X86MmVar clone() const { + return X86MmVar(*this); + } + + //! Reset X86MmVar operand. + ASMJIT_INLINE void reset() { + X86Var::reset(); + } + + // -------------------------------------------------------------------------- + // [Operator Overload] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE X86MmVar& operator=(const X86MmVar& other) { _copy(other); return *this; } + + ASMJIT_INLINE bool operator==(const X86MmVar& other) const { return X86Var::operator==(other); } + ASMJIT_INLINE bool operator!=(const X86MmVar& other) const { return X86Var::operator!=(other); } +}; + +// ============================================================================ +// [asmjit::X86XmmVar] +// ============================================================================ + +//! Xmm variable. +struct X86XmmVar : public X86Var { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new uninitialized `X86XmmVar` instance. + ASMJIT_INLINE X86XmmVar() : X86Var() {} + //! Create a new initialized `X86XmmVar` instance. + ASMJIT_INLINE X86XmmVar(Compiler& c, uint32_t type = kX86VarTypeXmm, const char* name = NULL) : X86Var(NoInit) { + c._newVar(this, type, name); + } + + //! Create a clone of `other`. + ASMJIT_INLINE X86XmmVar(const X86XmmVar& other) : X86Var(other) {} + + //! Create a new uninitialized `X86XmmVar` instance (internal). + explicit ASMJIT_INLINE X86XmmVar(const _NoInit&) : X86Var(NoInit) {} + + // -------------------------------------------------------------------------- + // [X86XmmVar Specific] + // -------------------------------------------------------------------------- + + //! Clone X86XmmVar operand. + ASMJIT_INLINE X86XmmVar clone() const { + return X86XmmVar(*this); + } + + //! Reset X86XmmVar operand. + ASMJIT_INLINE void reset() { + X86Var::reset(); + } + + // -------------------------------------------------------------------------- + // [Operator Overload] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE X86XmmVar& operator=(const X86XmmVar& other) { _copy(other); return *this; } + + ASMJIT_INLINE bool operator==(const X86XmmVar& other) const { return X86Var::operator==(other); } + ASMJIT_INLINE bool operator!=(const X86XmmVar& other) const { return X86Var::operator!=(other); } +}; + +// ============================================================================ +// [asmjit::X86YmmVar] +// ============================================================================ + +//! Ymm variable. +struct X86YmmVar : public X86Var { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new uninitialized `X86YmmVar` instance. + ASMJIT_INLINE X86YmmVar() : X86Var() {} + //! Create a new initialized `X86YmmVar` instance. + ASMJIT_INLINE X86YmmVar(Compiler& c, uint32_t type = kX86VarTypeYmm, const char* name = NULL) : X86Var(NoInit) { + c._newVar(this, type, name); + } + + //! Create a clone of `other`. + ASMJIT_INLINE X86YmmVar(const X86YmmVar& other) : X86Var(other) {} + + //! Create a new uninitialized `X86YmmVar` instance (internal). + explicit ASMJIT_INLINE X86YmmVar(const _NoInit&) : X86Var(NoInit) {} + + // -------------------------------------------------------------------------- + // [X86YmmVar Specific] + // -------------------------------------------------------------------------- + + //! Clone X86YmmVar operand. + ASMJIT_INLINE X86YmmVar clone() const { + return X86YmmVar(*this); + } + + //! Reset X86YmmVar operand. + ASMJIT_INLINE void reset() { + X86Var::reset(); + } + + // -------------------------------------------------------------------------- + // [Operator Overload] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE X86YmmVar& operator=(const X86YmmVar& other) { _copy(other); return *this; } + + ASMJIT_INLINE bool operator==(const X86YmmVar& other) const { return X86Var::operator==(other); } + ASMJIT_INLINE bool operator!=(const X86YmmVar& other) const { return X86Var::operator!=(other); } +}; + +// ============================================================================ +// [asmjit::X86VarMap] +// ============================================================================ + +struct X86VarMap : public VarMap { + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get variable-attributes list as VarAttr data. + ASMJIT_INLINE VarAttr* getVaList() const { + return const_cast(_list); + } + + //! Get variable-attributes list as VarAttr data (by class). + ASMJIT_INLINE VarAttr* getVaListByClass(uint32_t c) const { + return const_cast(_list) + _start.get(c); + } + + //! Get position of variables (by class). + ASMJIT_INLINE uint32_t getVaStart(uint32_t c) const { + return _start.get(c); + } + + //! Get count of variables (by class). + ASMJIT_INLINE uint32_t getVaCountByClass(uint32_t c) const { + return _count.get(c); + } + + //! Get VarAttr at `index`. + ASMJIT_INLINE VarAttr* getVa(uint32_t index) const { + ASMJIT_ASSERT(index < _vaCount); + return getVaList() + index; + } + + //! Get VarAttr of `c` class at `index`. + ASMJIT_INLINE VarAttr* getVaByClass(uint32_t c, uint32_t index) const { + ASMJIT_ASSERT(index < _count._regs[c]); + return getVaListByClass(c) + index; + } + + // -------------------------------------------------------------------------- + // [Utils] + // -------------------------------------------------------------------------- + + //! Find VarAttr. + ASMJIT_INLINE VarAttr* findVa(VarData* vd) const { + VarAttr* list = getVaList(); + uint32_t count = getVaCount(); + + for (uint32_t i = 0; i < count; i++) + if (list[i].getVd() == vd) + return &list[i]; + + return NULL; + } + + //! Find VarAttr (by class). + ASMJIT_INLINE VarAttr* findVaByClass(uint32_t c, VarData* vd) const { + VarAttr* list = getVaListByClass(c); + uint32_t count = getVaCountByClass(c); + + for (uint32_t i = 0; i < count; i++) + if (list[i].getVd() == vd) + return &list[i]; + + return NULL; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Special registers on input. + //! + //! Special register(s) restricted to one or more physical register. If there + //! is more than one special register it means that we have to duplicate the + //! variable content to all of them (it means that the same varible was used + //! by two or more operands). We forget about duplicates after the register + //! allocation finishes and marks all duplicates as non-assigned. + X86RegMask _inRegs; + + //! Special registers on output. + //! + //! Special register(s) used on output. Each variable can have only one + //! special register on the output, 'X86VarMap' contains all registers from + //! all 'VarAttr's. + X86RegMask _outRegs; + + //! Clobbered registers (by a function call). + X86RegMask _clobberedRegs; + + //! Start indexes of variables per register class. + X86RegCount _start; + //! Count of variables per register class. + X86RegCount _count; + + //! VarAttr list. + VarAttr _list[1]; +}; + +// ============================================================================ +// [asmjit::X86StateCell] +// ============================================================================ + +//! X86/X64 state-cell. +union X86StateCell { + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE uint32_t getState() const { + return _state; + } + + ASMJIT_INLINE void setState(uint32_t state) { + _state = static_cast(state); + } + + // -------------------------------------------------------------------------- + // [Reset] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE void reset() { _packed = 0; } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + uint8_t _packed; + + struct { + uint8_t _state : 2; + uint8_t _unused : 6; + }; +}; + +// ============================================================================ +// [asmjit::X86VarState] +// ============================================================================ + +//! X86/X64 state. +struct X86VarState : VarState { + enum { + //! Base index of Gp registers. + kGpIndex = 0, + //! Count of Gp registers. + kGpCount = 16, + + //! Base index of Mm registers. + kMmIndex = kGpIndex + kGpCount, + //! Count of Mm registers. + kMmCount = 8, + + //! Base index of Xmm registers. + kXmmIndex = kMmIndex + kMmCount, + //! Count of Xmm registers. + kXmmCount = 16, + + //! Count of all registers in `X86VarState`. + kAllCount = kXmmIndex + kXmmCount + }; + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE VarData** getList() { + return _list; + } + + ASMJIT_INLINE VarData** getListByClass(uint32_t c) { + switch (c) { + case kX86RegClassGp : return _listGp; + case kX86RegClassMm : return _listMm; + case kX86RegClassXyz: return _listXmm; + + default: + return NULL; + } + } + + // -------------------------------------------------------------------------- + // [Clear] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE void reset(size_t numCells) { + ::memset(this, 0, kAllCount * sizeof(VarData*) + + 2 * sizeof(X86RegMask) + + numCells * sizeof(X86StateCell)); + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + union { + //! List of all allocated variables in one array. + VarData* _list[kAllCount]; + + struct { + //! Allocated Gp registers. + VarData* _listGp[kGpCount]; + //! Allocated Mm registers. + VarData* _listMm[kMmCount]; + //! Allocated Xmm registers. + VarData* _listXmm[kXmmCount]; + }; + }; + + //! Occupied registers (mask). + X86RegMask _occupied; + //! Modified registers (mask). + X86RegMask _modified; + + //! Variables data, the length is stored in `X86Context`. + X86StateCell _cells[1]; +}; + +// ============================================================================ +// [asmjit::X86FuncDecl] +// ============================================================================ + +//! X86 function, including calling convention, arguments and their +//! register indices or stack positions. +struct X86FuncDecl : public FuncDecl { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new `X86FuncDecl` instance. + ASMJIT_INLINE X86FuncDecl() { + reset(); + } + + // -------------------------------------------------------------------------- + // [Accessors - X86] + // -------------------------------------------------------------------------- + + //! Get used registers (mask). + //! + //! \note The result depends on the function calling convention AND the + //! function prototype. Returned mask contains only registers actually used + //! to pass function arguments. + ASMJIT_INLINE uint32_t getUsed(uint32_t c) const { + return _used.get(c); + } + + //! Get passed registers (mask). + //! + //! \note The result depends on the function calling convention used; the + //! prototype of the function doesn't affect the mask returned. + ASMJIT_INLINE uint32_t getPassed(uint32_t c) const { + return _passed.get(c); + } + + //! Get preserved registers (mask). + //! + //! \note The result depends on the function calling convention used; the + //! prototype of the function doesn't affect the mask returned. + ASMJIT_INLINE uint32_t getPreserved(uint32_t c) const { + return _preserved.get(c); + } + + //! Get ther order of passed registers (Gp). + //! + //! \note The result depends on the function calling convention used; the + //! prototype of the function doesn't affect the mask returned. + ASMJIT_INLINE const uint8_t* getPassedOrderGp() const { + return _passedOrderGp; + } + + //! Get ther order of passed registers (Xmm). + //! + //! \note The result depends on the function calling convention used; the + //! prototype of the function doesn't affect the mask returned. + ASMJIT_INLINE const uint8_t* getPassedOrderXmm() const { + return _passedOrderXmm; + } + + // -------------------------------------------------------------------------- + // [SetPrototype] + // -------------------------------------------------------------------------- + + //! Set function prototype. + //! + //! This will set function calling convention and setup arguments variables. + //! + //! \note This function will allocate variables, it can be called only once. + ASMJIT_API Error setPrototype(uint32_t conv, const FuncPrototype& p); + + // -------------------------------------------------------------------------- + // [Reset] + // -------------------------------------------------------------------------- + + ASMJIT_API void reset(); + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Used registers. + X86RegMask _used; + + //! Passed registers (defined by the calling convention). + X86RegMask _passed; + //! Preserved registers (defined by the calling convention). + X86RegMask _preserved; + + //! Order of registers defined to pass function arguments (Gp). + uint8_t _passedOrderGp[8]; + //! Order of registers defined to pass function arguments (Xmm). + uint8_t _passedOrderXmm[8]; +}; + +// ============================================================================ +// [asmjit::X86FuncNode] +// ============================================================================ + +//! X86/X64 function node. +struct X86FuncNode : public FuncNode { + ASMJIT_NO_COPY(X86FuncNode) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new `X86FuncNode` instance. + ASMJIT_INLINE X86FuncNode(Compiler* compiler) : FuncNode(compiler) { + _decl = &_x86Decl; + _saveRestoreRegs.reset(); + + _alignStackSize = 0; + _alignedMemStackSize = 0; + _pushPopStackSize = 0; + _moveStackSize = 0; + _extraStackSize = 0; + + _stackFrameRegIndex = kInvalidReg; + _isStackFrameRegPreserved = false; + _stackFrameCopyGpIndex[0] = kInvalidReg; + _stackFrameCopyGpIndex[1] = kInvalidReg; + _stackFrameCopyGpIndex[2] = kInvalidReg; + _stackFrameCopyGpIndex[3] = kInvalidReg; + _stackFrameCopyGpIndex[4] = kInvalidReg; + _stackFrameCopyGpIndex[5] = kInvalidReg; + } + + //! Destroy the `X86FuncNode` instance. + ASMJIT_INLINE ~X86FuncNode() {} + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get function declaration as `X86FuncDecl`. + ASMJIT_INLINE X86FuncDecl* getDecl() const { + return const_cast(&_x86Decl); + } + + //! Get argument. + ASMJIT_INLINE VarData* getArg(uint32_t i) const { + ASMJIT_ASSERT(i < _x86Decl.getArgCount()); + return static_cast(_argList[i]); + } + + //! Get registers which have to be saved in prolog/epilog. + ASMJIT_INLINE uint32_t getSaveRestoreRegs(uint32_t c) { return _saveRestoreRegs.get(c); } + + //! Get stack size needed to align stack back to the nature alignment. + ASMJIT_INLINE uint32_t getAlignStackSize() const { return _alignStackSize; } + //! Set stack size needed to align stack back to the nature alignment. + ASMJIT_INLINE void setAlignStackSize(uint32_t s) { _alignStackSize = s; } + + //! Get aligned stack size used by variables and memory allocated on the stack. + ASMJIT_INLINE uint32_t getAlignedMemStackSize() const { return _alignedMemStackSize; } + + //! Get stack size used by push/pop sequences in prolog/epilog. + ASMJIT_INLINE uint32_t getPushPopStackSize() const { return _pushPopStackSize; } + //! Set stack size used by push/pop sequences in prolog/epilog. + ASMJIT_INLINE void setPushPopStackSize(uint32_t s) { _pushPopStackSize = s; } + + //! Get stack size used by mov sequences in prolog/epilog. + ASMJIT_INLINE uint32_t getMoveStackSize() const { return _moveStackSize; } + //! Set stack size used by mov sequences in prolog/epilog. + ASMJIT_INLINE void setMoveStackSize(uint32_t s) { _moveStackSize = s; } + + //! Get extra stack size. + ASMJIT_INLINE uint32_t getExtraStackSize() const { return _extraStackSize; } + //! Set extra stack size. + ASMJIT_INLINE void setExtraStackSize(uint32_t s) { _extraStackSize = s; } + + //! Get whether the function has stack frame register. + //! + //! \note Stack frame register can be used for both - aligning purposes or + //! generating standard prolog/epilog sequence. + //! + //! \note Used only when stack is misaligned. + ASMJIT_INLINE bool hasStackFrameReg() const { return _stackFrameRegIndex != kInvalidReg; } + //! Get stack frame register index. + //! + //! \note Used only when stack is misaligned. + ASMJIT_INLINE uint32_t getStackFrameRegIndex() const { return _stackFrameRegIndex; } + //! Get whether the stack frame register is preserved. + //! + //! \note Used only when stack is misaligned. + ASMJIT_INLINE bool isStackFrameRegPreserved() const { return static_cast(_isStackFrameRegPreserved); } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! X86 function decl. + X86FuncDecl _x86Decl; + //! Registers which must be saved/restored in prolog/epilog. + X86RegMask _saveRestoreRegs; + + //! Stack size needed to align function back to the nature alignment. + uint32_t _alignStackSize; + //! Like `_memStackSize`, but aligned. + uint32_t _alignedMemStackSize; + + //! Stack required for push/pop in prolog/epilog (X86/X64 specific). + uint32_t _pushPopStackSize; + //! Stack required for movs in prolog/epilog (X86/X64 specific). + uint32_t _moveStackSize; + + //! Stack required to put extra data (for example function arguments + //! when manually aligning to requested alignment). + uint32_t _extraStackSize; + + //! Stack frame register. + uint8_t _stackFrameRegIndex; + //! Whether the stack frame register is preserved. + uint8_t _isStackFrameRegPreserved; + //! Gp registers indexes that can be used to copy function arguments + //! to a new location in case we are doing manual stack alignment. + uint8_t _stackFrameCopyGpIndex[6]; +}; + +// ============================================================================ +// [asmjit::X86CallNode] +// ============================================================================ + +//! X86/X64 function-call node. +struct X86CallNode : public CallNode { + ASMJIT_NO_COPY(X86CallNode) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new `X86CallNode` instance. + ASMJIT_INLINE X86CallNode(Compiler* compiler, const Operand& target) : CallNode(compiler, target) { + _decl = &_x86Decl; + _usedArgs.reset(); + } + + //! Destroy the `X86CallNode` instance. + ASMJIT_INLINE ~X86CallNode() {} + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get function prototype. + ASMJIT_INLINE X86FuncDecl* getDecl() const { + return const_cast(&_x86Decl); + } + + // -------------------------------------------------------------------------- + // [Prototype] + // -------------------------------------------------------------------------- + + //! Set function prototype. + ASMJIT_API Error setPrototype(uint32_t conv, const FuncPrototype& p); + + // -------------------------------------------------------------------------- + // [Arg / Ret] + // -------------------------------------------------------------------------- + + //! Set argument at `i` to `op`. + ASMJIT_API bool _setArg(uint32_t i, const Operand& op); + //! Set return at `i` to `op`. + ASMJIT_API bool _setRet(uint32_t i, const Operand& op); + + //! Set argument at `i` to `var`. + ASMJIT_INLINE bool setArg(uint32_t i, const Var& var) { return _setArg(i, var); } + //! Set argument at `i` to `reg` (FP registers only). + ASMJIT_INLINE bool setArg(uint32_t i, const X86FpReg& reg) { return _setArg(i, reg); } + //! Set argument at `i` to `imm`. + ASMJIT_INLINE bool setArg(uint32_t i, const Imm& imm) { return _setArg(i, imm); } + + //! Set return at `i` to `var`. + ASMJIT_INLINE bool setRet(uint32_t i, const Var& var) { return _setRet(i, var); } + //! Set return at `i` to `reg` (FP registers only). + ASMJIT_INLINE bool setRet(uint32_t i, const X86FpReg& reg) { return _setRet(i, reg); } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! X86 declaration. + X86FuncDecl _x86Decl; + //! Mask of all registers actually used to pass function arguments. + //! + //! \note This bit-mask is not the same as `X86Func::_passed`. It contains + //! only registers actually used to do the call while `X86Func::_passed` + //! mask contains all registers for all function prototype combinations. + X86RegMask _usedArgs; +}; + +// ============================================================================ +// [asmjit::X86TypeId / VarMapping] +// ============================================================================ + +#if !defined(ASMJIT_DOCGEN) +ASMJIT_TYPE_ID(X86MmReg, kX86VarTypeMm); +ASMJIT_TYPE_ID(X86MmVar, kX86VarTypeMm); +ASMJIT_TYPE_ID(X86XmmReg, kX86VarTypeXmm); +ASMJIT_TYPE_ID(X86XmmVar, kX86VarTypeXmm); +ASMJIT_TYPE_ID(X86YmmReg, kX86VarTypeYmm); +ASMJIT_TYPE_ID(X86YmmVar, kX86VarTypeYmm); +#endif // !ASMJIT_DOCGEN + +// ============================================================================ +// [asmjit::X86Compiler] +// ============================================================================ + +//! X86/X64 compiler. +//! +//! This class is used to store instruction stream and allows to modify it on +//! the fly. It uses different concept than `Assembler` class and in fact +//! `Assembler` is only used as a backend. Compiler never emits machine code +//! and each instruction you use is stored to instruction array instead. This +//! allows to modify instruction stream later and for example to reorder +//! instructions to make better performance. +//! +//! `X86Compiler` moves code generation to a higher level. Higher level +//! constructs allows to write more abstract and extensible code that is not +//! possible with pure `X86Assembler`. +//! +//! The Story +//! --------- +//! +//! Before telling you how Compiler works I'd like to write a story. I'd like +//! to cover reasons why this class was created and why I'm recommending to use +//! it. When I released the first version of AsmJit (0.1) it was a toy. The +//! first function I wrote was function which is still available as testjit and +//! which simply returns 1024. The reason why function works for both 32-bit/ +//! 64-bit mode and for Windows/Unix specific calling conventions is luck, no +//! arguments usage and no registers usage except returning value in EAX/RAX. +//! +//! Then I started a project called BlitJit which was targetted to generating +//! JIT code for computer graphics. After writing some lines I decided that I +//! can't join pieces of code together without abstraction, should be +//! pixels source pointer in ESI/RSI or EDI/RDI or it's completelly +//! irrellevant? What about destination pointer and SSE2 register for reading +//! input pixels? The simple answer might be "just pick some one and use it". +//! +//! Another reason for abstraction is function calling-conventions. It's really +//! not easy to write assembler code for 32-bit and 64-bit platform supporting +//! three calling conventions (32-bit is similar between Windows and Unix, but +//! 64-bit calling conventions are different). +//! +//! At this time I realized that I can't write code which uses named registers, +//! I need to abstract it. In most cases you don't need specific register, you +//! need to emit instruction that does something with 'virtual' register(s), +//! memory, immediate or label. +//! +//! The first version of AsmJit with Compiler was 0.5 (or 0.6?, can't remember). +//! There was support for 32-bit and 64-bit mode, function calling conventions, +//! but when emitting instructions the developer needed to decide which +//! registers are changed, which are only read or completely overwritten. This +//! model helped a lot when generating code, especially when joining more +//! code-sections together, but there was also small possibility for mistakes. +//! Simply the first version of Compiler was great improvement over low-level +//! Assembler class, but the API design wasn't perfect. +//! +//! The second version of Compiler, completelly rewritten and based on +//! different goals, is part of AsmJit starting at version 1.0. This version +//! was designed after the first one and it contains serious improvements over +//! the old one. The first improvement is that you just use instructions with +//! virtual registers - called variables. When using compiler there is no way +//! to use native registers, there are variables instead. AsmJit is smarter +//! than before and it knows which register is needed only for read (r), +//! read/write (w) or overwrite (x). Supported are also instructions which +//! are using some registers in implicit way (these registers are not part of +//! instruction definition in string form). For example to use CPUID instruction +//! you must give it four variables which will be automatically allocated in +//! input/output registers (EAX, EBX, ECX, EDX). +//! +//! Another improvement is algorithm used by a register allocator. In first +//! version the registers were allocated when creating instruction stream. In +//! new version registers are allocated after calling `Compiler::make()`, +//! thus register allocator has information about scope of all variables and +//! statistics of their usage. The algorithm to allocate registers is very +//! simple and it's always called as a 'linear scan register allocator'. When +//! you get out of registers the all possible variables are scored and the worst +//! is spilled. Of course algorithm ignores the variables used for current +//! instruction. +//! +//! In addition, because registers are allocated after the code stream is +//! generated, the state switches between jumps are handled by Compiler too. +//! You don't need to worry about jumps, compiler always do this dirty work +//! for you. +//! +//! The nearly last thing I'd like to present is calling other functions from +//! the generated code. AsmJit uses a `FuncPrototype` class to hold function +//! parameters, their position in stack (or register index) and return value. +//! This class is used internally, but it can be used to create your own +//! function calling-convention. All standard function calling conventions are +//! implemented. +//! +//! Please enjoy the new version of Compiler, it was created for writing a +//! low-level code using high-level API, leaving developer to concentrate on +//! real problems and not to solving a register puzzle. +//! +//! Code Generation +//! --------------- +//! +//! First that is needed to know about compiler is that compiler never emits +//! machine code. It's used as a middleware between @c asmjit::Assembler and +//! your code. There is also convenience method @c make() that allows to +//! generate machine code directly without creating @c asmjit::Assembler +//! instance. +//! +//! Comparison of generating machine code through @c Assembler and directly +//! by @c Compiler: +//! +//! ~~~ +//! // Assembler instance is low level code generation class that emits +//! // machine code. +//! Assembler a; +//! +//! // Compiler instance is high level code generation class that stores all +//! // instructions in internal representation. +//! Compiler c; +//! +//! // ... put your code here ... +//! +//! // Final step - generate code. asmjit::Compiler::serialize() will send all +//! // instructions into Assembler and this ensures generating real machine code. +//! c.serialize(&a); +//! +//! // Your function +//! void* fn = a.make(); +//! ~~~ +//! +//! Example how to generate machine code using only @c Compiler (preferred): +//! +//! ~~~ +//! // Compiler instance is enough. +//! Compiler c; +//! +//! // ... put your code here ... +//! +//! // Your function +//! void* fn = c.make(); +//! ~~~ +//! +//! You can see that there is @c asmjit::Compiler::serialize() function that +//! emits instructions into @c asmjit::Assembler(). This layered architecture +//! means that each class is used for something different and there is no code +//! duplication. For convenience there is also @c asmjit::Compiler::make() +//! method that can create your function using @c asmjit::Assembler, but +//! internally (this is preferred bahavior when using @c asmjit::Compiler). +//! +//! The @c make() method allocates memory using `Runtime` instance passed +//! into the @c Compiler constructor. If code generator is used to create JIT +//! function then virtual memory allocated by `VMemMgr` is used. +//! +//! ~~~ +//! JitRuntime runtime; +//! Compiler c(&runtime); +//! +//! // ... put your code using Compiler instance ... +//! +//! // Your function +//! void* fn = c.make(); +//! +//! runtime.release(fn); +//! ~~~ +//! +//! Functions +//! --------- +//! +//! To build functions with @c Compiler, see @c asmjit::Compiler::addFunc() +//! method. +//! +//! Variables +//! --------- +//! +//! Compiler is able to manage variables and function arguments. Function +//! arguments are moved to variables by using @c setArg() method, where the +//! first parameter is argument index and second parameter is the variable +//! instance. To declare variable use @c newGpVar(), @c newMmVar() and @c +//! newXmmVar() methods. The @c newXXX() methods accept also parameter +//! describing the variable type. For example the @c newGpVar() method always +//! creates variable which size matches the target architecture size (for +//! 32-bit target the 32-bit variable is created, for 64-bit target the +//! variable size is 64-bit). To override this behavior the variable type +//! must be specified. +//! +//! ~~~ +//! // Compiler and function declaration - void f(int*); +//! Compiler c; +//! X86GpVar a0(c, kVarTypeIntPtr); +//! +//! c.addFunc(kFuncConvHost, FuncBuilder1()); +//! c.setArg(0, a0); +//! +//! // Create your variables. +//! X86GpVar x0(c, kVarTypeInt32); +//! X86GpVar x1(c, kVarTypeInt32); +//! +//! // Init your variables. +//! c.mov(x0, 1); +//! c.mov(x1, 2); +//! +//! // ... your code ... +//! c.add(x0, x1); +//! // ... your code ... +//! +//! // Store result to a given pointer in first argument +//! c.mov(dword_ptr(a0), x0); +//! +//! // End of function body. +//! c.endFunc(); +//! +//! // Make the function. +//! typedef void (*MyFunc)(int*); +//! MyFunc func = asmjit_cast(c.make()); +//! ~~~ +//! +//! This code snipped needs to be explained. You can see that there are more +//! variable types that can be used by `Compiler`. Most useful variables can +//! be allocated using general purpose registers (`X86GpVar`), MMX registers +//! (`X86MmVar`) or SSE/SSE2 registers (`X86XmmVar`). +//! +//! X86/X64 variable types: +//! +//! - `kVarTypeInt8` - Signed 8-bit integer, mapped to Gpd register (eax, ebx, ...). +//! - `kVarTypeUInt8` - Unsigned 8-bit integer, mapped to Gpd register (eax, ebx, ...). +//! +//! - `kVarTypeInt16` - Signed 16-bit integer, mapped to Gpd register (eax, ebx, ...). +//! - `kVarTypeUInt16` - Unsigned 16-bit integer, mapped to Gpd register (eax, ebx, ...). +//! +//! - `kVarTypeInt32` - Signed 32-bit integer, mapped to Gpd register (eax, ebx, ...). +//! - `kVarTypeUInt32` - Unsigned 32-bit integer, mapped to Gpd register (eax, ebx, ...). +//! +//! - `kVarTypeInt64` - Signed 64-bit integer, mapped to Gpq register (rax, rbx, ...). +//! - `kVarTypeUInt64` - Unsigned 64-bit integer, mapped to Gpq register (rax, rbx, ...). +//! +//! - `kVarTypeIntPtr` - intptr_t, mapped to Gpd/Gpq register; depends on target, not host! +//! - `kVarTypeUIntPtr` - uintptr_t, mapped to Gpd/Gpq register; depends on target, not host! +//! +//! - `kVarTypeFp32` - 32-bit floating point register (fp0, fp1, ...). +//! - `kVarTypeFp64` - 64-bit floating point register (fp0, fp1, ...). +//! +//! - `kX86VarTypeMm` - 64-bit Mm register (mm0, mm1, ...). +//! +//! - `kX86VarTypeXmm` - 128-bit SSE register. +//! - `kX86VarTypeXmmSs` - 128-bit SSE register that contains a scalar 32-bit SP-FP value. +//! - `kX86VarTypeXmmSd` - 128-bit SSE register that contains a scalar 64-bit DP-FP value. +//! - `kX86VarTypeXmmPs` - 128-bit SSE register that contains 4 packed 32-bit SP-FP values. +//! - `kX86VarTypeXmmPd` - 128-bit SSE register that contains 2 packed 64-bit DP-FP values. +//! +//! - `kX86VarTypeYmm` - 256-bit AVX register. +//! - `kX86VarTypeYmmPs` - 256-bit AVX register that contains 4 packed 32-bit SP-FP values. +//! - `kX86VarTypeYmmPd` - 256-bit AVX register that contains 2 packed 64-bit DP-FP values. +//! +//! Variable states: +//! +//! - `kVarStateUnused - State that is assigned to newly created variables or +//! to not used variables (dereferenced to zero). +//! - `kVarStateReg - State that means that variable is currently allocated in +//! register. +//! - `kVarStateMem - State that means that variable is currently only in +//! memory location. +//! +//! When you create new variable, initial state is always `kVarStateUnused`, +//! allocating it to register or spilling to memory changes this state to +//! `kVarStateReg` or `kVarStateMem`, respectively. During variable lifetime +//! it's usual that its state is changed multiple times. To generate better +//! code, you can control allocating and spilling by using up to four types +//! of methods that allows it (see next list). +//! +//! Explicit variable allocating / spilling methods: +//! +//! - `Compiler::alloc()` - Explicit method to alloc variable into register. +//! It can be used to force allocation a variable before a loop for example. +//! +//! - `Compiler::spill()` - Explicit method to spill variable. If variable +//! is in register and you call this method, it's moved to its home memory +//! location. If variable is not in register no operation is performed. +//! +//! - `Compiler::unuse()` - Unuse variable (you can use this to end the +//! variable scope or sub-scope). +//! +//! Please see AsmJit tutorials (testcompiler.cpp and testvariables.cpp) for +//! more complete examples. +//! +//! Memory Management +//! ----------------- +//! +//! Compiler Memory management follows these rules: +//! +//! - Everything created by `Compiler` is always freed by `Compiler`. +//! - To get decent performance, compiler always uses larger memory buffer +//! for objects to allocate and when compiler instance is destroyed, this +//! buffer is freed. Destructors of active objects are called when +//! destroying compiler instance. Destructors of abadonded compiler +//! objects are called immediately after abadonding them. +//! - This type of memory management is called 'zone memory management'. +//! +//! This means that you can't use any `Compiler` object after destructing it, +//! it also means that each object like `Label`, `Var` and others are created +//! and managed by @c Compiler itself. These objects contain ID which is +//! used internally by Compiler to store additional information about these +//! objects. +//! +//! Control-Flow and State Management +//! --------------------------------- +//! +//! The `Compiler` automatically manages state of the variables when using +//! control flow instructions like jumps, conditional jumps and calls. There +//! is minimal heuristics for choosing the method how state is saved or restored. +//! +//! Generally the state can be changed only when using jump or conditional jump +//! instruction. When using non-conditional jump then state change is embedded +//! into the instruction stream before the jump. When using conditional jump +//! the `Compiler` decides whether to restore state before the jump or whether +//! to use another block where state is restored. The last case is that no-code +//! have to be emitted and there is no state change (this is of course ideal). +//! +//! Choosing whether to embed 'restore-state' section before conditional jump +//! is quite simple. If jump is likely to be 'taken' then code is embedded, if +//! jump is unlikely to be taken then the small code section for state-switch +//! will be generated instead. +//! +//! Next example is the situation where the extended code block is used to +//! do state-change: +//! +//! ~~~ +//! Compiler c; +//! +//! c.addFunc(kFuncConvHost, FuncBuilder0()); +//! +//! // Labels. +//! Label L0(c); +//! +//! // Variables. +//! X86GpVar var0(c, kVarTypeInt32); +//! X86GpVar var1(c, kVarTypeInt32); +//! +//! // Cleanup. After these two lines, the var0 and var1 will be always stored +//! // in registers. Our example is very small, but in larger code the var0 can +//! // be spilled by xor(var1, var1). +//! c.xor_(var0, var0); +//! c.xor_(var1, var1); +//! c.cmp(var0, var1); +//! // State: +//! // var0 - register. +//! // var1 - register. +//! +//! // We manually spill these variables. +//! c.spill(var0); +//! c.spill(var1); +//! // State: +//! // var0 - memory. +//! // var1 - memory. +//! +//! // Conditional jump to L0. It will be always taken, but compiler thinks that +//! // it is unlikely taken so it will embed state change code somewhere. +//! c.je(L0); +//! +//! // Do something. The variables var0 and var1 will be allocated again. +//! c.add(var0, 1); +//! c.add(var1, 2); +//! // State: +//! // var0 - register. +//! // var1 - register. +//! +//! // Bind label here, the state is not changed. +//! c.bind(L0); +//! // State: +//! // var0 - register. +//! // var1 - register. +//! +//! // We need to use var0 and var1, because if compiler detects that variables +//! // are out of scope then it optimizes the state-change. +//! c.sub(var0, var1); +//! // State: +//! // var0 - register. +//! // var1 - register. +//! +//! c.endFunc(); +//! ~~~ +//! +//! The output: +//! +//! ~~~ +//! xor eax, eax ; xor var_0, var_0 +//! xor ecx, ecx ; xor var_1, var_1 +//! cmp eax, ecx ; cmp var_0, var_1 +//! mov [esp - 24], eax ; spill var_0 +//! mov [esp - 28], ecx ; spill var_1 +//! je L0_Switch +//! mov eax, [esp - 24] ; alloc var_0 +//! add eax, 1 ; add var_0, 1 +//! mov ecx, [esp - 28] ; alloc var_1 +//! add ecx, 2 ; add var_1, 2 +//! L0: +//! sub eax, ecx ; sub var_0, var_1 +//! ret +//! +//! ; state-switch begin +//! L0_Switch0: +//! mov eax, [esp - 24] ; alloc var_0 +//! mov ecx, [esp - 28] ; alloc var_1 +//! jmp short L0 +//! ; state-switch end +//! ~~~ +//! +//! You can see that the state-switch section was generated (see L0_Switch0). +//! The compiler is unable to restore state immediately when emitting the +//! forward jump (the code is generated from first to last instruction and +//! the target state is simply not known at this time). +//! +//! To tell `Compiler` that you want to embed state-switch code before jump +//! it's needed to create backward jump (where also processor expects that it +//! will be taken). To demonstrate the possibility to embed state-switch before +//! jump we use slightly modified code: +//! +//! ~~~ +//! Compiler c; +//! +//! c.addFunc(kFuncConvHost, FuncBuilder0()); +//! +//! // Labels. +//! Label L0(c); +//! +//! // Variables. +//! X86GpVar var0(c, kVarTypeInt32); +//! X86GpVar var1(c, kVarTypeInt32); +//! +//! // Cleanup. After these two lines, the var0 and var1 will be always stored +//! // in registers. Our example is very small, but in larger code the var0 can +//! // be spilled by xor(var1, var1). +//! c.xor_(var0, var0); +//! c.xor_(var1, var1); +//! // State: +//! // var0 - register. +//! // var1 - register. +//! +//! // We manually spill these variables. +//! c.spill(var0); +//! c.spill(var1); +//! // State: +//! // var0 - memory. +//! // var1 - memory. +//! +//! // Bind our label here. +//! c.bind(L0); +//! +//! // Do something, the variables will be allocated again. +//! c.add(var0, 1); +//! c.add(var1, 2); +//! // State: +//! // var0 - register. +//! // var1 - register. +//! +//! // Backward conditional jump to L0. The default behavior is that it is taken +//! // so state-change code will be embedded here. +//! c.je(L0); +//! +//! c.endFunc(); +//! ~~~ +//! +//! The output: +//! +//! ~~~ +//! xor ecx, ecx ; xor var_0, var_0 +//! xor edx, edx ; xor var_1, var_1 +//! mov [esp - 24], ecx ; spill var_0 +//! mov [esp - 28], edx ; spill var_1 +//! L2: +//! mov ecx, [esp - 24] ; alloc var_0 +//! add ecx, 1 ; add var_0, 1 +//! mov edx, [esp - 28] ; alloc var_1 +//! add edx, 2 ; add var_1, 2 +//! +//! ; state-switch begin +//! mov [esp - 24], ecx ; spill var_0 +//! mov [esp - 28], edx ; spill var_1 +//! ; state-switch end +//! +//! je short L2 +//! ret +//! ~~~ +//! +//! Please notice where the state-switch section is located. The `Compiler` +//! decided that jump is likely to be taken so the state change is embedded +//! before the conditional jump. To change this behavior into the previous +//! case it's needed to add an option (kInstOptionTaken/kInstOptionNotTaken). +//! +//! Replacing the c.je(L0) by c.taken(); c.je(L0) +//! will generate code like this: +//! +//! ~~~ +//! xor ecx, ecx ; xor var_0, var_0 +//! xor edx, edx ; xor var_1, var_1 +//! mov [esp - 24], ecx ; spill var_0 +//! mov [esp - 28], edx ; spill var_1 +//! L0: +//! mov ecx, [esp - 24] ; alloc var_0 +//! add ecx, 1 ; add var_0, a +//! mov edx, [esp - 28] ; alloc var_1 +//! add edx, 2 ; add var_1, 2 +//! je L0_Switch, 2 +//! ret +//! +//! ; state-switch begin +//! L0_Switch: +//! mov [esp - 24], ecx ; spill var_0 +//! mov [esp - 28], edx ; spill var_1 +//! jmp short L0 +//! ; state-switch end +//! ~~~ +//! +//! This section provided information about how state-change works. The +//! behavior is deterministic and it can be overridden. +//! +//! Advanced Code Generation +//! ------------------------ +//! +//! This section describes advanced method of code generation available to +//! `Compiler` (but also to `Assembler`). When emitting code to instruction +//! stream the methods like `mov()`, `add()`, `sub()` can be called directly +//! (advantage is static-type control performed also by C++ compiler) or +//! indirectly using `emit()` method. The `emit()` method needs only instruction +//! code and operands. +//! +//! Example of code generating by standard type-safe API: +//! +//! ~~~ +//! Compiler c; +//! +//! X86GpVar var0(c, kVarTypeInt32); +//! X86GpVar var1(c, kVarTypeInt32); +//! +//! ... +//! +//! c.mov(var0, 0); +//! c.add(var0, var1); +//! c.sub(var0, var1); +//! ~~~ +//! +//! The code above can be rewritten as: +//! +//! ~~~ +//! Compiler c; +//! +//! X86GpVar var0(c, kVarTypeInt32); +//! X86GpVar var1(c, kVarTypeInt32); +//! +//! ... +//! +//! c.emit(kX86InstIdMov, var0, 0); +//! c.emit(kX86InstIdAdd, var0, var1); +//! c.emit(kX86InstIdSub, var0, var1); +//! ~~~ +//! +//! The advantage of first snippet is very friendly API and type-safe control +//! that is controlled by the C++ compiler. The advantage of second snippet is +//! availability to replace or generate instruction code in different places. +//! See the next example how the `emit()` method can be used to generate abstract +//! code. +//! +//! Use case: +//! +//! ~~~ +//! bool emitArithmetic(Compiler& c, X86XmmVar& var0, X86XmmVar& var1, const char* op) { +//! uint32_t code = kInstIdNone; +//! +//! if (strcmp(op, "ADD") == 0) +//! code = kX86InstIdAddss; +//! else if (::strcmp(op, "SUBTRACT") == 0) +//! code = kX86InstIdSubss; +//! else if (::strcmp(op, "MULTIPLY") == 0) +//! code = kX86InstIdMulss; +//! else if (::strcmp(op, "DIVIDE") == 0) +//! code = kX86InstIdDivss; +//! else +//! // Invalid parameter? +//! return false; +//! +//! c.emit(code, var0, var1); +//! } +//! ~~~ +//! +//! Other use cases are waiting for you! Be sure that instruction you are +//! emitting is correct and encodable, because if not, Assembler will set +//! status code to `kErrorUnknownInst`. +struct ASMJIT_VCLASS X86Compiler : public Compiler { + ASMJIT_NO_COPY(X86Compiler) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a `X86Compiler` instance. + ASMJIT_API X86Compiler(Runtime* runtime, uint32_t arch +#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64) + = kArchHost +#endif // ASMJIT_HOST_X86 || ASMJIT_HOST_X64 + ); + + //! Destroy the `X86Compiler` instance. + ASMJIT_API ~X86Compiler(); + + // -------------------------------------------------------------------------- + // [Arch] + // -------------------------------------------------------------------------- + + //! \internal + //! + //! Set the architecture to `arch`. + ASMJIT_API Error setArch(uint32_t arch); + + //! Get count of registers of the current architecture and mode. + ASMJIT_INLINE const X86RegCount& getRegCount() const { + return _regCount; + } + + //! Get Gpd or Gpq register depending on the current architecture. + ASMJIT_INLINE X86GpReg gpz(uint32_t index) const { + return X86GpReg(zax, index); + } + + //! Create an architecture dependent intptr_t memory operand. + ASMJIT_INLINE X86Mem intptr_ptr(const X86GpReg& base, int32_t disp = 0) const { + return x86::ptr(base, disp, _regSize); + } + //! \overload + ASMJIT_INLINE X86Mem intptr_ptr(const X86GpReg& base, const X86GpReg& index, uint32_t shift = 0, int32_t disp = 0) const { + return x86::ptr(base, index, shift, disp, _regSize); + } + //! \overload + ASMJIT_INLINE X86Mem intptr_ptr(const Label& label, int32_t disp = 0) const { + return x86::ptr(label, disp, _regSize); + } + //! \overload + ASMJIT_INLINE X86Mem intptr_ptr(const Label& label, const X86GpReg& index, uint32_t shift, int32_t disp = 0) const { + return x86::ptr(label, index, shift, disp, _regSize); + } + //! \overload + ASMJIT_INLINE X86Mem intptr_ptr_abs(Ptr pAbs, int32_t disp = 0) const { + return x86::ptr_abs(pAbs, disp, _regSize); + } + //! \overload + ASMJIT_INLINE X86Mem intptr_ptr_abs(Ptr pAbs, const X86GpReg& index, uint32_t shift, int32_t disp = 0) const { + return x86::ptr_abs(pAbs, index, shift, disp, _regSize); + } + + //! \overload + ASMJIT_INLINE X86Mem intptr_ptr(const X86GpVar& base, int32_t disp = 0) { + return x86::ptr(base, disp, _regSize); + } + //! \overload + ASMJIT_INLINE X86Mem intptr_ptr(const X86GpVar& base, const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) { + return x86::ptr(base, index, shift, disp, _regSize); + } + //! \overload + ASMJIT_INLINE X86Mem intptr_ptr(const Label& label, const X86GpVar& index, uint32_t shift, int32_t disp = 0) { + return x86::ptr(label, index, shift, disp, _regSize); + } + //! \overload + ASMJIT_INLINE X86Mem intptr_ptr_abs(Ptr pAbs, const X86GpVar& index, uint32_t shift, int32_t disp = 0) { + return x86::ptr_abs(pAbs, index, shift, disp, _regSize); + } + + // -------------------------------------------------------------------------- + // [Inst / Emit] + // -------------------------------------------------------------------------- + + //! Create a new `InstNode`. + ASMJIT_API InstNode* newInst(uint32_t code); + //! \overload + ASMJIT_API InstNode* newInst(uint32_t code, const Operand& o0); + //! \overload + ASMJIT_API InstNode* newInst(uint32_t code, const Operand& o0, const Operand& o1); + //! \overload + ASMJIT_API InstNode* newInst(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2); + //! \overload + ASMJIT_API InstNode* newInst(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, const Operand& o3); + //! \overload + ASMJIT_API InstNode* newInst(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, const Operand& o3, const Operand& o4); + + //! Add a new `InstNode`. + ASMJIT_API InstNode* emit(uint32_t code); + //! \overload + ASMJIT_API InstNode* emit(uint32_t code, const Operand& o0); + //! \overload + ASMJIT_API InstNode* emit(uint32_t code, const Operand& o0, const Operand& o1); + //! \overload + ASMJIT_API InstNode* emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2); + //! \overload + ASMJIT_API InstNode* emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, const Operand& o3); + //! \overload + ASMJIT_API InstNode* emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, const Operand& o3, const Operand& o4); + + //! \overload + ASMJIT_API InstNode* emit(uint32_t code, int o0); + //! \overload + ASMJIT_API InstNode* emit(uint32_t code, uint64_t o0); + //! \overload + ASMJIT_API InstNode* emit(uint32_t code, const Operand& o0, int o1); + //! \overload + ASMJIT_API InstNode* emit(uint32_t code, const Operand& o0, uint64_t o1); + //! \overload + ASMJIT_API InstNode* emit(uint32_t code, const Operand& o0, const Operand& o1, int o2); + //! \overload + ASMJIT_API InstNode* emit(uint32_t code, const Operand& o0, const Operand& o1, uint64_t o2); + //! \overload + ASMJIT_API InstNode* emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, int o3); + //! \overload + ASMJIT_API InstNode* emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, uint64_t o3); + + // -------------------------------------------------------------------------- + // [Func] + // -------------------------------------------------------------------------- + + //! Create a new `X86FuncNode`. + ASMJIT_API X86FuncNode* newFunc(uint32_t conv, const FuncPrototype& p); + + //! Add a new function. + //! + //! \param conv Calling convention to use (see \ref kFuncConv enum) + //! \param params Function arguments prototype. + //! + //! This method is usually used as a first step when generating functions + //! by `Compiler`. First parameter `cconv` specifies function calling + //! convention to use. Second parameter `params` specifies function + //! arguments. To create function arguments are used templates + //! `FuncBuilder0<...>`, `FuncBuilder1<...>`, `FuncBuilder2<...>`, etc... + //! + //! Templates with FuncBuilder prefix are used to generate argument IDs + //! based on real C++ types. See next example how to generate function with + //! two 32-bit integer arguments. + //! + //! ~~~ + //! // Building function using asmjit::Compiler example. + //! + //! // Compiler instance + //! Compiler c; + //! + //! // Begin of function, also emits function prolog. + //! c.addFunc( + //! // Default calling convention (32-bit cdecl or 64-bit for host OS) + //! kFuncConvHost, + //! // Using function builder to generate arguments list + //! FuncBuilder2()); + //! + //! // End of function, also emits function epilog. + //! c.endFunc(); + //! ~~~ + //! + //! You can see that building functions is really easy. Previous code snipped + //! will generate code for function with two 32-bit integer arguments. You + //! can access arguments by `asmjit::Function::getArg()` method. Arguments + //! are indexed from 0 (like everything in C). + //! + //! ~~~ + //! // Accessing function arguments through asmjit::Function example. + //! + //! // Compiler instance + //! Compiler c; + //! X86GpVar a0(c, kVarTypeInt32); + //! X86GpVar a1(c, kVarTypeInt32); + //! + //! // Begin of function (also emits function prolog) + //! c.addFunc( + //! // Default calling convention (32-bit cdecl or 64-bit for host OS) + //! kFuncConvHost, + //! // Using function builder to generate arguments list + //! FuncBuilder2()); + //! + //! c.setArg(0, a0); + //! c.setArg(1, a1); + //! + //! // Use them. + //! c.add(a0, a1); + //! + //! // End of function - emits function epilog and return instruction. + //! c.endFunc(); + //! ~~~ + //! + //! Arguments are like variables. How to manipulate with variables is + //! documented in `Compiler`, variables section. + //! + //! \note To get current function use `getFunc()` method or save pointer to + //! `FuncNode` returned by `Compiler::addFunc<>` method. The recommended way + //! is saving the pointer and using it to specify function arguments and + //! return value. + //! + //! \sa FuncBuilder0, FuncBuilder1, FuncBuilder2, ... + ASMJIT_API X86FuncNode* addFunc(uint32_t conv, const FuncPrototype& p); + + //! End of current function. + ASMJIT_API EndNode* endFunc(); + + //! Get current function as `X86FuncNode`. + //! + //! This method can be called within `addFunc()` and `endFunc()` block to get + //! current function you are working with. It's recommended to store `FuncNode` + //! pointer returned by `addFunc<>` method, because this allows you in future + //! implement function sections outside of function itself. + ASMJIT_INLINE X86FuncNode* getFunc() const { + return static_cast(_func); + } + + // -------------------------------------------------------------------------- + // [Ret] + // -------------------------------------------------------------------------- + + //! Create a new `RetNode`. + ASMJIT_API RetNode* newRet(const Operand& o0, const Operand& o1); + //! Add a new `RetNode`. + ASMJIT_API RetNode* addRet(const Operand& o0, const Operand& o1); + + // -------------------------------------------------------------------------- + // [Call] + // -------------------------------------------------------------------------- + + //! Create a new `X86CallNode`. + ASMJIT_API X86CallNode* newCall(const Operand& o0, uint32_t conv, const FuncPrototype& p); + //! Add a new `X86CallNode`. + ASMJIT_API X86CallNode* addCall(const Operand& o0, uint32_t conv, const FuncPrototype& p); + + // -------------------------------------------------------------------------- + // [Vars] + // -------------------------------------------------------------------------- + + //! Set function argument to `var`. + ASMJIT_API Error setArg(uint32_t argIndex, Var& var); + + ASMJIT_API virtual Error _newVar(Var* var, uint32_t type, const char* name); + + //! Create a new Gp variable. + ASMJIT_INLINE X86GpVar newGpVar(uint32_t vType = kVarTypeIntPtr, const char* name = NULL) { + ASMJIT_ASSERT(vType < kX86VarTypeCount); + ASMJIT_ASSERT(IntUtil::inInterval(vType, _kVarTypeIntStart, _kVarTypeIntEnd)); + + X86GpVar var(NoInit); + _newVar(&var, vType, name); + return var; + } + + //! Create a new Mm variable. + ASMJIT_INLINE X86MmVar newMmVar(uint32_t vType = kX86VarTypeMm, const char* name = NULL) { + ASMJIT_ASSERT(vType < kX86VarTypeCount); + ASMJIT_ASSERT(IntUtil::inInterval(vType, _kX86VarTypeMmStart, _kX86VarTypeMmEnd)); + + X86MmVar var(NoInit); + _newVar(&var, vType, name); + return var; + } + + //! Create a new Xmm variable. + ASMJIT_INLINE X86XmmVar newXmmVar(uint32_t vType = kX86VarTypeXmm, const char* name = NULL) { + ASMJIT_ASSERT(vType < kX86VarTypeCount); + ASMJIT_ASSERT(IntUtil::inInterval(vType, _kX86VarTypeXmmStart, _kX86VarTypeXmmEnd)); + + X86XmmVar var(NoInit); + _newVar(&var, vType, name); + return var; + } + + //! Create a new Ymm variable. + ASMJIT_INLINE X86YmmVar newYmmVar(uint32_t vType = kX86VarTypeYmm, const char* name = NULL) { + ASMJIT_ASSERT(vType < kX86VarTypeCount); + ASMJIT_ASSERT(IntUtil::inInterval(vType, _kX86VarTypeYmmStart, _kX86VarTypeYmmEnd)); + + X86YmmVar var(NoInit); + _newVar(&var, vType, name); + return var; + } + + // -------------------------------------------------------------------------- + // [Stack] + // -------------------------------------------------------------------------- + + ASMJIT_API virtual Error _newStack(BaseMem* mem, uint32_t size, uint32_t alignment, const char* name); + + //! Create a new memory chunk allocated on the current function's stack. + ASMJIT_INLINE X86Mem newStack(uint32_t size, uint32_t alignment, const char* name = NULL) { + X86Mem m(NoInit); + _newStack(&m, size, alignment, name); + return m; + } + + // -------------------------------------------------------------------------- + // [Const] + // -------------------------------------------------------------------------- + + ASMJIT_API virtual Error _newConst(BaseMem* mem, uint32_t scope, const void* data, size_t size); + + //! Put data to a constant-pool and get a memory reference to it. + ASMJIT_INLINE X86Mem newConst(uint32_t scope, const void* data, size_t size) { + X86Mem m(NoInit); + _newConst(&m, scope, data, size); + return m; + } + + //! Put a BYTE `val` to a constant-pool. + ASMJIT_INLINE X86Mem newByteConst(uint32_t scope, uint8_t val) { return newConst(scope, &val, 1); } + //! Put a WORD `val` to a constant-pool. + ASMJIT_INLINE X86Mem newWordConst(uint32_t scope, uint16_t val) { return newConst(scope, &val, 2); } + //! Put a DWORD `val` to a constant-pool. + ASMJIT_INLINE X86Mem newDWordConst(uint32_t scope, uint32_t val) { return newConst(scope, &val, 4); } + //! Put a QWORD `val` to a constant-pool. + ASMJIT_INLINE X86Mem newQWordConst(uint32_t scope, uint64_t val) { return newConst(scope, &val, 8); } + + //! Put a WORD `val` to a constant-pool. + ASMJIT_INLINE X86Mem newInt16Const(uint32_t scope, int16_t val) { return newConst(scope, &val, 2); } + //! Put a WORD `val` to a constant-pool. + ASMJIT_INLINE X86Mem newUInt16Const(uint32_t scope, uint16_t val) { return newConst(scope, &val, 2); } + //! Put a DWORD `val` to a constant-pool. + ASMJIT_INLINE X86Mem newInt32Const(uint32_t scope, int32_t val) { return newConst(scope, &val, 4); } + //! Put a DWORD `val` to a constant-pool. + ASMJIT_INLINE X86Mem newUInt32Const(uint32_t scope, uint32_t val) { return newConst(scope, &val, 4); } + //! Put a QWORD `val` to a constant-pool. + ASMJIT_INLINE X86Mem newInt64Const(uint32_t scope, int64_t val) { return newConst(scope, &val, 8); } + //! Put a QWORD `val` to a constant-pool. + ASMJIT_INLINE X86Mem newUInt64Const(uint32_t scope, uint64_t val) { return newConst(scope, &val, 8); } + + //! Put a SP-FP `val` to a constant-pool. + ASMJIT_INLINE X86Mem newFloatConst(uint32_t scope, float val) { return newConst(scope, &val, 4); } + //! Put a DP-FP `val` to a constant-pool. + ASMJIT_INLINE X86Mem newDoubleConst(uint32_t scope, double val) { return newConst(scope, &val, 8); } + + //! Put a MMX `val` to a constant-pool. + ASMJIT_INLINE X86Mem newMmConst(uint32_t scope, const Vec64& val) { return newConst(scope, &val, 8); } + //! Put a XMM `val` to a constant-pool. + ASMJIT_INLINE X86Mem newXmmConst(uint32_t scope, const Vec128& val) { return newConst(scope, &val, 16); } + //! Put a YMM `val` to a constant-pool. + ASMJIT_INLINE X86Mem newYmmConst(uint32_t scope, const Vec256& val) { return newConst(scope, &val, 32); } + + // -------------------------------------------------------------------------- + // [Embed] + // -------------------------------------------------------------------------- + + //! Add 8-bit integer data to the instruction stream. + ASMJIT_INLINE EmbedNode* db(uint8_t x) { return embed(&x, 1); } + //! Add 16-bit integer data to the instruction stream. + ASMJIT_INLINE EmbedNode* dw(uint16_t x) { return embed(&x, 2); } + //! Add 32-bit integer data to the instruction stream. + ASMJIT_INLINE EmbedNode* dd(uint32_t x) { return embed(&x, 4); } + //! Add 64-bit integer data to the instruction stream. + ASMJIT_INLINE EmbedNode* dq(uint64_t x) { return embed(&x, 8); } + + //! Add 8-bit integer data to the instruction stream. + ASMJIT_INLINE EmbedNode* dint8(int8_t x) { return embed(&x, static_cast(sizeof(int8_t))); } + //! Add 8-bit integer data to the instruction stream. + ASMJIT_INLINE EmbedNode* duint8(uint8_t x) { return embed(&x, static_cast(sizeof(uint8_t))); } + + //! Add 16-bit integer data to the instruction stream. + ASMJIT_INLINE EmbedNode* dint16(int16_t x) { return embed(&x, static_cast(sizeof(int16_t))); } + //! Add 16-bit integer data to the instruction stream. + ASMJIT_INLINE EmbedNode* duint16(uint16_t x) { return embed(&x, static_cast(sizeof(uint16_t))); } + + //! Add 32-bit integer data to the instruction stream. + ASMJIT_INLINE EmbedNode* dint32(int32_t x) { return embed(&x, static_cast(sizeof(int32_t))); } + //! Add 32-bit integer data to the instruction stream. + ASMJIT_INLINE EmbedNode* duint32(uint32_t x) { return embed(&x, static_cast(sizeof(uint32_t))); } + + //! Add 64-bit integer data to the instruction stream. + ASMJIT_INLINE EmbedNode* dint64(int64_t x) { return embed(&x, static_cast(sizeof(int64_t))); } + //! Add 64-bit integer data to the instruction stream. + ASMJIT_INLINE EmbedNode* duint64(uint64_t x) { return embed(&x, static_cast(sizeof(uint64_t))); } + + //! Add float data to the instruction stream. + ASMJIT_INLINE EmbedNode* dfloat(float x) { return embed(&x, static_cast(sizeof(float))); } + //! Add double data to the instruction stream. + ASMJIT_INLINE EmbedNode* ddouble(double x) { return embed(&x, static_cast(sizeof(double))); } + + //! Add Mm data to the instruction stream. + ASMJIT_INLINE EmbedNode* dmm(const Vec64& x) { return embed(&x, static_cast(sizeof(Vec64))); } + //! Add Xmm data to the instruction stream. + ASMJIT_INLINE EmbedNode* dxmm(const Vec128& x) { return embed(&x, static_cast(sizeof(Vec128))); } + //! Add Ymm data to the instruction stream. + ASMJIT_INLINE EmbedNode* dymm(const Vec256& x) { return embed(&x, static_cast(sizeof(Vec256))); } + + //! Add data in a given structure instance to the instruction stream. + template + ASMJIT_INLINE EmbedNode* dstruct(const T& x) { return embed(&x, static_cast(sizeof(T))); } + + // -------------------------------------------------------------------------- + // [Make] + // -------------------------------------------------------------------------- + + ASMJIT_API virtual void* make(); + + // ------------------------------------------------------------------------- + // [Assembler] + // ------------------------------------------------------------------------- + + ASMJIT_API virtual Assembler* _newAssembler(); + + // ------------------------------------------------------------------------- + // [Serialize] + // ------------------------------------------------------------------------- + + ASMJIT_API virtual Error serialize(Assembler* assembler); + + // ------------------------------------------------------------------------- + // [Options] + // ------------------------------------------------------------------------- + + ASMJIT_X86_EMIT_OPTIONS(X86Compiler) + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Count of registers depending on the current architecture. + X86RegCount _regCount; + + //! EAX or RAX register depending on the current architecture. + X86GpReg zax; + //! ECX or RCX register depending on the current architecture. + X86GpReg zcx; + //! EDX or RDX register depending on the current architecture. + X86GpReg zdx; + //! EBX or RBX register depending on the current architecture. + X86GpReg zbx; + //! ESP or RSP register depending on the current architecture. + X86GpReg zsp; + //! EBP or RBP register depending on the current architecture. + X86GpReg zbp; + //! ESI or RSI register depending on the current architecture. + X86GpReg zsi; + //! EDI or RDI register depending on the current architecture. + X86GpReg zdi; + + // -------------------------------------------------------------------------- + // [Emit] + // -------------------------------------------------------------------------- + +#define INST_0x(_Inst_, _Code_) \ + ASMJIT_INLINE InstNode* _Inst_() { \ + return emit(_Code_); \ + } + +#define INST_1x(_Inst_, _Code_, _Op0_) \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0) { \ + return emit(_Code_, o0); \ + } + +#define INST_1x_(_Inst_, _Code_, _Op0_, _Cond_) \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0) { \ + ASMJIT_ASSERT(_Cond_); \ + return emit(_Code_, o0); \ + } + +#define INST_1i(_Inst_, _Code_, _Op0_) \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0) { \ + return emit(_Code_, o0); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(int o0) { \ + return emit(_Code_, o0); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(unsigned int o0) { \ + return emit(_Code_, static_cast(o0)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(int64_t o0) { \ + return emit(_Code_, static_cast(o0)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(uint64_t o0) { \ + return emit(_Code_, o0); \ + } + +#define INST_1cc(_Inst_, _Code_, _Translate_, _Op0_) \ + ASMJIT_INLINE InstNode* _Inst_(uint32_t cc, const _Op0_& o0) { \ + return emit(_Translate_(cc), o0); \ + } \ + \ + ASMJIT_INLINE InstNode* _Inst_##a(const _Op0_& o0) { return emit(_Code_##a, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##ae(const _Op0_& o0) { return emit(_Code_##ae, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##b(const _Op0_& o0) { return emit(_Code_##b, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##be(const _Op0_& o0) { return emit(_Code_##be, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##c(const _Op0_& o0) { return emit(_Code_##c, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##e(const _Op0_& o0) { return emit(_Code_##e, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##g(const _Op0_& o0) { return emit(_Code_##g, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##ge(const _Op0_& o0) { return emit(_Code_##ge, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##l(const _Op0_& o0) { return emit(_Code_##l, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##le(const _Op0_& o0) { return emit(_Code_##le, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##na(const _Op0_& o0) { return emit(_Code_##na, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##nae(const _Op0_& o0) { return emit(_Code_##nae, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##nb(const _Op0_& o0) { return emit(_Code_##nb, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##nbe(const _Op0_& o0) { return emit(_Code_##nbe, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##nc(const _Op0_& o0) { return emit(_Code_##nc, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##ne(const _Op0_& o0) { return emit(_Code_##ne, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##ng(const _Op0_& o0) { return emit(_Code_##ng, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##nge(const _Op0_& o0) { return emit(_Code_##nge, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##nl(const _Op0_& o0) { return emit(_Code_##nl, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##nle(const _Op0_& o0) { return emit(_Code_##nle, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##no(const _Op0_& o0) { return emit(_Code_##no, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##np(const _Op0_& o0) { return emit(_Code_##np, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##ns(const _Op0_& o0) { return emit(_Code_##ns, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##nz(const _Op0_& o0) { return emit(_Code_##nz, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##o(const _Op0_& o0) { return emit(_Code_##o, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##p(const _Op0_& o0) { return emit(_Code_##p, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##pe(const _Op0_& o0) { return emit(_Code_##pe, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##po(const _Op0_& o0) { return emit(_Code_##po, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##s(const _Op0_& o0) { return emit(_Code_##s, o0); } \ + ASMJIT_INLINE InstNode* _Inst_##z(const _Op0_& o0) { return emit(_Code_##z, o0); } + +#define INST_2x(_Inst_, _Code_, _Op0_, _Op1_) \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1) { \ + return emit(_Code_, o0, o1); \ + } + +#define INST_2x_(_Inst_, _Code_, _Op0_, _Op1_, _Cond_) \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1) { \ + ASMJIT_ASSERT(_Cond_); \ + return emit(_Code_, o0, o1); \ + } + +#define INST_2i(_Inst_, _Code_, _Op0_, _Op1_) \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1) { \ + return emit(_Code_, o0, o1); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, int o1) { \ + return emit(_Code_, o0, o1); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, unsigned int o1) { \ + return emit(_Code_, o0, static_cast(o1)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, int64_t o1) { \ + return emit(_Code_, o0, static_cast(o1)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, uint64_t o1) { \ + return emit(_Code_, o0, o1); \ + } + +#define INST_2cc(_Inst_, _Code_, _Translate_, _Op0_, _Op1_) \ + ASMJIT_INLINE InstNode* _Inst_(uint32_t cc, const _Op0_& o0, const _Op1_& o1) { \ + return emit(_Translate_(cc), o0, o1); \ + } \ + \ + ASMJIT_INLINE InstNode* _Inst_##a(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##a, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##ae(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##ae, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##b(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##b, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##be(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##be, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##c(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##c, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##e(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##e, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##g(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##g, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##ge(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##ge, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##l(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##l, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##le(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##le, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##na(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##na, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##nae(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##nae, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##nb(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##nb, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##nbe(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##nbe, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##nc(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##nc, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##ne(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##ne, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##ng(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##ng, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##nge(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##nge, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##nl(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##nl, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##nle(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##nle, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##no(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##no, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##np(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##np, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##ns(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##ns, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##nz(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##nz, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##o(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##o, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##p(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##p, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##pe(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##pe, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##po(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##po, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##s(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##s, o0, o1); } \ + ASMJIT_INLINE InstNode* _Inst_##z(const _Op0_& o0, const _Op1_& o1) { return emit(_Code_##z, o0, o1); } + +#define INST_3x(_Inst_, _Code_, _Op0_, _Op1_, _Op2_) \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2) { \ + return emit(_Code_, o0, o1, o2); \ + } + +#define INST_3x_(_Inst_, _Code_, _Op0_, _Op1_, _Op2_, _Cond_) \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2) { \ + ASMJIT_ASSERT(_Cond_); \ + return emit(_Code_, o0, o1, o2); \ + } + +#define INST_3i(_Inst_, _Code_, _Op0_, _Op1_, _Op2_) \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2) { \ + return emit(_Code_, o0, o1, o2); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, int o2) { \ + return emit(_Code_, o0, o1, o2); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, unsigned int o2) { \ + return emit(_Code_, o0, o1, static_cast(o2)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, int64_t o2) { \ + return emit(_Code_, o0, o1, static_cast(o2)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, uint64_t o2) { \ + return emit(_Code_, o0, o1, o2); \ + } + +#define INST_3ii(_Inst_, _Code_, _Op0_, _Op1_, _Op2_) \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2) { \ + return emit(_Code_, o0, o1, o2); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, int o1, int o2) { \ + Imm o1Imm(o1); \ + return emit(_Code_, o0, o1Imm, o2); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, unsigned int o1, unsigned int o2) { \ + Imm o1Imm(o1); \ + return emit(_Code_, o0, o1Imm, static_cast(o2)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, int64_t o1, int64_t o2) { \ + Imm o1Imm(o1); \ + return emit(_Code_, o0, o1Imm, static_cast(o2)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, uint64_t o1, uint64_t o2) { \ + Imm o1Imm(o1); \ + return emit(_Code_, o0, o1Imm, o2); \ + } + +#define INST_4x(_Inst_, _Code_, _Op0_, _Op1_, _Op2_) \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2, const _Op3_& o3) { \ + return emit(_Code_, o0, o1, o2, o3); \ + } + +#define INST_4x_(_Inst_, _Code_, _Op0_, _Op1_, _Op2_, _Cond_) \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2, const _Op3_& o3) { \ + ASMJIT_ASSERT(_Cond_); \ + return emit(_Code_, o0, o1, o2, o3); \ + } + +#define INST_4i(_Inst_, _Code_, _Op0_, _Op1_, _Op2_) \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2, const _Op3_& o3) { \ + return emit(_Code_, o0, o1, o2, o3); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2, int o3) { \ + return emit(_Code_, o0, o1, o2, o3); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2, unsigned int o3) { \ + return emit(_Code_, o0, o1, o2, static_cast(o3)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2, int64_t o3) { \ + return emit(_Code_, o0, o1, o2, static_cast(o3)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2, uint64_t o3) { \ + return emit(_Code_, o0, o1, o2, o3); \ + } + +#define INST_4ii(_Inst_, _Code_, _Op0_, _Op1_, _Op2_, _Op3_) \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, const _Op2_& o2, const _Op3_& o3) { \ + return emit(_Code_, o0, o1, o2, o3); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, int o2, int o3) { \ + Imm o2Imm(o2); \ + return emit(_Code_, o0, o1, o2Imm, o3); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, unsigned int o2, unsigned int o3) { \ + Imm o2Imm(o2); \ + return emit(_Code_, o0, o1, o2Imm, static_cast(o3)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, int64_t o2, int64_t o3) { \ + Imm o2Imm(o2); \ + return emit(_Code_, o0, o1, o2Imm, static_cast(o3)); \ + } \ + /*! \overload */ \ + ASMJIT_INLINE InstNode* _Inst_(const _Op0_& o0, const _Op1_& o1, uint64_t o2, uint64_t o3) { \ + Imm o2Imm(o2); \ + return emit(_Code_, o0, o1, o2Imm, o3); \ + } + + // -------------------------------------------------------------------------- + // [X86/X64] + // -------------------------------------------------------------------------- + + //! Add with carry. + INST_2x(adc, kX86InstIdAdc, X86GpVar, X86GpVar) + //! \overload + INST_2x(adc, kX86InstIdAdc, X86GpVar, X86Mem) + //! \overload + INST_2i(adc, kX86InstIdAdc, X86GpVar, Imm) + //! \overload + INST_2x(adc, kX86InstIdAdc, X86Mem, X86GpVar) + //! \overload + INST_2i(adc, kX86InstIdAdc, X86Mem, Imm) + + //! Add. + INST_2x(add, kX86InstIdAdd, X86GpVar, X86GpVar) + //! \overload + INST_2x(add, kX86InstIdAdd, X86GpVar, X86Mem) + //! \overload + INST_2i(add, kX86InstIdAdd, X86GpVar, Imm) + //! \overload + INST_2x(add, kX86InstIdAdd, X86Mem, X86GpVar) + //! \overload + INST_2i(add, kX86InstIdAdd, X86Mem, Imm) + + //! And. + INST_2x(and_, kX86InstIdAnd, X86GpVar, X86GpVar) + //! \overload + INST_2x(and_, kX86InstIdAnd, X86GpVar, X86Mem) + //! \overload + INST_2i(and_, kX86InstIdAnd, X86GpVar, Imm) + //! \overload + INST_2x(and_, kX86InstIdAnd, X86Mem, X86GpVar) + //! \overload + INST_2i(and_, kX86InstIdAnd, X86Mem, Imm) + + //! Bit scan forward. + INST_2x_(bsf, kX86InstIdBsf, X86GpVar, X86GpVar, !o0.isGpb()) + //! \overload + INST_2x_(bsf, kX86InstIdBsf, X86GpVar, X86Mem, !o0.isGpb()) + + //! Bit scan reverse. + INST_2x_(bsr, kX86InstIdBsr, X86GpVar, X86GpVar, !o0.isGpb()) + //! \overload + INST_2x_(bsr, kX86InstIdBsr, X86GpVar, X86Mem, !o0.isGpb()) + + //! Byte swap (32-bit or 64-bit registers only) (i486). + INST_1x_(bswap, kX86InstIdBswap, X86GpVar, o0.getSize() >= 4) + + //! Bit test. + INST_2x(bt, kX86InstIdBt, X86GpVar, X86GpVar) + //! \overload + INST_2i(bt, kX86InstIdBt, X86GpVar, Imm) + //! \overload + INST_2x(bt, kX86InstIdBt, X86Mem, X86GpVar) + //! \overload + INST_2i(bt, kX86InstIdBt, X86Mem, Imm) + + //! Bit test and complement. + INST_2x(btc, kX86InstIdBtc, X86GpVar, X86GpVar) + //! \overload + INST_2i(btc, kX86InstIdBtc, X86GpVar, Imm) + //! \overload + INST_2x(btc, kX86InstIdBtc, X86Mem, X86GpVar) + //! \overload + INST_2i(btc, kX86InstIdBtc, X86Mem, Imm) + + //! Bit test and reset. + INST_2x(btr, kX86InstIdBtr, X86GpVar, X86GpVar) + //! \overload + INST_2i(btr, kX86InstIdBtr, X86GpVar, Imm) + //! \overload + INST_2x(btr, kX86InstIdBtr, X86Mem, X86GpVar) + //! \overload + INST_2i(btr, kX86InstIdBtr, X86Mem, Imm) + + //! Bit test and set. + INST_2x(bts, kX86InstIdBts, X86GpVar, X86GpVar) + //! \overload + INST_2i(bts, kX86InstIdBts, X86GpVar, Imm) + //! \overload + INST_2x(bts, kX86InstIdBts, X86Mem, X86GpVar) + //! \overload + INST_2i(bts, kX86InstIdBts, X86Mem, Imm) + + //! Call a function. + ASMJIT_INLINE X86CallNode* call(const X86GpVar& dst, uint32_t conv, const FuncPrototype& p) { + return addCall(dst, conv, p); + } + //! \overload + ASMJIT_INLINE X86CallNode* call(const X86Mem& dst, uint32_t conv, const FuncPrototype& p) { + return addCall(dst, conv, p); + } + //! \overload + ASMJIT_INLINE X86CallNode* call(const Label& label, uint32_t conv, const FuncPrototype& p) { + return addCall(label, conv, p); + } + //! \overload + ASMJIT_INLINE X86CallNode* call(const Imm& dst, uint32_t conv, const FuncPrototype& p) { + return addCall(dst, conv, p); + } + //! \overload + ASMJIT_INLINE X86CallNode* call(Ptr dst, uint32_t conv, const FuncPrototype& p) { + return addCall(Imm(dst), conv, p); + } + + //! Clear carry flag + INST_0x(clc, kX86InstIdClc) + //! Clear direction flag + INST_0x(cld, kX86InstIdCld) + //! Complement carry Flag. + INST_0x(cmc, kX86InstIdCmc) + + //! Convert BYTE to WORD (AX <- Sign Extend AL). + INST_1x(cbw, kX86InstIdCbw, X86GpVar /* al */) + //! Convert DWORD to QWORD (EDX:EAX <- Sign Extend EAX). + INST_2x(cdq, kX86InstIdCdq, X86GpVar /* edx */, X86GpVar /* eax */) + //! Convert DWORD to QWORD (RAX <- Sign Extend EAX) (X64 Only). + INST_1x(cdqe, kX86InstIdCdqe, X86GpVar /* eax */) + //! Convert QWORD to OWORD (RDX:RAX <- Sign Extend RAX) (X64 Only). + INST_2x(cqo, kX86InstIdCdq, X86GpVar /* rdx */, X86GpVar /* rax */) + //! Convert WORD to DWORD (DX:AX <- Sign Extend AX). + INST_2x(cwd, kX86InstIdCwd, X86GpVar /* dx */, X86GpVar /* ax */) + //! Convert WORD to DWORD (EAX <- Sign Extend AX). + INST_1x(cwde, kX86InstIdCwde, X86GpVar /* eax */) + + //! Conditional move. + INST_2cc(cmov, kX86InstIdCmov, X86Util::condToCmovcc, X86GpVar, X86GpVar) + //! Conditional move. + INST_2cc(cmov, kX86InstIdCmov, X86Util::condToCmovcc, X86GpVar, X86Mem) + + //! Compare two operands. + INST_2x(cmp, kX86InstIdCmp, X86GpVar, X86GpVar) + //! \overload + INST_2x(cmp, kX86InstIdCmp, X86GpVar, X86Mem) + //! \overload + INST_2i(cmp, kX86InstIdCmp, X86GpVar, Imm) + //! \overload + INST_2x(cmp, kX86InstIdCmp, X86Mem, X86GpVar) + //! \overload + INST_2i(cmp, kX86InstIdCmp, X86Mem, Imm) + + //! Compare BYTE in ES:`o0` and DS:`o1`. + INST_2x(cmpsb, kX86InstIdCmpsB, X86GpVar, X86GpVar) + //! Compare DWORD in ES:`o0` and DS:`o1`. + INST_2x(cmpsd, kX86InstIdCmpsD, X86GpVar, X86GpVar) + //! Compare QWORD in ES:`o0` and DS:`o1` (X64 Only). + INST_2x(cmpsq, kX86InstIdCmpsQ, X86GpVar, X86GpVar) + //! Compare WORD in ES:`o0` and DS:`o1`. + INST_2x(cmpsw, kX86InstIdCmpsW, X86GpVar, X86GpVar) + + //! Compare and exchange (i486). + INST_3x(cmpxchg, kX86InstIdCmpxchg, X86GpVar /* eax */, X86GpVar, X86GpVar) + //! \overload + INST_3x(cmpxchg, kX86InstIdCmpxchg, X86GpVar /* eax */, X86Mem, X86GpVar) + + //! Compare and exchange 128-bit value in RDX:RAX with `x_mem` (X64 Only). + ASMJIT_INLINE InstNode* cmpxchg16b( + const X86GpVar& r_edx, const X86GpVar& r_eax, + const X86GpVar& r_ecx, const X86GpVar& r_ebx, + const X86Mem& x_mem) { + + return emit(kX86InstIdCmpxchg16b, r_edx, r_eax, r_ecx, r_ebx, x_mem); + } + + //! Compare and exchange 64-bit value in EDX:EAX with `x_mem` (Pentium). + ASMJIT_INLINE InstNode* cmpxchg8b( + const X86GpVar& r_edx, const X86GpVar& r_eax, + const X86GpVar& r_ecx, const X86GpVar& r_ebx, + const X86Mem& x_mem) { + + return emit(kX86InstIdCmpxchg8b, r_edx, r_eax, r_ecx, r_ebx, x_mem); + } + + //! CPU identification (i486). + ASMJIT_INLINE InstNode* cpuid( + const X86GpVar& x_eax, + const X86GpVar& w_ebx, + const X86GpVar& x_ecx, + const X86GpVar& w_edx) { + + // Destination variables must be different. + ASMJIT_ASSERT(x_eax.getId() != w_ebx.getId() && + w_ebx.getId() != x_ecx.getId() && + x_ecx.getId() != w_edx.getId()); + + return emit(kX86InstIdCpuid, x_eax, w_ebx, x_ecx, w_edx); + } + + //! Decimal adjust AL after addition (X86 Only). + INST_1x(daa, kX86InstIdDaa, X86GpVar) + //! Decimal adjust AL after subtraction (X86 Only). + INST_1x(das, kX86InstIdDas, X86GpVar) + + //! Decrement by 1. + INST_1x(dec, kX86InstIdDec, X86GpVar) + //! \overload + INST_1x(dec, kX86InstIdDec, X86Mem) + + //! Unsigned divide (o0:o1 <- o0:o1 / o2). + //! + //! Remainder is stored in `o0`, quotient is stored in `o1`. + INST_3x_(div, kX86InstIdDiv, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId()) + //! \overload + INST_3x_(div, kX86InstIdDiv, X86GpVar, X86GpVar, X86Mem, o0.getId() != o1.getId()) + + //! Signed divide (o0:o1 <- o0:o1 / o2). + //! + //! Remainder is stored in `o0`, quotient is stored in `o1`. + INST_3x_(idiv, kX86InstIdIdiv, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId()) + //! \overload + INST_3x_(idiv, kX86InstIdIdiv, X86GpVar, X86GpVar, X86Mem, o0.getId() != o1.getId()) + + //! Signed multiply (o0:o1 <- o1 * o2). + //! + //! Hi value is stored in `o0`, lo value is stored in `o1`. + INST_3x_(imul, kX86InstIdImul, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId()) + //! \overload + INST_3x_(imul, kX86InstIdImul, X86GpVar, X86GpVar, X86Mem, o0.getId() != o1.getId()) + + //! Signed multiply. + INST_2x(imul, kX86InstIdImul, X86GpVar, X86GpVar) + //! \overload + INST_2x(imul, kX86InstIdImul, X86GpVar, X86Mem) + //! \overload + INST_2i(imul, kX86InstIdImul, X86GpVar, Imm) + + //! Signed multiply. + INST_3i(imul, kX86InstIdImul, X86GpVar, X86GpVar, Imm) + //! \overload + INST_3i(imul, kX86InstIdImul, X86GpVar, X86Mem, Imm) + + //! Increment by 1. + INST_1x(inc, kX86InstIdInc, X86GpVar) + //! \overload + INST_1x(inc, kX86InstIdInc, X86Mem) + + //! Interrupt. + INST_1i(int_, kX86InstIdInt, Imm) + //! Interrupt 3 - trap to debugger. + ASMJIT_INLINE InstNode* int3() { return int_(3); } + + //! Jump to label `label` if condition `cc` is met. + INST_1cc(j, kX86InstIdJ, X86Util::condToJcc, Label) + + //! Short jump if CX/ECX/RCX is zero. + INST_2x(jecxz, kX86InstIdJecxz, X86GpVar, Label) + + //! Jump. + INST_1x(jmp, kX86InstIdJmp, X86GpVar) + //! \overload + INST_1x(jmp, kX86InstIdJmp, X86Mem) + //! \overload + INST_1x(jmp, kX86InstIdJmp, Label) + //! \overload + INST_1x(jmp, kX86InstIdJmp, Imm) + //! \overload + ASMJIT_INLINE InstNode* jmp(Ptr dst) { return jmp(Imm(dst)); } + + //! Load AH from flags. + INST_1x(lahf, kX86InstIdLahf, X86GpVar) + + //! Load effective address + INST_2x(lea, kX86InstIdLea, X86GpVar, X86Mem) + + //! Load BYTE from DS:`o1` to `o0`. + INST_2x(lodsb, kX86InstIdLodsB, X86GpVar, X86GpVar) + //! Load DWORD from DS:`o1` to `o0`. + INST_2x(lodsd, kX86InstIdLodsD, X86GpVar, X86GpVar) + //! Load QWORD from DS:`o1` to `o0` (X64 Only). + INST_2x(lodsq, kX86InstIdLodsQ, X86GpVar, X86GpVar) + //! Load WORD from DS:`o1` to `o0`. + INST_2x(lodsw, kX86InstIdLodsW, X86GpVar, X86GpVar) + + //! Move. + INST_2x(mov, kX86InstIdMov, X86GpVar, X86GpVar) + //! \overload + INST_2x(mov, kX86InstIdMov, X86GpVar, X86Mem) + //! \overload + INST_2i(mov, kX86InstIdMov, X86GpVar, Imm) + //! \overload + INST_2x(mov, kX86InstIdMov, X86Mem, X86GpVar) + //! \overload + INST_2i(mov, kX86InstIdMov, X86Mem, Imm) + + //! Move from segment register. + INST_2x(mov, kX86InstIdMov, X86GpVar, X86SegReg) + //! \overload + INST_2x(mov, kX86InstIdMov, X86Mem, X86SegReg) + //! Move to segment register. + INST_2x(mov, kX86InstIdMov, X86SegReg, X86GpVar) + //! \overload + INST_2x(mov, kX86InstIdMov, X86SegReg, X86Mem) + + //! Move (AL|AX|EAX|RAX <- absolute address in immediate). + INST_2x(mov_ptr, kX86InstIdMovPtr, X86GpReg, Imm); + //! \overload + ASMJIT_INLINE InstNode* mov_ptr(const X86GpReg& o0, Ptr o1) { + ASMJIT_ASSERT(o0.getRegIndex() == 0); + return emit(kX86InstIdMovPtr, o0, Imm(o1)); + } + + //! Move (absolute address in immediate <- AL|AX|EAX|RAX). + INST_2x(mov_ptr, kX86InstIdMovPtr, Imm, X86GpReg); + //! \overload + ASMJIT_INLINE InstNode* mov_ptr(Ptr o0, const X86GpReg& o1) { + ASMJIT_ASSERT(o1.getRegIndex() == 0); + return emit(kX86InstIdMovPtr, Imm(o0), o1); + } + + //! Move data after swapping bytes (SSE3 - Atom). + INST_2x_(movbe, kX86InstIdMovbe, X86GpVar, X86Mem, !o0.isGpb()); + //! \overload + INST_2x_(movbe, kX86InstIdMovbe, X86Mem, X86GpVar, !o1.isGpb()); + + //! Load BYTE from DS:`o1` to ES:`o0`. + INST_2x(movsb, kX86InstIdMovsB, X86GpVar, X86GpVar) + //! Load DWORD from DS:`o1` to ES:`o0`. + INST_2x(movsd, kX86InstIdMovsD, X86GpVar, X86GpVar) + //! Load QWORD from DS:`o1` to ES:`o0` (X64 Only). + INST_2x(movsq, kX86InstIdMovsQ, X86GpVar, X86GpVar) + //! Load WORD from DS:`o1` to ES:`o0`. + INST_2x(movsw, kX86InstIdMovsW, X86GpVar, X86GpVar) + + //! Move with sign-extension. + INST_2x(movsx, kX86InstIdMovsx, X86GpVar, X86GpVar) + //! \overload + INST_2x(movsx, kX86InstIdMovsx, X86GpVar, X86Mem) + + //! Move DWORD to QWORD with sign-extension (X64 Only). + INST_2x(movsxd, kX86InstIdMovsxd, X86GpVar, X86GpVar) + //! \overload + INST_2x(movsxd, kX86InstIdMovsxd, X86GpVar, X86Mem) + + //! Move with zero-extension. + INST_2x(movzx, kX86InstIdMovzx, X86GpVar, X86GpVar) + //! \overload + INST_2x(movzx, kX86InstIdMovzx, X86GpVar, X86Mem) + + //! Unsigned multiply (o0:o1 <- o1 * o2). + INST_3x_(mul, kX86InstIdMul, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId()) + //! \overload + INST_3x_(mul, kX86InstIdMul, X86GpVar, X86GpVar, X86Mem, o0.getId() != o1.getId()) + + //! Two's complement negation. + INST_1x(neg, kX86InstIdNeg, X86GpVar) + //! \overload + INST_1x(neg, kX86InstIdNeg, X86Mem) + + //! No operation. + INST_0x(nop, kX86InstIdNop) + + //! One's complement negation. + INST_1x(not_, kX86InstIdNot, X86GpVar) + //! \overload + INST_1x(not_, kX86InstIdNot, X86Mem) + + //! Or. + INST_2x(or_, kX86InstIdOr, X86GpVar, X86GpVar) + //! \overload + INST_2x(or_, kX86InstIdOr, X86GpVar, X86Mem) + //! \overload + INST_2i(or_, kX86InstIdOr, X86GpVar, Imm) + //! \overload + INST_2x(or_, kX86InstIdOr, X86Mem, X86GpVar) + //! \overload + INST_2i(or_, kX86InstIdOr, X86Mem, Imm) + + //! Pop a value from the stack. + INST_1x_(pop, kX86InstIdPop, X86GpVar, o0.getSize() == 2 || o0.getSize() == _regSize) + //! \overload + INST_1x_(pop, kX86InstIdPop, X86Mem, o0.getSize() == 2 || o0.getSize() == _regSize) + + //! Pop stack into EFLAGS Register (32-bit or 64-bit). + INST_0x(popf, kX86InstIdPopf) + + //! Push WORD or DWORD/QWORD on the stack. + INST_1x_(push, kX86InstIdPush, X86GpVar, o0.getSize() == 2 || o0.getSize() == _regSize) + //! Push WORD or DWORD/QWORD on the stack. + INST_1x_(push, kX86InstIdPush, X86Mem,o0.getSize() == 2 || o0.getSize() == _regSize) + //! Push segment register on the stack. + INST_1x(push, kX86InstIdPush, X86SegReg) + //! Push WORD or DWORD/QWORD on the stack. + INST_1i(push, kX86InstIdPush, Imm) + + //! Push EFLAGS register (32-bit or 64-bit) on the stack. + INST_0x(pushf, kX86InstIdPushf) + + //! Rotate bits left. + INST_2x(rcl, kX86InstIdRcl, X86GpVar, X86GpVar) + //! \overload + INST_2x(rcl, kX86InstIdRcl, X86Mem, X86GpVar) + //! Rotate bits left. + INST_2i(rcl, kX86InstIdRcl, X86GpVar, Imm) + //! \overload + INST_2i(rcl, kX86InstIdRcl, X86Mem, Imm) + + //! Rotate bits right. + INST_2x(rcr, kX86InstIdRcr, X86GpVar, X86GpVar) + //! \overload + INST_2x(rcr, kX86InstIdRcr, X86Mem, X86GpVar) + //! Rotate bits right. + INST_2i(rcr, kX86InstIdRcr, X86GpVar, Imm) + //! \overload + INST_2i(rcr, kX86InstIdRcr, X86Mem, Imm) + + //! Read time-stamp counter (Pentium). + INST_2x_(rdtsc, kX86InstIdRdtsc, X86GpVar, X86GpVar, o0.getId() != o1.getId()) + //! Read time-stamp counter and processor id (Pentium). + INST_3x_(rdtscp, kX86InstIdRdtscp, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + + //! Repeated load ECX/RCX BYTEs from DS:[ESI/RSI] to AL. + INST_3x_(rep_lodsb, kX86InstIdRepLodsB, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated load ECX/RCX DWORDs from DS:[ESI/RSI] to AL. + INST_3x_(rep_lodsd, kX86InstIdRepLodsD, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated load ECX/RCX QWORDs from DS:[RSI] to RAX (X64 Only). + INST_3x_(rep_lodsq, kX86InstIdRepLodsQ, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated load ECX/RCX WORDs from DS:[ESI/RSI] to AX. + INST_3x_(rep_lodsw, kX86InstIdRepLodsW, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + + //! Repeated move ECX/RCX BYTEs from DS:[ESI/RSI] to ES:[EDI/RDI]. + INST_3x_(rep_movsb, kX86InstIdRepMovsB, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated move ECX/RCX DWORDs from DS:[ESI/RSI] to ES:[EDI/RDI]. + INST_3x_(rep_movsd, kX86InstIdRepMovsD, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated move ECX/RCX QWORDs from DS:[RSI] to ES:[RDI] (X64 Only). + INST_3x_(rep_movsq, kX86InstIdRepMovsQ, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated move ECX/RCX DWORDs from DS:[ESI/RSI] to ES:[EDI/RDI]. + INST_3x_(rep_movsw, kX86InstIdRepMovsW, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + + //! Repeated fill ECX/RCX BYTEs at ES:[EDI/RDI] with AL. + INST_3x_(rep_stosb, kX86InstIdRepStosB, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated fill ECX/RCX DWORDs at ES:[EDI/RDI] with EAX. + INST_3x_(rep_stosd, kX86InstIdRepStosD, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated fill ECX/RCX QWORDs at ES:[RDI] with RAX (X64 Only). + INST_3x_(rep_stosq, kX86InstIdRepStosQ, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated fill ECX/RCX WORDs at ES:[EDI/RDI] with AX. + INST_3x_(rep_stosw, kX86InstIdRepStosW, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + + //! Repeated find non-AL BYTEs in ES:[EDI/RDI] and DS:[ESI/RDI]. + INST_3x_(repe_cmpsb, kX86InstIdRepeCmpsB, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated find non-EAX DWORDs in ES:[EDI/RDI] and DS:[ESI/RDI]. + INST_3x_(repe_cmpsd, kX86InstIdRepeCmpsD, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated find non-RAX QWORDs in ES:[RDI] and DS:[RDI] (X64 Only). + INST_3x_(repe_cmpsq, kX86InstIdRepeCmpsQ, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated find non-AX WORDs in ES:[EDI/RDI] and DS:[ESI/RDI]. + INST_3x_(repe_cmpsw, kX86InstIdRepeCmpsW, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + + //! Repeated find non-AL BYTE starting at ES:[EDI/RDI]. + INST_3x_(repe_scasb, kX86InstIdRepeScasB, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated find non-EAX DWORD starting at ES:[EDI/RDI]. + INST_3x_(repe_scasd, kX86InstIdRepeScasD, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated find non-RAX QWORD starting at ES:[RDI] (X64 Only). + INST_3x_(repe_scasq, kX86InstIdRepeScasQ, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated find non-AX WORD starting at ES:[EDI/RDI]. + INST_3x_(repe_scasw, kX86InstIdRepeScasW, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + + //! Repeated find AL BYTEs in [RDI] and [RSI]. + INST_3x_(repne_cmpsb, kX86InstIdRepneCmpsB, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated find EAX DWORDs in [RDI] and [RSI]. + INST_3x_(repne_cmpsd, kX86InstIdRepneCmpsD, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated find RAX QWORDs in [RDI] and [RSI] (X64 Only). + INST_3x_(repne_cmpsq, kX86InstIdRepneCmpsQ, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated find AX WORDs in [RDI] and [RSI]. + INST_3x_(repne_cmpsw, kX86InstIdRepneCmpsW, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + + //! Repeated Find AL BYTEs, starting at ES:[EDI/RDI]. + INST_3x_(repne_scasb, kX86InstIdRepneScasB, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated find EAX DWORDs, starting at ES:[EDI/RDI]. + INST_3x_(repne_scasd, kX86InstIdRepneScasD, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated find RAX QWORDs, starting at ES:[RDI] (X64 Only). + INST_3x_(repne_scasq, kX86InstIdRepneScasQ, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + //! Repeated find AX WORDs, starting at ES:[EDI/RDI]. + INST_3x_(repne_scasw, kX86InstIdRepneScasW, X86GpVar, X86GpVar, X86GpVar, o0.getId() != o1.getId() && o1.getId() != o2.getId()) + + //! Return. + ASMJIT_INLINE RetNode* ret() { return addRet(noOperand, noOperand); } + //! \overload + ASMJIT_INLINE RetNode* ret(const X86GpVar& o0) { return addRet(o0, noOperand); } + //! \overload + ASMJIT_INLINE RetNode* ret(const X86GpVar& o0, const X86GpVar& o1) { return addRet(o0, o1); } + //! \overload + ASMJIT_INLINE RetNode* ret(const X86XmmVar& o0) { return addRet(o0, noOperand); } + //! \overload + ASMJIT_INLINE RetNode* ret(const X86XmmVar& o0, const X86XmmVar& o1) { return addRet(o0, o1); } + + //! Rotate bits left. + INST_2x(rol, kX86InstIdRol, X86GpVar, X86GpVar) + //! \overload + INST_2x(rol, kX86InstIdRol, X86Mem, X86GpVar) + //! Rotate bits left. + INST_2i(rol, kX86InstIdRol, X86GpVar, Imm) + //! \overload + INST_2i(rol, kX86InstIdRol, X86Mem, Imm) + + //! Rotate bits right. + INST_2x(ror, kX86InstIdRor, X86GpVar, X86GpVar) + //! \overload + INST_2x(ror, kX86InstIdRor, X86Mem, X86GpVar) + //! Rotate bits right. + INST_2i(ror, kX86InstIdRor, X86GpVar, Imm) + //! \overload + INST_2i(ror, kX86InstIdRor, X86Mem, Imm) + + //! Store `a` (allocated in AH/AX/EAX/RAX) into Flags. + INST_1x(sahf, kX86InstIdSahf, X86GpVar) + + //! Integer subtraction with borrow. + INST_2x(sbb, kX86InstIdSbb, X86GpVar, X86GpVar) + //! \overload + INST_2x(sbb, kX86InstIdSbb, X86GpVar, X86Mem) + //! \overload + INST_2i(sbb, kX86InstIdSbb, X86GpVar, Imm) + //! \overload + INST_2x(sbb, kX86InstIdSbb, X86Mem, X86GpVar) + //! \overload + INST_2i(sbb, kX86InstIdSbb, X86Mem, Imm) + + //! Shift bits left. + INST_2x(sal, kX86InstIdSal, X86GpVar, X86GpVar) + //! \overload + INST_2x(sal, kX86InstIdSal, X86Mem, X86GpVar) + //! Shift bits left. + INST_2i(sal, kX86InstIdSal, X86GpVar, Imm) + //! \overload + INST_2i(sal, kX86InstIdSal, X86Mem, Imm) + + //! Shift bits right. + INST_2x(sar, kX86InstIdSar, X86GpVar, X86GpVar) + //! \overload + INST_2x(sar, kX86InstIdSar, X86Mem, X86GpVar) + //! Shift bits right. + INST_2i(sar, kX86InstIdSar, X86GpVar, Imm) + //! \overload + INST_2i(sar, kX86InstIdSar, X86Mem, Imm) + + //! Find non `o1` BYTE starting at ES:`o0`. + INST_2x(scasb, kX86InstIdScasB, X86GpVar, X86GpVar) + //! Find non `o1` DWORD starting at ES:`o0`. + INST_2x(scasd, kX86InstIdScasD, X86GpVar, X86GpVar) + //! Find non `o1` QWORD starting at ES:`o0` (X64 Only). + INST_2x(scasq, kX86InstIdScasQ, X86GpVar, X86GpVar) + //! Find non `o1` WORD starting at ES:`o0`. + INST_2x(scasw, kX86InstIdScasW, X86GpVar, X86GpVar) + + //! Set byte on condition. + INST_1cc(set, kX86InstIdSet, X86Util::condToSetcc, X86GpVar) + //! Set byte on condition. + INST_1cc(set, kX86InstIdSet, X86Util::condToSetcc, X86Mem) + + //! Shift bits left. + INST_2x(shl, kX86InstIdShl, X86GpVar, X86GpVar) + //! \overload + INST_2x(shl, kX86InstIdShl, X86Mem, X86GpVar) + //! Shift bits left. + INST_2i(shl, kX86InstIdShl, X86GpVar, Imm) + //! \overload + INST_2i(shl, kX86InstIdShl, X86Mem, Imm) + + //! Shift bits right. + INST_2x(shr, kX86InstIdShr, X86GpVar, X86GpVar) + //! \overload + INST_2x(shr, kX86InstIdShr, X86Mem, X86GpVar) + //! Shift bits right. + INST_2i(shr, kX86InstIdShr, X86GpVar, Imm) + //! \overload + INST_2i(shr, kX86InstIdShr, X86Mem, Imm) + + //! Double precision shift left. + INST_3x(shld, kX86InstIdShld, X86GpVar, X86GpVar, X86GpVar) + //! \overload + INST_3x(shld, kX86InstIdShld, X86Mem, X86GpVar, X86GpVar) + //! Double precision shift left. + INST_3i(shld, kX86InstIdShld, X86GpVar, X86GpVar, Imm) + //! \overload + INST_3i(shld, kX86InstIdShld, X86Mem, X86GpVar, Imm) + + //! Double precision shift right. + INST_3x(shrd, kX86InstIdShrd, X86GpVar, X86GpVar, X86GpVar) + //! \overload + INST_3x(shrd, kX86InstIdShrd, X86Mem, X86GpVar, X86GpVar) + //! Double precision shift right. + INST_3i(shrd, kX86InstIdShrd, X86GpVar, X86GpVar, Imm) + //! \overload + INST_3i(shrd, kX86InstIdShrd, X86Mem, X86GpVar, Imm) + + //! Set carry flag to 1. + INST_0x(stc, kX86InstIdStc) + //! Set direction flag to 1. + INST_0x(std, kX86InstIdStd) + + //! Fill BYTE at ES:`o0` with `o1`. + INST_2x(stosb, kX86InstIdStosB, X86GpVar, X86GpVar) + //! Fill DWORD at ES:`o0` with `o1`. + INST_2x(stosd, kX86InstIdStosD, X86GpVar, X86GpVar) + //! Fill QWORD at ES:`o0` with `o1` (X64 Only). + INST_2x(stosq, kX86InstIdStosQ, X86GpVar, X86GpVar) + //! Fill WORD at ES:`o0` with `o1`. + INST_2x(stosw, kX86InstIdStosW, X86GpVar, X86GpVar) + + //! Subtract. + INST_2x(sub, kX86InstIdSub, X86GpVar, X86GpVar) + //! \overload + INST_2x(sub, kX86InstIdSub, X86GpVar, X86Mem) + //! \overload + INST_2i(sub, kX86InstIdSub, X86GpVar, Imm) + //! \overload + INST_2x(sub, kX86InstIdSub, X86Mem, X86GpVar) + //! \overload + INST_2i(sub, kX86InstIdSub, X86Mem, Imm) + + //! Logical compare. + INST_2x(test, kX86InstIdTest, X86GpVar, X86GpVar) + //! \overload + INST_2i(test, kX86InstIdTest, X86GpVar, Imm) + //! \overload + INST_2x(test, kX86InstIdTest, X86Mem, X86GpVar) + //! \overload + INST_2i(test, kX86InstIdTest, X86Mem, Imm) + + //! Undefined instruction - Raise #UD exception. + INST_0x(ud2, kX86InstIdUd2) + + //! Exchange and add. + INST_2x(xadd, kX86InstIdXadd, X86GpVar, X86GpVar) + //! \overload + INST_2x(xadd, kX86InstIdXadd, X86Mem, X86GpVar) + + //! Exchange register/memory with register. + INST_2x(xchg, kX86InstIdXchg, X86GpVar, X86GpVar) + //! \overload + INST_2x(xchg, kX86InstIdXchg, X86Mem, X86GpVar) + //! \overload + INST_2x(xchg, kX86InstIdXchg, X86GpVar, X86Mem) + + //! Xor. + INST_2x(xor_, kX86InstIdXor, X86GpVar, X86GpVar) + //! \overload + INST_2x(xor_, kX86InstIdXor, X86GpVar, X86Mem) + //! \overload + INST_2i(xor_, kX86InstIdXor, X86GpVar, Imm) + //! \overload + INST_2x(xor_, kX86InstIdXor, X86Mem, X86GpVar) + //! \overload + INST_2i(xor_, kX86InstIdXor, X86Mem, Imm) + + // -------------------------------------------------------------------------- + // [FPU] + // -------------------------------------------------------------------------- + + //! Compute `2^x - 1` - `fp0 = POW(2, fp0) - 1` (FPU). + INST_0x(f2xm1, kX86InstIdF2xm1) + //! Abs `fp0 = ABS(fp0)` (FPU). + INST_0x(fabs, kX86InstIdFabs) + + //! Add `o0 = o0 + o1` (one operand has to be `fp0`) (FPU). + INST_2x_(fadd, kX86InstIdFadd, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0) + //! Add `fp0 = fp0 + float_or_double[o0]` (FPU). + INST_1x(fadd, kX86InstIdFadd, X86Mem) + //! Add `o0 = o0 + fp0` and POP (FPU). + INST_1x(faddp, kX86InstIdFaddp, X86FpReg) + //! Add `fp1 = fp1 + fp0` and POP (FPU). + INST_0x(faddp, kX86InstIdFaddp) + + //! Load BCD from `[o0]` and PUSH (FPU). + INST_1x(fbld, kX86InstIdFbld, X86Mem) + //! Store BCD-Integer to `[o0]` and POP (FPU). + INST_1x(fbstp, kX86InstIdFbstp, X86Mem) + + //! Complement Sign `fp0 = -fp0` (FPU). + INST_0x(fchs, kX86InstIdFchs) + + //! Clear exceptions (FPU). + INST_0x(fclex, kX86InstIdFclex) + + //! Conditional move `if (CF=1) fp0 = o0` (FPU). + INST_1x(fcmovb, kX86InstIdFcmovb, X86FpReg) + //! Conditional move `if (CF|ZF=1) fp0 = o0` (FPU). + INST_1x(fcmovbe, kX86InstIdFcmovbe, X86FpReg) + //! Conditional move `if (ZF=1) fp0 = o0` (FPU). + INST_1x(fcmove, kX86InstIdFcmove, X86FpReg) + //! Conditional move `if (CF=0) fp0 = o0` (FPU). + INST_1x(fcmovnb, kX86InstIdFcmovnb, X86FpReg) + //! Conditional move `if (CF|ZF=0) fp0 = o0` (FPU). + INST_1x(fcmovnbe, kX86InstIdFcmovnbe, X86FpReg) + //! Conditional move `if (ZF=0) fp0 = o0` (FPU). + INST_1x(fcmovne, kX86InstIdFcmovne, X86FpReg) + //! Conditional move `if (PF=0) fp0 = o0` (FPU). + INST_1x(fcmovnu, kX86InstIdFcmovnu, X86FpReg) + //! Conditional move `if (PF=1) fp0 = o0` (FPU). + INST_1x(fcmovu, kX86InstIdFcmovu, X86FpReg) + + //! Compare `fp0` with `o0` (FPU). + INST_1x(fcom, kX86InstIdFcom, X86FpReg) + //! Compare `fp0` with `fp1` (FPU). + INST_0x(fcom, kX86InstIdFcom) + //! Compare `fp0` with `float_or_double[o0]` (FPU). + INST_1x(fcom, kX86InstIdFcom, X86Mem) + //! Compare `fp0` with `o0` and POP (FPU). + INST_1x(fcomp, kX86InstIdFcomp, X86FpReg) + //! Compare `fp0` with `fp1` and POP (FPU). + INST_0x(fcomp, kX86InstIdFcomp) + //! Compare `fp0` with `float_or_double[o0]` and POP (FPU). + INST_1x(fcomp, kX86InstIdFcomp, X86Mem) + //! Compare `fp0` with `fp1` and POP twice (FPU). + INST_0x(fcompp, kX86InstIdFcompp) + //! Compare `fp0` with `o0` and set EFLAGS (FPU). + INST_1x(fcomi, kX86InstIdFcomi, X86FpReg) + //! Compare `fp0` with `o0` and set EFLAGS and POP (FPU). + INST_1x(fcomip, kX86InstIdFcomip, X86FpReg) + + //! Cos `fp0 = cos(fp0)` (FPU). + INST_0x(fcos, kX86InstIdFcos) + + //! Decrement FPU stack pointer (FPU). + INST_0x(fdecstp, kX86InstIdFdecstp) + + //! Divide `o0 = o0 / o1` (one has to be `fp0`) (FPU). + INST_2x_(fdiv, kX86InstIdFdiv, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0) + //! Divide `fp0 = fp0 / float_or_double[o0]` (FPU). + INST_1x(fdiv, kX86InstIdFdiv, X86Mem) + //! Divide `o0 = o0 / fp0` and POP (FPU). + INST_1x(fdivp, kX86InstIdFdivp, X86FpReg) + //! Divide `fp1 = fp1 / fp0` and POP (FPU). + INST_0x(fdivp, kX86InstIdFdivp) + + //! Reverse divide `o0 = o1 / o0` (one has to be `fp0`) (FPU). + INST_2x_(fdivr, kX86InstIdFdivr, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0) + //! Reverse divide `fp0 = float_or_double[o0] / fp0` (FPU). + INST_1x(fdivr, kX86InstIdFdivr, X86Mem) + //! Reverse divide `o0 = fp0 / o0` and POP (FPU). + INST_1x(fdivrp, kX86InstIdFdivrp, X86FpReg) + //! Reverse divide `fp1 = fp0 / fp1` and POP (FPU). + INST_0x(fdivrp, kX86InstIdFdivrp) + + //! Free FP register (FPU). + INST_1x(ffree, kX86InstIdFfree, X86FpReg) + + //! Add `fp0 = fp0 + short_or_int[o0]` (FPU). + INST_1x_(fiadd, kX86InstIdFiadd, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + //! Compare `fp0` with `short_or_int[o0]` (FPU). + INST_1x_(ficom, kX86InstIdFicom, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + //! Compare `fp0` with `short_or_int[o0]` and POP (FPU). + INST_1x_(ficomp, kX86InstIdFicomp, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + //! Divide `fp0 = fp0 / short_or_int[o0]` (FPU). + INST_1x_(fidiv, kX86InstIdFidiv, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + //! Reverse divide `fp0 = short_or_int[o0] / fp0` (FPU). + INST_1x_(fidivr, kX86InstIdFidivr, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + + //! Load `short_or_int_or_long[o0]` and PUSH (FPU). + INST_1x_(fild, kX86InstIdFild, X86Mem, o0.getSize() == 2 || o0.getSize() == 4 || o0.getSize() == 8) + //! Multiply `fp0 *= short_or_int[o0]` (FPU). + INST_1x_(fimul, kX86InstIdFimul, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + + //! Increment FPU stack pointer (FPU). + INST_0x(fincstp, kX86InstIdFincstp) + //! Initialize FPU (FPU). + INST_0x(finit, kX86InstIdFinit) + + //! Subtract `fp0 = fp0 - short_or_int[o0]` (FPU). + INST_1x_(fisub, kX86InstIdFisub, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + //! Reverse subtract `fp0 = short_or_int[o0] - fp0` (FPU). + INST_1x_(fisubr, kX86InstIdFisubr, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + + //! Initialize FPU without checking for pending unmasked exceptions (FPU). + INST_0x(fninit, kX86InstIdFninit) + + //! Store `fp0` as `short_or_int[o0]` (FPU). + INST_1x_(fist, kX86InstIdFist, X86Mem, o0.getSize() == 2 || o0.getSize() == 4) + //! Store `fp0` as `short_or_int_or_long[o0]` and POP (FPU). + INST_1x_(fistp, kX86InstIdFistp, X86Mem, o0.getSize() == 2 || o0.getSize() == 4 || o0.getSize() == 8) + + //! Load `float_or_double_or_extended[o0]` and PUSH (FPU). + INST_1x_(fld, kX86InstIdFld, X86Mem, o0.getSize() == 4 || o0.getSize() == 8 || o0.getSize() == 10) + //! PUSH `o0` (FPU). + INST_1x(fld, kX86InstIdFld, X86FpReg) + + //! PUSH `1.0` (FPU). + INST_0x(fld1, kX86InstIdFld1) + //! PUSH `log2(10)` (FPU). + INST_0x(fldl2t, kX86InstIdFldl2t) + //! PUSH `log2(e)` (FPU). + INST_0x(fldl2e, kX86InstIdFldl2e) + //! PUSH `pi` (FPU). + INST_0x(fldpi, kX86InstIdFldpi) + //! PUSH `log10(2)` (FPU). + INST_0x(fldlg2, kX86InstIdFldlg2) + //! PUSH `ln(2)` (FPU). + INST_0x(fldln2, kX86InstIdFldln2) + //! PUSH `+0.0` (FPU). + INST_0x(fldz, kX86InstIdFldz) + + //! Load x87 FPU control word from `word_ptr[o0]` (FPU). + INST_1x(fldcw, kX86InstIdFldcw, X86Mem) + //! Load x87 FPU environment (14 or 28 bytes) from `[o0]` (FPU). + INST_1x(fldenv, kX86InstIdFldenv, X86Mem) + + //! Multiply `o0 = o0 * o1` (one has to be `fp0`) (FPU). + INST_2x_(fmul, kX86InstIdFmul, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0) + //! Multiply `fp0 = fp0 * float_or_double[o0]` (FPU). + INST_1x(fmul, kX86InstIdFmul, X86Mem) + //! Multiply `o0 = o0 * fp0` and POP (FPU). + INST_1x(fmulp, kX86InstIdFmulp, X86FpReg) + //! Multiply `fp1 = fp1 * fp0` and POP (FPU). + INST_0x(fmulp, kX86InstIdFmulp) + + //! Clear exceptions (FPU). + INST_0x(fnclex, kX86InstIdFnclex) + //! No operation (FPU). + INST_0x(fnop, kX86InstIdFnop) + //! Save FPU state to `[o0]` (FPU). + INST_1x(fnsave, kX86InstIdFnsave, X86Mem) + //! Store x87 FPU environment to `[o0]` (FPU). + INST_1x(fnstenv, kX86InstIdFnstenv, X86Mem) + //! Store x87 FPU control word to `[o0]` (FPU). + INST_1x(fnstcw, kX86InstIdFnstcw, X86Mem) + + //! Store x87 FPU status word to `o0` (AX) (FPU). + INST_1x(fnstsw, kX86InstIdFnstsw, X86GpVar) + //! Store x87 FPU status word to `word_ptr[o0]` (FPU). + INST_1x(fnstsw, kX86InstIdFnstsw, X86Mem) + + //! Partial Arctan `fp1 = atan2(fp1, fp0)` and POP (FPU). + INST_0x(fpatan, kX86InstIdFpatan) + //! Partial Remainder[Trunc] `fp1 = fp0 % fp1` and POP (FPU). + INST_0x(fprem, kX86InstIdFprem) + //! Partial Remainder[Round] `fp1 = fp0 % fp1` and POP (FPU). + INST_0x(fprem1, kX86InstIdFprem1) + //! Partial Tan `fp0 = tan(fp0)` and PUSH `1.0` (FPU). + INST_0x(fptan, kX86InstIdFptan) + //! Round `fp0 = round(fp0)` (FPU). + INST_0x(frndint, kX86InstIdFrndint) + + //! Restore FPU state from `[o0]` (94 or 108 bytes) (FPU). + INST_1x(frstor, kX86InstIdFrstor, X86Mem) + //! Save FPU state to `[o0]` (94 or 108 bytes) (FPU). + INST_1x(fsave, kX86InstIdFsave, X86Mem) + + //! Scale `fp0 = fp0 * pow(2, RoundTowardsZero(fp1))` (FPU). + INST_0x(fscale, kX86InstIdFscale) + //! Sin `fp0 = sin(fp0)` (FPU). + INST_0x(fsin, kX86InstIdFsin) + //! Sincos `fp0 = sin(fp0)` and PUSH `cos(fp0)` (FPU). + INST_0x(fsincos, kX86InstIdFsincos) + //! Square root `fp0 = sqrt(fp0)` (FPU). + INST_0x(fsqrt, kX86InstIdFsqrt) + + //! Store floating point value to `float_or_double[o0]` (FPU). + INST_1x_(fst, kX86InstIdFst, X86Mem, o0.getSize() == 4 || o0.getSize() == 8) + //! Copy `o0 = fp0` (FPU). + INST_1x(fst, kX86InstIdFst, X86FpReg) + //! Store floating point value to `float_or_double_or_extended[o0]` and POP (FPU). + INST_1x_(fstp, kX86InstIdFstp, X86Mem, o0.getSize() == 4 || o0.getSize() == 8 || o0.getSize() == 10) + //! Copy `o0 = fp0` and POP (FPU). + INST_1x(fstp, kX86InstIdFstp, X86FpReg) + + //! Store x87 FPU control word to `word_ptr[o0]` (FPU). + INST_1x(fstcw, kX86InstIdFstcw, X86Mem) + //! Store x87 FPU environment to `[o0]` (14 or 28 bytes) (FPU). + INST_1x(fstenv, kX86InstIdFstenv, X86Mem) + //! Store x87 FPU status word to `o0` (AX) (FPU). + INST_1x(fstsw, kX86InstIdFstsw, X86GpVar) + //! Store x87 FPU status word to `word_ptr[o0]` (FPU). + INST_1x(fstsw, kX86InstIdFstsw, X86Mem) + + //! Subtract `o0 = o0 - o1` (one has to be `fp0`) (FPU). + INST_2x_(fsub, kX86InstIdFsub, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0) + //! Subtract `fp0 = fp0 - float_or_double[o0]` (FPU). + INST_1x_(fsub, kX86InstIdFsub, X86Mem, o0.getSize() == 4 || o0.getSize() == 8) + //! Subtract `o0 = o0 - fp0` and POP (FPU). + INST_1x(fsubp, kX86InstIdFsubp, X86FpReg) + //! Subtract `fp1 = fp1 - fp0` and POP (FPU). + INST_0x(fsubp, kX86InstIdFsubp) + + //! Reverse subtract `o0 = o1 - o0` (one has to be `fp0`) (FPU). + INST_2x_(fsubr, kX86InstIdFsubr, X86FpReg, X86FpReg, o0.getRegIndex() == 0 || o1.getRegIndex() == 0) + //! Reverse subtract `fp0 = fp0 - float_or_double[o0]` (FPU). + INST_1x_(fsubr, kX86InstIdFsubr, X86Mem, o0.getSize() == 4 || o0.getSize() == 8) + //! Reverse subtract `o0 = o0 - fp0` and POP (FPU). + INST_1x(fsubrp, kX86InstIdFsubrp, X86FpReg) + //! Reverse subtract `fp1 = fp1 - fp0` and POP (FPU). + INST_0x(fsubrp, kX86InstIdFsubrp) + + //! Compare `fp0` with `0.0` (FPU). + INST_0x(ftst, kX86InstIdFtst) + + //! Unordered compare `fp0` with `o0` (FPU). + INST_1x(fucom, kX86InstIdFucom, X86FpReg) + //! Unordered compare `fp0` with `fp1` (FPU). + INST_0x(fucom, kX86InstIdFucom) + //! Unordered compare `fp0` with `o0`, check for ordered values and set EFLAGS (FPU). + INST_1x(fucomi, kX86InstIdFucomi, X86FpReg) + //! Unordered compare `fp0` with `o0`, check for ordered values and set EFLAGS and POP (FPU). + INST_1x(fucomip, kX86InstIdFucomip, X86FpReg) + //! Unordered compare `fp0` with `o0` and POP (FPU). + INST_1x(fucomp, kX86InstIdFucomp, X86FpReg) + //! Unordered compare `fp0` with `fp1` and POP (FPU). + INST_0x(fucomp, kX86InstIdFucomp) + //! Unordered compare `fp0` with `fp1` and POP twice (FPU). + INST_0x(fucompp, kX86InstIdFucompp) + + INST_0x(fwait, kX86InstIdFwait) + + //! Examine fp0 (FPU). + INST_0x(fxam, kX86InstIdFxam) + //! Exchange `fp0` with `o0` (FPU). + INST_1x(fxch, kX86InstIdFxch, X86FpReg) + + //! Restore FP/MMX/SIMD extension states to `o0` (512 bytes) (FPU, MMX, SSE). + INST_1x(fxrstor, kX86InstIdFxrstor, X86Mem) + //! Store FP/MMX/SIMD extension states to `o0` (512 bytes) (FPU, MMX, SSE). + INST_1x(fxsave, kX86InstIdFxsave, X86Mem) + //! Extract `fp0 = exponent(fp0)` and PUSH `significant(fp0)` (FPU). + INST_0x(fxtract, kX86InstIdFxtract) + + //! Compute `fp1 = fp1 * log2(fp0)` and POP (FPU). + INST_0x(fyl2x, kX86InstIdFyl2x) + //! Compute `fp1 = fp1 * log2(fp0 + 1)` and POP (FPU). + INST_0x(fyl2xp1, kX86InstIdFyl2xp1) + + // -------------------------------------------------------------------------- + // [MMX] + // -------------------------------------------------------------------------- + + //! Move DWORD (MMX). + INST_2x(movd, kX86InstIdMovd, X86Mem, X86MmVar) + //! \overload + INST_2x(movd, kX86InstIdMovd, X86GpVar, X86MmVar) + //! \overload + INST_2x(movd, kX86InstIdMovd, X86MmVar, X86Mem) + //! \overload + INST_2x(movd, kX86InstIdMovd, X86MmVar, X86GpVar) + + //! Move QWORD (MMX). + INST_2x(movq, kX86InstIdMovq, X86MmVar, X86MmVar) + //! \overload + INST_2x(movq, kX86InstIdMovq, X86Mem, X86MmVar) + //! \overload + INST_2x(movq, kX86InstIdMovq, X86MmVar, X86Mem) + + //! Move QWORD (X64 Only). + INST_2x(movq, kX86InstIdMovq, X86GpVar, X86MmVar) + //! \overload + INST_2x(movq, kX86InstIdMovq, X86MmVar, X86GpVar) + + //! Pack DWORDs to WORDs with signed saturation (MMX). + INST_2x(packssdw, kX86InstIdPackssdw, X86MmVar, X86MmVar) + //! \overload + INST_2x(packssdw, kX86InstIdPackssdw, X86MmVar, X86Mem) + + //! Pack WORDs to BYTEs with signed saturation (MMX). + INST_2x(packsswb, kX86InstIdPacksswb, X86MmVar, X86MmVar) + //! \overload + INST_2x(packsswb, kX86InstIdPacksswb, X86MmVar, X86Mem) + + //! Pack WORDs to BYTEs with unsigned saturation (MMX). + INST_2x(packuswb, kX86InstIdPackuswb, X86MmVar, X86MmVar) + //! \overload + INST_2x(packuswb, kX86InstIdPackuswb, X86MmVar, X86Mem) + + //! Packed BYTE add (MMX). + INST_2x(paddb, kX86InstIdPaddb, X86MmVar, X86MmVar) + //! \overload + INST_2x(paddb, kX86InstIdPaddb, X86MmVar, X86Mem) + + //! Packed DWORD add (MMX). + INST_2x(paddd, kX86InstIdPaddd, X86MmVar, X86MmVar) + //! \overload + INST_2x(paddd, kX86InstIdPaddd, X86MmVar, X86Mem) + + //! Packed BYTE add with saturation (MMX). + INST_2x(paddsb, kX86InstIdPaddsb, X86MmVar, X86MmVar) + //! \overload + INST_2x(paddsb, kX86InstIdPaddsb, X86MmVar, X86Mem) + + //! Packed WORD add with saturation (MMX). + INST_2x(paddsw, kX86InstIdPaddsw, X86MmVar, X86MmVar) + //! \overload + INST_2x(paddsw, kX86InstIdPaddsw, X86MmVar, X86Mem) + + //! Packed BYTE add with unsigned saturation (MMX). + INST_2x(paddusb, kX86InstIdPaddusb, X86MmVar, X86MmVar) + //! \overload + INST_2x(paddusb, kX86InstIdPaddusb, X86MmVar, X86Mem) + + //! Packed WORD add with unsigned saturation (MMX). + INST_2x(paddusw, kX86InstIdPaddusw, X86MmVar, X86MmVar) + //! \overload + INST_2x(paddusw, kX86InstIdPaddusw, X86MmVar, X86Mem) + + //! Packed WORD add (MMX). + INST_2x(paddw, kX86InstIdPaddw, X86MmVar, X86MmVar) + //! \overload + INST_2x(paddw, kX86InstIdPaddw, X86MmVar, X86Mem) + + //! Packed and (MMX). + INST_2x(pand, kX86InstIdPand, X86MmVar, X86MmVar) + //! \overload + INST_2x(pand, kX86InstIdPand, X86MmVar, X86Mem) + + //! Packed and-not (MMX). + INST_2x(pandn, kX86InstIdPandn, X86MmVar, X86MmVar) + //! \overload + INST_2x(pandn, kX86InstIdPandn, X86MmVar, X86Mem) + + //! Packed BYTEs compare for equality (MMX). + INST_2x(pcmpeqb, kX86InstIdPcmpeqb, X86MmVar, X86MmVar) + //! \overload + INST_2x(pcmpeqb, kX86InstIdPcmpeqb, X86MmVar, X86Mem) + + //! Packed DWORDs compare for equality (MMX). + INST_2x(pcmpeqd, kX86InstIdPcmpeqd, X86MmVar, X86MmVar) + //! \overload + INST_2x(pcmpeqd, kX86InstIdPcmpeqd, X86MmVar, X86Mem) + + //! Packed WORDs compare for equality (MMX). + INST_2x(pcmpeqw, kX86InstIdPcmpeqw, X86MmVar, X86MmVar) + //! \overload + INST_2x(pcmpeqw, kX86InstIdPcmpeqw, X86MmVar, X86Mem) + + //! Packed BYTEs compare if greater than (MMX). + INST_2x(pcmpgtb, kX86InstIdPcmpgtb, X86MmVar, X86MmVar) + //! \overload + INST_2x(pcmpgtb, kX86InstIdPcmpgtb, X86MmVar, X86Mem) + + //! Packed DWORDs compare if greater than (MMX). + INST_2x(pcmpgtd, kX86InstIdPcmpgtd, X86MmVar, X86MmVar) + //! \overload + INST_2x(pcmpgtd, kX86InstIdPcmpgtd, X86MmVar, X86Mem) + + //! Packed WORDs compare if greater than (MMX). + INST_2x(pcmpgtw, kX86InstIdPcmpgtw, X86MmVar, X86MmVar) + //! \overload + INST_2x(pcmpgtw, kX86InstIdPcmpgtw, X86MmVar, X86Mem) + + //! Packed WORD multiply high (MMX). + INST_2x(pmulhw, kX86InstIdPmulhw, X86MmVar, X86MmVar) + //! \overload + INST_2x(pmulhw, kX86InstIdPmulhw, X86MmVar, X86Mem) + + //! Packed WORD multiply low (MMX). + INST_2x(pmullw, kX86InstIdPmullw, X86MmVar, X86MmVar) + //! \overload + INST_2x(pmullw, kX86InstIdPmullw, X86MmVar, X86Mem) + + //! Packed bitwise or (MMX). + INST_2x(por, kX86InstIdPor, X86MmVar, X86MmVar) + //! \overload + INST_2x(por, kX86InstIdPor, X86MmVar, X86Mem) + + //! Packed WORD multiply and add to packed DWORD (MMX). + INST_2x(pmaddwd, kX86InstIdPmaddwd, X86MmVar, X86MmVar) + //! \overload + INST_2x(pmaddwd, kX86InstIdPmaddwd, X86MmVar, X86Mem) + + //! Packed DWORD shift left logical (MMX). + INST_2x(pslld, kX86InstIdPslld, X86MmVar, X86MmVar) + //! \overload + INST_2x(pslld, kX86InstIdPslld, X86MmVar, X86Mem) + //! \overload + INST_2i(pslld, kX86InstIdPslld, X86MmVar, Imm) + + //! Packed QWORD shift left logical (MMX). + INST_2x(psllq, kX86InstIdPsllq, X86MmVar, X86MmVar) + //! \overload + INST_2x(psllq, kX86InstIdPsllq, X86MmVar, X86Mem) + //! \overload + INST_2i(psllq, kX86InstIdPsllq, X86MmVar, Imm) + + //! Packed WORD shift left logical (MMX). + INST_2x(psllw, kX86InstIdPsllw, X86MmVar, X86MmVar) + //! \overload + INST_2x(psllw, kX86InstIdPsllw, X86MmVar, X86Mem) + //! \overload + INST_2i(psllw, kX86InstIdPsllw, X86MmVar, Imm) + + //! Packed DWORD shift right arithmetic (MMX). + INST_2x(psrad, kX86InstIdPsrad, X86MmVar, X86MmVar) + //! \overload + INST_2x(psrad, kX86InstIdPsrad, X86MmVar, X86Mem) + //! \overload + INST_2i(psrad, kX86InstIdPsrad, X86MmVar, Imm) + + //! Packed WORD shift right arithmetic (MMX). + INST_2x(psraw, kX86InstIdPsraw, X86MmVar, X86MmVar) + //! \overload + INST_2x(psraw, kX86InstIdPsraw, X86MmVar, X86Mem) + //! \overload + INST_2i(psraw, kX86InstIdPsraw, X86MmVar, Imm) + + //! Packed DWORD shift right logical (MMX). + INST_2x(psrld, kX86InstIdPsrld, X86MmVar, X86MmVar) + //! \overload + INST_2x(psrld, kX86InstIdPsrld, X86MmVar, X86Mem) + //! \overload + INST_2i(psrld, kX86InstIdPsrld, X86MmVar, Imm) + + //! Packed QWORD shift right logical (MMX). + INST_2x(psrlq, kX86InstIdPsrlq, X86MmVar, X86MmVar) + //! \overload + INST_2x(psrlq, kX86InstIdPsrlq, X86MmVar, X86Mem) + //! \overload + INST_2i(psrlq, kX86InstIdPsrlq, X86MmVar, Imm) + + //! Packed WORD shift right logical (MMX). + INST_2x(psrlw, kX86InstIdPsrlw, X86MmVar, X86MmVar) + //! \overload + INST_2x(psrlw, kX86InstIdPsrlw, X86MmVar, X86Mem) + //! \overload + INST_2i(psrlw, kX86InstIdPsrlw, X86MmVar, Imm) + + //! Packed BYTE subtract (MMX). + INST_2x(psubb, kX86InstIdPsubb, X86MmVar, X86MmVar) + //! \overload + INST_2x(psubb, kX86InstIdPsubb, X86MmVar, X86Mem) + + //! Packed DWORD subtract (MMX). + INST_2x(psubd, kX86InstIdPsubd, X86MmVar, X86MmVar) + //! \overload + INST_2x(psubd, kX86InstIdPsubd, X86MmVar, X86Mem) + + //! Packed BYTE subtract with saturation (MMX). + INST_2x(psubsb, kX86InstIdPsubsb, X86MmVar, X86MmVar) + //! \overload + INST_2x(psubsb, kX86InstIdPsubsb, X86MmVar, X86Mem) + + //! Packed WORD subtract with saturation (MMX). + INST_2x(psubsw, kX86InstIdPsubsw, X86MmVar, X86MmVar) + //! \overload + INST_2x(psubsw, kX86InstIdPsubsw, X86MmVar, X86Mem) + + //! Packed BYTE subtract with unsigned saturation (MMX). + INST_2x(psubusb, kX86InstIdPsubusb, X86MmVar, X86MmVar) + //! \overload + INST_2x(psubusb, kX86InstIdPsubusb, X86MmVar, X86Mem) + + //! Packed WORD subtract with unsigned saturation (MMX). + INST_2x(psubusw, kX86InstIdPsubusw, X86MmVar, X86MmVar) + //! \overload + INST_2x(psubusw, kX86InstIdPsubusw, X86MmVar, X86Mem) + + //! Packed WORD subtract (MMX). + INST_2x(psubw, kX86InstIdPsubw, X86MmVar, X86MmVar) + //! \overload + INST_2x(psubw, kX86InstIdPsubw, X86MmVar, X86Mem) + + //! Unpack high packed BYTEs to WORDs (MMX). + INST_2x(punpckhbw, kX86InstIdPunpckhbw, X86MmVar, X86MmVar) + //! \overload + INST_2x(punpckhbw, kX86InstIdPunpckhbw, X86MmVar, X86Mem) + + //! Unpack high packed DWORDs to QWORDs (MMX). + INST_2x(punpckhdq, kX86InstIdPunpckhdq, X86MmVar, X86MmVar) + //! \overload + INST_2x(punpckhdq, kX86InstIdPunpckhdq, X86MmVar, X86Mem) + + //! Unpack high packed WORDs to DWORDs (MMX). + INST_2x(punpckhwd, kX86InstIdPunpckhwd, X86MmVar, X86MmVar) + //! \overload + INST_2x(punpckhwd, kX86InstIdPunpckhwd, X86MmVar, X86Mem) + + //! Unpack low packed BYTEs to WORDs (MMX). + INST_2x(punpcklbw, kX86InstIdPunpcklbw, X86MmVar, X86MmVar) + //! \overload + INST_2x(punpcklbw, kX86InstIdPunpcklbw, X86MmVar, X86Mem) + + //! Unpack low packed DWORDs to QWORDs (MMX). + INST_2x(punpckldq, kX86InstIdPunpckldq, X86MmVar, X86MmVar) + //! \overload + INST_2x(punpckldq, kX86InstIdPunpckldq, X86MmVar, X86Mem) + + //! Unpack low packed WORDs to DWORDs (MMX). + INST_2x(punpcklwd, kX86InstIdPunpcklwd, X86MmVar, X86MmVar) + //! \overload + INST_2x(punpcklwd, kX86InstIdPunpcklwd, X86MmVar, X86Mem) + + //! Packed bitwise xor (MMX). + INST_2x(pxor, kX86InstIdPxor, X86MmVar, X86MmVar) + //! \overload + INST_2x(pxor, kX86InstIdPxor, X86MmVar, X86Mem) + + //! Empty MMX state. + INST_0x(emms, kX86InstIdEmms) + + // -------------------------------------------------------------------------- + // [3DNOW] + // -------------------------------------------------------------------------- + + //! Packed SP-FP to DWORD convert (3dNow!). + INST_2x(pf2id, kX86InstIdPf2id, X86MmVar, X86MmVar) + //! \overload + INST_2x(pf2id, kX86InstIdPf2id, X86MmVar, X86Mem) + + //! Packed SP-FP to WORD convert (3dNow!). + INST_2x(pf2iw, kX86InstIdPf2iw, X86MmVar, X86MmVar) + //! \overload + INST_2x(pf2iw, kX86InstIdPf2iw, X86MmVar, X86Mem) + + //! Packed SP-FP accumulate (3dNow!). + INST_2x(pfacc, kX86InstIdPfacc, X86MmVar, X86MmVar) + //! \overload + INST_2x(pfacc, kX86InstIdPfacc, X86MmVar, X86Mem) + + //! Packed SP-FP addition (3dNow!). + INST_2x(pfadd, kX86InstIdPfadd, X86MmVar, X86MmVar) + //! \overload + INST_2x(pfadd, kX86InstIdPfadd, X86MmVar, X86Mem) + + //! Packed SP-FP compare - dst == src (3dNow!). + INST_2x(pfcmpeq, kX86InstIdPfcmpeq, X86MmVar, X86MmVar) + //! \overload + INST_2x(pfcmpeq, kX86InstIdPfcmpeq, X86MmVar, X86Mem) + + //! Packed SP-FP compare - dst >= src (3dNow!). + INST_2x(pfcmpge, kX86InstIdPfcmpge, X86MmVar, X86MmVar) + //! \overload + INST_2x(pfcmpge, kX86InstIdPfcmpge, X86MmVar, X86Mem) + + //! Packed SP-FP compare - dst > src (3dNow!). + INST_2x(pfcmpgt, kX86InstIdPfcmpgt, X86MmVar, X86MmVar) + //! \overload + INST_2x(pfcmpgt, kX86InstIdPfcmpgt, X86MmVar, X86Mem) + + //! Packed SP-FP maximum (3dNow!). + INST_2x(pfmax, kX86InstIdPfmax, X86MmVar, X86MmVar) + //! \overload + INST_2x(pfmax, kX86InstIdPfmax, X86MmVar, X86Mem) + + //! Packed SP-FP minimum (3dNow!). + INST_2x(pfmin, kX86InstIdPfmin, X86MmVar, X86MmVar) + //! \overload + INST_2x(pfmin, kX86InstIdPfmin, X86MmVar, X86Mem) + + //! Packed SP-FP multiply (3dNow!). + INST_2x(pfmul, kX86InstIdPfmul, X86MmVar, X86MmVar) + //! \overload + INST_2x(pfmul, kX86InstIdPfmul, X86MmVar, X86Mem) + + //! Packed SP-FP negative accumulate (3dNow!). + INST_2x(pfnacc, kX86InstIdPfnacc, X86MmVar, X86MmVar) + //! \overload + INST_2x(pfnacc, kX86InstIdPfnacc, X86MmVar, X86Mem) + + //! Packed SP-FP mixed accumulate (3dNow!). + INST_2x(pfpnacc, kX86InstIdPfpnacc, X86MmVar, X86MmVar) + //! \overload + INST_2x(pfpnacc, kX86InstIdPfpnacc, X86MmVar, X86Mem) + + //! Packed SP-FP reciprocal approximation (3dNow!). + INST_2x(pfrcp, kX86InstIdPfrcp, X86MmVar, X86MmVar) + //! \overload + INST_2x(pfrcp, kX86InstIdPfrcp, X86MmVar, X86Mem) + + //! Packed SP-FP reciprocal, first iteration step (3dNow!). + INST_2x(pfrcpit1, kX86InstIdPfrcpit1, X86MmVar, X86MmVar) + //! \overload + INST_2x(pfrcpit1, kX86InstIdPfrcpit1, X86MmVar, X86Mem) + + //! Packed SP-FP reciprocal, second iteration step (3dNow!). + INST_2x(pfrcpit2, kX86InstIdPfrcpit2, X86MmVar, X86MmVar) + //! \overload + INST_2x(pfrcpit2, kX86InstIdPfrcpit2, X86MmVar, X86Mem) + + //! Packed SP-FP reciprocal square root, first iteration step (3dNow!). + INST_2x(pfrsqit1, kX86InstIdPfrsqit1, X86MmVar, X86MmVar) + //! \overload + INST_2x(pfrsqit1, kX86InstIdPfrsqit1, X86MmVar, X86Mem) + + //! Packed SP-FP reciprocal square root approximation (3dNow!). + INST_2x(pfrsqrt, kX86InstIdPfrsqrt, X86MmVar, X86MmVar) + //! \overload + INST_2x(pfrsqrt, kX86InstIdPfrsqrt, X86MmVar, X86Mem) + + //! Packed SP-FP subtract (3dNow!). + INST_2x(pfsub, kX86InstIdPfsub, X86MmVar, X86MmVar) + //! \overload + INST_2x(pfsub, kX86InstIdPfsub, X86MmVar, X86Mem) + + //! Packed SP-FP reverse subtract (3dNow!). + INST_2x(pfsubr, kX86InstIdPfsubr, X86MmVar, X86MmVar) + //! \overload + INST_2x(pfsubr, kX86InstIdPfsubr, X86MmVar, X86Mem) + + //! Packed DWORDs to SP-FP (3dNow!). + INST_2x(pi2fd, kX86InstIdPi2fd, X86MmVar, X86MmVar) + //! \overload + INST_2x(pi2fd, kX86InstIdPi2fd, X86MmVar, X86Mem) + + //! Packed WORDs to SP-FP (3dNow!). + INST_2x(pi2fw, kX86InstIdPi2fw, X86MmVar, X86MmVar) + //! \overload + INST_2x(pi2fw, kX86InstIdPi2fw, X86MmVar, X86Mem) + + //! Packed swap DWORDs (3dNow!) + INST_2x(pswapd, kX86InstIdPswapd, X86MmVar, X86MmVar) + //! \overload + INST_2x(pswapd, kX86InstIdPswapd, X86MmVar, X86Mem) + + //! Prefetch (3dNow!). + INST_1x(prefetch_3dnow, kX86InstIdPrefetch3dNow, X86Mem) + + //! Prefetch and set cache to modified (3dNow!). + INST_1x(prefetchw_3dnow, kX86InstIdPrefetchw3dNow, X86Mem) + + //! Faster EMMS (3dNow!). + INST_0x(femms, kX86InstIdFemms) + + // -------------------------------------------------------------------------- + // [SSE] + // -------------------------------------------------------------------------- + + //! Packed SP-FP add (SSE). + INST_2x(addps, kX86InstIdAddps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(addps, kX86InstIdAddps, X86XmmVar, X86Mem) + + //! Scalar SP-FP add (SSE). + INST_2x(addss, kX86InstIdAddss, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(addss, kX86InstIdAddss, X86XmmVar, X86Mem) + + //! Packed SP-FP bitwise and-not (SSE). + INST_2x(andnps, kX86InstIdAndnps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(andnps, kX86InstIdAndnps, X86XmmVar, X86Mem) + + //! Packed SP-FP bitwise and (SSE). + INST_2x(andps, kX86InstIdAndps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(andps, kX86InstIdAndps, X86XmmVar, X86Mem) + + //! Packed SP-FP compare (SSE). + INST_3i(cmpps, kX86InstIdCmpps, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(cmpps, kX86InstIdCmpps, X86XmmVar, X86Mem, Imm) + + //! Compare scalar SP-FP Values (SSE). + INST_3i(cmpss, kX86InstIdCmpss, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(cmpss, kX86InstIdCmpss, X86XmmVar, X86Mem, Imm) + + //! Scalar ordered SP-FP compare and set EFLAGS (SSE). + INST_2x(comiss, kX86InstIdComiss, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(comiss, kX86InstIdComiss, X86XmmVar, X86Mem) + + //! Packed signed INT32 to packed SP-FP conversion (SSE). + INST_2x(cvtpi2ps, kX86InstIdCvtpi2ps, X86XmmVar, X86MmVar) + //! \overload + INST_2x(cvtpi2ps, kX86InstIdCvtpi2ps, X86XmmVar, X86Mem) + + //! Packed SP-FP to packed INT32 conversion (SSE). + INST_2x(cvtps2pi, kX86InstIdCvtps2pi, X86MmVar, X86XmmVar) + //! \overload + INST_2x(cvtps2pi, kX86InstIdCvtps2pi, X86MmVar, X86Mem) + + //! Convert scalar INT32 to SP-FP (SSE). + INST_2x(cvtsi2ss, kX86InstIdCvtsi2ss, X86XmmVar, X86GpVar) + //! \overload + INST_2x(cvtsi2ss, kX86InstIdCvtsi2ss, X86XmmVar, X86Mem) + + //! Convert scalar SP-FP to INT32 (SSE). + INST_2x(cvtss2si, kX86InstIdCvtss2si, X86GpVar, X86XmmVar) + //! \overload + INST_2x(cvtss2si, kX86InstIdCvtss2si, X86GpVar, X86Mem) + + //! Convert with truncation packed SP-FP to packed INT32 (SSE). + INST_2x(cvttps2pi, kX86InstIdCvttps2pi, X86MmVar, X86XmmVar) + //! \overload + INST_2x(cvttps2pi, kX86InstIdCvttps2pi, X86MmVar, X86Mem) + + //! Convert with truncation scalar SP-FP to INT32 (SSE). + INST_2x(cvttss2si, kX86InstIdCvttss2si, X86GpVar, X86XmmVar) + //! \overload + INST_2x(cvttss2si, kX86InstIdCvttss2si, X86GpVar, X86Mem) + + //! Packed SP-FP divide (SSE). + INST_2x(divps, kX86InstIdDivps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(divps, kX86InstIdDivps, X86XmmVar, X86Mem) + + //! Scalar SP-FP divide (SSE). + INST_2x(divss, kX86InstIdDivss, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(divss, kX86InstIdDivss, X86XmmVar, X86Mem) + + //! Load streaming SIMD extension control/status (SSE). + INST_1x(ldmxcsr, kX86InstIdLdmxcsr, X86Mem) + + //! Byte mask write (SSE). + INST_3x(maskmovq, kX86InstIdMaskmovq, X86GpVar /* zdi */, X86MmVar, X86MmVar) + + //! Packed SP-FP maximum (SSE). + INST_2x(maxps, kX86InstIdMaxps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(maxps, kX86InstIdMaxps, X86XmmVar, X86Mem) + + //! Scalar SP-FP maximum (SSE). + INST_2x(maxss, kX86InstIdMaxss, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(maxss, kX86InstIdMaxss, X86XmmVar, X86Mem) + + //! Packed SP-FP minimum (SSE). + INST_2x(minps, kX86InstIdMinps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(minps, kX86InstIdMinps, X86XmmVar, X86Mem) + + //! Scalar SP-FP minimum (SSE). + INST_2x(minss, kX86InstIdMinss, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(minss, kX86InstIdMinss, X86XmmVar, X86Mem) + + //! Move aligned packed SP-FP (SSE). + INST_2x(movaps, kX86InstIdMovaps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(movaps, kX86InstIdMovaps, X86XmmVar, X86Mem) + //! Move aligned packed SP-FP (SSE). + INST_2x(movaps, kX86InstIdMovaps, X86Mem, X86XmmVar) + + //! Move DWORD. + INST_2x(movd, kX86InstIdMovd, X86Mem, X86XmmVar) + //! \overload + INST_2x(movd, kX86InstIdMovd, X86GpVar, X86XmmVar) + //! \overload + INST_2x(movd, kX86InstIdMovd, X86XmmVar, X86Mem) + //! \overload + INST_2x(movd, kX86InstIdMovd, X86XmmVar, X86GpVar) + + //! Move QWORD (SSE). + INST_2x(movq, kX86InstIdMovq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(movq, kX86InstIdMovq, X86Mem, X86XmmVar) + //! \overload + INST_2x(movq, kX86InstIdMovq, X86XmmVar, X86Mem) + + //! Move QWORD (X64 Only). + INST_2x(movq, kX86InstIdMovq, X86GpVar, X86XmmVar) + //! \overload + INST_2x(movq, kX86InstIdMovq, X86XmmVar, X86GpVar) + + //! Move QWORD using NT hint (SSE). + INST_2x(movntq, kX86InstIdMovntq, X86Mem, X86MmVar) + + //! Move high to low packed SP-FP (SSE). + INST_2x(movhlps, kX86InstIdMovhlps, X86XmmVar, X86XmmVar) + + //! Move high packed SP-FP (SSE). + INST_2x(movhps, kX86InstIdMovhps, X86XmmVar, X86Mem) + //! Move high packed SP-FP (SSE). + INST_2x(movhps, kX86InstIdMovhps, X86Mem, X86XmmVar) + + //! Move low to high packed SP-FP (SSE). + INST_2x(movlhps, kX86InstIdMovlhps, X86XmmVar, X86XmmVar) + + //! Move low packed SP-FP (SSE). + INST_2x(movlps, kX86InstIdMovlps, X86XmmVar, X86Mem) + //! Move low packed SP-FP (SSE). + INST_2x(movlps, kX86InstIdMovlps, X86Mem, X86XmmVar) + + //! Move aligned packed SP-FP using NT hint (SSE). + INST_2x(movntps, kX86InstIdMovntps, X86Mem, X86XmmVar) + + //! Move scalar SP-FP (SSE). + INST_2x(movss, kX86InstIdMovss, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(movss, kX86InstIdMovss, X86XmmVar, X86Mem) + //! \overload + INST_2x(movss, kX86InstIdMovss, X86Mem, X86XmmVar) + + //! Move unaligned packed SP-FP (SSE). + INST_2x(movups, kX86InstIdMovups, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(movups, kX86InstIdMovups, X86XmmVar, X86Mem) + //! \overload + INST_2x(movups, kX86InstIdMovups, X86Mem, X86XmmVar) + + //! Packed SP-FP multiply (SSE). + INST_2x(mulps, kX86InstIdMulps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(mulps, kX86InstIdMulps, X86XmmVar, X86Mem) + + //! Scalar SP-FP multiply (SSE). + INST_2x(mulss, kX86InstIdMulss, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(mulss, kX86InstIdMulss, X86XmmVar, X86Mem) + + //! Packed SP-FP bitwise or (SSE). + INST_2x(orps, kX86InstIdOrps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(orps, kX86InstIdOrps, X86XmmVar, X86Mem) + + //! Packed BYTE average (SSE). + INST_2x(pavgb, kX86InstIdPavgb, X86MmVar, X86MmVar) + //! \overload + INST_2x(pavgb, kX86InstIdPavgb, X86MmVar, X86Mem) + + //! Packed WORD average (SSE). + INST_2x(pavgw, kX86InstIdPavgw, X86MmVar, X86MmVar) + //! \overload + INST_2x(pavgw, kX86InstIdPavgw, X86MmVar, X86Mem) + + //! Extract WORD based on selector (SSE). + INST_3i(pextrw, kX86InstIdPextrw, X86GpVar, X86MmVar, Imm) + + //! Insert WORD based on selector (SSE). + INST_3i(pinsrw, kX86InstIdPinsrw, X86MmVar, X86GpVar, Imm) + //! \overload + INST_3i(pinsrw, kX86InstIdPinsrw, X86MmVar, X86Mem, Imm) + + //! Packed WORD maximum (SSE). + INST_2x(pmaxsw, kX86InstIdPmaxsw, X86MmVar, X86MmVar) + //! \overload + INST_2x(pmaxsw, kX86InstIdPmaxsw, X86MmVar, X86Mem) + + //! Packed BYTE unsigned maximum (SSE). + INST_2x(pmaxub, kX86InstIdPmaxub, X86MmVar, X86MmVar) + //! \overload + INST_2x(pmaxub, kX86InstIdPmaxub, X86MmVar, X86Mem) + + //! Packed WORD minimum (SSE). + INST_2x(pminsw, kX86InstIdPminsw, X86MmVar, X86MmVar) + //! \overload + INST_2x(pminsw, kX86InstIdPminsw, X86MmVar, X86Mem) + + //! Packed BYTE unsigned minimum (SSE). + INST_2x(pminub, kX86InstIdPminub, X86MmVar, X86MmVar) + //! \overload + INST_2x(pminub, kX86InstIdPminub, X86MmVar, X86Mem) + + //! Move byte mask to integer (SSE). + INST_2x(pmovmskb, kX86InstIdPmovmskb, X86GpVar, X86MmVar) + + //! Packed WORD unsigned multiply high (SSE). + INST_2x(pmulhuw, kX86InstIdPmulhuw, X86MmVar, X86MmVar) + //! \overload + INST_2x(pmulhuw, kX86InstIdPmulhuw, X86MmVar, X86Mem) + + //! Packed WORD sum of absolute differences (SSE). + INST_2x(psadbw, kX86InstIdPsadbw, X86MmVar, X86MmVar) + //! \overload + INST_2x(psadbw, kX86InstIdPsadbw, X86MmVar, X86Mem) + + //! Packed WORD shuffle (SSE). + INST_3i(pshufw, kX86InstIdPshufw, X86MmVar, X86MmVar, Imm) + //! \overload + INST_3i(pshufw, kX86InstIdPshufw, X86MmVar, X86Mem, Imm) + + //! Packed SP-FP reciprocal (SSE). + INST_2x(rcpps, kX86InstIdRcpps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(rcpps, kX86InstIdRcpps, X86XmmVar, X86Mem) + + //! Scalar SP-FP reciprocal (SSE). + INST_2x(rcpss, kX86InstIdRcpss, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(rcpss, kX86InstIdRcpss, X86XmmVar, X86Mem) + + //! Prefetch (SSE). + INST_2i(prefetch, kX86InstIdPrefetch, X86Mem, Imm) + + //! Packed WORD sum of absolute differences (SSE). + INST_2x(psadbw, kX86InstIdPsadbw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psadbw, kX86InstIdPsadbw, X86XmmVar, X86Mem) + + //! Packed SP-FP Square root reciprocal (SSE). + INST_2x(rsqrtps, kX86InstIdRsqrtps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(rsqrtps, kX86InstIdRsqrtps, X86XmmVar, X86Mem) + + //! Scalar SP-FP Square root reciprocal (SSE). + INST_2x(rsqrtss, kX86InstIdRsqrtss, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(rsqrtss, kX86InstIdRsqrtss, X86XmmVar, X86Mem) + + //! Store fence (SSE). + INST_0x(sfence, kX86InstIdSfence) + + //! Shuffle SP-FP (SSE). + INST_3i(shufps, kX86InstIdShufps, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(shufps, kX86InstIdShufps, X86XmmVar, X86Mem, Imm) + + //! Packed SP-FP square root (SSE). + INST_2x(sqrtps, kX86InstIdSqrtps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(sqrtps, kX86InstIdSqrtps, X86XmmVar, X86Mem) + + //! Scalar SP-FP square root (SSE). + INST_2x(sqrtss, kX86InstIdSqrtss, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(sqrtss, kX86InstIdSqrtss, X86XmmVar, X86Mem) + + //! Store streaming SIMD extension control/status (SSE). + INST_1x(stmxcsr, kX86InstIdStmxcsr, X86Mem) + + //! Packed SP-FP subtract (SSE). + INST_2x(subps, kX86InstIdSubps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(subps, kX86InstIdSubps, X86XmmVar, X86Mem) + + //! Scalar SP-FP subtract (SSE). + INST_2x(subss, kX86InstIdSubss, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(subss, kX86InstIdSubss, X86XmmVar, X86Mem) + + //! Unordered scalar SP-FP compare and set EFLAGS (SSE). + INST_2x(ucomiss, kX86InstIdUcomiss, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(ucomiss, kX86InstIdUcomiss, X86XmmVar, X86Mem) + + //! Unpack high packed SP-FP data (SSE). + INST_2x(unpckhps, kX86InstIdUnpckhps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(unpckhps, kX86InstIdUnpckhps, X86XmmVar, X86Mem) + + //! Unpack low packed SP-FP data (SSE). + INST_2x(unpcklps, kX86InstIdUnpcklps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(unpcklps, kX86InstIdUnpcklps, X86XmmVar, X86Mem) + + //! Packed SP-FP bitwise xor (SSE). + INST_2x(xorps, kX86InstIdXorps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(xorps, kX86InstIdXorps, X86XmmVar, X86Mem) + + // -------------------------------------------------------------------------- + // [SSE2] + // -------------------------------------------------------------------------- + + //! Packed DP-FP add (SSE2). + INST_2x(addpd, kX86InstIdAddpd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(addpd, kX86InstIdAddpd, X86XmmVar, X86Mem) + + //! Scalar DP-FP add (SSE2). + INST_2x(addsd, kX86InstIdAddsd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(addsd, kX86InstIdAddsd, X86XmmVar, X86Mem) + + //! Packed DP-FP bitwise and-not (SSE2). + INST_2x(andnpd, kX86InstIdAndnpd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(andnpd, kX86InstIdAndnpd, X86XmmVar, X86Mem) + + //! Packed DP-FP bitwise and (SSE2). + INST_2x(andpd, kX86InstIdAndpd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(andpd, kX86InstIdAndpd, X86XmmVar, X86Mem) + + //! Flush cache line (SSE2). + INST_1x(clflush, kX86InstIdClflush, X86Mem) + + //! Packed DP-FP compare (SSE2). + INST_3i(cmppd, kX86InstIdCmppd, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(cmppd, kX86InstIdCmppd, X86XmmVar, X86Mem, Imm) + + //! Scalar SP-FP compare (SSE2). + INST_3i(cmpsd, kX86InstIdCmpsd, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(cmpsd, kX86InstIdCmpsd, X86XmmVar, X86Mem, Imm) + + //! Scalar ordered DP-FP compare and set EFLAGS (SSE2). + INST_2x(comisd, kX86InstIdComisd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(comisd, kX86InstIdComisd, X86XmmVar, X86Mem) + + //! Convert packed DWORD integers to packed DP-FP (SSE2). + INST_2x(cvtdq2pd, kX86InstIdCvtdq2pd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(cvtdq2pd, kX86InstIdCvtdq2pd, X86XmmVar, X86Mem) + + //! Convert packed DWORD integers to packed SP-FP (SSE2). + INST_2x(cvtdq2ps, kX86InstIdCvtdq2ps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(cvtdq2ps, kX86InstIdCvtdq2ps, X86XmmVar, X86Mem) + + //! Convert packed DP-FP to packed DWORDs (SSE2). + INST_2x(cvtpd2dq, kX86InstIdCvtpd2dq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(cvtpd2dq, kX86InstIdCvtpd2dq, X86XmmVar, X86Mem) + + //! Convert packed DP-FP to packed DWORDs (SSE2). + INST_2x(cvtpd2pi, kX86InstIdCvtpd2pi, X86MmVar, X86XmmVar) + //! \overload + INST_2x(cvtpd2pi, kX86InstIdCvtpd2pi, X86MmVar, X86Mem) + + //! Convert packed DP-FP to packed SP-FP (SSE2). + INST_2x(cvtpd2ps, kX86InstIdCvtpd2ps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(cvtpd2ps, kX86InstIdCvtpd2ps, X86XmmVar, X86Mem) + + //! Convert packed DWORDs to packed DP-FP (SSE2). + INST_2x(cvtpi2pd, kX86InstIdCvtpi2pd, X86XmmVar, X86MmVar) + //! \overload + INST_2x(cvtpi2pd, kX86InstIdCvtpi2pd, X86XmmVar, X86Mem) + + //! Convert packed SP-FP to packed DWORDs (SSE2). + INST_2x(cvtps2dq, kX86InstIdCvtps2dq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(cvtps2dq, kX86InstIdCvtps2dq, X86XmmVar, X86Mem) + + //! Convert packed SP-FP to packed DP-FP (SSE2). + INST_2x(cvtps2pd, kX86InstIdCvtps2pd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(cvtps2pd, kX86InstIdCvtps2pd, X86XmmVar, X86Mem) + + //! Convert scalar DP-FP to DWORD (SSE2). + INST_2x(cvtsd2si, kX86InstIdCvtsd2si, X86GpVar, X86XmmVar) + //! \overload + INST_2x(cvtsd2si, kX86InstIdCvtsd2si, X86GpVar, X86Mem) + + //! Convert scalar DP-FP to scalar SP-FP (SSE2). + INST_2x(cvtsd2ss, kX86InstIdCvtsd2ss, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(cvtsd2ss, kX86InstIdCvtsd2ss, X86XmmVar, X86Mem) + + //! Convert DWORD to scalar DP-FP (SSE2). + INST_2x(cvtsi2sd, kX86InstIdCvtsi2sd, X86XmmVar, X86GpVar) + //! \overload + INST_2x(cvtsi2sd, kX86InstIdCvtsi2sd, X86XmmVar, X86Mem) + + //! Convert scalar SP-FP to DP-FP (SSE2). + INST_2x(cvtss2sd, kX86InstIdCvtss2sd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(cvtss2sd, kX86InstIdCvtss2sd, X86XmmVar, X86Mem) + + //! Convert with truncation packed DP-FP to packed DWORDs (SSE2). + INST_2x(cvttpd2pi, kX86InstIdCvttpd2pi, X86MmVar, X86XmmVar) + //! \overload + INST_2x(cvttpd2pi, kX86InstIdCvttpd2pi, X86MmVar, X86Mem) + + //! Convert with truncation packed DP-FP to packed QWORDs (SSE2). + INST_2x(cvttpd2dq, kX86InstIdCvttpd2dq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(cvttpd2dq, kX86InstIdCvttpd2dq, X86XmmVar, X86Mem) + + //! Convert with truncation packed SP-FP to packed QWORDs (SSE2). + INST_2x(cvttps2dq, kX86InstIdCvttps2dq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(cvttps2dq, kX86InstIdCvttps2dq, X86XmmVar, X86Mem) + + //! Convert with truncation scalar DP-FP to DWORD (SSE2). + INST_2x(cvttsd2si, kX86InstIdCvttsd2si, X86GpVar, X86XmmVar) + //! \overload + INST_2x(cvttsd2si, kX86InstIdCvttsd2si, X86GpVar, X86Mem) + + //! Packed DP-FP divide (SSE2). + INST_2x(divpd, kX86InstIdDivpd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(divpd, kX86InstIdDivpd, X86XmmVar, X86Mem) + + //! Scalar DP-FP divide (SSE2). + INST_2x(divsd, kX86InstIdDivsd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(divsd, kX86InstIdDivsd, X86XmmVar, X86Mem) + + //! Load fence (SSE2). + INST_0x(lfence, kX86InstIdLfence) + + //! Store selected bytes of OWORD (SSE2). + INST_3x(maskmovdqu, kX86InstIdMaskmovdqu, X86GpVar /* zdi */, X86XmmVar, X86XmmVar) + + //! Packed DP-FP maximum (SSE2). + INST_2x(maxpd, kX86InstIdMaxpd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(maxpd, kX86InstIdMaxpd, X86XmmVar, X86Mem) + + //! Scalar DP-FP maximum (SSE2). + INST_2x(maxsd, kX86InstIdMaxsd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(maxsd, kX86InstIdMaxsd, X86XmmVar, X86Mem) + + //! Memory fence (SSE2). + INST_0x(mfence, kX86InstIdMfence) + + //! Packed DP-FP minimum (SSE2). + INST_2x(minpd, kX86InstIdMinpd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(minpd, kX86InstIdMinpd, X86XmmVar, X86Mem) + + //! Scalar DP-FP minimum (SSE2). + INST_2x(minsd, kX86InstIdMinsd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(minsd, kX86InstIdMinsd, X86XmmVar, X86Mem) + + //! Move aligned OWORD (SSE2). + INST_2x(movdqa, kX86InstIdMovdqa, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(movdqa, kX86InstIdMovdqa, X86XmmVar, X86Mem) + //! \overload + INST_2x(movdqa, kX86InstIdMovdqa, X86Mem, X86XmmVar) + + //! Move unaligned OWORD (SSE2). + INST_2x(movdqu, kX86InstIdMovdqu, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(movdqu, kX86InstIdMovdqu, X86XmmVar, X86Mem) + //! \overload + INST_2x(movdqu, kX86InstIdMovdqu, X86Mem, X86XmmVar) + + //! Extract packed SP-FP sign mask (SSE2). + INST_2x(movmskps, kX86InstIdMovmskps, X86GpVar, X86XmmVar) + + //! Extract packed DP-FP sign mask (SSE2). + INST_2x(movmskpd, kX86InstIdMovmskpd, X86GpVar, X86XmmVar) + + //! Move scalar DP-FP (SSE2). + INST_2x(movsd, kX86InstIdMovsd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(movsd, kX86InstIdMovsd, X86XmmVar, X86Mem) + //! \overload + INST_2x(movsd, kX86InstIdMovsd, X86Mem, X86XmmVar) + + //! Move aligned packed DP-FP (SSE2). + INST_2x(movapd, kX86InstIdMovapd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(movapd, kX86InstIdMovapd, X86XmmVar, X86Mem) + //! \overload + INST_2x(movapd, kX86InstIdMovapd, X86Mem, X86XmmVar) + + //! Move QWORD from Xmm to Mm register (SSE2). + INST_2x(movdq2q, kX86InstIdMovdq2q, X86MmVar, X86XmmVar) + + //! Move QWORD from Mm to Xmm register (SSE2). + INST_2x(movq2dq, kX86InstIdMovq2dq, X86XmmVar, X86MmVar) + + //! Move high packed DP-FP (SSE2). + INST_2x(movhpd, kX86InstIdMovhpd, X86XmmVar, X86Mem) + //! \overload + INST_2x(movhpd, kX86InstIdMovhpd, X86Mem, X86XmmVar) + + //! Move low packed DP-FP (SSE2). + INST_2x(movlpd, kX86InstIdMovlpd, X86XmmVar, X86Mem) + //! \overload + INST_2x(movlpd, kX86InstIdMovlpd, X86Mem, X86XmmVar) + + //! Store OWORD using NT hint (SSE2). + INST_2x(movntdq, kX86InstIdMovntdq, X86Mem, X86XmmVar) + + //! Store DWORD using NT hint (SSE2). + INST_2x(movnti, kX86InstIdMovnti, X86Mem, X86GpVar) + + //! Store packed DP-FP using NT hint (SSE2). + INST_2x(movntpd, kX86InstIdMovntpd, X86Mem, X86XmmVar) + + //! Move unaligned packed DP-FP (SSE2). + INST_2x(movupd, kX86InstIdMovupd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(movupd, kX86InstIdMovupd, X86XmmVar, X86Mem) + //! \overload + INST_2x(movupd, kX86InstIdMovupd, X86Mem, X86XmmVar) + + //! Packed DP-FP multiply (SSE2). + INST_2x(mulpd, kX86InstIdMulpd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(mulpd, kX86InstIdMulpd, X86XmmVar, X86Mem) + + //! Scalar DP-FP multiply (SSE2). + INST_2x(mulsd, kX86InstIdMulsd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(mulsd, kX86InstIdMulsd, X86XmmVar, X86Mem) + + //! Packed DP-FP bitwise or (SSE2). + INST_2x(orpd, kX86InstIdOrpd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(orpd, kX86InstIdOrpd, X86XmmVar, X86Mem) + + //! Pack WORDs to BYTEs with signed saturation (SSE2). + INST_2x(packsswb, kX86InstIdPacksswb, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(packsswb, kX86InstIdPacksswb, X86XmmVar, X86Mem) + + //! Pack DWORDs to WORDs with signed saturation (SSE2). + INST_2x(packssdw, kX86InstIdPackssdw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(packssdw, kX86InstIdPackssdw, X86XmmVar, X86Mem) + + //! Pack WORDs to BYTEs with unsigned saturation (SSE2). + INST_2x(packuswb, kX86InstIdPackuswb, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(packuswb, kX86InstIdPackuswb, X86XmmVar, X86Mem) + + //! Packed BYTE add (SSE2). + INST_2x(paddb, kX86InstIdPaddb, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(paddb, kX86InstIdPaddb, X86XmmVar, X86Mem) + + //! Packed WORD add (SSE2). + INST_2x(paddw, kX86InstIdPaddw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(paddw, kX86InstIdPaddw, X86XmmVar, X86Mem) + + //! Packed DWORD add (SSE2). + INST_2x(paddd, kX86InstIdPaddd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(paddd, kX86InstIdPaddd, X86XmmVar, X86Mem) + + //! Packed QWORD add (SSE2). + INST_2x(paddq, kX86InstIdPaddq, X86MmVar, X86MmVar) + //! \overload + INST_2x(paddq, kX86InstIdPaddq, X86MmVar, X86Mem) + + //! Packed QWORD add (SSE2). + INST_2x(paddq, kX86InstIdPaddq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(paddq, kX86InstIdPaddq, X86XmmVar, X86Mem) + + //! Packed BYTE add with saturation (SSE2). + INST_2x(paddsb, kX86InstIdPaddsb, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(paddsb, kX86InstIdPaddsb, X86XmmVar, X86Mem) + + //! Packed WORD add with saturation (SSE2). + INST_2x(paddsw, kX86InstIdPaddsw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(paddsw, kX86InstIdPaddsw, X86XmmVar, X86Mem) + + //! Packed BYTE add with unsigned saturation (SSE2). + INST_2x(paddusb, kX86InstIdPaddusb, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(paddusb, kX86InstIdPaddusb, X86XmmVar, X86Mem) + + //! Packed WORD add with unsigned saturation (SSE2). + INST_2x(paddusw, kX86InstIdPaddusw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(paddusw, kX86InstIdPaddusw, X86XmmVar, X86Mem) + + //! Packed bitwise and (SSE2). + INST_2x(pand, kX86InstIdPand, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pand, kX86InstIdPand, X86XmmVar, X86Mem) + + //! Packed bitwise and-not (SSE2). + INST_2x(pandn, kX86InstIdPandn, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pandn, kX86InstIdPandn, X86XmmVar, X86Mem) + + //! Spin loop hint (SSE2). + INST_0x(pause, kX86InstIdPause) + + //! Packed BYTE average (SSE2). + INST_2x(pavgb, kX86InstIdPavgb, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pavgb, kX86InstIdPavgb, X86XmmVar, X86Mem) + + //! Packed WORD average (SSE2). + INST_2x(pavgw, kX86InstIdPavgw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pavgw, kX86InstIdPavgw, X86XmmVar, X86Mem) + + //! Packed BYTE compare for equality (SSE2). + INST_2x(pcmpeqb, kX86InstIdPcmpeqb, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pcmpeqb, kX86InstIdPcmpeqb, X86XmmVar, X86Mem) + + //! Packed WROD compare for equality (SSE2). + INST_2x(pcmpeqw, kX86InstIdPcmpeqw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pcmpeqw, kX86InstIdPcmpeqw, X86XmmVar, X86Mem) + + //! Packed DWORD compare for equality (SSE2). + INST_2x(pcmpeqd, kX86InstIdPcmpeqd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pcmpeqd, kX86InstIdPcmpeqd, X86XmmVar, X86Mem) + + //! Packed BYTE compare if greater than (SSE2). + INST_2x(pcmpgtb, kX86InstIdPcmpgtb, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pcmpgtb, kX86InstIdPcmpgtb, X86XmmVar, X86Mem) + + //! Packed WORD compare if greater than (SSE2). + INST_2x(pcmpgtw, kX86InstIdPcmpgtw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pcmpgtw, kX86InstIdPcmpgtw, X86XmmVar, X86Mem) + + //! Packed DWORD compare if greater than (SSE2). + INST_2x(pcmpgtd, kX86InstIdPcmpgtd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pcmpgtd, kX86InstIdPcmpgtd, X86XmmVar, X86Mem) + + //! Extract WORD based on selector (SSE2). + INST_3i(pextrw, kX86InstIdPextrw, X86GpVar, X86XmmVar, Imm) + + //! Insert WORD based on selector (SSE2). + INST_3i(pinsrw, kX86InstIdPinsrw, X86XmmVar, X86GpVar, Imm) + //! \overload + INST_3i(pinsrw, kX86InstIdPinsrw, X86XmmVar, X86Mem, Imm) + + //! Packed WORD maximum (SSE2). + INST_2x(pmaxsw, kX86InstIdPmaxsw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmaxsw, kX86InstIdPmaxsw, X86XmmVar, X86Mem) + + //! Packed BYTE unsigned maximum (SSE2). + INST_2x(pmaxub, kX86InstIdPmaxub, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmaxub, kX86InstIdPmaxub, X86XmmVar, X86Mem) + + //! Packed WORD minimum (SSE2). + INST_2x(pminsw, kX86InstIdPminsw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pminsw, kX86InstIdPminsw, X86XmmVar, X86Mem) + + //! Packed BYTE unsigned minimum (SSE2). + INST_2x(pminub, kX86InstIdPminub, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pminub, kX86InstIdPminub, X86XmmVar, X86Mem) + + //! Move BYTE mask (SSE2). + INST_2x(pmovmskb, kX86InstIdPmovmskb, X86GpVar, X86XmmVar) + + //! Packed WORD multiply high (SSE2). + INST_2x(pmulhw, kX86InstIdPmulhw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmulhw, kX86InstIdPmulhw, X86XmmVar, X86Mem) + + //! Packed WORD unsigned multiply high (SSE2). + INST_2x(pmulhuw, kX86InstIdPmulhuw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmulhuw, kX86InstIdPmulhuw, X86XmmVar, X86Mem) + + //! Packed WORD multiply low (SSE2). + INST_2x(pmullw, kX86InstIdPmullw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmullw, kX86InstIdPmullw, X86XmmVar, X86Mem) + + //! Packed DWORD multiply to QWORD (SSE2). + INST_2x(pmuludq, kX86InstIdPmuludq, X86MmVar, X86MmVar) + //! \overload + INST_2x(pmuludq, kX86InstIdPmuludq, X86MmVar, X86Mem) + + //! Packed DWORD multiply to QWORD (SSE2). + INST_2x(pmuludq, kX86InstIdPmuludq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmuludq, kX86InstIdPmuludq, X86XmmVar, X86Mem) + + //! Packed bitwise or (SSE2). + INST_2x(por, kX86InstIdPor, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(por, kX86InstIdPor, X86XmmVar, X86Mem) + + //! Packed DWORD shift left logical (SSE2). + INST_2x(pslld, kX86InstIdPslld, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pslld, kX86InstIdPslld, X86XmmVar, X86Mem) + //! \overload + INST_2i(pslld, kX86InstIdPslld, X86XmmVar, Imm) + + //! Packed QWORD shift left logical (SSE2). + INST_2x(psllq, kX86InstIdPsllq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psllq, kX86InstIdPsllq, X86XmmVar, X86Mem) + //! \overload + INST_2i(psllq, kX86InstIdPsllq, X86XmmVar, Imm) + + //! Packed WORD shift left logical (SSE2). + INST_2x(psllw, kX86InstIdPsllw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psllw, kX86InstIdPsllw, X86XmmVar, X86Mem) + //! \overload + INST_2i(psllw, kX86InstIdPsllw, X86XmmVar, Imm) + + //! Packed OWORD shift left logical (SSE2). + INST_2i(pslldq, kX86InstIdPslldq, X86XmmVar, Imm) + + //! Packed DWORD shift right arithmetic (SSE2). + INST_2x(psrad, kX86InstIdPsrad, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psrad, kX86InstIdPsrad, X86XmmVar, X86Mem) + //! \overload + INST_2i(psrad, kX86InstIdPsrad, X86XmmVar, Imm) + + //! Packed WORD shift right arithmetic (SSE2). + INST_2x(psraw, kX86InstIdPsraw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psraw, kX86InstIdPsraw, X86XmmVar, X86Mem) + //! \overload + INST_2i(psraw, kX86InstIdPsraw, X86XmmVar, Imm) + + //! Packed BYTE subtract (SSE2). + INST_2x(psubb, kX86InstIdPsubb, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psubb, kX86InstIdPsubb, X86XmmVar, X86Mem) + + //! Packed DWORD subtract (SSE2). + INST_2x(psubd, kX86InstIdPsubd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psubd, kX86InstIdPsubd, X86XmmVar, X86Mem) + + //! Packed QWORD subtract (SSE2). + INST_2x(psubq, kX86InstIdPsubq, X86MmVar, X86MmVar) + //! \overload + INST_2x(psubq, kX86InstIdPsubq, X86MmVar, X86Mem) + + //! Packed QWORD subtract (SSE2). + INST_2x(psubq, kX86InstIdPsubq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psubq, kX86InstIdPsubq, X86XmmVar, X86Mem) + + //! Packed WORD subtract (SSE2). + INST_2x(psubw, kX86InstIdPsubw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psubw, kX86InstIdPsubw, X86XmmVar, X86Mem) + + //! Packed WORD to DWORD multiply and add (SSE2). + INST_2x(pmaddwd, kX86InstIdPmaddwd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmaddwd, kX86InstIdPmaddwd, X86XmmVar, X86Mem) + + //! Packed DWORD shuffle (SSE2). + INST_3i(pshufd, kX86InstIdPshufd, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(pshufd, kX86InstIdPshufd, X86XmmVar, X86Mem, Imm) + + //! Packed WORD shuffle high (SSE2). + INST_3i(pshufhw, kX86InstIdPshufhw, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(pshufhw, kX86InstIdPshufhw, X86XmmVar, X86Mem, Imm) + + //! Packed WORD shuffle low (SSE2). + INST_3i(pshuflw, kX86InstIdPshuflw, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(pshuflw, kX86InstIdPshuflw, X86XmmVar, X86Mem, Imm) + + //! Packed DWORD shift right logical (SSE2). + INST_2x(psrld, kX86InstIdPsrld, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psrld, kX86InstIdPsrld, X86XmmVar, X86Mem) + //! \overload + INST_2i(psrld, kX86InstIdPsrld, X86XmmVar, Imm) + + //! Packed QWORD shift right logical (SSE2). + INST_2x(psrlq, kX86InstIdPsrlq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psrlq, kX86InstIdPsrlq, X86XmmVar, X86Mem) + //! \overload + INST_2i(psrlq, kX86InstIdPsrlq, X86XmmVar, Imm) + + //! Scalar OWORD shift right logical (SSE2). + INST_2i(psrldq, kX86InstIdPsrldq, X86XmmVar, Imm) + + //! Packed WORD shift right logical (SSE2). + INST_2x(psrlw, kX86InstIdPsrlw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psrlw, kX86InstIdPsrlw, X86XmmVar, X86Mem) + //! \overload + INST_2i(psrlw, kX86InstIdPsrlw, X86XmmVar, Imm) + + //! Packed BYTE subtract with saturation (SSE2). + INST_2x(psubsb, kX86InstIdPsubsb, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psubsb, kX86InstIdPsubsb, X86XmmVar, X86Mem) + + //! Packed WORD subtract with saturation (SSE2). + INST_2x(psubsw, kX86InstIdPsubsw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psubsw, kX86InstIdPsubsw, X86XmmVar, X86Mem) + + //! Packed BYTE subtract with unsigned saturation (SSE2). + INST_2x(psubusb, kX86InstIdPsubusb, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psubusb, kX86InstIdPsubusb, X86XmmVar, X86Mem) + + //! Packed WORD subtract with unsigned saturation (SSE2). + INST_2x(psubusw, kX86InstIdPsubusw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psubusw, kX86InstIdPsubusw, X86XmmVar, X86Mem) + + //! Unpack high packed BYTEs to WORDs (SSE2). + INST_2x(punpckhbw, kX86InstIdPunpckhbw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(punpckhbw, kX86InstIdPunpckhbw, X86XmmVar, X86Mem) + + //! Unpack high packed DWORDs to QWORDs (SSE2). + INST_2x(punpckhdq, kX86InstIdPunpckhdq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(punpckhdq, kX86InstIdPunpckhdq, X86XmmVar, X86Mem) + + //! Unpack high packed QWORDs to OWORD (SSE2). + INST_2x(punpckhqdq, kX86InstIdPunpckhqdq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(punpckhqdq, kX86InstIdPunpckhqdq, X86XmmVar, X86Mem) + + //! Unpack high packed WORDs to DWORDs (SSE2). + INST_2x(punpckhwd, kX86InstIdPunpckhwd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(punpckhwd, kX86InstIdPunpckhwd, X86XmmVar, X86Mem) + + //! Unpack low packed BYTEs to WORDs (SSE2). + INST_2x(punpcklbw, kX86InstIdPunpcklbw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(punpcklbw, kX86InstIdPunpcklbw, X86XmmVar, X86Mem) + + //! Unpack low packed DWORDs to QWORDs (SSE2). + INST_2x(punpckldq, kX86InstIdPunpckldq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(punpckldq, kX86InstIdPunpckldq, X86XmmVar, X86Mem) + + //! Unpack low packed QWORDs to OWORD (SSE2). + INST_2x(punpcklqdq, kX86InstIdPunpcklqdq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(punpcklqdq, kX86InstIdPunpcklqdq, X86XmmVar, X86Mem) + + //! Unpack low packed WORDs to DWORDs (SSE2). + INST_2x(punpcklwd, kX86InstIdPunpcklwd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(punpcklwd, kX86InstIdPunpcklwd, X86XmmVar, X86Mem) + + //! Packed bitwise xor (SSE2). + INST_2x(pxor, kX86InstIdPxor, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pxor, kX86InstIdPxor, X86XmmVar, X86Mem) + + //! Shuffle DP-FP (SSE2). + INST_3i(shufpd, kX86InstIdShufpd, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(shufpd, kX86InstIdShufpd, X86XmmVar, X86Mem, Imm) + + //! Packed DP-FP square root (SSE2). + INST_2x(sqrtpd, kX86InstIdSqrtpd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(sqrtpd, kX86InstIdSqrtpd, X86XmmVar, X86Mem) + + //! Scalar DP-FP square root (SSE2). + INST_2x(sqrtsd, kX86InstIdSqrtsd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(sqrtsd, kX86InstIdSqrtsd, X86XmmVar, X86Mem) + + //! Packed DP-FP subtract (SSE2). + INST_2x(subpd, kX86InstIdSubpd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(subpd, kX86InstIdSubpd, X86XmmVar, X86Mem) + + //! Scalar DP-FP subtract (SSE2). + INST_2x(subsd, kX86InstIdSubsd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(subsd, kX86InstIdSubsd, X86XmmVar, X86Mem) + + //! Scalar DP-FP unordered compare and set EFLAGS (SSE2). + INST_2x(ucomisd, kX86InstIdUcomisd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(ucomisd, kX86InstIdUcomisd, X86XmmVar, X86Mem) + + //! Unpack and interleave high packed DP-FP (SSE2). + INST_2x(unpckhpd, kX86InstIdUnpckhpd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(unpckhpd, kX86InstIdUnpckhpd, X86XmmVar, X86Mem) + + //! Unpack and interleave low packed DP-FP (SSE2). + INST_2x(unpcklpd, kX86InstIdUnpcklpd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(unpcklpd, kX86InstIdUnpcklpd, X86XmmVar, X86Mem) + + //! Packed DP-FP bitwise xor (SSE2). + INST_2x(xorpd, kX86InstIdXorpd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(xorpd, kX86InstIdXorpd, X86XmmVar, X86Mem) + + // -------------------------------------------------------------------------- + // [SSE3] + // -------------------------------------------------------------------------- + + //! Packed DP-FP add/subtract (SSE3). + INST_2x(addsubpd, kX86InstIdAddsubpd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(addsubpd, kX86InstIdAddsubpd, X86XmmVar, X86Mem) + + //! Packed SP-FP add/subtract (SSE3). + INST_2x(addsubps, kX86InstIdAddsubps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(addsubps, kX86InstIdAddsubps, X86XmmVar, X86Mem) + + //! Store truncated `fp0` to `short_or_int_or_long[o0]` and POP (FPU & SSE3). + INST_1x(fisttp, kX86InstIdFisttp, X86Mem) + + //! Packed DP-FP horizontal add (SSE3). + INST_2x(haddpd, kX86InstIdHaddpd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(haddpd, kX86InstIdHaddpd, X86XmmVar, X86Mem) + + //! Packed SP-FP horizontal add (SSE3). + INST_2x(haddps, kX86InstIdHaddps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(haddps, kX86InstIdHaddps, X86XmmVar, X86Mem) + + //! Packed DP-FP horizontal subtract (SSE3). + INST_2x(hsubpd, kX86InstIdHsubpd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(hsubpd, kX86InstIdHsubpd, X86XmmVar, X86Mem) + + //! Packed SP-FP horizontal subtract (SSE3). + INST_2x(hsubps, kX86InstIdHsubps, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(hsubps, kX86InstIdHsubps, X86XmmVar, X86Mem) + + //! Load 128-bits unaligned (SSE3). + INST_2x(lddqu, kX86InstIdLddqu, X86XmmVar, X86Mem) + + // //! Setup monitor address (SSE3). + // INST_0x(monitor, kX86InstIdMonitor) + + //! Move one DP-FP and duplicate (SSE3). + INST_2x(movddup, kX86InstIdMovddup, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(movddup, kX86InstIdMovddup, X86XmmVar, X86Mem) + + //! Move packed SP-FP high and duplicate (SSE3). + INST_2x(movshdup, kX86InstIdMovshdup, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(movshdup, kX86InstIdMovshdup, X86XmmVar, X86Mem) + + //! Move packed SP-FP low and duplicate (SSE3). + INST_2x(movsldup, kX86InstIdMovsldup, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(movsldup, kX86InstIdMovsldup, X86XmmVar, X86Mem) + + // //! Monitor wait (SSE3). + // INST_0x(mwait, kX86InstIdMwait) + + // -------------------------------------------------------------------------- + // [SSSE3] + // -------------------------------------------------------------------------- + + //! Packed BYTE sign (SSSE3). + INST_2x(psignb, kX86InstIdPsignb, X86MmVar, X86MmVar) + //! \overload + INST_2x(psignb, kX86InstIdPsignb, X86MmVar, X86Mem) + + //! PackedBYTE sign (SSSE3). + INST_2x(psignb, kX86InstIdPsignb, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psignb, kX86InstIdPsignb, X86XmmVar, X86Mem) + + //! Packed DWORD sign (SSSE3). + INST_2x(psignd, kX86InstIdPsignd, X86MmVar, X86MmVar) + //! \overload + INST_2x(psignd, kX86InstIdPsignd, X86MmVar, X86Mem) + + //! Packed DWORD sign (SSSE3). + INST_2x(psignd, kX86InstIdPsignd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psignd, kX86InstIdPsignd, X86XmmVar, X86Mem) + + //! Packed WORD sign (SSSE3). + INST_2x(psignw, kX86InstIdPsignw, X86MmVar, X86MmVar) + //! \overload + INST_2x(psignw, kX86InstIdPsignw, X86MmVar, X86Mem) + + //! Packed WORD sign (SSSE3). + INST_2x(psignw, kX86InstIdPsignw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(psignw, kX86InstIdPsignw, X86XmmVar, X86Mem) + + //! Packed DWORD horizontal add (SSSE3). + INST_2x(phaddd, kX86InstIdPhaddd, X86MmVar, X86MmVar) + //! \overload + INST_2x(phaddd, kX86InstIdPhaddd, X86MmVar, X86Mem) + + //! Packed DWORD horizontal add (SSSE3). + INST_2x(phaddd, kX86InstIdPhaddd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(phaddd, kX86InstIdPhaddd, X86XmmVar, X86Mem) + + //! Packed WORD horizontal add with saturation (SSSE3). + INST_2x(phaddsw, kX86InstIdPhaddsw, X86MmVar, X86MmVar) + //! \overload + INST_2x(phaddsw, kX86InstIdPhaddsw, X86MmVar, X86Mem) + + //! Packed WORD horizontal add with with saturation (SSSE3). + INST_2x(phaddsw, kX86InstIdPhaddsw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(phaddsw, kX86InstIdPhaddsw, X86XmmVar, X86Mem) + + //! Packed WORD horizontal add (SSSE3). + INST_2x(phaddw, kX86InstIdPhaddw, X86MmVar, X86MmVar) + //! \overload + INST_2x(phaddw, kX86InstIdPhaddw, X86MmVar, X86Mem) + + //! Packed WORD horizontal add (SSSE3). + INST_2x(phaddw, kX86InstIdPhaddw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(phaddw, kX86InstIdPhaddw, X86XmmVar, X86Mem) + + //! Packed DWORD horizontal subtract (SSSE3). + INST_2x(phsubd, kX86InstIdPhsubd, X86MmVar, X86MmVar) + //! \overload + INST_2x(phsubd, kX86InstIdPhsubd, X86MmVar, X86Mem) + + //! Packed DWORD horizontal subtract (SSSE3). + INST_2x(phsubd, kX86InstIdPhsubd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(phsubd, kX86InstIdPhsubd, X86XmmVar, X86Mem) + + //! Packed WORD horizontal subtract with saturation (SSSE3). + INST_2x(phsubsw, kX86InstIdPhsubsw, X86MmVar, X86MmVar) + //! \overload + INST_2x(phsubsw, kX86InstIdPhsubsw, X86MmVar, X86Mem) + + //! Packed WORD horizontal subtract with saturation (SSSE3). + INST_2x(phsubsw, kX86InstIdPhsubsw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(phsubsw, kX86InstIdPhsubsw, X86XmmVar, X86Mem) + + //! Packed WORD horizontal subtract (SSSE3). + INST_2x(phsubw, kX86InstIdPhsubw, X86MmVar, X86MmVar) + //! \overload + INST_2x(phsubw, kX86InstIdPhsubw, X86MmVar, X86Mem) + + //! Packed WORD horizontal subtract (SSSE3). + INST_2x(phsubw, kX86InstIdPhsubw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(phsubw, kX86InstIdPhsubw, X86XmmVar, X86Mem) + + //! Packed multiply and add signed and unsigned bytes (SSSE3). + INST_2x(pmaddubsw, kX86InstIdPmaddubsw, X86MmVar, X86MmVar) + //! \overload + INST_2x(pmaddubsw, kX86InstIdPmaddubsw, X86MmVar, X86Mem) + + //! Packed multiply and add signed and unsigned bytes (SSSE3). + INST_2x(pmaddubsw, kX86InstIdPmaddubsw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmaddubsw, kX86InstIdPmaddubsw, X86XmmVar, X86Mem) + + //! Packed BYTE absolute value (SSSE3). + INST_2x(pabsb, kX86InstIdPabsb, X86MmVar, X86MmVar) + //! \overload + INST_2x(pabsb, kX86InstIdPabsb, X86MmVar, X86Mem) + + //! Packed BYTE absolute value (SSSE3). + INST_2x(pabsb, kX86InstIdPabsb, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pabsb, kX86InstIdPabsb, X86XmmVar, X86Mem) + + //! Packed DWORD absolute value (SSSE3). + INST_2x(pabsd, kX86InstIdPabsd, X86MmVar, X86MmVar) + //! \overload + INST_2x(pabsd, kX86InstIdPabsd, X86MmVar, X86Mem) + + //! Packed DWORD absolute value (SSSE3). + INST_2x(pabsd, kX86InstIdPabsd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pabsd, kX86InstIdPabsd, X86XmmVar, X86Mem) + + //! Packed WORD absolute value (SSSE3). + INST_2x(pabsw, kX86InstIdPabsw, X86MmVar, X86MmVar) + //! \overload + INST_2x(pabsw, kX86InstIdPabsw, X86MmVar, X86Mem) + + //! Packed WORD absolute value (SSSE3). + INST_2x(pabsw, kX86InstIdPabsw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pabsw, kX86InstIdPabsw, X86XmmVar, X86Mem) + + //! Packed WORD multiply high, round and scale (SSSE3). + INST_2x(pmulhrsw, kX86InstIdPmulhrsw, X86MmVar, X86MmVar) + //! \overload + INST_2x(pmulhrsw, kX86InstIdPmulhrsw, X86MmVar, X86Mem) + + //! Packed WORD multiply high, round and scale (SSSE3). + INST_2x(pmulhrsw, kX86InstIdPmulhrsw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmulhrsw, kX86InstIdPmulhrsw, X86XmmVar, X86Mem) + + //! Packed BYTE shuffle (SSSE3). + INST_2x(pshufb, kX86InstIdPshufb, X86MmVar, X86MmVar) + //! \overload + INST_2x(pshufb, kX86InstIdPshufb, X86MmVar, X86Mem) + + //! Packed BYTE shuffle (SSSE3). + INST_2x(pshufb, kX86InstIdPshufb, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pshufb, kX86InstIdPshufb, X86XmmVar, X86Mem) + + //! Packed align right (SSSE3). + INST_3i(palignr, kX86InstIdPalignr, X86MmVar, X86MmVar, Imm) + //! \overload + INST_3i(palignr, kX86InstIdPalignr, X86MmVar, X86Mem, Imm) + + //! Packed align right (SSSE3). + INST_3i(palignr, kX86InstIdPalignr, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(palignr, kX86InstIdPalignr, X86XmmVar, X86Mem, Imm) + + // -------------------------------------------------------------------------- + // [SSE4.1] + // -------------------------------------------------------------------------- + + //! Packed DP-FP blend (SSE4.1). + INST_3i(blendpd, kX86InstIdBlendpd, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(blendpd, kX86InstIdBlendpd, X86XmmVar, X86Mem, Imm) + + //! Packed SP-FP blend (SSE4.1). + INST_3i(blendps, kX86InstIdBlendps, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(blendps, kX86InstIdBlendps, X86XmmVar, X86Mem, Imm) + + //! Packed DP-FP variable blend (SSE4.1). + INST_3x(blendvpd, kX86InstIdBlendvpd, X86XmmVar, X86XmmVar, X86XmmVar) + //! \overload + INST_3x(blendvpd, kX86InstIdBlendvpd, X86XmmVar, X86Mem, X86XmmVar) + + //! Packed SP-FP variable blend (SSE4.1). + INST_3x(blendvps, kX86InstIdBlendvps, X86XmmVar, X86XmmVar, X86XmmVar) + //! \overload + INST_3x(blendvps, kX86InstIdBlendvps, X86XmmVar, X86Mem, X86XmmVar) + + //! Packed DP-FP dot product (SSE4.1). + INST_3i(dppd, kX86InstIdDppd, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(dppd, kX86InstIdDppd, X86XmmVar, X86Mem, Imm) + + //! Packed SP-FP dot product (SSE4.1). + INST_3i(dpps, kX86InstIdDpps, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(dpps, kX86InstIdDpps, X86XmmVar, X86Mem, Imm) + + //! Extract SP-FP based on selector (SSE4.1). + INST_3i(extractps, kX86InstIdExtractps, X86GpVar, X86XmmVar, Imm) + //! \overload + INST_3i(extractps, kX86InstIdExtractps, X86Mem, X86XmmVar, Imm) + + //! Insert SP-FP based on selector (SSE4.1). + INST_3i(insertps, kX86InstIdInsertps, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(insertps, kX86InstIdInsertps, X86XmmVar, X86Mem, Imm) + + //! Load OWORD aligned using NT hint (SSE4.1). + INST_2x(movntdqa, kX86InstIdMovntdqa, X86XmmVar, X86Mem) + + //! Packed WORD sums of absolute difference (SSE4.1). + INST_3i(mpsadbw, kX86InstIdMpsadbw, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(mpsadbw, kX86InstIdMpsadbw, X86XmmVar, X86Mem, Imm) + + //! Pack DWORDs to WORDs with unsigned saturation (SSE4.1). + INST_2x(packusdw, kX86InstIdPackusdw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(packusdw, kX86InstIdPackusdw, X86XmmVar, X86Mem) + + //! Packed BYTE variable blend (SSE4.1). + INST_3x(pblendvb, kX86InstIdPblendvb, X86XmmVar, X86XmmVar, X86XmmVar) + //! \overload + INST_3x(pblendvb, kX86InstIdPblendvb, X86XmmVar, X86Mem, X86XmmVar) + + //! Packed WORD blend (SSE4.1). + INST_3i(pblendw, kX86InstIdPblendw, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(pblendw, kX86InstIdPblendw, X86XmmVar, X86Mem, Imm) + + //! Packed QWORD compare for equality (SSE4.1). + INST_2x(pcmpeqq, kX86InstIdPcmpeqq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pcmpeqq, kX86InstIdPcmpeqq, X86XmmVar, X86Mem) + + //! Extract BYTE based on selector (SSE4.1). + INST_3i(pextrb, kX86InstIdPextrb, X86GpVar, X86XmmVar, Imm) + //! \overload + INST_3i(pextrb, kX86InstIdPextrb, X86Mem, X86XmmVar, Imm) + + //! Extract DWORD based on selector (SSE4.1). + INST_3i(pextrd, kX86InstIdPextrd, X86GpVar, X86XmmVar, Imm) + //! \overload + INST_3i(pextrd, kX86InstIdPextrd, X86Mem, X86XmmVar, Imm) + + //! Extract QWORD based on selector (SSE4.1). + INST_3i(pextrq, kX86InstIdPextrq, X86GpVar, X86XmmVar, Imm) + //! \overload + INST_3i(pextrq, kX86InstIdPextrq, X86Mem, X86XmmVar, Imm) + + //! Extract WORD based on selector (SSE4.1). + INST_3i(pextrw, kX86InstIdPextrw, X86Mem, X86XmmVar, Imm) + + //! Packed WORD horizontal minimum (SSE4.1). + INST_2x(phminposuw, kX86InstIdPhminposuw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(phminposuw, kX86InstIdPhminposuw, X86XmmVar, X86Mem) + + //! Insert BYTE based on selector (SSE4.1). + INST_3i(pinsrb, kX86InstIdPinsrb, X86XmmVar, X86GpVar, Imm) + //! \overload + INST_3i(pinsrb, kX86InstIdPinsrb, X86XmmVar, X86Mem, Imm) + + //! Insert DWORD based on selector (SSE4.1). + INST_3i(pinsrd, kX86InstIdPinsrd, X86XmmVar, X86GpVar, Imm) + //! \overload + INST_3i(pinsrd, kX86InstIdPinsrd, X86XmmVar, X86Mem, Imm) + + //! Insert QWORD based on selector (SSE4.1). + INST_3i(pinsrq, kX86InstIdPinsrq, X86XmmVar, X86GpVar, Imm) + //! \overload + INST_3i(pinsrq, kX86InstIdPinsrq, X86XmmVar, X86Mem, Imm) + + //! Packed BYTE maximum (SSE4.1). + INST_2x(pmaxsb, kX86InstIdPmaxsb, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmaxsb, kX86InstIdPmaxsb, X86XmmVar, X86Mem) + + //! Packed DWORD maximum (SSE4.1). + INST_2x(pmaxsd, kX86InstIdPmaxsd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmaxsd, kX86InstIdPmaxsd, X86XmmVar, X86Mem) + + //! Packed DWORD unsigned maximum (SSE4.1). + INST_2x(pmaxud, kX86InstIdPmaxud, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmaxud,kX86InstIdPmaxud , X86XmmVar, X86Mem) + + //! Packed WORD unsigned maximum (SSE4.1). + INST_2x(pmaxuw, kX86InstIdPmaxuw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmaxuw, kX86InstIdPmaxuw, X86XmmVar, X86Mem) + + //! Packed BYTE minimum (SSE4.1). + INST_2x(pminsb, kX86InstIdPminsb, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pminsb, kX86InstIdPminsb, X86XmmVar, X86Mem) + + //! Packed DWORD minimum (SSE4.1). + INST_2x(pminsd, kX86InstIdPminsd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pminsd, kX86InstIdPminsd, X86XmmVar, X86Mem) + + //! Packed WORD unsigned minimum (SSE4.1). + INST_2x(pminuw, kX86InstIdPminuw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pminuw, kX86InstIdPminuw, X86XmmVar, X86Mem) + + //! Packed DWORD unsigned minimum (SSE4.1). + INST_2x(pminud, kX86InstIdPminud, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pminud, kX86InstIdPminud, X86XmmVar, X86Mem) + + //! Packed BYTE to DWORD with sign extend (SSE4.1). + INST_2x(pmovsxbd, kX86InstIdPmovsxbd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmovsxbd, kX86InstIdPmovsxbd, X86XmmVar, X86Mem) + + //! Packed BYTE to QWORD with sign extend (SSE4.1). + INST_2x(pmovsxbq, kX86InstIdPmovsxbq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmovsxbq, kX86InstIdPmovsxbq, X86XmmVar, X86Mem) + + //! Packed BYTE to WORD with sign extend (SSE4.1). + INST_2x(pmovsxbw, kX86InstIdPmovsxbw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmovsxbw, kX86InstIdPmovsxbw, X86XmmVar, X86Mem) + + //! Packed DWORD to QWORD with sign extend (SSE4.1). + INST_2x(pmovsxdq, kX86InstIdPmovsxdq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmovsxdq, kX86InstIdPmovsxdq, X86XmmVar, X86Mem) + + //! Packed WORD to DWORD with sign extend (SSE4.1). + INST_2x(pmovsxwd, kX86InstIdPmovsxwd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmovsxwd, kX86InstIdPmovsxwd, X86XmmVar, X86Mem) + + //! Packed WORD to QWORD with sign extend (SSE4.1). + INST_2x(pmovsxwq, kX86InstIdPmovsxwq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmovsxwq, kX86InstIdPmovsxwq, X86XmmVar, X86Mem) + + //! BYTE to DWORD with zero extend (SSE4.1). + INST_2x(pmovzxbd, kX86InstIdPmovzxbd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmovzxbd, kX86InstIdPmovzxbd, X86XmmVar, X86Mem) + + //! Packed BYTE to QWORD with zero extend (SSE4.1). + INST_2x(pmovzxbq, kX86InstIdPmovzxbq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmovzxbq, kX86InstIdPmovzxbq, X86XmmVar, X86Mem) + + //! BYTE to WORD with zero extend (SSE4.1). + INST_2x(pmovzxbw, kX86InstIdPmovzxbw, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmovzxbw, kX86InstIdPmovzxbw, X86XmmVar, X86Mem) + + //! Packed DWORD to QWORD with zero extend (SSE4.1). + INST_2x(pmovzxdq, kX86InstIdPmovzxdq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmovzxdq, kX86InstIdPmovzxdq, X86XmmVar, X86Mem) + + //! Packed WORD to DWORD with zero extend (SSE4.1). + INST_2x(pmovzxwd, kX86InstIdPmovzxwd, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmovzxwd, kX86InstIdPmovzxwd, X86XmmVar, X86Mem) + + //! Packed WORD to QWORD with zero extend (SSE4.1). + INST_2x(pmovzxwq, kX86InstIdPmovzxwq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmovzxwq, kX86InstIdPmovzxwq, X86XmmVar, X86Mem) + + //! Packed DWORD to QWORD multiply (SSE4.1). + INST_2x(pmuldq, kX86InstIdPmuldq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmuldq, kX86InstIdPmuldq, X86XmmVar, X86Mem) + + //! Packed DWORD multiply low (SSE4.1). + INST_2x(pmulld, kX86InstIdPmulld, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pmulld, kX86InstIdPmulld, X86XmmVar, X86Mem) + + //! Logical compare (SSE4.1). + INST_2x(ptest, kX86InstIdPtest, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(ptest, kX86InstIdPtest, X86XmmVar, X86Mem) + + //! Packed DP-FP round (SSE4.1). + INST_3i(roundpd, kX86InstIdRoundpd, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(roundpd, kX86InstIdRoundpd, X86XmmVar, X86Mem, Imm) + + //! Packed SP-FP round (SSE4.1). + INST_3i(roundps, kX86InstIdRoundps, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(roundps, kX86InstIdRoundps, X86XmmVar, X86Mem, Imm) + + //! Scalar DP-FP round (SSE4.1). + INST_3i(roundsd, kX86InstIdRoundsd, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(roundsd, kX86InstIdRoundsd, X86XmmVar, X86Mem, Imm) + + //! Scalar SP-FP round (SSE4.1). + INST_3i(roundss, kX86InstIdRoundss, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(roundss, kX86InstIdRoundss, X86XmmVar, X86Mem, Imm) + + // -------------------------------------------------------------------------- + // [SSE4.2] + // -------------------------------------------------------------------------- + + //! Accumulate crc32 value (polynomial 0x11EDC6F41) (SSE4.2). + INST_2x_(crc32, kX86InstIdCrc32, X86GpVar, X86GpVar, o0.isRegType(kX86RegTypeGpd) || o0.isRegType(kX86RegTypeGpq)) + //! \overload + INST_2x_(crc32, kX86InstIdCrc32, X86GpVar, X86Mem, o0.isRegType(kX86RegTypeGpd) || o0.isRegType(kX86RegTypeGpq)) + + //! Packed compare explicit length strings, return index (SSE4.2). + INST_3i(pcmpestri, kX86InstIdPcmpestri, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(pcmpestri, kX86InstIdPcmpestri, X86XmmVar, X86Mem, Imm) + + //! Packed compare explicit length strings, return mask (SSE4.2). + INST_3i(pcmpestrm, kX86InstIdPcmpestrm, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(pcmpestrm, kX86InstIdPcmpestrm, X86XmmVar, X86Mem, Imm) + + //! Packed compare implicit length strings, return index (SSE4.2). + INST_3i(pcmpistri, kX86InstIdPcmpistri, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(pcmpistri, kX86InstIdPcmpistri, X86XmmVar, X86Mem, Imm) + + //! Packed compare implicit length strings, return mask (SSE4.2). + INST_3i(pcmpistrm, kX86InstIdPcmpistrm, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(pcmpistrm, kX86InstIdPcmpistrm, X86XmmVar, X86Mem, Imm) + + //! Packed QWORD compare if greater than (SSE4.2). + INST_2x(pcmpgtq, kX86InstIdPcmpgtq, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(pcmpgtq, kX86InstIdPcmpgtq, X86XmmVar, X86Mem) + + // -------------------------------------------------------------------------- + // [SSE4a] + // -------------------------------------------------------------------------- + + //! Extract Field (SSE4a). + INST_2x(extrq, kX86InstIdExtrq, X86XmmVar, X86XmmVar) + //! Extract Field (SSE4a). + INST_3ii(extrq, kX86InstIdExtrq, X86XmmVar, Imm, Imm) + + //! Insert Field (SSE4a). + INST_2x(insertq, kX86InstIdInsertq, X86XmmVar, X86XmmVar) + //! Insert Field (SSE4a). + INST_4ii(insertq, kX86InstIdInsertq, X86XmmVar, X86XmmVar, Imm, Imm) + + //! Move Non-Temporal Scalar DP-FP (SSE4a). + INST_2x(movntsd, kX86InstIdMovntsd, X86Mem, X86XmmVar) + //! Move Non-Temporal Scalar SP-FP (SSE4a). + INST_2x(movntss, kX86InstIdMovntss, X86Mem, X86XmmVar) + + // -------------------------------------------------------------------------- + // [POPCNT] + // -------------------------------------------------------------------------- + + //! Return the count of number of bits set to 1 (POPCNT). + INST_2x_(popcnt, kX86InstIdPopcnt, X86GpVar, X86GpVar, !o0.isGpb() && o0.getSize() == o1.getSize()) + //! \overload + INST_2x_(popcnt, kX86InstIdPopcnt, X86GpVar, X86Mem, !o0.isGpb()) + + // -------------------------------------------------------------------------- + // [LZCNT] + // -------------------------------------------------------------------------- + + //! Count the number of leading zero bits (LZCNT). + INST_2x(lzcnt, kX86InstIdLzcnt, X86GpVar, X86GpVar) + //! \overload + INST_2x(lzcnt, kX86InstIdLzcnt, X86GpVar, X86Mem) + + // -------------------------------------------------------------------------- + // [AESNI] + // -------------------------------------------------------------------------- + + //! Perform a single round of the AES decryption flow. + INST_2x(aesdec, kX86InstIdAesdec, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(aesdec, kX86InstIdAesdec, X86XmmVar, X86Mem) + + //! Perform the last round of the AES decryption flow. + INST_2x(aesdeclast, kX86InstIdAesdeclast, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(aesdeclast, kX86InstIdAesdeclast, X86XmmVar, X86Mem) + + //! Perform a single round of the AES encryption flow. + INST_2x(aesenc, kX86InstIdAesenc, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(aesenc, kX86InstIdAesenc, X86XmmVar, X86Mem) + + //! Perform the last round of the AES encryption flow. + INST_2x(aesenclast, kX86InstIdAesenclast, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(aesenclast, kX86InstIdAesenclast, X86XmmVar, X86Mem) + + //! Perform the InvMixColumns transformation. + INST_2x(aesimc, kX86InstIdAesimc, X86XmmVar, X86XmmVar) + //! \overload + INST_2x(aesimc, kX86InstIdAesimc, X86XmmVar, X86Mem) + + //! Assist in expanding the AES cipher key. + INST_3i(aeskeygenassist, kX86InstIdAeskeygenassist, X86XmmVar, X86XmmVar, Imm) + //! \overload + INST_3i(aeskeygenassist, kX86InstIdAeskeygenassist, X86XmmVar, X86Mem, Imm) + + // -------------------------------------------------------------------------- + // [PCLMULQDQ] + // -------------------------------------------------------------------------- + + //! Packed QWORD to OWORD carry-less multiply (PCLMULQDQ). + INST_3i(pclmulqdq, kX86InstIdPclmulqdq, X86XmmVar, X86XmmVar, Imm); + //! \overload + INST_3i(pclmulqdq, kX86InstIdPclmulqdq, X86XmmVar, X86Mem, Imm); + + // -------------------------------------------------------------------------- + // [XSAVE] + // -------------------------------------------------------------------------- + + //! Restore Processor Extended States specified by `o1:o2` (XSAVE). + INST_3x(xrstor, kX86InstIdXrstor, X86Mem, X86GpVar, X86GpVar) + //! Restore Processor Extended States specified by `o1:o2` (XSAVE&X64). + INST_3x(xrstor64, kX86InstIdXrstor64, X86Mem, X86GpVar, X86GpVar) + + //! Save Processor Extended States specified by `o1:o2` (XSAVE). + INST_3x(xsave, kX86InstIdXsave, X86Mem, X86GpVar, X86GpVar) + //! Save Processor Extended States specified by `o1:o2` (XSAVE&X64). + INST_3x(xsave64, kX86InstIdXsave64, X86Mem, X86GpVar, X86GpVar) + + //! Save Processor Extended States specified by `o1:o2` (Optimized) (XSAVEOPT). + INST_3x(xsaveopt, kX86InstIdXsave, X86Mem, X86GpVar, X86GpVar) + //! Save Processor Extended States specified by `o1:o2` (Optimized) (XSAVEOPT&X64). + INST_3x(xsaveopt64, kX86InstIdXsave64, X86Mem, X86GpVar, X86GpVar) + + //! Get XCR - `o1:o2 <- XCR[o0]` (`EDX:EAX <- XCR[ECX]`) (XSAVE). + INST_3x(xgetbv, kX86InstIdXgetbv, X86GpVar, X86GpVar, X86GpVar) + //! Set XCR - `XCR[o0] <- o1:o2` (`XCR[ECX] <- EDX:EAX`) (XSAVE). + INST_3x(xsetbv, kX86InstIdXsetbv, X86GpVar, X86GpVar, X86GpVar) + + // -------------------------------------------------------------------------- + // [Cleanup] + // -------------------------------------------------------------------------- + +#undef INST_0x + +#undef INST_1x +#undef INST_1x_ +#undef INST_1i +#undef INST_1cc + +#undef INST_2x +#undef INST_2x_ +#undef INST_2i +#undef INST_2cc + +#undef INST_3x +#undef INST_3x_ +#undef INST_3i +#undef INST_3ii + +#undef INST_4x +#undef INST_4x_ +#undef INST_4i +#undef INST_4ii +}; + +//! \} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // !ASMJIT_DISABLE_COMPILER +#endif // _ASMJIT_X86_X86COMPILER_H diff --git a/third/Blackbone/src/3rd_party/AsmJit/x86/x86context.cpp b/third/Blackbone/src/3rd_party/AsmJit/x86/x86context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3bac51665a7ff6f3e9e3c5888b00eb6a1c692df1 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/x86/x86context.cpp @@ -0,0 +1,5730 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Guard] +#include "../build.h" +#if !defined(ASMJIT_DISABLE_COMPILER) && (defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64)) + +// [Dependencies - AsmJit] +#include "../base/intutil.h" +#include "../base/string.h" +#include "../x86/x86assembler.h" +#include "../x86/x86compiler.h" +#include "../x86/x86context_p.h" +#include "../x86/x86cpuinfo.h" +#include "../x86/x86scheduler_p.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [Forward Declarations] +// ============================================================================ + +static Error X86Context_translateOperands(X86Context* self, Operand* opList, uint32_t opCount); + +// ============================================================================ +// [asmjit::X86Context - Utils] +// ============================================================================ + +// Getting `VarClass` is the only safe operation when dealing with denormalized +// `varType`. Any other property would require to map vType to the architecture +// specific type. +static ASMJIT_INLINE uint32_t x86VarTypeToClass(uint32_t vType) { + ASMJIT_ASSERT(vType < kX86VarTypeCount); + return _x86VarInfo[vType].getClass(); +} + +// ============================================================================ +// [asmjit::X86Context - Annotate] +// ============================================================================ + +// Annotation is also used by ASMJIT_TRACE. +#if !defined(ASMJIT_DISABLE_LOGGER) +static void X86Context_annotateVariable(X86Context* self, + StringBuilder& sb, const VarData* vd) { + + const char* name = vd->getName(); + if (name != NULL && name[0] != '\0') { + sb.appendString(name); + } + else { + sb.appendChar('v'); + sb.appendUInt(vd->getId() & kOperandIdNum); + } +} + +static void X86Context_annotateOperand(X86Context* self, + StringBuilder& sb, const Operand* op) { + + if (op->isVar()) { + X86Context_annotateVariable(self, sb, self->_compiler->getVdById(op->getId())); + } + else if (op->isMem()) { + const X86Mem* m = static_cast(op); + bool isAbsolute = false; + + sb.appendChar('['); + switch (m->getMemType()) { + case kMemTypeBaseIndex: + case kMemTypeStackIndex: + // [base + index << shift + displacement] + X86Context_annotateVariable(self, sb, self->_compiler->getVdById(m->getBase())); + break; + + case kMemTypeLabel: + // [label + index << shift + displacement] + sb.appendFormat("L%u", m->getBase()); + break; + + case kMemTypeAbsolute: + // [absolute] + isAbsolute = true; + sb.appendUInt(static_cast(m->getDisplacement()), 16); + break; + } + + if (m->hasIndex()) { + sb.appendChar('+'); + X86Context_annotateVariable(self, sb, self->_compiler->getVdById(m->getIndex())); + + if (m->getShift()) { + sb.appendChar('*'); + sb.appendChar("1248"[m->getShift() & 3]); + } + } + + if (m->getDisplacement() && !isAbsolute) { + uint32_t base = 10; + int32_t dispOffset = m->getDisplacement(); + + char prefix = '+'; + if (dispOffset < 0) { + dispOffset = -dispOffset; + prefix = '-'; + } + + sb.appendChar(prefix); + /* + if ((loggerOptions & (1 << kLoggerOptionHexDisplacement)) != 0 && dispOffset > 9) { + sb.appendString("0x", 2); + base = 16; + } + */ + sb.appendUInt(static_cast(dispOffset), base); + } + + sb.appendChar(']'); + } + else if (op->isImm()) { + const Imm* i = static_cast(op); + int64_t val = i->getInt64(); + + /* + if ((loggerOptions & (1 << kLoggerOptionHexImmediate)) && static_cast(val) > 9) + sb.appendUInt(static_cast(val), 16); + else*/ + sb.appendInt(val, 10); + } + else if (op->isLabel()) { + sb.appendFormat("L%u", op->getId()); + } + else { + sb.appendString("None", 4); + } +} + +static bool X86Context_annotateInstruction(X86Context* self, + StringBuilder& sb, uint32_t instId, const Operand* opList, uint32_t opCount) { + + sb.appendString(_x86InstInfo[instId].getInstName()); + for (uint32_t i = 0; i < opCount; i++) { + if (i == 0) + sb.appendChar(' '); + else + sb.appendString(", ", 2); + X86Context_annotateOperand(self, sb, &opList[i]); + } + return true; +} +#endif // !ASMJIT_DISABLE_LOGGER + +#if defined(ASMJIT_TRACE) +static void X86Context_traceNode(X86Context* self, Node* node_) { + StringBuilderT<256> sb; + + switch (node_->getType()) { + case kNodeTypeAlign: { + AlignNode* node = static_cast(node_); + sb.appendFormat(".align %u (%s)", + node->getOffset(), + node->getMode() == kAlignCode ? "code" : "data"); + break; + } + + case kNodeTypeEmbed: { + EmbedNode* node = static_cast(node_); + sb.appendFormat(".embed (%u bytes)", node->getSize()); + break; + } + + case kNodeTypeComment: { + CommentNode* node = static_cast(node_); + sb.appendFormat("; %s", node->getComment()); + break; + } + + case kNodeTypeHint: { + HintNode* node = static_cast(node_); + static const char* hint[16] = { + "alloc", + "spill", + "save", + "save-unuse", + "unuse" + }; + sb.appendFormat("[%s] %s", + hint[node->getHint()], node->getVd()->getName()); + break; + } + + case kNodeTypeTarget: { + TargetNode* node = static_cast(node_); + sb.appendFormat("L%u: (NumRefs=%u)", + node->getLabelId(), + node->getNumRefs()); + break; + } + + case kNodeTypeInst: { + InstNode* node = static_cast(node_); + X86Context_annotateInstruction(self, sb, + node->getInstId(), node->getOpList(), node->getOpCount()); + break; + } + + case kNodeTypeFunc: { + FuncNode* node = static_cast(node_); + sb.appendFormat("[func]"); + break; + } + + case kNodeTypeEnd: { + EndNode* node = static_cast(node_); + sb.appendFormat("[end]"); + break; + } + + case kNodeTypeRet: { + RetNode* node = static_cast(node_); + sb.appendFormat("[ret]"); + break; + } + + case kNodeTypeCall: { + CallNode* node = static_cast(node_); + sb.appendFormat("[call]"); + break; + } + + case kNodeTypeSArg: { + SArgNode* node = static_cast(node_); + sb.appendFormat("[sarg]"); + break; + } + + default: { + sb.appendFormat("[unknown]"); + break; + } + } + + ASMJIT_TLOG("[%05u] %s\n", node_->getFlowId(), sb.getData()); +} +#endif // ASMJIT_TRACE + +// ============================================================================ +// [asmjit::X86Context - Construction / Destruction] +// ============================================================================ + +X86Context::X86Context(X86Compiler* compiler) : Context(compiler) { + _varMapToVaListOffset = ASMJIT_OFFSET_OF(X86VarMap, _list); + _regCount = compiler->_regCount; + + _zsp = compiler->zsp; + _zbp = compiler->zbp; + + _memSlot._vmem.type = kMemTypeStackIndex; + _memSlot.setGpdBase(compiler->getArch() == kArchX86); + +#if !defined(ASMJIT_DISABLE_LOGGER) + _emitComments = compiler->hasLogger(); +#endif // !ASMJIT_DISABLE_LOGGER + + _state = &_x86State; + reset(); +} + +X86Context::~X86Context() {} + +// ============================================================================ +// [asmjit::X86Context - Reset] +// ============================================================================ + +void X86Context::reset(bool releaseMemory) { + Context::reset(releaseMemory); + + _x86State.reset(0); + _clobberedRegs.reset(); + + _stackFrameCell = NULL; + _gaRegs[kX86RegClassGp ] = IntUtil::bits(_regCount.getGp()) & ~IntUtil::mask(kX86RegIndexSp); + _gaRegs[kX86RegClassMm ] = IntUtil::bits(_regCount.getMm()); + _gaRegs[kX86RegClassK ] = IntUtil::bits(_regCount.getK()); + _gaRegs[kX86RegClassXyz] = IntUtil::bits(_regCount.getXyz()); + + _argBaseReg = kInvalidReg; // Used by patcher. + _varBaseReg = kInvalidReg; // Used by patcher. + + _argBaseOffset = 0; // Used by patcher. + _varBaseOffset = 0; // Used by patcher. + + _argActualDisp = 0; // Used by translator. + _varActualDisp = 0; // Used by translator. +} + +// ============================================================================ +// [asmjit::X86SpecialInst] +// ============================================================================ + +struct X86SpecialInst { + uint8_t inReg; + uint8_t outReg; + uint16_t flags; +}; + +static const X86SpecialInst x86SpecialInstCpuid[] = { + { kX86RegIndexAx, kX86RegIndexAx, kVarAttrInOutReg }, + { kInvalidReg , kX86RegIndexBx, kVarAttrOutReg }, + { kInvalidReg , kX86RegIndexCx, kVarAttrOutReg }, + { kInvalidReg , kX86RegIndexDx, kVarAttrOutReg } +}; + +static const X86SpecialInst x86SpecialInstCbwCdqeCwde[] = { + { kX86RegIndexAx, kX86RegIndexAx, kVarAttrInOutReg } +}; + +static const X86SpecialInst x86SpecialInstCdqCwdCqo[] = { + { kInvalidReg , kX86RegIndexDx, kVarAttrOutReg }, + { kX86RegIndexAx, kInvalidReg , kVarAttrInReg } +}; + +static const X86SpecialInst x86SpecialInstCmpxchg[] = { + { kX86RegIndexAx, kX86RegIndexAx, kVarAttrInOutReg }, + { kInvalidReg , kInvalidReg , kVarAttrInOutReg }, + { kInvalidReg , kInvalidReg , kVarAttrInReg } +}; + +static const X86SpecialInst x86SpecialInstCmpxchg8b16b[] = { + { kX86RegIndexDx, kX86RegIndexDx, kVarAttrInOutReg }, + { kX86RegIndexAx, kX86RegIndexAx, kVarAttrInOutReg }, + { kX86RegIndexCx, kInvalidReg , kVarAttrInReg }, + { kX86RegIndexBx, kInvalidReg , kVarAttrInReg } +}; + +static const X86SpecialInst x86SpecialInstDaaDas[] = { + { kX86RegIndexAx, kX86RegIndexAx, kVarAttrInOutReg } +}; + +static const X86SpecialInst x86SpecialInstDiv[] = { + { kInvalidReg , kX86RegIndexDx, kVarAttrInOutReg }, + { kX86RegIndexAx, kX86RegIndexAx, kVarAttrInOutReg }, + { kInvalidReg , kInvalidReg , kVarAttrInReg } +}; + +static const X86SpecialInst x86SpecialInstJecxz[] = { + { kX86RegIndexCx, kInvalidReg , kVarAttrInReg } +}; + +static const X86SpecialInst x86SpecialInstLods[] = { + { kInvalidReg , kX86RegIndexAx, kVarAttrOutReg }, + { kX86RegIndexSi, kX86RegIndexSi, kVarAttrInOutReg }, + { kX86RegIndexCx, kX86RegIndexCx, kVarAttrInOutReg } +}; + +static const X86SpecialInst x86SpecialInstMul[] = { + { kInvalidReg , kX86RegIndexDx, kVarAttrOutReg }, + { kX86RegIndexAx, kX86RegIndexAx, kVarAttrInOutReg }, + { kInvalidReg , kInvalidReg , kVarAttrInReg } +}; + +static const X86SpecialInst x86SpecialInstMovPtr[] = { + { kInvalidReg , kX86RegIndexAx, kVarAttrOutReg }, + { kX86RegIndexAx, kInvalidReg , kVarAttrInReg } +}; + +static const X86SpecialInst x86SpecialInstMovsCmps[] = { + { kX86RegIndexDi, kX86RegIndexDi, kVarAttrInOutReg }, + { kX86RegIndexSi, kX86RegIndexSi, kVarAttrInOutReg }, + { kX86RegIndexCx, kX86RegIndexCx, kVarAttrInOutReg } +}; + +static const X86SpecialInst x86SpecialInstLahf[] = { + { kInvalidReg , kX86RegIndexAx, kVarAttrOutReg } +}; + +static const X86SpecialInst x86SpecialInstSahf[] = { + { kX86RegIndexAx, kInvalidReg , kVarAttrInReg } +}; + +static const X86SpecialInst x86SpecialInstMaskmovqMaskmovdqu[] = { + { kInvalidReg , kX86RegIndexDi, kVarAttrInReg }, + { kInvalidReg , kInvalidReg , kVarAttrInReg }, + { kInvalidReg , kInvalidReg , kVarAttrInReg } +}; + +static const X86SpecialInst x86SpecialInstRdtscRdtscp[] = { + { kInvalidReg , kX86RegIndexDx, kVarAttrOutReg }, + { kInvalidReg , kX86RegIndexAx, kVarAttrOutReg }, + { kInvalidReg , kX86RegIndexCx, kVarAttrOutReg } +}; + +static const X86SpecialInst x86SpecialInstRot[] = { + { kInvalidReg , kInvalidReg , kVarAttrInOutReg }, + { kX86RegIndexCx, kInvalidReg , kVarAttrInReg } +}; + +static const X86SpecialInst x86SpecialInstScas[] = { + { kX86RegIndexDi, kX86RegIndexDi, kVarAttrInOutReg }, + { kX86RegIndexAx, kInvalidReg , kVarAttrInReg }, + { kX86RegIndexCx, kX86RegIndexCx, kVarAttrInOutReg } +}; + +static const X86SpecialInst x86SpecialInstShlrd[] = { + { kInvalidReg , kInvalidReg , kVarAttrInOutReg }, + { kInvalidReg , kInvalidReg , kVarAttrInReg }, + { kX86RegIndexCx, kInvalidReg , kVarAttrInReg } +}; + +static const X86SpecialInst x86SpecialInstStos[] = { + { kX86RegIndexDi, kInvalidReg , kVarAttrInReg }, + { kX86RegIndexAx, kInvalidReg , kVarAttrInReg }, + { kX86RegIndexCx, kX86RegIndexCx, kVarAttrInOutReg } +}; + +static const X86SpecialInst x86SpecialInstBlend[] = { + { kInvalidReg , kInvalidReg , kVarAttrOutReg }, + { kInvalidReg , kInvalidReg , kVarAttrInReg }, + { 0 , kInvalidReg , kVarAttrInReg } +}; + +static const X86SpecialInst x86SpecialInstXsaveXrstor[] = { + { kInvalidReg , kInvalidReg , 0 }, + { kX86RegIndexDx, kInvalidReg , kVarAttrInReg }, + { kX86RegIndexAx, kInvalidReg , kVarAttrInReg } +}; + +static const X86SpecialInst x86SpecialInstXgetbv[] = { + { kX86RegIndexCx, kInvalidReg , kVarAttrInReg }, + { kInvalidReg , kX86RegIndexDx, kVarAttrOutReg }, + { kInvalidReg , kX86RegIndexAx, kVarAttrOutReg } +}; + +static const X86SpecialInst x86SpecialInstXsetbv[] = { + { kX86RegIndexCx, kInvalidReg , kVarAttrInReg }, + { kX86RegIndexDx, kInvalidReg , kVarAttrInReg }, + { kX86RegIndexAx, kInvalidReg , kVarAttrInReg } +}; + +static ASMJIT_INLINE const X86SpecialInst* X86SpecialInst_get(uint32_t instId, const Operand* opList, uint32_t opCount) { + switch (instId) { + case kX86InstIdCpuid: + return x86SpecialInstCpuid; + + case kX86InstIdCbw: + case kX86InstIdCdqe: + case kX86InstIdCwde: + return x86SpecialInstCbwCdqeCwde; + + case kX86InstIdCdq: + case kX86InstIdCwd: + case kX86InstIdCqo: + return x86SpecialInstCdqCwdCqo; + + case kX86InstIdCmpsB: + case kX86InstIdCmpsD: + case kX86InstIdCmpsQ: + case kX86InstIdCmpsW: + case kX86InstIdRepeCmpsB: + case kX86InstIdRepeCmpsD: + case kX86InstIdRepeCmpsQ: + case kX86InstIdRepeCmpsW: + case kX86InstIdRepneCmpsB: + case kX86InstIdRepneCmpsD: + case kX86InstIdRepneCmpsQ: + case kX86InstIdRepneCmpsW: + return x86SpecialInstMovsCmps; + + case kX86InstIdCmpxchg: + return x86SpecialInstCmpxchg; + + case kX86InstIdCmpxchg8b: + case kX86InstIdCmpxchg16b: + return x86SpecialInstCmpxchg8b16b; + + case kX86InstIdDaa: + case kX86InstIdDas: + return x86SpecialInstDaaDas; + + case kX86InstIdJecxz: + return x86SpecialInstJecxz; + + case kX86InstIdIdiv: + case kX86InstIdDiv: + return x86SpecialInstDiv; + + case kX86InstIdImul: + if (opCount == 2) + return NULL; + if (opCount == 3 && !(opList[0].isVar() && opList[1].isVar() && opList[2].isVarOrMem())) + return NULL; + // ... Fall through ... + case kX86InstIdMul: + return x86SpecialInstMul; + + case kX86InstIdMovPtr: + return x86SpecialInstMovPtr; + + case kX86InstIdLodsB: + case kX86InstIdLodsD: + case kX86InstIdLodsQ: + case kX86InstIdLodsW: + case kX86InstIdRepLodsB: + case kX86InstIdRepLodsD: + case kX86InstIdRepLodsQ: + case kX86InstIdRepLodsW: + return x86SpecialInstLods; + + case kX86InstIdMovsB: + case kX86InstIdMovsD: + case kX86InstIdMovsQ: + case kX86InstIdMovsW: + case kX86InstIdRepMovsB: + case kX86InstIdRepMovsD: + case kX86InstIdRepMovsQ: + case kX86InstIdRepMovsW: + return x86SpecialInstMovsCmps; + + case kX86InstIdLahf: + return x86SpecialInstLahf; + + case kX86InstIdSahf: + return x86SpecialInstSahf; + + case kX86InstIdMaskmovq: + case kX86InstIdMaskmovdqu: + return x86SpecialInstMaskmovqMaskmovdqu; + + // Not supported. + case kX86InstIdEnter: + case kX86InstIdLeave: + return NULL; + + // Not supported. + case kX86InstIdRet: + return NULL; + + case kX86InstIdMonitor: + case kX86InstIdMwait: + // TODO: [COMPILER] Monitor/MWait. + return NULL; + + case kX86InstIdPop: + // TODO: [COMPILER] Pop. + return NULL; + + // Not supported. + case kX86InstIdPopa: + case kX86InstIdPopf: + return NULL; + + case kX86InstIdPush: + // TODO: [COMPILER] Push. + return NULL; + + // Not supported. + case kX86InstIdPusha: + case kX86InstIdPushf: + return NULL; + + // Rot instruction is special only if the last operand is a variable. + case kX86InstIdRcl: + case kX86InstIdRcr: + case kX86InstIdRol: + case kX86InstIdRor: + case kX86InstIdSal: + case kX86InstIdSar: + case kX86InstIdShl: + case kX86InstIdShr: + if (!opList[1].isVar()) + return NULL; + return x86SpecialInstRot; + + // Shld/Shrd instruction is special only if the last operand is a variable. + case kX86InstIdShld: + case kX86InstIdShrd: + if (!opList[2].isVar()) + return NULL; + return x86SpecialInstShlrd; + + case kX86InstIdRdtsc: + case kX86InstIdRdtscp: + return x86SpecialInstRdtscRdtscp; + + case kX86InstIdScasB: + case kX86InstIdScasD: + case kX86InstIdScasQ: + case kX86InstIdScasW: + case kX86InstIdRepeScasB: + case kX86InstIdRepeScasD: + case kX86InstIdRepeScasQ: + case kX86InstIdRepeScasW: + case kX86InstIdRepneScasB: + case kX86InstIdRepneScasD: + case kX86InstIdRepneScasQ: + case kX86InstIdRepneScasW: + return x86SpecialInstScas; + + case kX86InstIdStosB: + case kX86InstIdStosD: + case kX86InstIdStosQ: + case kX86InstIdStosW: + case kX86InstIdRepStosB: + case kX86InstIdRepStosD: + case kX86InstIdRepStosQ: + case kX86InstIdRepStosW: + return x86SpecialInstStos; + + case kX86InstIdBlendvpd: + case kX86InstIdBlendvps: + case kX86InstIdPblendvb: + return x86SpecialInstBlend; + + case kX86InstIdXrstor: + case kX86InstIdXrstor64: + case kX86InstIdXsave: + case kX86InstIdXsave64: + case kX86InstIdXsaveopt: + case kX86InstIdXsaveopt64: + return x86SpecialInstXsaveXrstor; + + case kX86InstIdXgetbv: + return x86SpecialInstXgetbv; + + case kX86InstIdXsetbv: + return x86SpecialInstXsetbv; + + default: + return NULL; + } +} + +// ============================================================================ +// [asmjit::X86Context - EmitLoad] +// ============================================================================ + +void X86Context::emitLoad(VarData* vd, uint32_t regIndex, const char* reason) { + ASMJIT_ASSERT(regIndex != kInvalidReg); + + X86Compiler* compiler = getCompiler(); + X86Mem m = getVarMem(vd); + + Node* node = NULL; + bool comment = _emitComments; + + switch (vd->getType()) { + case kVarTypeInt8: + case kVarTypeUInt8: + node = compiler->emit(kX86InstIdMov, x86::gpb_lo(regIndex), m); + if (comment) goto _Comment; + break; + + case kVarTypeInt16: + case kVarTypeUInt16: + node = compiler->emit(kX86InstIdMov, x86::gpw(regIndex), m); + if (comment) goto _Comment; + break; + + case kVarTypeInt32: + case kVarTypeUInt32: + node = compiler->emit(kX86InstIdMov, x86::gpd(regIndex), m); + if (comment) goto _Comment; + break; + +#if defined(ASMJIT_BUILD_X64) + case kVarTypeInt64: + case kVarTypeUInt64: + node = compiler->emit(kX86InstIdMov, x86::gpq(regIndex), m); + if (comment) goto _Comment; + break; +#endif // ASMJIT_BUILD_X64 + + case kVarTypeFp32: + case kVarTypeFp64: + // TODO: [COMPILER] FPU. + break; + + case kX86VarTypeMm: + node = compiler->emit(kX86InstIdMovq, x86::mm(regIndex), m); + if (comment) goto _Comment; + break; + + case kX86VarTypeXmm: + node = compiler->emit(kX86InstIdMovdqa, x86::xmm(regIndex), m); + if (comment) goto _Comment; + break; + + case kX86VarTypeXmmSs: + node = compiler->emit(kX86InstIdMovss, x86::xmm(regIndex), m); + if (comment) goto _Comment; + break; + + case kX86VarTypeXmmSd: + node = compiler->emit(kX86InstIdMovsd, x86::xmm(regIndex), m); + if (comment) goto _Comment; + break; + + case kX86VarTypeXmmPs: + node = compiler->emit(kX86InstIdMovaps, x86::xmm(regIndex), m); + if (comment) goto _Comment; + break; + + case kX86VarTypeXmmPd: + node = compiler->emit(kX86InstIdMovapd, x86::xmm(regIndex), m); + if (comment) goto _Comment; + break; + } + return; + +_Comment: + node->setComment(compiler->_stringZone.sformat("[%s] %s", reason, vd->getName())); +} + +// ============================================================================ +// [asmjit::X86Context - EmitSave] +// ============================================================================ + +void X86Context::emitSave(VarData* vd, uint32_t regIndex, const char* reason) { + ASMJIT_ASSERT(regIndex != kInvalidReg); + + X86Compiler* compiler = getCompiler(); + X86Mem m = getVarMem(vd); + + Node* node = NULL; + bool comment = _emitComments; + + switch (vd->getType()) { + case kVarTypeInt8: + case kVarTypeUInt8: + node = compiler->emit(kX86InstIdMov, m, x86::gpb_lo(regIndex)); + if (comment) goto _Comment; + break; + + case kVarTypeInt16: + case kVarTypeUInt16: + node = compiler->emit(kX86InstIdMov, m, x86::gpw(regIndex)); + if (comment) goto _Comment; + break; + + case kVarTypeInt32: + case kVarTypeUInt32: + node = compiler->emit(kX86InstIdMov, m, x86::gpd(regIndex)); + if (comment) goto _Comment; + break; + +#if defined(ASMJIT_BUILD_X64) + case kVarTypeInt64: + case kVarTypeUInt64: + node = compiler->emit(kX86InstIdMov, m, x86::gpq(regIndex)); + if (comment) goto _Comment; + break; +#endif // ASMJIT_BUILD_X64 + + case kVarTypeFp32: + case kVarTypeFp64: + // TODO: [COMPILER] FPU. + break; + + case kX86VarTypeMm: + node = compiler->emit(kX86InstIdMovq, m, x86::mm(regIndex)); + if (comment) goto _Comment; + break; + + case kX86VarTypeXmm: + node = compiler->emit(kX86InstIdMovdqa, m, x86::xmm(regIndex)); + if (comment) goto _Comment; + break; + + case kX86VarTypeXmmSs: + node = compiler->emit(kX86InstIdMovss, m, x86::xmm(regIndex)); + if (comment) goto _Comment; + break; + + case kX86VarTypeXmmSd: + node = compiler->emit(kX86InstIdMovsd, m, x86::xmm(regIndex)); + if (comment) goto _Comment; + break; + + case kX86VarTypeXmmPs: + node = compiler->emit(kX86InstIdMovaps, m, x86::xmm(regIndex)); + if (comment) goto _Comment; + break; + + case kX86VarTypeXmmPd: + node = compiler->emit(kX86InstIdMovapd, m, x86::xmm(regIndex)); + if (comment) goto _Comment; + break; + } + return; + +_Comment: + node->setComment(compiler->_stringZone.sformat("[%s] %s", reason, vd->getName())); +} + +// ============================================================================ +// [asmjit::X86Context - EmitMove] +// ============================================================================ + +void X86Context::emitMove(VarData* vd, uint32_t toRegIndex, uint32_t fromRegIndex, const char* reason) { + ASMJIT_ASSERT(toRegIndex != kInvalidReg); + ASMJIT_ASSERT(fromRegIndex != kInvalidReg); + + X86Compiler* compiler = getCompiler(); + + Node* node = NULL; + bool comment = _emitComments; + + switch (vd->getType()) { + case kVarTypeInt8: + case kVarTypeUInt8: + case kVarTypeInt16: + case kVarTypeUInt16: + case kVarTypeInt32: + case kVarTypeUInt32: + node = compiler->emit(kX86InstIdMov, x86::gpd(toRegIndex), x86::gpd(fromRegIndex)); + if (comment) goto _Comment; + break; + +#if defined(ASMJIT_BUILD_X64) + case kVarTypeInt64: + case kVarTypeUInt64: + node = compiler->emit(kX86InstIdMov, x86::gpq(toRegIndex), x86::gpq(fromRegIndex)); + if (comment) goto _Comment; + break; +#endif // ASMJIT_BUILD_X64 + + case kVarTypeFp32: + case kVarTypeFp64: + // TODO: [COMPILER] FPU. + break; + + case kX86VarTypeMm: + node = compiler->emit(kX86InstIdMovq, x86::mm(toRegIndex), x86::mm(fromRegIndex)); + if (comment) goto _Comment; + break; + + case kX86VarTypeXmm: + node = compiler->emit(kX86InstIdMovaps, x86::xmm(toRegIndex), x86::xmm(fromRegIndex)); + if (comment) goto _Comment; + break; + + case kX86VarTypeXmmSs: + node = compiler->emit(kX86InstIdMovss, x86::xmm(toRegIndex), x86::xmm(fromRegIndex)); + if (comment) goto _Comment; + break; + + case kX86VarTypeXmmSd: + node = compiler->emit(kX86InstIdMovsd, x86::xmm(toRegIndex), x86::xmm(fromRegIndex)); + if (comment) goto _Comment; + break; + + case kX86VarTypeXmmPs: + case kX86VarTypeXmmPd: + node = compiler->emit(kX86InstIdMovaps, x86::xmm(toRegIndex), x86::xmm(fromRegIndex)); + if (comment) goto _Comment; + break; + } + return; + +_Comment: + node->setComment(compiler->_stringZone.sformat("[%s] %s", reason, vd->getName())); +} + +// ============================================================================ +// [asmjit::X86Context - EmitSwap] +// ============================================================================ + +void X86Context::emitSwapGp(VarData* aVd, VarData* bVd, uint32_t aIndex, uint32_t bIndex, const char* reason) { + ASMJIT_ASSERT(aIndex != kInvalidReg); + ASMJIT_ASSERT(bIndex != kInvalidReg); + + X86Compiler* compiler = getCompiler(); + + Node* node = NULL; + bool comment = _emitComments; + +#if defined(ASMJIT_BUILD_X64) + uint32_t vType = IntUtil::iMax(aVd->getType(), bVd->getType()); + + if (vType == kVarTypeInt64 || vType == kVarTypeUInt64) { + node = compiler->emit(kX86InstIdXchg, x86::gpq(aIndex), x86::gpq(bIndex)); + if (comment) goto _Comment; + return; + } +#endif // ASMJIT_BUILD_X64 + + node = compiler->emit(kX86InstIdXchg, x86::gpd(aIndex), x86::gpd(bIndex)); + if (comment) goto _Comment; + return; + +_Comment: + node->setComment(compiler->_stringZone.sformat("[%s] %s, %s", reason, aVd->getName(), bVd->getName())); +} + +// ============================================================================ +// [asmjit::X86Context - EmitPushSequence / EmitPopSequence] +// ============================================================================ + +void X86Context::emitPushSequence(uint32_t regs) { + X86Compiler* compiler = getCompiler(); + uint32_t i = 0; + + X86GpReg gpReg(_zsp); + while (regs != 0) { + ASMJIT_ASSERT(i < _regCount.getGp()); + if ((regs & 0x1) != 0) + compiler->emit(kX86InstIdPush, gpReg.setIndex(i)); + i++; + regs >>= 1; + } +} + +void X86Context::emitPopSequence(uint32_t regs) { + X86Compiler* compiler = getCompiler(); + + if (regs == 0) + return; + + uint32_t i = static_cast(_regCount.getGp()); + uint32_t mask = 0x1 << static_cast(i - 1); + + X86GpReg gpReg(_zsp); + while (i) { + i--; + if ((regs & mask) != 0) + compiler->emit(kX86InstIdPop, gpReg.setIndex(i)); + mask >>= 1; + } +} + +// ============================================================================ +// [asmjit::X86Context - EmitConvertVarToVar] +// ============================================================================ + +void X86Context::emitConvertVarToVar(uint32_t dstType, uint32_t dstIndex, uint32_t srcType, uint32_t srcIndex) { + X86Compiler* compiler = getCompiler(); + + switch (dstType) { + case kVarTypeInt8: + case kVarTypeUInt8: + case kVarTypeInt16: + case kVarTypeUInt16: + case kVarTypeInt32: + case kVarTypeUInt32: + case kVarTypeInt64: + case kVarTypeUInt64: + break; + + case kX86VarTypeXmmPs: + if (srcType == kX86VarTypeXmmPd || srcType == kX86VarTypeYmmPd) { + compiler->emit(kX86InstIdCvtpd2ps, x86::xmm(dstIndex), x86::xmm(srcIndex)); + return; + } + // ... Fall through ... + + case kX86VarTypeXmmSs: + if (srcType == kX86VarTypeXmmSd || srcType == kX86VarTypeXmmPd || srcType == kX86VarTypeYmmPd) { + compiler->emit(kX86InstIdCvtsd2ss, x86::xmm(dstIndex), x86::xmm(srcIndex)); + return; + } + + if (IntUtil::inInterval(srcType, _kVarTypeIntStart, _kVarTypeIntEnd)) { + // TODO: + ASMJIT_ASSERT(!"Reached"); + } + break; + + case kX86VarTypeXmmPd: + if (srcType == kX86VarTypeXmmPs || srcType == kX86VarTypeYmmPs) { + compiler->emit(kX86InstIdCvtps2pd, x86::xmm(dstIndex), x86::xmm(srcIndex)); + return; + } + // ... Fall through ... + + case kX86VarTypeXmmSd: + if (srcType == kX86VarTypeXmmSs || srcType == kX86VarTypeXmmPs || srcType == kX86VarTypeYmmPs) { + compiler->emit(kX86InstIdCvtss2sd, x86::xmm(dstIndex), x86::xmm(srcIndex)); + return; + } + + if (IntUtil::inInterval(srcType, _kVarTypeIntStart, _kVarTypeIntEnd)) { + // TODO: + ASMJIT_ASSERT(!"Reached"); + } + break; + } +} + +// ============================================================================ +// [asmjit::X86Context - EmitMoveVarOnStack / EmitMoveImmOnStack] +// ============================================================================ + +void X86Context::emitMoveVarOnStack( + uint32_t dstType, const X86Mem* dst, + uint32_t srcType, uint32_t srcIndex) { + + ASMJIT_ASSERT(srcIndex != kInvalidReg); + X86Compiler* compiler = getCompiler(); + + X86Mem m0(*dst); + X86Reg r0, r1; + + uint32_t regSize = compiler->getRegSize(); + uint32_t instId; + + switch (dstType) { + case kVarTypeInt8: + case kVarTypeUInt8: + // Move DWORD (Gp). + if (IntUtil::inInterval(srcType, kVarTypeInt8, kVarTypeUInt64)) + goto _MovGpD; + + // Move DWORD (Mm). + if (IntUtil::inInterval(srcType, kX86VarTypeMm, kX86VarTypeMm)) + goto _MovMmD; + + // Move DWORD (Xmm). + if (IntUtil::inInterval(srcType, kX86VarTypeXmm, kX86VarTypeXmmPd)) + goto _MovXmmD; + + break; + + case kVarTypeInt16: + case kVarTypeUInt16: + // Extend BYTE->WORD (Gp). + if (IntUtil::inInterval(srcType, kVarTypeInt8, kVarTypeUInt8)) { + r1.setSize(1); + r1.setCode(kX86RegTypeGpbLo, srcIndex); + + instId = (dstType == kVarTypeInt16 && srcType == kVarTypeInt8) ? kX86InstIdMovsx : kX86InstIdMovzx; + goto _ExtendMovGpD; + } + + // Move DWORD (Gp). + if (IntUtil::inInterval(srcType, kVarTypeInt16, kVarTypeUInt64)) + goto _MovGpD; + + // Move DWORD (Mm). + if (IntUtil::inInterval(srcType, kX86VarTypeMm, kX86VarTypeMm)) + goto _MovMmD; + + // Move DWORD (Xmm). + if (IntUtil::inInterval(srcType, kX86VarTypeXmm, kX86VarTypeXmmPd)) + goto _MovXmmD; + + break; + + case kVarTypeInt32: + case kVarTypeUInt32: + // Extend BYTE->DWORD (Gp). + if (IntUtil::inInterval(srcType, kVarTypeInt8, kVarTypeUInt8)) { + r1.setSize(1); + r1.setCode(kX86RegTypeGpbLo, srcIndex); + + instId = (dstType == kVarTypeInt32 && srcType == kVarTypeInt8) ? kX86InstIdMovsx : kX86InstIdMovzx; + goto _ExtendMovGpD; + } + + // Extend WORD->DWORD (Gp). + if (IntUtil::inInterval(srcType, kVarTypeInt16, kVarTypeUInt16)) { + r1.setSize(2); + r1.setCode(kX86RegTypeGpw, srcIndex); + + instId = (dstType == kVarTypeInt32 && srcType == kVarTypeInt16) ? kX86InstIdMovsx : kX86InstIdMovzx; + goto _ExtendMovGpD; + } + + // Move DWORD (Gp). + if (IntUtil::inInterval(srcType, kVarTypeInt32, kVarTypeUInt64)) + goto _MovGpD; + + // Move DWORD (Mm). + if (IntUtil::inInterval(srcType, kX86VarTypeMm, kX86VarTypeMm)) + goto _MovMmD; + + // Move DWORD (Xmm). + if (IntUtil::inInterval(srcType, kX86VarTypeXmm, kX86VarTypeXmmPd)) + goto _MovXmmD; + break; + + case kVarTypeInt64: + case kVarTypeUInt64: + // Extend BYTE->QWORD (Gp). + if (IntUtil::inInterval(srcType, kVarTypeInt8, kVarTypeUInt8)) { + r1.setSize(1); + r1.setCode(kX86RegTypeGpbLo, srcIndex); + + instId = (dstType == kVarTypeInt64 && srcType == kVarTypeInt8) ? kX86InstIdMovsx : kX86InstIdMovzx; + goto _ExtendMovGpXQ; + } + + // Extend WORD->QWORD (Gp). + if (IntUtil::inInterval(srcType, kVarTypeInt16, kVarTypeUInt16)) { + r1.setSize(2); + r1.setCode(kX86RegTypeGpw, srcIndex); + + instId = (dstType == kVarTypeInt64 && srcType == kVarTypeInt16) ? kX86InstIdMovsx : kX86InstIdMovzx; + goto _ExtendMovGpXQ; + } + + // Extend DWORD->QWORD (Gp). + if (IntUtil::inInterval(srcType, kVarTypeInt32, kVarTypeUInt32)) { + r1.setSize(4); + r1.setCode(kX86RegTypeGpd, srcIndex); + + instId = kX86InstIdMovsxd; + if (dstType == kVarTypeInt64 && srcType == kVarTypeInt32) + goto _ExtendMovGpXQ; + else + goto _ZeroExtendGpDQ; + } + + // Move QWORD (Gp). + if (IntUtil::inInterval(srcType, kVarTypeInt64, kVarTypeUInt64)) + goto _MovGpQ; + + // Move QWORD (Mm). + if (IntUtil::inInterval(srcType, kX86VarTypeMm, kX86VarTypeMm)) + goto _MovMmQ; + + // Move QWORD (Xmm). + if (IntUtil::inInterval(srcType, kX86VarTypeXmm, kX86VarTypeXmmPd)) + goto _MovXmmQ; + break; + + case kX86VarTypeMm: + // Extend BYTE->QWORD (Gp). + if (IntUtil::inInterval(srcType, kVarTypeInt8, kVarTypeUInt8)) { + r1.setSize(1); + r1.setCode(kX86RegTypeGpbLo, srcIndex); + + instId = kX86InstIdMovzx; + goto _ExtendMovGpXQ; + } + + // Extend WORD->QWORD (Gp). + if (IntUtil::inInterval(srcType, kVarTypeInt16, kVarTypeUInt16)) { + r1.setSize(2); + r1.setCode(kX86RegTypeGpw, srcIndex); + + instId = kX86InstIdMovzx; + goto _ExtendMovGpXQ; + } + + // Extend DWORD->QWORD (Gp). + if (IntUtil::inInterval(srcType, kVarTypeInt32, kVarTypeUInt32)) + goto _ExtendMovGpDQ; + + // Move QWORD (Gp). + if (IntUtil::inInterval(srcType, kVarTypeInt64, kVarTypeUInt64)) + goto _MovGpQ; + + // Move QWORD (Mm). + if (IntUtil::inInterval(srcType, kX86VarTypeMm, kX86VarTypeMm)) + goto _MovMmQ; + + // Move QWORD (Xmm). + if (IntUtil::inInterval(srcType, kX86VarTypeXmm, kX86VarTypeXmmPd)) + goto _MovXmmQ; + break; + + case kVarTypeFp32: + case kX86VarTypeXmmSs: + // Move FLOAT. + if (srcType == kX86VarTypeXmmSs || srcType == kX86VarTypeXmmPs || srcType == kX86VarTypeXmm) + goto _MovXmmD; + + ASMJIT_ASSERT(!"Reached"); + break; + + case kVarTypeFp64: + case kX86VarTypeXmmSd: + // Move DOUBLE. + if (srcType == kX86VarTypeXmmSd || srcType == kX86VarTypeXmmPd || srcType == kX86VarTypeXmm) + goto _MovXmmQ; + + ASMJIT_ASSERT(!"Reached"); + break; + + case kX86VarTypeXmm: + // TODO: [COMPILER]. + ASMJIT_ASSERT(!"Reached"); + break; + + case kX86VarTypeXmmPs: + // TODO: [COMPILER]. + ASMJIT_ASSERT(!"Reached"); + break; + + case kX86VarTypeXmmPd: + // TODO: [COMPILER]. + ASMJIT_ASSERT(!"Reached"); + break; + } + return; + + // Extend+Move Gp. +_ExtendMovGpD: + m0.setSize(4); + r0.setSize(4); + r0.setCode(kX86RegTypeGpd, srcIndex); + + compiler->emit(instId, r0, r1); + compiler->emit(kX86InstIdMov, m0, r0); + return; + +_ExtendMovGpXQ: + if (regSize == 8) { + m0.setSize(8); + r0.setSize(8); + r0.setCode(kX86RegTypeGpq, srcIndex); + + compiler->emit(instId, r0, r1); + compiler->emit(kX86InstIdMov, m0, r0); + } + else { + m0.setSize(4); + r0.setSize(4); + r0.setCode(kX86RegTypeGpd, srcIndex); + + compiler->emit(instId, r0, r1); + +_ExtendMovGpDQ: + compiler->emit(kX86InstIdMov, m0, r0); + m0.adjust(4); + compiler->emit(kX86InstIdAnd, m0, 0); + } + return; + +_ZeroExtendGpDQ: + m0.setSize(4); + r0.setSize(4); + r0.setCode(kX86RegTypeGpd, srcIndex); + goto _ExtendMovGpDQ; + + // Move Gp. +_MovGpD: + m0.setSize(4); + r0.setSize(4); + r0.setCode(kX86RegTypeGpd, srcIndex); + compiler->emit(kX86InstIdMov, m0, r0); + return; + +_MovGpQ: + m0.setSize(8); + r0.setSize(8); + r0.setCode(kX86RegTypeGpq, srcIndex); + compiler->emit(kX86InstIdMov, m0, r0); + return; + + // Move Mm. +_MovMmD: + m0.setSize(4); + r0.setSize(8); + r0.setCode(kX86RegTypeMm, srcIndex); + compiler->emit(kX86InstIdMovd, m0, r0); + return; + +_MovMmQ: + m0.setSize(8); + r0.setSize(8); + r0.setCode(kX86RegTypeMm, srcIndex); + compiler->emit(kX86InstIdMovq, m0, r0); + return; + + // Move Xmm. +_MovXmmD: + m0.setSize(4); + r0.setSize(16); + r0.setCode(kX86RegTypeXmm, srcIndex); + compiler->emit(kX86InstIdMovss, m0, r0); + return; + +_MovXmmQ: + m0.setSize(8); + r0.setSize(16); + r0.setCode(kX86RegTypeXmm, srcIndex); + compiler->emit(kX86InstIdMovlps, m0, r0); +} + +void X86Context::emitMoveImmOnStack(uint32_t dstType, const X86Mem* dst, const Imm* src) { + X86Compiler* compiler = getCompiler(); + + X86Mem mem(*dst); + Imm imm(*src); + + uint32_t regSize = compiler->getRegSize(); + + // One stack entry is equal to the native register size. That means that if + // we want to move 32-bit integer on the stack, we need to extend it to 64-bit + // integer. + mem.setSize(regSize); + + switch (dstType) { + case kVarTypeInt8: + case kVarTypeUInt8: + imm.truncateTo8Bits(); + goto _Move32; + + case kVarTypeInt16: + case kVarTypeUInt16: + imm.truncateTo16Bits(); + goto _Move32; + + case kVarTypeInt32: + case kVarTypeUInt32: +_Move32: + imm.truncateTo32Bits(); + compiler->emit(kX86InstIdMov, mem, imm); + break; + + case kVarTypeInt64: + case kVarTypeUInt64: +_Move64: + if (regSize == 4) { + uint32_t hi = imm.getUInt32Hi(); + + // Lo-Part. + compiler->emit(kX86InstIdMov, mem, imm.truncateTo32Bits()); + mem.adjust(regSize); + + // Hi-Part. + compiler->emit(kX86InstIdMov, mem, imm.setUInt32(hi)); + } + else { + compiler->emit(kX86InstIdMov, mem, imm); + } + break; + + case kVarTypeFp32: + goto _Move32; + + case kVarTypeFp64: + goto _Move64; + + case kX86VarTypeMm: + goto _Move64; + + case kX86VarTypeXmm: + case kX86VarTypeXmmSs: + case kX86VarTypeXmmPs: + case kX86VarTypeXmmSd: + case kX86VarTypeXmmPd: + if (regSize == 4) { + uint32_t hi = imm.getUInt32Hi(); + + // Lo part. + compiler->emit(kX86InstIdMov, mem, imm.truncateTo32Bits()); + mem.adjust(regSize); + + // Hi part. + compiler->emit(kX86InstIdMov, mem, imm.setUInt32(hi)); + mem.adjust(regSize); + + // Zero part. + compiler->emit(kX86InstIdMov, mem, imm.setUInt32(0)); + mem.adjust(regSize); + + compiler->emit(kX86InstIdMov, mem, imm); + } + else { + // Lo/Hi parts. + compiler->emit(kX86InstIdMov, mem, imm); + mem.adjust(regSize); + + // Zero part. + compiler->emit(kX86InstIdMov, mem, imm.setUInt32(0)); + } + break; + + default: + ASMJIT_ASSERT(!"Reached"); + break; + } +} + +// ============================================================================ +// [asmjit::X86Context - EmitMoveImmToReg] +// ============================================================================ + +void X86Context::emitMoveImmToReg(uint32_t dstType, uint32_t dstIndex, const Imm* src) { + ASMJIT_ASSERT(dstIndex != kInvalidReg); + X86Compiler* compiler = getCompiler(); + + X86Reg r0; + Imm imm(*src); + + switch (dstType) { + case kVarTypeInt8: + case kVarTypeUInt8: + imm.truncateTo8Bits(); + goto _Move32; + + case kVarTypeInt16: + case kVarTypeUInt16: + imm.truncateTo16Bits(); + goto _Move32; + + case kVarTypeInt32: + case kVarTypeUInt32: +_Move32Truncate: + imm.truncateTo32Bits(); +_Move32: + r0.setSize(4); + r0.setCode(kX86RegTypeGpd, dstIndex); + compiler->emit(kX86InstIdMov, r0, imm); + break; + + case kVarTypeInt64: + case kVarTypeUInt64: + // Move to Gpd register will also clear high DWORD of Gpq register in + // 64-bit mode. + if (imm.isUInt32()) + goto _Move32Truncate; + + r0.setSize(8); + r0.setCode(kX86RegTypeGpq, dstIndex); + compiler->emit(kX86InstIdMov, r0, imm); + break; + + case kVarTypeFp32: + case kVarTypeFp64: + // TODO: [COMPILER] EmitMoveImmToReg. + break; + + case kX86VarTypeMm: + // TODO: [COMPILER] EmitMoveImmToReg. + break; + + case kX86VarTypeXmm: + case kX86VarTypeXmmSs: + case kX86VarTypeXmmSd: + case kX86VarTypeXmmPs: + case kX86VarTypeXmmPd: + // TODO: [COMPILER] EmitMoveImmToReg. + break; + + default: + ASMJIT_ASSERT(!"Reached"); + break; + } +} + +// ============================================================================ +// [asmjit::X86Context - Register Management] +// ============================================================================ + +#if defined(ASMJIT_DEBUG) +template +static ASMJIT_INLINE void X86Context_checkStateVars(X86Context* self) { + X86VarState* state = self->getState(); + VarData** sVars = state->getListByClass(C); + + uint32_t regIndex; + uint32_t regMask; + uint32_t regCount = self->_regCount.get(C); + + uint32_t occupied = state->_occupied.get(C); + uint32_t modified = state->_modified.get(C); + + for (regIndex = 0, regMask = 1; regIndex < regCount; regIndex++, regMask <<= 1) { + VarData* vd = sVars[regIndex]; + + if (vd == NULL) { + ASMJIT_ASSERT((occupied & regMask) == 0); + ASMJIT_ASSERT((modified & regMask) == 0); + } + else { + ASMJIT_ASSERT((occupied & regMask) != 0); + ASMJIT_ASSERT((modified & regMask) == (static_cast(vd->isModified()) << regIndex)); + + ASMJIT_ASSERT(vd->getClass() == C); + ASMJIT_ASSERT(vd->getState() == kVarStateReg); + ASMJIT_ASSERT(vd->getRegIndex() == regIndex); + } + } +} + +void X86Context::_checkState() { + X86Context_checkStateVars(this); + X86Context_checkStateVars(this); + X86Context_checkStateVars(this); +} +#else +void X86Context::_checkState() {} +#endif // ASMJIT_DEBUG + +// ============================================================================ +// [asmjit::X86Context - State - Load] +// ============================================================================ + +template +static ASMJIT_INLINE void X86Context_loadStateVars(X86Context* self, X86VarState* src) { + X86VarState* cur = self->getState(); + + VarData** cVars = cur->getListByClass(C); + VarData** sVars = src->getListByClass(C); + + uint32_t regIndex; + uint32_t modified = src->_modified.get(C); + uint32_t regCount = self->_regCount.get(C); + + for (regIndex = 0; regIndex < regCount; regIndex++, modified >>= 1) { + VarData* vd = sVars[regIndex]; + cVars[regIndex] = vd; + + if (vd == NULL) + continue; + + vd->setState(kVarStateReg); + vd->setRegIndex(regIndex); + vd->setModified(modified & 0x1); + } +} + +void X86Context::loadState(VarState* src_) { + X86VarState* cur = getState(); + X86VarState* src = static_cast(src_); + + VarData** vdArray = _contextVd.getData(); + uint32_t vdCount = static_cast(_contextVd.getLength()); + + // Load allocated variables. + X86Context_loadStateVars(this, src); + X86Context_loadStateVars(this, src); + X86Context_loadStateVars(this, src); + + // Load masks. + cur->_occupied = src->_occupied; + cur->_modified = src->_modified; + + // Load states of other variables and clear their 'Modified' flags. + for (uint32_t i = 0; i < vdCount; i++) { + uint32_t vState = src->_cells[i].getState(); + + if (vState == kVarStateReg) + continue; + + vdArray[i]->setState(vState); + vdArray[i]->setRegIndex(kInvalidReg); + vdArray[i]->setModified(false); + } + + ASMJIT_X86_CHECK_STATE +} + +// ============================================================================ +// [asmjit::X86Context - State - Save] +// ============================================================================ + +VarState* X86Context::saveState() { + VarData** vdArray = _contextVd.getData(); + uint32_t vdCount = static_cast(_contextVd.getLength()); + + size_t size = IntUtil::alignTo( + sizeof(X86VarState) + vdCount * sizeof(X86StateCell), sizeof(void*)); + + X86VarState* cur = getState(); + X86VarState* dst = _baseZone.allocT(size); + + if (dst == NULL) + return NULL; + + // Store links. + ::memcpy(dst->_list, cur->_list, X86VarState::kAllCount * sizeof(VarData*)); + + // Store masks. + dst->_occupied = cur->_occupied; + dst->_modified = cur->_modified; + + // Store cells. + for (uint32_t i = 0; i < vdCount; i++) { + VarData* vd = static_cast(vdArray[i]); + X86StateCell& cell = dst->_cells[i]; + + cell.reset(); + cell.setState(vd->getState()); + } + + return dst; +} + +// ============================================================================ +// [asmjit::X86Context - State - Switch] +// ============================================================================ + +template +static ASMJIT_INLINE void X86Context_switchStateVars(X86Context* self, X86VarState* src) { + X86VarState* dst = self->getState(); + + VarData** dstVars = dst->getListByClass(C); + VarData** srcVars = src->getListByClass(C); + + uint32_t regIndex; + uint32_t regMask; + uint32_t regCount = self->_regCount.get(C); + + X86StateCell* cells = src->_cells; + + bool didWork; + do { + didWork = false; + + for (regIndex = 0, regMask = 0x1; regIndex < regCount; regIndex++, regMask <<= 1) { + VarData* dVd = dstVars[regIndex]; + VarData* sVd = srcVars[regIndex]; + + if (dVd == sVd) + continue; + + if (dVd != NULL) { + X86StateCell& cell = cells[dVd->getContextId()]; + + if (cell.getState() != kVarStateReg) { + if (cell.getState() == kVarStateMem) + self->spill(dVd); + else + self->unuse(dVd); + + dVd = NULL; + didWork = true; + + if (sVd == NULL) + continue; + } + } + + if (dVd == NULL && sVd != NULL) { +_MoveOrLoad: + if (sVd->getRegIndex() != kInvalidReg) + self->move(sVd, regIndex); + else + self->load(sVd, regIndex); + + didWork = true; + continue; + } + + if (dVd != NULL && sVd == NULL) { + X86StateCell& cell = cells[dVd->getContextId()]; + if (cell.getState() == kVarStateReg) + continue; + + if (cell.getState() == kVarStateMem) + self->spill(dVd); + else + self->unuse(dVd); + + didWork = true; + continue; + } + else { + X86StateCell& cell = cells[dVd->getContextId()]; + + if (cell.getState() == kVarStateReg) { + if (dVd->getRegIndex() != kInvalidReg && sVd->getRegIndex() != kInvalidReg) { + if (C == kX86RegClassGp) { + self->swapGp(dVd, sVd); + } + else { + self->spill(dVd); + self->move(sVd, regIndex); + } + + didWork = true; + continue; + } + else { + didWork = true; + continue; + } + } + + if (cell.getState() == kVarStateMem) + self->spill(dVd); + else + self->unuse(dVd); + goto _MoveOrLoad; + } + } + } while (didWork); + + uint32_t dstModified = dst->_modified.get(C); + uint32_t srcModified = src->_modified.get(C); + + if (dstModified != srcModified) { + for (regIndex = 0, regMask = 0x1; regIndex < regCount; regIndex++, regMask <<= 1) { + VarData* vd = dstVars[regIndex]; + + if (vd == NULL) + continue; + + if ((dstModified & regMask) && !(srcModified & regMask)) { + self->save(vd); + continue; + } + + if (!(dstModified & regMask) && (srcModified & regMask)) { + self->modify(vd); + continue; + } + } + } +} + +void X86Context::switchState(VarState* src_) { + ASMJIT_ASSERT(src_ != NULL); + + X86VarState* cur = getState(); + X86VarState* src = static_cast(src_); + + // Ignore if both states are equal. + if (cur == src) + return; + + // Switch variables. + X86Context_switchStateVars(this, src); + X86Context_switchStateVars(this, src); + X86Context_switchStateVars(this, src); + + // Calculate changed state. + VarData** vdArray = _contextVd.getData(); + uint32_t vdCount = static_cast(_contextVd.getLength()); + + X86StateCell* cells = src->_cells; + for (uint32_t i = 0; i < vdCount; i++) { + VarData* vd = static_cast(vdArray[i]); + X86StateCell& cell = cells[i]; + + uint32_t vState = cell.getState(); + if (vState != kVarStateReg) { + vd->setState(vState); + vd->setModified(false); + } + } + + ASMJIT_X86_CHECK_STATE +} + +// ============================================================================ +// [asmjit::X86Context - State - Intersect] +// ============================================================================ + +void X86Context::intersectStates(VarState* a_, VarState* b_) { + X86VarState* aState = static_cast(a_); + X86VarState* bState = static_cast(b_); + + // TODO: [COMPILER] Intersect states. + ASMJIT_X86_CHECK_STATE +} + +// ============================================================================ +// [asmjit::X86Context - GetJccFlow / GetOppositeJccFlow] +// ============================================================================ + +//! \internal +static ASMJIT_INLINE Node* X86Context_getJccFlow(JumpNode* jNode) { + if (jNode->isTaken()) + return jNode->getTarget(); + else + return jNode->getNext(); +} + +//! \internal +static ASMJIT_INLINE Node* X86Context_getOppositeJccFlow(JumpNode* jNode) { + if (jNode->isTaken()) + return jNode->getNext(); + else + return jNode->getTarget(); +} + +// ============================================================================ +// [asmjit::X86Context - SingleVarInst] +// ============================================================================ + +//! \internal +static void X86Context_prepareSingleVarInst(uint32_t instId, VarAttr* va) { + switch (instId) { + // - andn reg, reg ; Set all bits in reg to 0. + // - xor/pxor reg, reg ; Set all bits in reg to 0. + // - sub/psub reg, reg ; Set all bits in reg to 0. + // - pcmpgt reg, reg ; Set all bits in reg to 0. + // - pcmpeq reg, reg ; Set all bits in reg to 1. + case kX86InstIdPandn : + case kX86InstIdXor : case kX86InstIdXorpd : case kX86InstIdXorps : case kX86InstIdPxor : + case kX86InstIdSub: + case kX86InstIdPsubb : case kX86InstIdPsubw : case kX86InstIdPsubd : case kX86InstIdPsubq : + case kX86InstIdPsubsb : case kX86InstIdPsubsw : case kX86InstIdPsubusb : case kX86InstIdPsubusw : + case kX86InstIdPcmpeqb : case kX86InstIdPcmpeqw : case kX86InstIdPcmpeqd : case kX86InstIdPcmpeqq : + case kX86InstIdPcmpgtb : case kX86InstIdPcmpgtw : case kX86InstIdPcmpgtd : case kX86InstIdPcmpgtq : + va->andNotFlags(kVarAttrInReg); + break; + + // - and reg, reg ; Nop. + // - or reg, reg ; Nop. + // - xchg reg, reg ; Nop. + case kX86InstIdAnd : case kX86InstIdAndpd : case kX86InstIdAndps : case kX86InstIdPand : + case kX86InstIdOr : case kX86InstIdOrpd : case kX86InstIdOrps : case kX86InstIdPor : + case kX86InstIdXchg : + va->andNotFlags(kVarAttrOutReg); + break; + } +} + +// ============================================================================ +// [asmjit::X86Context - Helpers] +// ============================================================================ + +//! \internal +//! +//! Add unreachable-flow data to the unreachable flow list. +static ASMJIT_INLINE Error X86Context_addUnreachableNode(X86Context* self, Node* node) { + PodList::Link* link = self->_baseZone.allocT::Link>(); + if (link == NULL) + return self->setError(kErrorNoHeapMemory); + + link->setValue(node); + self->_unreachableList.append(link); + + return kErrorOk; +} + +//! \internal +//! +//! Add jump-flow data to the jcc flow list. +static ASMJIT_INLINE Error X86Context_addJccNode(X86Context* self, Node* node) { + PodList::Link* link = self->_baseZone.allocT::Link>(); + + if (link == NULL) + ASMJIT_PROPAGATE_ERROR(self->setError(kErrorNoHeapMemory)); + + link->setValue(node); + self->_jccList.append(link); + + return kErrorOk; +} + +//! \internal +//! +//! Get mask of all registers actually used to pass function arguments. +static ASMJIT_INLINE X86RegMask X86Context_getUsedArgs(X86Context* self, X86CallNode* node, X86FuncDecl* decl) { + X86RegMask regs; + regs.reset(); + + uint32_t i; + uint32_t argCount = decl->getArgCount(); + + for (i = 0; i < argCount; i++) { + const FuncInOut& arg = decl->getArg(i); + if (!arg.hasRegIndex()) + continue; + regs.or_(x86VarTypeToClass(arg.getVarType()), IntUtil::mask(arg.getRegIndex())); + } + + return regs; +} + +// ============================================================================ +// [asmjit::X86Context - SArg Insertion] +// ============================================================================ + +struct SArgData { + VarData* sVd; + VarData* cVd; + SArgNode* sArg; + uint32_t aType; +}; + +#define SARG(_Dst_, S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15, S16, S17, S18, S19, S20) \ + (S0 << 0) | (S1 << 1) | (S2 << 2) | (S3 << 3) | \ + (S4 << 4) | (S5 << 5) | (S6 << 6) | (S7 << 7) | \ + (S8 << 8) | (S9 << 9) | (S10 << 10) | (S11 << 11) | \ + (S12 << 12) | (S13 << 13) | (S14 << 14) | (S15 << 15) | \ + (S16 << 16) | (S17 << 17) | (S18 << 18) | (S19 << 19) | \ + (S20 << 20) +#define A 0 /* Auto-convert (doesn't need conversion step). */ +static const uint32_t X86Context_sArgConvTable[kX86VarTypeCount] = { + // dst <- | i8| u8|i16|u16|i32|u32|i64|u64| iP| uP|f32|f64|mmx|xmm|xSs|xPs|xSd|xPd|ymm|yPs|yPd| + //--------+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + SARG(i8 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , A , A , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 ), + SARG(u8 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , A , A , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 ), + SARG(i16 , A , A , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , A , A , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 ), + SARG(u16 , A , A , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , A , A , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 ), + SARG(i32 , A , A , A , A , 0 , 0 , 0 , 0 , 0 , 0 , A , A , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 ), + SARG(u32 , A , A , A , A , 0 , 0 , 0 , 0 , 0 , 0 , A , A , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 ), + SARG(i64 , A , A , A , A , A , A , 0 , 0 , A , A , A , A , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 ), + SARG(u64 , A , A , A , A , A , A , 0 , 0 , A , A , A , A , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 ), + SARG(iPtr , A , A , A , A , A , A , A , A , 0 , 0 , A , A , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 ), + SARG(uPtr , A , A , A , A , A , A , A , A , 0 , 0 , A , A , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 ), + SARG(f32 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , A , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 1 ), + SARG(f64 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , A , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 0 ), + SARG(mmx , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ), + SARG(xmm , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ), + SARG(xSs , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 1 ), + SARG(xPs , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 1 ), + SARG(xSd , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 0 ), + SARG(xPd , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 0 ), + SARG(ymm , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ), + SARG(yPs , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 1 ), + SARG(yPd , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 0 ) +}; +#undef A +#undef SARG + +static ASMJIT_INLINE bool X86Context_mustConvertSArg(X86Context* self, uint32_t aType, uint32_t sType) { + return (X86Context_sArgConvTable[aType] & (1 << sType)) != 0; +} + +static ASMJIT_INLINE uint32_t X86Context_typeOfConvertedSArg(X86Context* self, uint32_t aType, uint32_t sType) { + ASMJIT_ASSERT(X86Context_mustConvertSArg(self, aType, sType)); + + if (IntUtil::inInterval(aType, _kVarTypeIntStart, _kVarTypeIntEnd)) + return aType; + + if (aType == kVarTypeFp32) + return kX86VarTypeXmmSs; + + if (aType == kVarTypeFp64) + return kX86VarTypeXmmSd; + + if (IntUtil::inInterval(aType, _kX86VarTypeXmmStart, _kX86VarTypeXmmEnd)) + return aType; + + if (IntUtil::inInterval(aType, _kX86VarTypeYmmStart, _kX86VarTypeYmmEnd)) + return aType; + + ASMJIT_ASSERT(!"Reached"); + return aType; +} + +static ASMJIT_INLINE Error X86Context_insertSArgNode( + X86Context* self, X86CallNode* call, + VarData* sVd, const uint32_t* gaRegs, + const FuncInOut& arg, uint32_t argIndex, + SArgData* sArgList, uint32_t& sArgCount) { + + X86Compiler* compiler = self->getCompiler(); + uint32_t i; + + uint32_t aType = arg.getVarType(); + uint32_t sType = sVd->getType(); + + // First locate or create sArgBase. + for (i = 0; i < sArgCount; i++) { + if (sArgList[i].sVd == sVd && sArgList[i].cVd == NULL) + break; + } + + SArgData* sArgData = &sArgList[i]; + + if (i == sArgCount) { + sArgData->sVd = sVd; + sArgData->cVd = NULL; + sArgData->sArg = NULL; + sArgData->aType = 0xFF; + sArgCount++; + } + + const X86VarInfo& sInfo = _x86VarInfo[sType]; + uint32_t sClass = sInfo.getClass(); + + if (X86Context_mustConvertSArg(self, aType, sType)) { + uint32_t cType = X86Context_typeOfConvertedSArg(self, aType, sType); + + const X86VarInfo& cInfo = _x86VarInfo[cType]; + uint32_t cClass = cInfo.getClass(); + + while (++i < sArgCount) { + sArgData = &sArgList[i]; + if (sArgData->sVd != sVd) + break; + + if (sArgData->cVd->getType() != cType || sArgData->aType != aType) + continue; + + sArgData->sArg->_args |= IntUtil::mask(argIndex); + return kErrorOk; + } + + VarData* cVd = compiler->_newVd(cType, cInfo.getSize(), cInfo.getClass(), NULL); + if (cVd == NULL) + return kErrorNoHeapMemory; + + SArgNode* sArg = compiler->newNode(call, sVd, cVd); + if (sArg == NULL) + return kErrorNoHeapMemory; + + X86VarMap* map = self->newVarMap(2); + if (map == NULL) + return kErrorNoHeapMemory; + + ASMJIT_PROPAGATE_ERROR(self->_registerContextVar(cVd)); + ASMJIT_PROPAGATE_ERROR(self->_registerContextVar(sVd)); + + map->_vaCount = 2; + map->_count.reset(); + map->_count.add(sClass); + map->_count.add(cClass); + + map->_start.reset(); + map->_inRegs.reset(); + map->_outRegs.reset(); + map->_clobberedRegs.reset(); + + if (sClass <= cClass) { + map->_list[0].setup(sVd, kVarAttrInReg , 0, gaRegs[sClass]); + map->_list[1].setup(cVd, kVarAttrOutReg, 0, gaRegs[cClass]); + map->_start.set(cClass, sClass != cClass); + } + else { + map->_list[0].setup(cVd, kVarAttrOutReg, 0, gaRegs[cClass]); + map->_list[1].setup(sVd, kVarAttrInReg , 0, gaRegs[sClass]); + map->_start.set(sClass, 1); + } + + sArg->setMap(map); + sArg->_args |= IntUtil::mask(argIndex); + + compiler->addNodeBefore(sArg, call); + ::memmove(sArgData + 1, sArgData, (sArgCount - i) * sizeof(SArgData)); + + sArgData->sVd = sVd; + sArgData->cVd = cVd; + sArgData->sArg = sArg; + sArgData->aType = aType; + + sArgCount++; + return kErrorOk; + } + else { + SArgNode* sArg = sArgData->sArg; + ASMJIT_PROPAGATE_ERROR(self->_registerContextVar(sVd)); + + if (sArg == NULL) { + sArg = compiler->newNode(call, sVd, (VarData*)NULL); + if (sArg == NULL) + return kErrorNoHeapMemory; + + X86VarMap* map = self->newVarMap(1); + if (map == NULL) + return kErrorNoHeapMemory; + + map->_vaCount = 1; + map->_count.reset(); + map->_count.add(sClass); + map->_start.reset(); + map->_inRegs.reset(); + map->_outRegs.reset(); + map->_clobberedRegs.reset(); + map->_list[0].setup(sVd, kVarAttrInReg, 0, gaRegs[sClass]); + + sArg->setMap(map); + sArgData->sArg = sArg; + + compiler->addNodeBefore(sArg, call); + } + + sArg->_args |= IntUtil::mask(argIndex); + return kErrorOk; + } +} + +// ============================================================================ +// [asmjit::X86Context - Fetch] +// ============================================================================ + +//! \internal +//! +//! Prepare the given function `func`. +//! +//! For each node: +//! - Create and assign groupId and flowId. +//! - Collect all variables and merge them to vaList. +Error X86Context::fetch() { + ASMJIT_TLOG("[Fetch] === Begin ===\n"); + + X86Compiler* compiler = getCompiler(); + X86FuncNode* func = getFunc(); + + uint32_t arch = compiler->getArch(); + + Node* node_ = func; + Node* next = NULL; + Node* stop = getStop(); + + uint32_t flowId = 0; + + VarAttr vaTmpList[80]; + SArgData sArgList[80]; + + PodList::Link* jLink = NULL; + + // Function flags. + func->clearFuncFlags( + kFuncFlagIsNaked | + kX86FuncFlagPushPop | + kX86FuncFlagEmms | + kX86FuncFlagSFence | + kX86FuncFlagLFence ); + + if (func->getHint(kFuncHintNaked ) != 0) func->addFuncFlags(kFuncFlagIsNaked ); + if (func->getHint(kFuncHintCompact ) != 0) func->addFuncFlags(kX86FuncFlagPushPop | kX86FuncFlagEnter | kX86FuncFlagLeave); + if (func->getHint(kX86FuncHintPushPop) != 0) func->addFuncFlags(kX86FuncFlagPushPop); + if (func->getHint(kX86FuncHintEmms ) != 0) func->addFuncFlags(kX86FuncFlagEmms ); + if (func->getHint(kX86FuncHintSFence ) != 0) func->addFuncFlags(kX86FuncFlagSFence ); + if (func->getHint(kX86FuncHintLFence ) != 0) func->addFuncFlags(kX86FuncFlagLFence ); + + // Global allocable registers. + uint32_t* gaRegs = _gaRegs; + + if (!func->hasFuncFlag(kFuncFlagIsNaked)) + gaRegs[kX86RegClassGp] &= ~IntUtil::mask(kX86RegIndexBp); + + // Allowed index registers (Gp/Xmm/Ymm). + const uint32_t indexMask = IntUtil::bits(_regCount.getGp()) & ~(IntUtil::mask(4, 12)); + + // -------------------------------------------------------------------------- + // [VI Macros] + // -------------------------------------------------------------------------- + +#define VI_BEGIN() \ + do { \ + uint32_t vaCount = 0; \ + X86RegCount regCount; \ + \ + X86RegMask inRegs; \ + X86RegMask outRegs; \ + X86RegMask clobberedRegs; \ + \ + regCount.reset(); \ + inRegs.reset(); \ + outRegs.reset(); \ + clobberedRegs.reset() + +#define VI_END(_Node_) \ + if (vaCount == 0 && clobberedRegs.isEmpty()) \ + break; \ + \ + X86VarMap* map = newVarMap(vaCount); \ + if (map == NULL) \ + goto _NoMemory; \ + \ + X86RegCount vaIndex; \ + vaIndex.indexFromRegCount(regCount); \ + \ + map->_vaCount = vaCount; \ + map->_count = regCount; \ + map->_start = vaIndex; \ + \ + map->_inRegs = inRegs; \ + map->_outRegs = outRegs; \ + map->_clobberedRegs = clobberedRegs; \ + \ + VarAttr* va = vaTmpList; \ + while (vaCount) { \ + VarData* vd = va->getVd(); \ + \ + uint32_t class_ = vd->getClass(); \ + uint32_t index = vaIndex.get(class_); \ + \ + vaIndex.add(class_); \ + \ + if (va->_inRegs) \ + va->_allocableRegs = va->_inRegs; \ + else if (va->_outRegIndex != kInvalidReg) \ + va->_allocableRegs = IntUtil::mask(va->_outRegIndex); \ + else \ + va->_allocableRegs &= ~inRegs.get(class_); \ + \ + vd->_va = NULL; \ + map->getVa(index)[0] = va[0]; \ + \ + va++; \ + vaCount--; \ + } \ + \ + _Node_->setMap(map); \ + } while (0) + +#define VI_ADD_VAR(_Vd_, _Va_, _Flags_, _NewAllocable_) \ + do { \ + ASMJIT_ASSERT(_Vd_->_va == NULL); \ + \ + _Va_ = &vaTmpList[vaCount++]; \ + _Va_->setup(_Vd_, _Flags_, 0, _NewAllocable_); \ + _Va_->addVarCount(1); \ + _Vd_->setVa(_Va_); \ + \ + if (_registerContextVar(_Vd_) != kErrorOk) \ + goto _NoMemory; \ + regCount.add(_Vd_->getClass()); \ + } while (0) + +#define VI_MERGE_VAR(_Vd_, _Va_, _Flags_, _NewAllocable_) \ + do { \ + _Va_ = _Vd_->getVa(); \ + \ + if (_Va_ == NULL) { \ + _Va_ = &vaTmpList[vaCount++]; \ + _Va_->setup(_Vd_, 0, 0, _NewAllocable_); \ + _Vd_->setVa(_Va_); \ + \ + if (_registerContextVar(_Vd_) != kErrorOk) \ + goto _NoMemory; \ + regCount.add(_Vd_->getClass()); \ + } \ + \ + _Va_->orFlags(_Flags_); \ + _Va_->addVarCount(1); \ + } while (0) + + // -------------------------------------------------------------------------- + // [Loop] + // -------------------------------------------------------------------------- + + do { +_Do: + while (node_->isFetched()) { +_NextGroup: + if (jLink == NULL) + jLink = _jccList.getFirst(); + else + jLink = jLink->getNext(); + + if (jLink == NULL) + goto _Done; + node_ = X86Context_getOppositeJccFlow(static_cast(jLink->getValue())); + } + + flowId++; + + next = node_->getNext(); + node_->setFlowId(flowId); + + ASMJIT_TSEC({ + X86Context_traceNode(this, node_); + }); + + switch (node_->getType()) { + // ---------------------------------------------------------------------- + // [Align/Embed] + // ---------------------------------------------------------------------- + + case kNodeTypeAlign: + case kNodeTypeEmbed: + break; + + // ---------------------------------------------------------------------- + // [Hint] + // ---------------------------------------------------------------------- + + case kNodeTypeHint: { + HintNode* node = static_cast(node_); + VI_BEGIN(); + + if (node->getHint() == kVarHintAlloc) { + uint32_t remain[_kX86RegClassManagedCount]; + HintNode* cur = node; + + remain[kX86RegClassGp ] = _regCount.getGp() - 1 - func->hasFuncFlag(kFuncFlagIsNaked); + remain[kX86RegClassMm ] = _regCount.getMm(); + remain[kX86RegClassK ] = _regCount.getK(); + remain[kX86RegClassXyz] = _regCount.getXyz(); + + // Merge as many alloc-hints as possible. + for (;;) { + VarData* vd = static_cast(cur->getVd()); + VarAttr* va = vd->getVa(); + + uint32_t regClass = vd->getClass(); + uint32_t regIndex = cur->getValue(); + uint32_t regMask = 0; + + // We handle both kInvalidReg and kInvalidValue. + if (regIndex < kInvalidReg) + regMask = IntUtil::mask(regIndex); + + if (va == NULL) { + if (inRegs.has(regClass, regMask)) + break; + if (remain[regClass] == 0) + break; + VI_ADD_VAR(vd, va, kVarAttrInReg, gaRegs[regClass]); + + if (regMask != 0) { + inRegs.xor_(regClass, regMask); + va->setInRegs(regMask); + va->setInRegIndex(regIndex); + } + + remain[regClass]--; + } + else if (regMask != 0) { + if (inRegs.has(regClass, regMask) && va->getInRegs() != regMask) + break; + + inRegs.xor_(regClass, va->getInRegs() | regMask); + va->setInRegs(regMask); + va->setInRegIndex(regIndex); + } + + if (cur != node) + compiler->removeNode(cur); + + cur = static_cast(node->getNext()); + if (cur == NULL || cur->getType() != kNodeTypeHint || cur->getHint() != kVarHintAlloc) + break; + } + + next = node->getNext(); + } + else { + VarData* vd = static_cast(node->getVd()); + VarAttr* va; + + uint32_t flags = 0; + + switch (node->getHint()) { + case kVarHintSpill: + flags = kVarAttrInMem | kVarAttrSpill; + break; + case kVarHintSave: + flags = kVarAttrInMem; + break; + case kVarHintSaveAndUnuse: + flags = kVarAttrInMem | kVarAttrUnuse; + break; + case kVarHintUnuse: + flags = kVarAttrUnuse; + break; + } + + VI_ADD_VAR(vd, va, flags, 0); + } + + VI_END(node_); + break; + } + + // ---------------------------------------------------------------------- + // [Target] + // ---------------------------------------------------------------------- + + case kNodeTypeTarget: { + break; + } + + // ---------------------------------------------------------------------- + // [Inst] + // ---------------------------------------------------------------------- + + case kNodeTypeInst: { + InstNode* node = static_cast(node_); + + uint32_t instId = node->getInstId(); + uint32_t flags = node->getFlags(); + + Operand* opList = node->getOpList(); + uint32_t opCount = node->getOpCount(); + + if (opCount) { + const X86InstExtendedInfo& extendedInfo = _x86InstInfo[instId].getExtendedInfo(); + const X86SpecialInst* special = NULL; + VI_BEGIN(); + + // Collect instruction flags and merge all 'VarAttr's. + if (extendedInfo.isFp()) + flags |= kNodeFlagIsFp; + + if (extendedInfo.isSpecial() && (special = X86SpecialInst_get(instId, opList, opCount)) != NULL) + flags |= kNodeFlagIsSpecial; + + uint32_t gpAllowedMask = 0xFFFFFFFF; + + for (uint32_t i = 0; i < opCount; i++) { + Operand* op = &opList[i]; + VarData* vd; + VarAttr* va; + + if (op->isVar()) { + vd = compiler->getVdById(op->getId()); + VI_MERGE_VAR(vd, va, 0, gaRegs[vd->getClass()] & gpAllowedMask); + + if (static_cast(op)->isGpb()) { + va->orFlags(static_cast(op)->isGpbLo() ? kX86VarAttrGpbLo : kX86VarAttrGpbHi); + if (arch == kArchX86) { + // If a byte register is accessed in 32-bit mode we have to limit + // all allocable registers for that variable to eax/ebx/ecx/edx. + // Other variables are not affected. + va->_allocableRegs &= 0x0F; + } + else { + // It's fine if lo-byte register is accessed in 64-bit mode; + // however, hi-byte has to be checked and if it's used all + // registers (Gp/Xmm) could be only allocated in the lower eight + // half. To do that, we patch 'allocableRegs' of all variables + // we collected until now and change the allocable restriction + // for variables that come after. + if (static_cast(op)->isGpbHi()) { + va->_allocableRegs &= 0x0F; + + if (gpAllowedMask != 0xFF) { + for (uint32_t j = 0; j < i; j++) + vaTmpList[j]._allocableRegs &= vaTmpList[j].hasFlag(kX86VarAttrGpbHi) ? 0x0F : 0xFF; + gpAllowedMask = 0xFF; + } + } + } + } + + if (special != NULL) { + uint32_t inReg = special[i].inReg; + uint32_t outReg = special[i].outReg; + uint32_t c; + + if (static_cast(op)->isGp()) + c = kX86RegClassGp; + else + c = kX86RegClassXyz; + + if (inReg != kInvalidReg) { + uint32_t mask = IntUtil::mask(inReg); + inRegs.or_(c, mask); + va->addInRegs(mask); + } + + if (outReg != kInvalidReg) { + uint32_t mask = IntUtil::mask(outReg); + outRegs.or_(c, mask); + va->setOutRegIndex(outReg); + } + + va->orFlags(special[i].flags); + } + else { + uint32_t inFlags = kVarAttrInReg; + uint32_t outFlags = kVarAttrOutReg; + uint32_t combinedFlags; + + if (i == 0) { + // Read/Write is usualy the combination of the first operand. + combinedFlags = inFlags | outFlags; + + // Move instructions typically overwrite the first operand, + // but there are some exceptions based on the operands' size + // and type. + if (extendedInfo.isMove()) { + uint32_t movSize = extendedInfo.getWriteSize(); + uint32_t varSize = vd->getSize(); + + // Exception - If the source operand is a memory location + // promote move size into 16 bytes. + if (extendedInfo.isZeroIfMem() && opList[1].isMem()) + movSize = 16; + + if (movSize >= varSize) { + // If move size is greater than or equal to the size of + // the variable there is nothing to do, because the move + // will overwrite the variable in all cases. + combinedFlags = outFlags; + } + else if (static_cast(op)->isGp()) { + uint32_t opSize = static_cast(op)->getSize(); + + // Move size is zero in case that it should be determined + // from the destination register. + if (movSize == 0) + movSize = opSize; + + // Handle the case that a 32-bit operation in 64-bit mode + // always zeroes the rest of the destination register and + // the case that move size is actually greater than or + // equal to the size of the variable. + if (movSize >= 4 || movSize >= varSize) + combinedFlags = outFlags; + } + } + // Comparison/Test instructions don't modify any operand. + else if (extendedInfo.isTest()) { + combinedFlags = inFlags; + } + // Imul. + else if (instId == kX86InstIdImul && opCount == 3) { + combinedFlags = outFlags; + } + } + else { + // Read-Only is usualy the combination of the second/third/fourth operands. + combinedFlags = inFlags; + + // Idiv is a special instruction, never handled here. + ASMJIT_ASSERT(instId != kX86InstIdIdiv); + + // Xchg/Xadd/Imul. + if (extendedInfo.isXchg() || (instId == kX86InstIdImul && opCount == 3 && i == 1)) + combinedFlags = inFlags | outFlags; + } + va->orFlags(combinedFlags); + } + } + else if (op->isMem()) { + X86Mem* m = static_cast(op); + node->setMemOpIndex(i); + + if (OperandUtil::isVarId(m->getBase()) && m->isBaseIndexType()) { + vd = compiler->getVdById(m->getBase()); + if (!vd->isStack()) { + VI_MERGE_VAR(vd, va, 0, gaRegs[vd->getClass()] & gpAllowedMask); + if (m->getMemType() == kMemTypeBaseIndex) { + va->orFlags(kVarAttrInReg); + } + else { + uint32_t inFlags = kVarAttrInMem; + uint32_t outFlags = kVarAttrOutMem; + uint32_t combinedFlags; + + if (i == 0) { + // Default for the first operand. + combinedFlags = inFlags | outFlags; + + // Move to memory - setting the right flags is important + // as if it's just move to the register. It's just a bit + // simpler as there are no special cases. + if (extendedInfo.isMove()) { + uint32_t movSize = IntUtil::iMax(extendedInfo.getWriteSize(), m->getSize()); + uint32_t varSize = vd->getSize(); + + if (movSize >= varSize) + combinedFlags = outFlags; + } + // Comparison/Test instructions don't modify any operand. + else if (extendedInfo.isTest()) { + combinedFlags = inFlags; + } + } + else { + // Default for the second operand. + combinedFlags = inFlags; + + // Handle Xchg instruction (modifies both operands). + if (extendedInfo.isXchg()) + combinedFlags = inFlags | outFlags; + } + + va->orFlags(combinedFlags); + } + } + } + + if (OperandUtil::isVarId(m->getIndex())) { + // Restrict allocation to all registers except ESP/RSP/R12. + vd = compiler->getVdById(m->getIndex()); + VI_MERGE_VAR(vd, va, 0, gaRegs[kX86RegClassGp] & gpAllowedMask); + va->andAllocableRegs(indexMask); + va->orFlags(kVarAttrInReg); + } + } + } + + node->setFlags(flags); + if (vaCount) { + // Handle instructions which result in zeros/ones or nop if used with the + // same destination and source operand. + if (vaCount == 1 && opCount >= 2 && opList[0].isVar() && opList[1].isVar() && !node->hasMemOp()) + X86Context_prepareSingleVarInst(instId, &vaTmpList[0]); + } + + VI_END(node_); + } + + // Handle conditional/unconditional jump. + if (node->isJmpOrJcc()) { + JumpNode* jNode = static_cast(node); + + Node* jNext = jNode->getNext(); + TargetNode* jTarget = jNode->getTarget(); + + // If this jump is unconditional we put next node to unreachable node + // list so we can eliminate possible dead code. We have to do this in + // all cases since we are unable to translate without fetch() step. + // + // We also advance our node pointer to the target node to simulate + // natural flow of the function. + if (jNode->isJmp()) { + if (!jNext->isFetched()) + ASMJIT_PROPAGATE_ERROR(X86Context_addUnreachableNode(this, jNext)); + + node_ = jTarget; + goto _Do; + } + else { + if (jTarget->isFetched()) { + uint32_t jTargetFlowId = jTarget->getFlowId(); + + // Update kNodeFlagIsTaken flag to true if this is a conditional + // backward jump. This behavior can be overridden by using + // `kInstOptionTaken` when the instruction is created. + if (!jNode->isTaken() && opCount == 1 && jTargetFlowId <= flowId) { + jNode->orFlags(kNodeFlagIsTaken); + } + } + else if (jNext->isFetched()) { + node_ = jTarget; + goto _Do; + } + else { + ASMJIT_PROPAGATE_ERROR(X86Context_addJccNode(this, jNode)); + + node_ = X86Context_getJccFlow(jNode); + goto _Do; + } + } + } + break; + } + + // ---------------------------------------------------------------------- + // [Func] + // ---------------------------------------------------------------------- + + case kNodeTypeFunc: { + ASMJIT_ASSERT(node_ == func); + X86FuncDecl* decl = func->getDecl(); + + VI_BEGIN(); + for (uint32_t i = 0, argCount = decl->getArgCount(); i < argCount; i++) { + const FuncInOut& arg = decl->getArg(i); + + VarData* vd = func->getArg(i); + VarAttr* va; + + if (vd == NULL) + continue; + + // Overlapped function arguments. + if (vd->getVa() != NULL) + return compiler->setError(kErrorOverlappedArgs); + VI_ADD_VAR(vd, va, 0, 0); + + uint32_t aType = arg.getVarType(); + uint32_t vType = vd->getType(); + + if (arg.hasRegIndex()) { + if (x86VarTypeToClass(aType) == vd->getClass()) { + va->orFlags(kVarAttrOutReg); + va->setOutRegIndex(arg.getRegIndex()); + } + else { + va->orFlags(kVarAttrOutConv); + } + } + else { + if ((x86VarTypeToClass(aType) == vd->getClass()) || + (vType == kX86VarTypeXmmSs && aType == kVarTypeFp32) || + (vType == kX86VarTypeXmmSd && aType == kVarTypeFp64)) { + va->orFlags(kVarAttrOutMem); + } + else { + // TODO: [COMPILER] Not implemented. + ASMJIT_ASSERT(!"Implemented"); + } + } + } + VI_END(node_); + break; + } + + // ---------------------------------------------------------------------- + // [End] + // ---------------------------------------------------------------------- + + case kNodeTypeEnd: { + goto _NextGroup; + } + + // ---------------------------------------------------------------------- + // [Ret] + // ---------------------------------------------------------------------- + + case kNodeTypeRet: { + RetNode* node = static_cast(node_); + X86FuncDecl* decl = func->getDecl(); + + if (decl->hasRet()) { + const FuncInOut& ret = decl->getRet(0); + uint32_t retClass = x86VarTypeToClass(ret.getVarType()); + + VI_BEGIN(); + for (uint32_t i = 0; i < 2; i++) { + Operand* op = &node->_ret[i]; + + if (op->isVar()) { + VarData* vd = compiler->getVdById(op->getId()); + VarAttr* va; + + if (vd->getClass() == retClass) { + // TODO: [COMPILER] Fix RetNode fetch. + VI_MERGE_VAR(vd, va, 0, 0); + va->setInRegs(i == 0 ? IntUtil::mask(kX86RegIndexAx) : IntUtil::mask(kX86RegIndexDx)); + va->orFlags(kVarAttrInReg); + inRegs.or_(retClass, va->getInRegs()); + } + } + } + VI_END(node_); + } + break; + } + + // ---------------------------------------------------------------------- + // [Call] + // ---------------------------------------------------------------------- + + case kNodeTypeCall: { + X86CallNode* node = static_cast(node_); + X86FuncDecl* decl = node->getDecl(); + + Operand* target = &node->_target; + Operand* argList = node->_args; + Operand* retList = node->_ret; + + func->addFuncFlags(kFuncFlagIsCaller); + func->mergeCallStackSize(node->_x86Decl.getArgStackSize()); + node->_usedArgs = X86Context_getUsedArgs(this, node, decl); + + uint32_t i; + uint32_t argCount = decl->getArgCount(); + uint32_t sArgCount = 0; + uint32_t gpAllocableMask = gaRegs[kX86RegClassGp] & ~node->_usedArgs.get(kX86RegClassGp); + + VarData* vd; + VarAttr* va; + + VI_BEGIN(); + + // Function-call operand. + if (target->isVar()) { + vd = compiler->getVdById(target->getId()); + VI_MERGE_VAR(vd, va, 0, 0); + + va->orFlags(kVarAttrInReg | kVarAttrInCall); + if (va->getInRegs() == 0) + va->addAllocableRegs(gpAllocableMask); + } + else if (target->isMem()) { + X86Mem* m = static_cast(target); + + if (OperandUtil::isVarId(m->getBase()) && m->isBaseIndexType()) { + vd = compiler->getVdById(m->getBase()); + if (!vd->isStack()) { + VI_MERGE_VAR(vd, va, 0, 0); + if (m->getMemType() == kMemTypeBaseIndex) { + va->orFlags(kVarAttrInReg | kVarAttrInCall); + if (va->getInRegs() == 0) + va->addAllocableRegs(gpAllocableMask); + } + else { + va->orFlags(kVarAttrInMem | kVarAttrInCall); + } + } + } + + if (OperandUtil::isVarId(m->getIndex())) { + // Restrict allocation to all registers except ESP/RSP/R12. + vd = compiler->getVdById(m->getIndex()); + VI_MERGE_VAR(vd, va, 0, 0); + + va->orFlags(kVarAttrInReg | kVarAttrInCall); + if ((va->getInRegs() & ~indexMask) == 0) + va->andAllocableRegs(gpAllocableMask & indexMask); + } + } + + // Function-call arguments. + for (i = 0; i < argCount; i++) { + Operand* op = &argList[i]; + if (!op->isVar()) + continue; + + vd = compiler->getVdById(op->getId()); + const FuncInOut& arg = decl->getArg(i); + + if (arg.hasRegIndex()) { + VI_MERGE_VAR(vd, va, 0, 0); + + uint32_t argType = arg.getVarType(); + uint32_t argClass = x86VarTypeToClass(argType); + + if (vd->getClass() == argClass) { + va->addInRegs(IntUtil::mask(arg.getRegIndex())); + va->orFlags(kVarAttrInReg | kVarAttrInArg); + } + else { + va->orFlags(kVarAttrInConv | kVarAttrInArg); + } + } + // If this is a stack-based argument we insert SArgNode instead of + // using VarAttr. It improves the code, because the argument can be + // moved onto stack as soon as it is ready and the register used by + // the variable can be reused for something else. It is also much + // easier to handle argument conversions, because there will be at + // most only one node per conversion. + else { + if (X86Context_insertSArgNode(this, node, vd, gaRegs, arg, i, sArgList, sArgCount) != kErrorOk) + goto _NoMemory; + } + } + + // Function-call return(s). + for (i = 0; i < 2; i++) { + Operand* op = &retList[i]; + if (!op->isVar()) + continue; + + const FuncInOut& ret = decl->getRet(i); + if (ret.hasRegIndex()) { + uint32_t retType = ret.getVarType(); + uint32_t retClass = x86VarTypeToClass(retType); + + vd = compiler->getVdById(op->getId()); + VI_MERGE_VAR(vd, va, 0, 0); + + if (vd->getClass() == retClass) { + va->setOutRegIndex(ret.getRegIndex()); + va->orFlags(kVarAttrOutReg | kVarAttrOutRet); + } + else { + va->orFlags(kVarAttrOutConv | kVarAttrOutRet); + } + } + } + + // Init clobbered. + clobberedRegs.set(kX86RegClassGp , IntUtil::bits(_regCount.getGp()) & (~decl->getPreserved(kX86RegClassGp ))); + clobberedRegs.set(kX86RegClassMm , IntUtil::bits(_regCount.getMm()) & (~decl->getPreserved(kX86RegClassMm ))); + clobberedRegs.set(kX86RegClassK , IntUtil::bits(_regCount.getK()) & (~decl->getPreserved(kX86RegClassK ))); + clobberedRegs.set(kX86RegClassXyz, IntUtil::bits(_regCount.getXyz()) & (~decl->getPreserved(kX86RegClassXyz))); + + VI_END(node_); + break; + } + + default: + break; + } + + node_ = next; + } while (node_ != stop); + +_Done: + ASMJIT_TLOG("[Fetch] === Done ===\n\n"); + return kErrorOk; + + // -------------------------------------------------------------------------- + // [Failure] + // -------------------------------------------------------------------------- + +_NoMemory: + ASMJIT_TLOG("[Fetch] === Out of Memory ===\n"); + return compiler->setError(kErrorNoHeapMemory); +} + +// ============================================================================ +// [asmjit::X86Context - Annotate] +// ============================================================================ + +Error X86Context::annotate() { +#if !defined(ASMJIT_DISABLE_LOGGER) + FuncNode* func = getFunc(); + + Node* node_ = func; + Node* end = func->getEnd(); + + Zone& sa = _compiler->_stringZone; + StringBuilderT<128> sb; + + uint32_t maxLen = 0; + while (node_ != end) { + if (node_->getComment() == NULL) { + if (node_->getType() == kNodeTypeInst) { + InstNode* node = static_cast(node_); + X86Context_annotateInstruction(this, sb, node->getInstId(), node->getOpList(), node->getOpCount()); + + node_->setComment(static_cast(sa.dup(sb.getData(), sb.getLength() + 1))); + maxLen = IntUtil::iMax(maxLen, static_cast(sb.getLength())); + + sb.clear(); + } + } + + node_ = node_->getNext(); + } + _annotationLength = maxLen + 1; +#endif // !ASMJIT_DISABLE_LOGGER + + return kErrorOk; +} + +// ============================================================================ +// [asmjit::X86BaseAlloc] +// ============================================================================ + +struct X86BaseAlloc { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE X86BaseAlloc(X86Context* context) { + _context = context; + _compiler = context->getCompiler(); + } + ASMJIT_INLINE ~X86BaseAlloc() {} + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get the context. + ASMJIT_INLINE X86Context* getContext() const { return _context; } + //! Get the current state (always the same instance as X86Context::_x86State). + ASMJIT_INLINE X86VarState* getState() const { return _context->getState(); } + + //! Get the node. + ASMJIT_INLINE Node* getNode() const { return _node; } + + //! Get VarAttr list (all). + ASMJIT_INLINE VarAttr* getVaList() const { return _vaList[0]; } + //! Get VarAttr list (per class). + ASMJIT_INLINE VarAttr* getVaListByClass(uint32_t c) const { return _vaList[c]; } + + //! Get VarAttr count (all). + ASMJIT_INLINE uint32_t getVaCount() const { return _vaCount; } + //! Get VarAttr count (per class). + ASMJIT_INLINE uint32_t getVaCountByClass(uint32_t c) const { return _count.get(c); } + + //! Get whether all variables of class `c` are done. + ASMJIT_INLINE bool isVaDone(uint32_t c) const { return _done.get(c) == _count.get(c); } + + //! Get how many variables have been allocated. + ASMJIT_INLINE uint32_t getVaDone(uint32_t c) const { return _done.get(c); } + + ASMJIT_INLINE void addVaDone(uint32_t c, uint32_t n = 1) { _done.add(c, n); } + + //! Get number of allocable registers per class. + ASMJIT_INLINE uint32_t getGaRegs(uint32_t c) const { + return _context->_gaRegs[c]; + } + + // -------------------------------------------------------------------------- + // [Init / Cleanup] + // -------------------------------------------------------------------------- + +protected: + // Just to prevent calling these methods by X86Context::translate(). + + ASMJIT_INLINE void init(Node* node, X86VarMap* map); + ASMJIT_INLINE void cleanup(); + + // -------------------------------------------------------------------------- + // [Unuse] + // -------------------------------------------------------------------------- + + template + ASMJIT_INLINE void unuseBefore(); + + template + ASMJIT_INLINE void unuseAfter(); + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Context. + X86Context* _context; + //! Compiler. + X86Compiler* _compiler; + + //! Node. + Node* _node; + + //! Variable map. + X86VarMap* _map; + //! VarAttr list (per register class). + VarAttr* _vaList[_kX86RegClassManagedCount]; + + //! Count of all VarAttr's. + uint32_t _vaCount; + + //! VarAttr's total counter. + X86RegCount _count; + //! VarAttr's done counter. + X86RegCount _done; +}; + +// ============================================================================ +// [asmjit::X86BaseAlloc - Init / Cleanup] +// ============================================================================ + +ASMJIT_INLINE void X86BaseAlloc::init(Node* node, X86VarMap* map) { + _node = node; + _map = map; + + // We have to set the correct cursor in case any instruction is emitted + // during the allocation phase; it has to be emitted before the current + // instruction. + _compiler->_setCursor(node->getPrev()); + + // Setup the lists of variables. + { + VarAttr* va = map->getVaList(); + _vaList[kX86RegClassGp ] = va; + _vaList[kX86RegClassMm ] = va + map->getVaStart(kX86RegClassMm ); + _vaList[kX86RegClassK ] = va + map->getVaStart(kX86RegClassK ); + _vaList[kX86RegClassXyz] = va + map->getVaStart(kX86RegClassXyz); + } + + // Setup counters. + _vaCount = map->getVaCount(); + + _count = map->_count; + _done.reset(); + + // Connect Vd->Va. + for (uint32_t i = 0; i < _vaCount; i++) { + VarAttr* va = &_vaList[0][i]; + VarData* vd = va->getVd(); + + vd->setVa(va); + } +} + +ASMJIT_INLINE void X86BaseAlloc::cleanup() { + // Disconnect Vd->Va. + for (uint32_t i = 0; i < _vaCount; i++) { + VarAttr* va = &_vaList[0][i]; + VarData* vd = va->getVd(); + + vd->setVa(NULL); + } +} + +// ============================================================================ +// [asmjit::X86BaseAlloc - Unuse] +// ============================================================================ + +template +ASMJIT_INLINE void X86BaseAlloc::unuseBefore() { + VarAttr* list = getVaListByClass(C); + uint32_t count = getVaCountByClass(C); + + const uint32_t checkFlags = + kVarAttrInOutReg | + kVarAttrInMem | + kVarAttrInArg | + kVarAttrInCall | + kVarAttrInConv ; + + for (uint32_t i = 0; i < count; i++) { + VarAttr* va = &list[i]; + + if ((va->getFlags() & checkFlags) == kVarAttrOutReg) { + _context->unuse(va->getVd()); + } + } +} + +template +ASMJIT_INLINE void X86BaseAlloc::unuseAfter() { + VarAttr* list = getVaListByClass(C); + uint32_t count = getVaCountByClass(C); + + for (uint32_t i = 0; i < count; i++) { + VarAttr* va = &list[i]; + + if (va->getFlags() & kVarAttrUnuse) + _context->unuse(va->getVd()); + } +} + +// ============================================================================ +// [asmjit::X86VarAlloc] +// ============================================================================ + +//! \internal +//! +//! Register allocator context (asm instructions). +struct X86VarAlloc : public X86BaseAlloc { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE X86VarAlloc(X86Context* context) : X86BaseAlloc(context) {} + ASMJIT_INLINE ~X86VarAlloc() {} + + // -------------------------------------------------------------------------- + // [Run] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE Error run(Node* node); + + // -------------------------------------------------------------------------- + // [Init / Cleanup] + // -------------------------------------------------------------------------- + +protected: + // Just to prevent calling these methods by X86Context::translate(). + + ASMJIT_INLINE void init(Node* node, X86VarMap* map); + ASMJIT_INLINE void cleanup(); + + // -------------------------------------------------------------------------- + // [Plan / Spill / Alloc] + // -------------------------------------------------------------------------- + + template + ASMJIT_INLINE void plan(); + + template + ASMJIT_INLINE void spill(); + + template + ASMJIT_INLINE void alloc(); + + // -------------------------------------------------------------------------- + // [GuessAlloc / GuessSpill] + // -------------------------------------------------------------------------- + + //! Guess which register is the best candidate for 'vd' from + //! 'allocableRegs'. + //! + //! The guess is based on looking ahead and inspecting register allocator + //! instructions. The main reason is to prevent allocation to a register + //! which is needed by next instruction(s). The guess look tries to go as far + //! as possible, after the remaining registers are zero, the mask of previous + //! registers (called 'safeRegs') is returned. + template + ASMJIT_INLINE uint32_t guessAlloc(VarData* vd, uint32_t allocableRegs); + + //! Guess whether to move the given 'vd' instead of spill. + template + ASMJIT_INLINE uint32_t guessSpill(VarData* vd, uint32_t allocableRegs); + + // -------------------------------------------------------------------------- + // [Modified] + // -------------------------------------------------------------------------- + + template + ASMJIT_INLINE void modified(); + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Will alloc to these registers. + X86RegMask _willAlloc; + //! Will spill these registers. + X86RegMask _willSpill; +}; + +// ============================================================================ +// [asmjit::X86VarAlloc - Run] +// ============================================================================ + +ASMJIT_INLINE Error X86VarAlloc::run(Node* node_) { + // Initialize. + X86VarMap* map = node_->getMap(); + if (map == NULL) + return kErrorOk; + + // Initialize the allocator; connect Vd->Va. + init(node_, map); + + // Unuse overwritten variables. + unuseBefore(); + unuseBefore(); + unuseBefore(); + + // Plan the allocation. Planner assigns input/output registers for each + // variable and decides whether to allocate it in register or stack. + plan(); + plan(); + plan(); + + // Spill all variables marked by plan(). + spill(); + spill(); + spill(); + + // Alloc all variables marked by plan(). + alloc(); + alloc(); + alloc(); + + // Translate node operands. + if (node_->getType() == kNodeTypeInst) { + InstNode* node = static_cast(node_); + ASMJIT_PROPAGATE_ERROR(X86Context_translateOperands(_context, node->getOpList(), node->getOpCount())); + } + else if (node_->getType() == kNodeTypeSArg) { + SArgNode* node = static_cast(node_); + + X86CallNode* call = static_cast(node->getCall()); + X86FuncDecl* decl = call->getDecl(); + + uint32_t argIndex = 0; + uint32_t argMask = node->_args; + + VarData* sVd = node->getSVd(); + VarData* cVd = node->getCVd(); + + // Convert first. + ASMJIT_ASSERT(sVd->getRegIndex() != kInvalidReg); + + if (cVd != NULL) { + ASMJIT_ASSERT(cVd->getRegIndex() != kInvalidReg); + _context->emitConvertVarToVar( + cVd->getType(), cVd->getRegIndex(), + sVd->getType(), sVd->getRegIndex()); + sVd = cVd; + } + + while (argMask != 0) { + if (argMask & 0x1) { + FuncInOut& arg = decl->getArg(argIndex); + ASMJIT_ASSERT(arg.hasStackOffset()); + + X86Mem dst = x86::ptr(_context->_zsp, -static_cast(_context->getRegSize()) + arg.getStackOffset()); + _context->emitMoveVarOnStack(arg.getVarType(), &dst, sVd->getType(), sVd->getRegIndex()); + } + + argIndex++; + argMask >>= 1; + } + } + + // Mark variables as modified. + modified(); + modified(); + modified(); + + // Cleanup; disconnect Vd->Va. + cleanup(); + + // Update clobbered mask. + _context->_clobberedRegs.or_(_willAlloc); + _context->_clobberedRegs.or_(map->_clobberedRegs); + + // Unuse. + unuseAfter(); + unuseAfter(); + unuseAfter(); + + return kErrorOk; +} + +// ============================================================================ +// [asmjit::X86VarAlloc - Init / Cleanup] +// ============================================================================ + +ASMJIT_INLINE void X86VarAlloc::init(Node* node, X86VarMap* map) { + X86BaseAlloc::init(node, map); + + // These will block planner from assigning them during planning. Planner will + // add more registers when assigning registers to variables that don't need + // any specific register. + _willAlloc = map->_inRegs; + _willAlloc.or_(map->_outRegs); + _willSpill.reset(); +} + +ASMJIT_INLINE void X86VarAlloc::cleanup() { + X86BaseAlloc::cleanup(); +} + +// ============================================================================ +// [asmjit::X86VarAlloc - Plan / Spill / Alloc] +// ============================================================================ + +template +ASMJIT_INLINE void X86VarAlloc::plan() { + if (isVaDone(C)) + return; + + uint32_t i; + + uint32_t willAlloc = _willAlloc.get(C); + uint32_t willFree = 0; + + VarAttr* list = getVaListByClass(C); + uint32_t count = getVaCountByClass(C); + + X86VarState* state = getState(); + VarData** sVars = state->getListByClass(C); + + // Calculate 'willAlloc' and 'willFree' masks based on mandatory masks. + for (i = 0; i < count; i++) { + VarAttr* va = &list[i]; + VarData* vd = va->getVd(); + + uint32_t vaFlags = va->getFlags(); + uint32_t regIndex = vd->getRegIndex(); + uint32_t regMask = (regIndex != kInvalidReg) ? IntUtil::mask(regIndex) : 0; + + if ((vaFlags & kVarAttrInOutReg) != 0) { + // Planning register allocation. First check whether the variable is + // already allocated in register and if it can stay allocated there. + // + // The following conditions may happen: + // + // a) Allocated register is one of the mandatoryRegs. + // b) Allocated register is one of the allocableRegs. + uint32_t mandatoryRegs = va->getInRegs(); + uint32_t allocableRegs = va->getAllocableRegs(); + + ASMJIT_TLOG("[RA-PLAN ] %s (%s)\n", + vd->getName(), + (vaFlags & kVarAttrInOutReg) == kVarAttrOutReg ? "Out Reg" : "In/Out Reg"); + + ASMJIT_TLOG("[RA-PLAN ] RegMask=%08X Mandatory=%08X Allocable=%08X\n", + regMask, mandatoryRegs, allocableRegs); + + if (regMask != 0) { + // Special path for planning output-only registers. + if ((vaFlags & kVarAttrInOutReg) == kVarAttrOutReg) { + uint32_t outRegIndex = va->getOutRegIndex(); + mandatoryRegs = (outRegIndex != kInvalidReg) ? IntUtil::mask(outRegIndex) : 0; + + if ((mandatoryRegs | allocableRegs) & regMask) { + va->setOutRegIndex(regIndex); + va->orFlags(kVarAttrAllocOutDone); + + if (mandatoryRegs & regMask) { + // Case 'a' - 'willAlloc' contains initially all inRegs from all VarAttr's. + ASMJIT_ASSERT((willAlloc & regMask) != 0); + } + else { + // Case 'b'. + va->setOutRegIndex(regIndex); + willAlloc |= regMask; + } + + ASMJIT_TLOG("[RA-PLAN ] WillAlloc\n"); + addVaDone(C); + + continue; + } + } + else { + if ((mandatoryRegs | allocableRegs) & regMask) { + va->setInRegIndex(regIndex); + va->orFlags(kVarAttrAllocInDone); + + if (mandatoryRegs & regMask) { + // Case 'a' - 'willAlloc' contains initially all inRegs from all VarAttr's. + ASMJIT_ASSERT((willAlloc & regMask) != 0); + } + else { + // Case 'b'. + va->addInRegs(regMask); + willAlloc |= regMask; + } + + ASMJIT_TLOG("[RA-PLAN ] WillAlloc\n"); + addVaDone(C); + + continue; + } + } + + // Trace it here so we don't pollute log by `WillFree` of zero regMask. + ASMJIT_TLOG("[RA-PLAN ] WillFree\n"); + } + + // Variable is not allocated or allocated in register that doesn't + // match inRegs or allocableRegs. The next step is to pick the best + // register for this variable. If `inRegs` contains any register the + // decision is simple - we have to follow, in other case will use + // the advantage of `guessAlloc()` to find a register (or registers) + // by looking ahead. But the best way to find a good register is not + // here since now we have no information about the registers that + // will be freed. So instead of finding register here, we just mark + // the current register (if variable is allocated) as `willFree` so + // the planner can use this information in second step to plan other + // allocation of other variables. + willFree |= regMask; + continue; + } + else { + // Memory access - if variable is allocated it has to be freed. + ASMJIT_TLOG("[RA-PLAN ] %s (Memory)\n", vd->getName()); + + if (regMask != 0) { + ASMJIT_TLOG("[RA-PLAN ] WillFree\n"); + willFree |= regMask; + continue; + } + else { + ASMJIT_TLOG("[RA-PLAN ] Done\n"); + va->orFlags(kVarAttrAllocInDone); + addVaDone(C); + continue; + } + } + } + + // Occupied registers without 'willFree' registers; contains basically + // all the registers we can use to allocate variables without inRegs + // speficied. + uint32_t occupied = state->_occupied.get(C) & ~willFree; + uint32_t willSpill = 0; + + // Find the best registers for variables that are not allocated yet. + for (i = 0; i < count; i++) { + VarAttr* va = &list[i]; + VarData* vd = va->getVd(); + + uint32_t vaFlags = va->getFlags(); + + if ((vaFlags & kVarAttrInOutReg) != 0) { + if ((vaFlags & kVarAttrInOutReg) == kVarAttrOutReg) { + if (vaFlags & kVarAttrAllocOutDone) + continue; + + // Skip all registers that have assigned outRegIndex. Spill if occupied. + if (va->hasOutRegIndex()) { + uint32_t outRegs = IntUtil::mask(va->getOutRegIndex()); + willSpill |= occupied & outRegs; + continue; + } + } + else { + if (vaFlags & kVarAttrAllocInDone) + continue; + + // We skip all registers that have assigned inRegIndex, indicates that + // the register to allocate in is known. + if (va->hasInRegIndex()) { + uint32_t inRegs = va->getInRegs(); + willSpill |= occupied & inRegs; + continue; + } + } + + uint32_t m = va->getInRegs(); + if (va->hasOutRegIndex()) + m |= IntUtil::mask(va->getOutRegIndex()); + + m = va->getAllocableRegs() & ~(willAlloc ^ m); + m = guessAlloc(vd, m); + ASMJIT_ASSERT(m != 0); + + uint32_t candidateRegs = m & ~occupied; + uint32_t homeMask = vd->getHomeMask(); + + uint32_t regIndex; + uint32_t regMask; + + if (candidateRegs == 0) { + candidateRegs = m & occupied & ~state->_modified.get(C); + if (candidateRegs == 0) + candidateRegs = m; + } + + if (candidateRegs & homeMask) + candidateRegs &= homeMask; + + regIndex = IntUtil::findFirstBit(candidateRegs); + regMask = IntUtil::mask(regIndex); + + if ((vaFlags & kVarAttrInOutReg) == kVarAttrOutReg) { + va->setOutRegIndex(regIndex); + } + else { + va->setInRegIndex(regIndex); + va->setInRegs(regMask); + } + + willAlloc |= regMask; + willSpill |= regMask & occupied; + willFree &=~regMask; + occupied |= regMask; + + continue; + } + else if ((vaFlags & kVarAttrInOutMem) != 0) { + uint32_t regIndex = vd->getRegIndex(); + if (regIndex != kInvalidReg && (vaFlags & kVarAttrInOutMem) != kVarAttrOutMem) { + willSpill |= IntUtil::mask(regIndex); + } + } + } + + // Set calculated masks back to the allocator; needed by spill() and alloc(). + _willSpill.set(C, willSpill); + _willAlloc.set(C, willAlloc); +} + +template +ASMJIT_INLINE void X86VarAlloc::spill() { + uint32_t m = _willSpill.get(C); + uint32_t i = static_cast(0) - 1; + + if (m == 0) + return; + + X86VarState* state = getState(); + VarData** sVars = state->getListByClass(C); + + // Available registers for decision if move has any benefit over spill. + uint32_t availableRegs = getGaRegs(C) & ~(state->_occupied.get(C) | m | _willAlloc.get(C)); + + do { + // We always advance one more to destroy the bit that we have found. + uint32_t bitIndex = IntUtil::findFirstBit(m) + 1; + + i += bitIndex; + m >>= bitIndex; + + VarData* vd = sVars[i]; + ASMJIT_ASSERT(vd != NULL); + + VarAttr* va = vd->getVa(); + ASMJIT_ASSERT(va == NULL || !va->hasFlag(kVarAttrInOutReg)); + + if (vd->isModified() && availableRegs) { + // Don't check for alternatives if the variable has to be spilled. + if (va == NULL || !va->hasFlag(kVarAttrSpill)) { + uint32_t altRegs = guessSpill(vd, availableRegs); + + if (altRegs != 0) { + uint32_t regIndex = IntUtil::findFirstBit(altRegs); + uint32_t regMask = IntUtil::mask(regIndex); + + _context->move(vd, regIndex); + availableRegs ^= regMask; + continue; + } + } + } + + _context->spill(vd); + } while (m != 0); +} + +template +ASMJIT_INLINE void X86VarAlloc::alloc() { + if (isVaDone(C)) + return; + + VarAttr* list = getVaListByClass(C); + uint32_t count = getVaCountByClass(C); + + X86VarState* state = getState(); + VarData** sVars = state->getListByClass(C); + + uint32_t i; + bool didWork; + + // Alloc 'in' regs. + do { + didWork = false; + for (i = 0; i < count; i++) { + VarAttr* aVa = &list[i]; + VarData* aVd = aVa->getVd(); + + if ((aVa->getFlags() & (kVarAttrInReg | kVarAttrAllocInDone)) != kVarAttrInReg) + continue; + + uint32_t aIndex = aVd->getRegIndex(); + uint32_t bIndex = aVa->getInRegIndex(); + + // Shouldn't be the same. + ASMJIT_ASSERT(aIndex != bIndex); + + VarData* bVd = getState()->getListByClass(C)[bIndex]; + if (bVd != NULL) { + // Gp registers only - Swap two registers if we can solve two + // allocation tasks by a single 'xchg' instruction, swapping + // two registers required by the instruction/node or one register + // required with another non-required. + if (C == kX86RegClassGp && aIndex != kInvalidReg) { + VarAttr* bVa = bVd->getVa(); + _context->swapGp(aVd, bVd); + + aVa->orFlags(kVarAttrAllocInDone); + addVaDone(C); + + // Doublehit, two registers allocated by a single swap. + if (bVa != NULL && bVa->getInRegIndex() == aIndex) { + bVa->orFlags(kVarAttrAllocInDone); + addVaDone(C); + } + + didWork = true; + continue; + } + } + else if (aIndex != kInvalidReg) { + _context->move(aVd, bIndex); + + aVa->orFlags(kVarAttrAllocInDone); + addVaDone(C); + + didWork = true; + continue; + } + else { + _context->alloc(aVd, bIndex); + + aVa->orFlags(kVarAttrAllocInDone); + addVaDone(C); + + didWork = true; + continue; + } + } + } while (didWork); + + // Alloc 'out' regs. + for (i = 0; i < count; i++) { + VarAttr* va = &list[i]; + VarData* vd = va->getVd(); + + if ((va->getFlags() & (kVarAttrInOutReg | kVarAttrAllocOutDone)) != kVarAttrOutReg) + continue; + + uint32_t regIndex = va->getOutRegIndex(); + ASMJIT_ASSERT(regIndex != kInvalidReg); + + if (vd->getRegIndex() != regIndex) { + ASMJIT_ASSERT(sVars[regIndex] == NULL); + _context->attach(vd, regIndex, false); + } + + va->orFlags(kVarAttrAllocOutDone); + addVaDone(C); + } +} + +// ============================================================================ +// [asmjit::X86VarAlloc - GuessAlloc / GuessSpill] +// ============================================================================ + +template +ASMJIT_INLINE uint32_t X86VarAlloc::guessAlloc(VarData* vd, uint32_t allocableRegs) { + ASMJIT_ASSERT(allocableRegs != 0); + + // Stop now if there is only one bit (register) set in `allocableRegs` mask. + if (IntUtil::isPowerOf2(allocableRegs)) + return allocableRegs; + + uint32_t cId = vd->getContextId(); + uint32_t safeRegs = allocableRegs; + + uint32_t i; + uint32_t maxLookAhead = _compiler->getMaxLookAhead(); + + // Look ahead and calculate mask of special registers on both - input/output. + Node* node = _node; + for (i = 0; i < maxLookAhead; i++) { + VarBits* liveness = node->getLiveness(); + + // If the variable becomes dead it doesn't make sense to continue. + if (liveness != NULL && !liveness->getBit(cId)) + break; + + // Stop on 'RetNode' and 'EndNode. + if (node->hasFlag(kNodeFlagIsRet)) + break; + + // Stop on conditional jump, we don't follow them. + if (node->hasFlag(kNodeFlagIsJcc)) + break; + + // Advance on non-conditional jump. + if (node->hasFlag(kNodeFlagIsJmp)) + node = static_cast(node)->getTarget(); + + node = node->getNext(); + ASMJIT_ASSERT(node != NULL); + + X86VarMap* map = node->getMap(); + if (map != NULL) { + VarAttr* va = map->findVaByClass(C, vd); + uint32_t mask; + + if (va != NULL) { + // If the variable is overwritten it doesn't mase sense to continue. + if (!(va->getFlags() & kVarAttrInAll)) + break; + + mask = va->getAllocableRegs(); + if (mask != 0) { + allocableRegs &= mask; + if (allocableRegs == 0) + break; + safeRegs = allocableRegs; + } + + mask = va->getInRegs(); + if (mask != 0) { + allocableRegs &= mask; + if (allocableRegs == 0) + break; + safeRegs = allocableRegs; + break; + } + + allocableRegs &= ~(map->_outRegs.get(C) | map->_clobberedRegs.get(C)); + if (allocableRegs == 0) + break; + } + else { + allocableRegs &= ~(map->_inRegs.get(C) | map->_outRegs.get(C) | map->_clobberedRegs.get(C)); + if (allocableRegs == 0) + break; + } + + safeRegs = allocableRegs; + } + } + + return safeRegs; +} + +template +ASMJIT_INLINE uint32_t X86VarAlloc::guessSpill(VarData* vd, uint32_t allocableRegs) { + ASMJIT_ASSERT(allocableRegs != 0); + + return 0; +} + +// ============================================================================ +// [asmjit::X86VarAlloc - Modified] +// ============================================================================ + +template +ASMJIT_INLINE void X86VarAlloc::modified() { + VarAttr* list = getVaListByClass(C); + uint32_t count = getVaCountByClass(C); + + for (uint32_t i = 0; i < count; i++) { + VarAttr* va = &list[i]; + + if (va->hasFlag(kVarAttrOutReg)) { + VarData* vd = va->getVd(); + + uint32_t regIndex = vd->getRegIndex(); + uint32_t regMask = IntUtil::mask(regIndex); + + vd->setModified(true); + _context->_x86State._modified.or_(C, regMask); + } + } +} + +// ============================================================================ +// [asmjit::X86CallAlloc] +// ============================================================================ + +//! \internal +//! +//! Register allocator context (function call). +struct X86CallAlloc : public X86BaseAlloc { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE X86CallAlloc(X86Context* context) : X86BaseAlloc(context) {} + ASMJIT_INLINE ~X86CallAlloc() {} + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get the node. + ASMJIT_INLINE X86CallNode* getNode() const { return static_cast(_node); } + + // -------------------------------------------------------------------------- + // [Run] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE Error run(X86CallNode* node); + + // -------------------------------------------------------------------------- + // [Init / Cleanup] + // -------------------------------------------------------------------------- + +protected: + // Just to prevent calling these methods from X86Context::translate(). + + ASMJIT_INLINE void init(X86CallNode* node, X86VarMap* map); + ASMJIT_INLINE void cleanup(); + + // -------------------------------------------------------------------------- + // [Plan / Alloc / Spill / Move] + // -------------------------------------------------------------------------- + + template + ASMJIT_INLINE void plan(); + + template + ASMJIT_INLINE void spill(); + + template + ASMJIT_INLINE void alloc(); + + // -------------------------------------------------------------------------- + // [AllocImmsOnStack] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE void allocImmsOnStack(); + + // -------------------------------------------------------------------------- + // [Duplicate] + // -------------------------------------------------------------------------- + + template + ASMJIT_INLINE void duplicate(); + + // -------------------------------------------------------------------------- + // [GuessAlloc / GuessSpill] + // -------------------------------------------------------------------------- + + template + ASMJIT_INLINE uint32_t guessAlloc(VarData* vd, uint32_t allocableRegs); + + template + ASMJIT_INLINE uint32_t guessSpill(VarData* vd, uint32_t allocableRegs); + + // -------------------------------------------------------------------------- + // [Save] + // -------------------------------------------------------------------------- + + template + ASMJIT_INLINE void save(); + + // -------------------------------------------------------------------------- + // [Clobber] + // -------------------------------------------------------------------------- + + template + ASMJIT_INLINE void clobber(); + + // -------------------------------------------------------------------------- + // [Ret] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE void ret(); + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Will alloc to these registers. + X86RegMask _willAlloc; + //! Will spill these registers. + X86RegMask _willSpill; +}; + +// ============================================================================ +// [asmjit::X86CallAlloc - Run] +// ============================================================================ + +ASMJIT_INLINE Error X86CallAlloc::run(X86CallNode* node) { + // Initialize. + X86VarMap* map = node->getMap(); + if (map == NULL) + return kErrorOk; + + // Initialize the allocator; prepare basics and connect Vd->Va. + init(node, map); + + // Plan register allocation. Planner is only able to assign one register per + // variable. If any variable is used multiple times it will be handled later. + plan(); + plan(); + plan(); + + // Spill. + spill(); + spill(); + spill(); + + // Alloc. + alloc(); + alloc(); + alloc(); + + // Unuse clobbered registers that are not used to pass function arguments and + // save variables used to pass function arguments that will be reused later on. + save(); + save(); + save(); + + // Allocate immediates in registers and on the stack. + allocImmsOnStack(); + + // Duplicate. + duplicate(); + duplicate(); + duplicate(); + + // Translate call operand. + ASMJIT_PROPAGATE_ERROR(X86Context_translateOperands(_context, &node->_target, 1)); + + // To emit instructions after call. + _compiler->_setCursor(node); + + // If the callee pops stack it has to be manually adjusted back. + X86FuncDecl* decl = node->getDecl(); + if (decl->getCalleePopsStack() && decl->getArgStackSize() != 0) { + _compiler->emit(kX86InstIdSub, _context->_zsp, static_cast(decl->getArgStackSize())); + } + + // Clobber. + clobber(); + clobber(); + clobber(); + + // Return. + ret(); + + // Unuse. + unuseAfter(); + unuseAfter(); + unuseAfter(); + + // Cleanup; disconnect Vd->Va. + cleanup(); + + return kErrorOk; +} + +// ============================================================================ +// [asmjit::X86CallAlloc - Init / Cleanup] +// ============================================================================ + +ASMJIT_INLINE void X86CallAlloc::init(X86CallNode* node, X86VarMap* map) { + X86BaseAlloc::init(node, map); + + // Create mask of all registers that will be used to pass function arguments. + _willAlloc = node->_usedArgs; + _willSpill.reset(); +} + +ASMJIT_INLINE void X86CallAlloc::cleanup() { + X86BaseAlloc::cleanup(); +} + +// ============================================================================ +// [asmjit::X86CallAlloc - Plan / Spill / Alloc] +// ============================================================================ + +template +ASMJIT_INLINE void X86CallAlloc::plan() { + uint32_t i; + uint32_t clobbered = _map->_clobberedRegs.get(C); + + uint32_t willAlloc = _willAlloc.get(C); + uint32_t willFree = clobbered & ~willAlloc; + + VarAttr* list = getVaListByClass(C); + uint32_t count = getVaCountByClass(C); + + X86VarState* state = getState(); + VarData** sVars = state->getListByClass(C); + + // Calculate 'willAlloc' and 'willFree' masks based on mandatory masks. + for (i = 0; i < count; i++) { + VarAttr* va = &list[i]; + VarData* vd = va->getVd(); + + uint32_t vaFlags = va->getFlags(); + uint32_t regIndex = vd->getRegIndex(); + uint32_t regMask = (regIndex != kInvalidReg) ? IntUtil::mask(regIndex) : 0; + + if ((vaFlags & kVarAttrInReg) != 0) { + // Planning register allocation. First check whether the variable is + // already allocated in register and if it can stay there. Function + // arguments are passed either in a specific register or in stack so + // we care mostly of mandatory registers. + uint32_t inRegs = va->getInRegs(); + + if (inRegs == 0) { + inRegs = va->getAllocableRegs(); + } + + // Optimize situation where the variable has to be allocated in a + // mandatory register, but it's already allocated in register that + // is not clobbered (i.e. it will survive function call). + if ((regMask & inRegs) != 0 || ((regMask & ~clobbered) != 0 && (vaFlags & kVarAttrUnuse) == 0)) { + va->setInRegIndex(regIndex); + va->orFlags(kVarAttrAllocInDone); + addVaDone(C); + } + else { + willFree |= regMask; + } + } + else { + // Memory access - if variable is allocated it has to be freed. + if (regMask != 0) { + willFree |= regMask; + } + else { + va->orFlags(kVarAttrAllocInDone); + addVaDone(C); + } + } + } + + // Occupied registers without 'willFree' registers; contains basically + // all the registers we can use to allocate variables without inRegs + // speficied. + uint32_t occupied = state->_occupied.get(C) & ~willFree; + uint32_t willSpill = 0; + + // Find the best registers for variables that are not allocated yet. Only + // useful for Gp registers used as call operand. + for (i = 0; i < count; i++) { + VarAttr* va = &list[i]; + VarData* vd = va->getVd(); + + uint32_t vaFlags = va->getFlags(); + if ((vaFlags & kVarAttrAllocInDone) != 0 || (vaFlags & kVarAttrInReg) == 0) + continue; + + // All registers except Gp used by call itself must have inRegIndex. + uint32_t m = va->getInRegs(); + if (C != kX86RegClassGp || m) { + ASMJIT_ASSERT(m != 0); + va->setInRegIndex(IntUtil::findFirstBit(m)); + willSpill |= occupied & m; + continue; + } + + m = va->getAllocableRegs() & ~(willAlloc ^ m); + m = guessAlloc(vd, m); + ASMJIT_ASSERT(m != 0); + + uint32_t candidateRegs = m & ~occupied; + if (candidateRegs == 0) { + candidateRegs = m & occupied & ~state->_modified.get(C); + if (candidateRegs == 0) + candidateRegs = m; + } + + if (!(vaFlags & (kVarAttrOutReg | kVarAttrUnuse)) && (candidateRegs & ~clobbered)) + candidateRegs &= ~clobbered; + + uint32_t regIndex = IntUtil::findFirstBit(candidateRegs); + uint32_t regMask = IntUtil::mask(regIndex); + + va->setInRegIndex(regIndex); + va->setInRegs(regMask); + + willAlloc |= regMask; + willSpill |= regMask & occupied; + willFree &= ~regMask; + + occupied |= regMask; + continue; + } + + // Set calculated masks back to the allocator; needed by spill() and alloc(). + _willSpill.set(C, willSpill); + _willAlloc.set(C, willAlloc); +} + +template +ASMJIT_INLINE void X86CallAlloc::spill() { + uint32_t m = _willSpill.get(C); + uint32_t i = static_cast(0) - 1; + + if (m == 0) + return; + + X86VarState* state = getState(); + VarData** sVars = state->getListByClass(C); + + // Available registers for decision if move has any benefit over spill. + uint32_t availableRegs = getGaRegs(C) & ~(state->_occupied.get(C) | m | _willAlloc.get(C)); + + do { + // We always advance one more to destroy the bit that we have found. + uint32_t bitIndex = IntUtil::findFirstBit(m) + 1; + + i += bitIndex; + m >>= bitIndex; + + VarData* vd = sVars[i]; + ASMJIT_ASSERT(vd != NULL); + ASMJIT_ASSERT(vd->getVa() == NULL); + + if (vd->isModified() && availableRegs) { + uint32_t m = guessSpill(vd, availableRegs); + + if (m != 0) { + uint32_t regIndex = IntUtil::findFirstBit(m); + uint32_t regMask = IntUtil::mask(regIndex); + + _context->move(vd, regIndex); + availableRegs ^= regMask; + continue; + } + } + + _context->spill(vd); + } while (m != 0); +} + +template +ASMJIT_INLINE void X86CallAlloc::alloc() { + if (isVaDone(C)) + return; + + VarAttr* list = getVaListByClass(C); + uint32_t count = getVaCountByClass(C); + + X86VarState* state = getState(); + VarData** sVars = state->getListByClass(C); + + uint32_t i; + bool didWork; + + do { + didWork = false; + for (i = 0; i < count; i++) { + VarAttr* aVa = &list[i]; + VarData* aVd = aVa->getVd(); + + if ((aVa->getFlags() & (kVarAttrInReg | kVarAttrAllocInDone)) != kVarAttrInReg) + continue; + + uint32_t aIndex = aVd->getRegIndex(); + uint32_t bIndex = aVa->getInRegIndex(); + + // Shouldn't be the same. + ASMJIT_ASSERT(aIndex != bIndex); + + VarData* bVd = getState()->getListByClass(C)[bIndex]; + if (bVd != NULL) { + VarAttr* bVa = bVd->getVa(); + + // Gp registers only - Swap two registers if we can solve two + // allocation tasks by a single 'xchg' instruction, swapping + // two registers required by the instruction/node or one register + // required with another non-required. + if (C == kX86RegClassGp) { + _context->swapGp(aVd, bVd); + + aVa->orFlags(kVarAttrAllocInDone); + addVaDone(C); + + // Doublehit, two registers allocated by a single swap. + if (bVa != NULL && bVa->getInRegIndex() == aIndex) { + bVa->orFlags(kVarAttrAllocInDone); + addVaDone(C); + } + + didWork = true; + continue; + } + } + else if (aIndex != kInvalidReg) { + _context->move(aVd, bIndex); + + aVa->orFlags(kVarAttrAllocInDone); + addVaDone(C); + + didWork = true; + continue; + } + else { + _context->alloc(aVd, bIndex); + + aVa->orFlags(kVarAttrAllocInDone); + addVaDone(C); + + didWork = true; + continue; + } + } + } while (didWork); +} + +// ============================================================================ +// [asmjit::X86CallAlloc - AllocImmsOnStack] +// ============================================================================ + +ASMJIT_INLINE void X86CallAlloc::allocImmsOnStack() { + X86CallNode* node = getNode(); + X86FuncDecl* decl = node->getDecl(); + + uint32_t argCount = decl->getArgCount(); + Operand* argList = node->_args; + + for (uint32_t i = 0; i < argCount; i++) { + Operand& op = argList[i]; + + if (!op.isImm()) + continue; + + const Imm& imm = static_cast(op); + const FuncInOut& arg = decl->getArg(i); + uint32_t varType = arg.getVarType(); + + if (arg.hasStackOffset()) { + X86Mem dst = x86::ptr(_context->_zsp, -static_cast(_context->getRegSize()) + arg.getStackOffset()); + _context->emitMoveImmOnStack(varType, &dst, &imm); + } + else { + _context->emitMoveImmToReg(varType, arg.getRegIndex(), &imm); + } + } +} + +// ============================================================================ +// [asmjit::X86CallAlloc - Duplicate] +// ============================================================================ + +template +ASMJIT_INLINE void X86CallAlloc::duplicate() { + VarAttr* list = getVaListByClass(C); + uint32_t count = getVaCountByClass(C); + + for (uint32_t i = 0; i < count; i++) { + VarAttr* va = &list[i]; + if (!va->hasFlag(kVarAttrInReg)) + continue; + + uint32_t inRegs = va->getInRegs(); + if (!inRegs) + continue; + + VarData* vd = va->getVd(); + uint32_t regIndex = vd->getRegIndex(); + + ASMJIT_ASSERT(regIndex != kInvalidReg); + + inRegs &= ~IntUtil::mask(regIndex); + if (!inRegs) + continue; + + for (uint32_t dupIndex = 0; inRegs != 0; dupIndex++, inRegs >>= 1) { + if (inRegs & 0x1) { + _context->emitMove(vd, dupIndex, regIndex, "Duplicate"); + _context->_clobberedRegs.or_(C, IntUtil::mask(dupIndex)); + } + } + } +} + +// ============================================================================ +// [asmjit::X86CallAlloc - GuessAlloc / GuessSpill] +// ============================================================================ + +template +ASMJIT_INLINE uint32_t X86CallAlloc::guessAlloc(VarData* vd, uint32_t allocableRegs) { + ASMJIT_ASSERT(allocableRegs != 0); + + // Stop now if there is only one bit (register) set in 'allocableRegs' mask. + if (IntUtil::isPowerOf2(allocableRegs)) + return allocableRegs; + + uint32_t i; + uint32_t safeRegs = allocableRegs; + uint32_t maxLookAhead = _compiler->getMaxLookAhead(); + + // Look ahead and calculate mask of special registers on both - input/output. + Node* node = _node; + for (i = 0; i < maxLookAhead; i++) { + // Stop on 'RetNode' and 'EndNode. + if (node->hasFlag(kNodeFlagIsRet)) + break; + + // Stop on conditional jump, we don't follow them. + if (node->hasFlag(kNodeFlagIsJcc)) + break; + + // Advance on non-conditional jump. + if (node->hasFlag(kNodeFlagIsJmp)) + node = static_cast(node)->getTarget(); + + node = node->getNext(); + ASMJIT_ASSERT(node != NULL); + + X86VarMap* map = node->getMap(); + if (map != NULL) { + VarAttr* va = map->findVaByClass(C, vd); + if (va != NULL) { + uint32_t inRegs = va->getInRegs(); + if (inRegs != 0) { + safeRegs = allocableRegs; + allocableRegs &= inRegs; + + if (allocableRegs == 0) + goto _UseSafeRegs; + else + return allocableRegs; + } + } + + safeRegs = allocableRegs; + allocableRegs &= ~(map->_inRegs.get(C) | map->_outRegs.get(C) | map->_clobberedRegs.get(C)); + + if (allocableRegs == 0) + break; + } + } + +_UseSafeRegs: + return safeRegs; +} + +template +ASMJIT_INLINE uint32_t X86CallAlloc::guessSpill(VarData* vd, uint32_t allocableRegs) { + ASMJIT_ASSERT(allocableRegs != 0); + + return 0; +} + +// ============================================================================ +// [asmjit::X86CallAlloc - Save] +// ============================================================================ + +template +ASMJIT_INLINE void X86CallAlloc::save() { + X86VarState* state = getState(); + VarData** sVars = state->getListByClass(C); + + uint32_t i; + uint32_t affected = _map->_clobberedRegs.get(C) & state->_occupied.get(C) & state->_modified.get(C); + + for (i = 0; affected != 0; i++, affected >>= 1) { + if (affected & 0x1) { + VarData* vd = sVars[i]; + ASMJIT_ASSERT(vd != NULL); + ASMJIT_ASSERT(vd->isModified()); + + VarAttr* va = vd->getVa(); + if (va == NULL || (va->getFlags() & (kVarAttrOutReg | kVarAttrUnuse)) == 0) { + _context->save(vd); + } + } + } +} + +// ============================================================================ +// [asmjit::X86CallAlloc - Clobber] +// ============================================================================ + +template +ASMJIT_INLINE void X86CallAlloc::clobber() { + X86VarState* state = getState(); + VarData** sVars = state->getListByClass(C); + + uint32_t i; + uint32_t affected = _map->_clobberedRegs.get(C) & state->_occupied.get(C); + + for (i = 0; affected != 0; i++, affected >>= 1) { + if (affected & 0x1) { + VarData* vd = sVars[i]; + ASMJIT_ASSERT(vd != NULL); + + VarAttr* va = vd->getVa(); + uint32_t vdState = kVarStateUnused; + + if (!vd->isModified() || (va != NULL && (va->getFlags() & (kVarAttrOutAll | kVarAttrUnuse)) != 0)) { + vdState = kVarStateMem; + } + + _context->unuse(vd, vdState); + } + } +} + +// ============================================================================ +// [asmjit::X86CallAlloc - Ret] +// ============================================================================ + +ASMJIT_INLINE void X86CallAlloc::ret() { + X86CallNode* node = getNode(); + X86FuncDecl* decl = node->getDecl(); + + uint32_t i; + Operand* retList = node->_ret; + + for (i = 0; i < 2; i++) { + const FuncInOut& ret = decl->getRet(i); + Operand* op = &retList[i]; + + if (!ret.hasRegIndex() || !op->isVar()) + continue; + + VarData* vd = _compiler->getVdById(op->getId()); + uint32_t regIndex = ret.getRegIndex(); + + switch (vd->getClass()) { + case kX86RegClassGp: + if (vd->getRegIndex() != kInvalidReg) + _context->unuse(vd); + _context->attach(vd, regIndex, true); + break; + case kX86RegClassMm: + if (vd->getRegIndex() != kInvalidReg) + _context->unuse(vd); + _context->attach(vd, regIndex, true); + break; + case kX86RegClassXyz: + if (vd->getRegIndex() != kInvalidReg) + _context->unuse(vd); + _context->attach(vd, regIndex, true); + break; + } + } +} + +// ============================================================================ +// [asmjit::X86Context - TranslateOperands] +// ============================================================================ + +//! \internal +static Error X86Context_translateOperands(X86Context* self, Operand* opList, uint32_t opCount) { + X86Compiler* compiler = self->getCompiler(); + uint32_t hasGpdBase = compiler->getRegSize() == 4; + + // Translate variables into registers. + for (uint32_t i = 0; i < opCount; i++) { + Operand* op = &opList[i]; + + if (op->isVar()) { + VarData* vd = compiler->getVdById(op->getId()); + ASMJIT_ASSERT(vd != NULL); + ASMJIT_ASSERT(vd->getRegIndex() != kInvalidReg); + + op->_vreg.op = kOperandTypeReg; + op->_vreg.index = vd->getRegIndex(); + } + else if (op->isMem()) { + X86Mem* m = static_cast(op); + + if (m->isBaseIndexType() && OperandUtil::isVarId(m->getBase())) { + VarData* vd = compiler->getVdById(m->getBase()); + + if (m->getMemType() == kMemTypeBaseIndex) { + ASMJIT_ASSERT(vd->getRegIndex() != kInvalidReg); + op->_vmem.base = vd->getRegIndex(); + } + else { + if (!vd->isMemArg()) + self->getVarCell(vd); + + // Offset will be patched later by X86Context_patchFuncMem(). + m->setGpdBase(hasGpdBase); + m->adjust(vd->isMemArg() ? self->_argActualDisp : self->_varActualDisp); + } + } + + if (OperandUtil::isVarId(m->getIndex())) { + VarData* vd = compiler->getVdById(m->getIndex()); + ASMJIT_ASSERT(vd->getRegIndex() != kInvalidReg); + ASMJIT_ASSERT(vd->getRegIndex() != kX86RegIndexR12); + op->_vmem.index = vd->getRegIndex(); + } + } + } + + return kErrorOk; +} + +// ============================================================================ +// [asmjit::X86Context - TranslatePrologEpilog] +// ============================================================================ + +//! \internal +static Error X86Context_initFunc(X86Context* self, X86FuncNode* func) { + X86Compiler* compiler = self->getCompiler(); + X86FuncDecl* decl = func->getDecl(); + + X86RegMask& clobberedRegs = self->_clobberedRegs; + uint32_t regSize = compiler->getRegSize(); + + // Setup "Save-Restore" registers. + func->_saveRestoreRegs.set(kX86RegClassGp , clobberedRegs.get(kX86RegClassGp ) & decl->getPreserved(kX86RegClassGp )); + func->_saveRestoreRegs.set(kX86RegClassMm , clobberedRegs.get(kX86RegClassMm ) & decl->getPreserved(kX86RegClassMm )); + func->_saveRestoreRegs.set(kX86RegClassK , 0); + func->_saveRestoreRegs.set(kX86RegClassXyz, clobberedRegs.get(kX86RegClassXyz) & decl->getPreserved(kX86RegClassXyz)); + + ASMJIT_ASSERT(!func->_saveRestoreRegs.has(kX86RegClassGp, IntUtil::mask(kX86RegIndexSp))); + + // Setup required stack alignment and kFuncFlagIsStackMisaligned. + { + uint32_t requiredStackAlignment = IntUtil::iMax(self->_memMaxAlign, self->getRegSize()); + + if (requiredStackAlignment < 16) { + // Require 16-byte alignment if 8-byte vars are used. + if (self->_mem8ByteVarsUsed) + requiredStackAlignment = 16; + else if (func->_saveRestoreRegs.get(kX86RegClassMm) || func->_saveRestoreRegs.get(kX86RegClassXyz)) + requiredStackAlignment = 16; + else if (IntUtil::inInterval(func->getRequiredStackAlignment(), 8, 16)) + requiredStackAlignment = 16; + } + + if (func->getRequiredStackAlignment() < requiredStackAlignment) + func->setRequiredStackAlignment(requiredStackAlignment); + + func->updateRequiredStackAlignment(); + } + + // Adjust stack pointer if function is caller. + if (func->isCaller()) { + func->addFuncFlags(kFuncFlagIsStackAdjusted); + } + + // Adjust stack pointer if manual stack alignment is needed. + if (func->isStackMisaligned() && func->isNaked()) { + // Get a memory cell where the original stack frame will be stored. + MemCell* cell = self->_newStackCell(regSize, regSize); + if (cell == NULL) + return self->getError(); + + func->addFuncFlags(kFuncFlagIsStackAdjusted); + self->_stackFrameCell = cell; + + if (decl->getArgStackSize() > 0) { + func->addFuncFlags(kX86FuncFlagMoveArgs); + func->setExtraStackSize(decl->getArgStackSize()); + } + + // Get temporary register which will be used to align the stack frame. + uint32_t fRegMask = IntUtil::bits(self->_regCount.getGp()); + uint32_t stackFrameCopyRegs; + + fRegMask &= ~(decl->getUsed(kX86RegClassGp) | IntUtil::mask(kX86RegIndexSp)); + stackFrameCopyRegs = fRegMask; + + // Try to remove modified registers from the mask. + uint32_t tRegMask = fRegMask & ~self->getClobberedRegs(kX86RegClassGp); + if (tRegMask != 0) + fRegMask = tRegMask; + + // Try to remove preserved registers from the mask. + tRegMask = fRegMask & ~decl->getPreserved(kX86RegClassGp); + if (tRegMask != 0) + fRegMask = tRegMask; + + ASMJIT_ASSERT(fRegMask != 0); + + uint32_t fRegIndex = IntUtil::findFirstBit(fRegMask); + func->_stackFrameRegIndex = static_cast(fRegIndex); + + // We have to save the register on the stack (it will be the part of prolog + // and epilog), however we shouldn't save it twice, so we will remove it + // from '_saveRestoreRegs' in case that it is preserved. + fRegMask = IntUtil::mask(fRegIndex); + if ((fRegMask & decl->getPreserved(kX86RegClassGp)) != 0) { + func->_saveRestoreRegs.andNot(kX86RegClassGp, fRegMask); + func->_isStackFrameRegPreserved = true; + } + + if (func->hasFuncFlag(kX86FuncFlagMoveArgs)) { + uint32_t maxRegs = (func->getArgStackSize() + regSize - 1) / regSize; + stackFrameCopyRegs &= ~fRegMask; + + tRegMask = stackFrameCopyRegs & self->getClobberedRegs(kX86RegClassGp); + uint32_t tRegCnt = IntUtil::bitCount(tRegMask); + + if (tRegCnt > 1 || (tRegCnt > 0 && tRegCnt <= maxRegs)) + stackFrameCopyRegs = tRegMask; + else + stackFrameCopyRegs = IntUtil::keepNOnesFromRight(stackFrameCopyRegs, IntUtil::iMin(maxRegs, 2)); + + func->_saveRestoreRegs.or_(kX86RegClassGp, stackFrameCopyRegs & decl->getPreserved(kX86RegClassGp)); + IntUtil::indexNOnesFromRight(func->_stackFrameCopyGpIndex, stackFrameCopyRegs, maxRegs); + } + } + // If function is not naked we generate standard "EBP/RBP" stack frame. + else if (!func->isNaked()) { + uint32_t fRegIndex = kX86RegIndexBp; + + func->_stackFrameRegIndex = static_cast(fRegIndex); + func->_isStackFrameRegPreserved = true; + } + + ASMJIT_PROPAGATE_ERROR(self->resolveCellOffsets()); + + // Adjust stack pointer if requested memory can't fit into "Red Zone" or "Spill Zone". + if (self->_memAllTotal > IntUtil::iMax(func->getRedZoneSize(), func->getSpillZoneSize())) { + func->addFuncFlags(kFuncFlagIsStackAdjusted); + } + + // Setup stack size used to save preserved registers. + { + uint32_t memGpSize = IntUtil::bitCount(func->_saveRestoreRegs.get(kX86RegClassGp )) * regSize; + uint32_t memMmSize = IntUtil::bitCount(func->_saveRestoreRegs.get(kX86RegClassMm )) * 8; + uint32_t memXmmSize = IntUtil::bitCount(func->_saveRestoreRegs.get(kX86RegClassXyz)) * 16; + + if (func->hasFuncFlag(kX86FuncFlagPushPop)) { + func->_pushPopStackSize = memGpSize; + func->_moveStackSize = memXmmSize + IntUtil::alignTo(memMmSize, 16); + } + else { + func->_pushPopStackSize = 0; + func->_moveStackSize = memXmmSize + IntUtil::alignTo(memMmSize + memGpSize, 16); + } + } + + // Setup adjusted stack size. + if (func->isStackMisaligned()) { + func->_alignStackSize = 0; + } + else { + // If function is aligned, the RETURN address is stored in the aligned + // [ZSP - PtrSize] which makes current ZSP unaligned. + int32_t v = static_cast(regSize); + + // If we have to store function frame pointer we have to count it as well, + // because it is the first thing pushed on the stack. + if (func->hasStackFrameReg() && func->isStackFrameRegPreserved()) + v += regSize; + + // Count push/pop sequence. + v += func->getPushPopStackSize(); + + // Calculate the final offset to keep stack alignment. + func->_alignStackSize = IntUtil::deltaTo(v, func->getRequiredStackAlignment()); + } + + // Memory stack size. + func->_memStackSize = self->_memAllTotal; + func->_alignedMemStackSize = IntUtil::alignTo(func->_memStackSize, func->_requiredStackAlignment); + + if (func->isNaked()) { + self->_argBaseReg = kX86RegIndexSp; + + if (func->isStackAdjusted()) { + if (func->isStackMisaligned()) { + self->_argBaseOffset = static_cast( + func->getCallStackSize() + + func->getAlignedMemStackSize() + + func->getMoveStackSize() + + func->getAlignStackSize()); + self->_argBaseOffset -= regSize; + } + else { + self->_argBaseOffset = static_cast( + func->getCallStackSize() + + func->getAlignedMemStackSize() + + func->getMoveStackSize() + + func->getPushPopStackSize() + + func->getExtraStackSize() + + func->getAlignStackSize()); + } + } + else { + self->_argBaseOffset = func->getPushPopStackSize(); + } + } + else { + self->_argBaseReg = kX86RegIndexBp; + // Caused by "push zbp". + self->_argBaseOffset = regSize; + } + + self->_varBaseReg = kX86RegIndexSp; + self->_varBaseOffset = func->getCallStackSize(); + + if (!func->isStackAdjusted()) { + self->_varBaseOffset = -static_cast( + func->_alignStackSize + + func->_alignedMemStackSize + + func->_moveStackSize); + } + + return kErrorOk; +} + +//! \internal +static Error X86Context_patchFuncMem(X86Context* self, X86FuncNode* func, Node* stop) { + X86Compiler* compiler = self->getCompiler(); + Node* node = func; + + do { + if (node->getType() == kNodeTypeInst) { + InstNode* iNode = static_cast(node); + + if (iNode->hasMemOp()) { + X86Mem* m = iNode->getMemOp(); + + if (m->getMemType() == kMemTypeStackIndex && OperandUtil::isVarId(m->getBase())) { + VarData* vd = compiler->getVdById(m->getBase()); + ASMJIT_ASSERT(vd != NULL); + + if (vd->isMemArg()) { + m->_vmem.base = self->_argBaseReg; + m->_vmem.displacement += vd->getMemOffset(); + m->_vmem.displacement += self->_argBaseOffset; + } + else { + MemCell* cell = vd->getMemCell(); + ASMJIT_ASSERT(cell != NULL); + + m->_vmem.base = self->_varBaseReg; + m->_vmem.displacement += cell->getOffset(); + m->_vmem.displacement += self->_varBaseOffset; + } + } + } + } + + node = node->getNext(); + } while (node != stop); + + return kErrorOk; +} + +//! \internal +static Error X86Context_translatePrologEpilog(X86Context* self, X86FuncNode* func) { + X86Compiler* compiler = self->getCompiler(); + X86FuncDecl* decl = func->getDecl(); + + uint32_t regSize = compiler->getRegSize(); + + int32_t stackSize = static_cast( + func->getAlignStackSize() + + func->getCallStackSize() + + func->getAlignedMemStackSize() + + func->getMoveStackSize() + + func->getExtraStackSize()); + int32_t stackAlignment = func->getRequiredStackAlignment(); + + int32_t stackBase; + int32_t stackPtr; + + if (func->isStackAdjusted()) { + stackBase = static_cast( + func->getCallStackSize() + + func->getAlignedMemStackSize()); + } + else { + stackBase = -static_cast( + func->getAlignedMemStackSize() + + func->getAlignStackSize() + + func->getExtraStackSize()); + } + + uint32_t i, mask; + uint32_t regsGp = func->getSaveRestoreRegs(kX86RegClassGp ); + uint32_t regsMm = func->getSaveRestoreRegs(kX86RegClassMm ); + uint32_t regsXmm = func->getSaveRestoreRegs(kX86RegClassXyz); + + bool earlyPushPop = false; + bool useLeaEpilog = false; + + X86GpReg gpReg(self->_zsp); + X86GpReg fpReg(self->_zbp); + + X86Mem fpOffset; + + // -------------------------------------------------------------------------- + // [Prolog] + // -------------------------------------------------------------------------- + + compiler->_setCursor(func->getEntryNode()); + + // Entry. + if (func->isNaked()) { + if (func->isStackMisaligned()) { + fpReg.setIndex(func->getStackFrameRegIndex()); + fpOffset = x86::ptr(self->_zsp, static_cast(self->_stackFrameCell->getOffset())); + + earlyPushPop = func->hasFuncFlag(kX86FuncFlagPushPop); + if (earlyPushPop) + self->emitPushSequence(regsGp); + + if (func->isStackFrameRegPreserved()) + compiler->emit(kX86InstIdPush, fpReg); + + compiler->emit(kX86InstIdMov, fpReg, self->_zsp); + } + } + else { + compiler->emit(kX86InstIdPush, fpReg); + compiler->emit(kX86InstIdMov, fpReg, self->_zsp); + } + + if (func->hasFuncFlag(kX86FuncFlagPushPop) && !earlyPushPop) { + self->emitPushSequence(regsGp); + if (func->isStackMisaligned() && regsGp != 0) + useLeaEpilog = true; + } + + // Adjust stack pointer. + if (func->isStackAdjusted()) { + stackBase = static_cast(func->getAlignedMemStackSize() + func->getCallStackSize()); + + if (stackSize) + compiler->emit(kX86InstIdSub, self->_zsp, stackSize); + + if (func->isStackMisaligned()) + compiler->emit(kX86InstIdAnd, self->_zsp, -stackAlignment); + + if (func->isStackMisaligned() && func->isNaked()) + compiler->emit(kX86InstIdMov, fpOffset, fpReg); + } + else { + stackBase = -static_cast(func->getAlignStackSize() + func->getMoveStackSize()); + } + + // Save Xmm/Mm/Gp (Mov). + stackPtr = stackBase; + for (i = 0, mask = regsXmm; mask != 0; i++, mask >>= 1) { + if (mask & 0x1) { + compiler->emit(kX86InstIdMovaps, x86::oword_ptr(self->_zsp, stackPtr), x86::xmm(i)); + stackPtr += 16; + } + } + + for (i = 0, mask = regsMm; mask != 0; i++, mask >>= 1) { + if (mask & 0x1) { + compiler->emit(kX86InstIdMovq, x86::qword_ptr(self->_zsp, stackPtr), x86::mm(i)); + stackPtr += 8; + } + } + + if (!func->hasFuncFlag(kX86FuncFlagPushPop)) { + for (i = 0, mask = regsGp; mask != 0; i++, mask >>= 1) { + if (mask & 0x1) { + compiler->emit(kX86InstIdMov, x86::ptr(self->_zsp, stackPtr), gpReg.setIndex(i)); + stackPtr += regSize; + } + } + } + + // -------------------------------------------------------------------------- + // [Move-Args] + // -------------------------------------------------------------------------- + + if (func->hasFuncFlag(kX86FuncFlagMoveArgs)) { + uint32_t argStackPos = 0; + uint32_t argStackSize = decl->getArgStackSize(); + + uint32_t moveIndex = 0; + uint32_t moveCount = (argStackSize + regSize - 1) / regSize; + + X86GpReg r[8]; + uint32_t numRegs = 0; + + for (i = 0; i < 6; i++) + if (func->_stackFrameCopyGpIndex[i] != kInvalidReg) + r[numRegs++] = gpReg.setIndex(func->_stackFrameCopyGpIndex[i]); + + int32_t dSrc = func->getPushPopStackSize() + regSize; + int32_t dDst = func->getAlignStackSize() + + func->getCallStackSize() + + func->getAlignedMemStackSize() + + func->getMoveStackSize(); + + if (func->isStackFrameRegPreserved()) + dSrc += regSize; + + X86Mem mSrc = x86::ptr(fpReg, dSrc); + X86Mem mDst = x86::ptr(self->_zsp, dDst); + + while (moveIndex < moveCount) { + uint32_t numMovs = IntUtil::iMin(moveCount - moveIndex, numRegs); + + for (i = 0; i < numMovs; i++) + compiler->emit(kX86InstIdMov, r[i], mSrc.adjusted((moveIndex + i) * regSize)); + for (i = 0; i < numMovs; i++) + compiler->emit(kX86InstIdMov, mDst.adjusted((moveIndex + i) * regSize), r[i]); + + argStackPos += numMovs * regSize; + moveIndex += numMovs; + } + } + + // -------------------------------------------------------------------------- + // [Epilog] + // -------------------------------------------------------------------------- + + compiler->_setCursor(func->getExitNode()); + + // Restore Xmm/Mm/Gp (Mov). + stackPtr = stackBase; + for (i = 0, mask = regsXmm; mask != 0; i++, mask >>= 1) { + if (mask & 0x1) { + compiler->emit(kX86InstIdMovaps, x86::xmm(i), x86::oword_ptr(self->_zsp, stackPtr)); + stackPtr += 16; + } + } + + for (i = 0, mask = regsMm; mask != 0; i++, mask >>= 1) { + if (mask & 0x1) { + compiler->emit(kX86InstIdMovq, x86::mm(i), x86::qword_ptr(self->_zsp, stackPtr)); + stackPtr += 8; + } + } + + if (!func->hasFuncFlag(kX86FuncFlagPushPop)) { + for (i = 0, mask = regsGp; mask != 0; i++, mask >>= 1) { + if (mask & 0x1) { + compiler->emit(kX86InstIdMov, gpReg.setIndex(i), x86::ptr(self->_zsp, stackPtr)); + stackPtr += regSize; + } + } + } + + // Adjust stack. + if (useLeaEpilog) { + compiler->emit(kX86InstIdLea, self->_zsp, x86::ptr(fpReg, -static_cast(func->getPushPopStackSize()))); + } + else if (!func->isStackMisaligned()) { + if (func->isStackAdjusted() && stackSize != 0) + compiler->emit(kX86InstIdAdd, self->_zsp, stackSize); + } + + // Restore Gp (Push/Pop). + if (func->hasFuncFlag(kX86FuncFlagPushPop) && !earlyPushPop) + self->emitPopSequence(regsGp); + + // Emms. + if (func->hasFuncFlag(kX86FuncFlagEmms)) + compiler->emit(kX86InstIdEmms); + + // MFence/SFence/LFence. + if (func->hasFuncFlag(kX86FuncFlagSFence) & func->hasFuncFlag(kX86FuncFlagLFence)) + compiler->emit(kX86InstIdMfence); + else if (func->hasFuncFlag(kX86FuncFlagSFence)) + compiler->emit(kX86InstIdSfence); + else if (func->hasFuncFlag(kX86FuncFlagLFence)) + compiler->emit(kX86InstIdLfence); + + // Leave. + if (func->isNaked()) { + if (func->isStackMisaligned()) { + compiler->emit(kX86InstIdMov, self->_zsp, fpOffset); + + if (func->isStackFrameRegPreserved()) + compiler->emit(kX86InstIdPop, fpReg); + + if (earlyPushPop) + self->emitPopSequence(regsGp); + } + } + else { + if (useLeaEpilog) { + compiler->emit(kX86InstIdPop, fpReg); + } + else if (func->hasFuncFlag(kX86FuncFlagLeave)) { + compiler->emit(kX86InstIdLeave); + } + else { + compiler->emit(kX86InstIdMov, self->_zsp, fpReg); + compiler->emit(kX86InstIdPop, fpReg); + } + } + + // Emit return. + if (decl->getCalleePopsStack()) + compiler->emit(kX86InstIdRet, static_cast(decl->getArgStackSize())); + else + compiler->emit(kX86InstIdRet); + + return kErrorOk; +} + +// ============================================================================ +// [asmjit::X86Context - Translate - Jump] +// ============================================================================ + +//! \internal +static void X86Context_translateJump(X86Context* self, JumpNode* jNode, TargetNode* jTarget) { + X86Compiler* compiler = self->getCompiler(); + Node* extNode = self->getExtraBlock(); + + // TODO: [COMPILER] State Change. + compiler->_setCursor(extNode); + self->switchState(jTarget->getState()); + + // If one or more instruction has been added during switchState() it will be + // moved at the end of the function body. + if (compiler->getCursor() != extNode) { + TargetNode* jTrampolineTarget = compiler->newTarget(); + + // Add the jump to the target. + compiler->jmp(jTarget->getLabel()); + + // Add the trampoline-label we jump to change the state. + extNode = compiler->setCursor(extNode); + compiler->addNode(jTrampolineTarget); + + // Finally, patch the jump target. + ASMJIT_ASSERT(jNode->getOpCount() > 0); + jNode->_opList[0] = jTrampolineTarget->getLabel(); + jNode->_target = jTrampolineTarget; + } + + // Store the extNode and load the state back. + self->setExtraBlock(extNode); + self->loadState(jNode->_state); +} + +// ============================================================================ +// [asmjit::X86Context - Translate - Ret] +// ============================================================================ + +static Error X86Context_translateRet(X86Context* self, RetNode* rNode, TargetNode* exitTarget) { + Node* node = rNode->getNext(); + + while (node != NULL) { + switch (node->getType()) { + // If we have found an exit label we just return, there is no need to + // emit jump to that. + case kNodeTypeTarget: + if (static_cast(node) == exitTarget) + return kErrorOk; + goto _EmitRet; + + case kNodeTypeEmbed: + case kNodeTypeInst: + case kNodeTypeCall: + case kNodeTypeRet: + goto _EmitRet; + + // Continue iterating. + case kNodeTypeComment: + case kNodeTypeAlign: + case kNodeTypeHint: + break; + + // Invalid node to be here. + case kNodeTypeFunc: + return self->getCompiler()->setError(kErrorInvalidState); + + // We can't go forward from here. + case kNodeTypeEnd: + return kErrorOk; + } + + node = node->getNext(); + } + +_EmitRet: + { + X86Compiler* compiler = self->getCompiler(); + + compiler->_setCursor(rNode); + compiler->jmp(exitTarget->getLabel()); + } + return kErrorOk; +} + +// ============================================================================ +// [asmjit::X86Context - Translate - Func] +// ============================================================================ + +Error X86Context::translate() { + ASMJIT_TLOG("[Translate] === Begin ===\n"); + + X86Compiler* compiler = getCompiler(); + X86FuncNode* func = getFunc(); + + // Register allocator contexts. + X86VarAlloc vAlloc(this); + X86CallAlloc cAlloc(this); + + // Flow. + Node* node_ = func; + Node* next = NULL; + Node* stop = getStop(); + + PodList::Link* jLink = _jccList.getFirst(); + + for (;;) { + while (node_->isTranslated()) { + // Switch state if we went to the already translated node. + if (node_->getType() == kNodeTypeTarget) { + TargetNode* node = static_cast(node_); + compiler->_setCursor(node->getPrev()); + switchState(node->getState()); + } + +_NextGroup: + if (jLink == NULL) { + goto _Done; + } + else { + node_ = jLink->getValue(); + jLink = jLink->getNext(); + + Node* jFlow = X86Context_getOppositeJccFlow(static_cast(node_)); + loadState(node_->getState()); + + if (jFlow->getState()) { + X86Context_translateJump(this, + static_cast(node_), + static_cast(jFlow)); + + node_ = jFlow; + if (node_->isTranslated()) + goto _NextGroup; + } + else { + node_ = jFlow; + } + + break; + } + } + + next = node_->getNext(); + node_->orFlags(kNodeFlagIsTranslated); + + ASMJIT_TSEC({ + X86Context_traceNode(this, node_); + }); + + switch (node_->getType()) { + // ---------------------------------------------------------------------- + // [Align / Embed] + // ---------------------------------------------------------------------- + + case kNodeTypeAlign: + case kNodeTypeEmbed: + break; + + // ---------------------------------------------------------------------- + // [Target] + // ---------------------------------------------------------------------- + + case kNodeTypeTarget: { + TargetNode* node = static_cast(node_); + ASMJIT_ASSERT(!node->hasState()); + node->setState(saveState()); + break; + } + + // ---------------------------------------------------------------------- + // [Inst/Call/SArg/Ret] + // ---------------------------------------------------------------------- + + case kNodeTypeInst: + case kNodeTypeCall: + case kNodeTypeSArg: + // Update VarAttr's unuse flags based on liveness of the next node. + if (!node_->isJcc()) { + X86VarMap* map = static_cast(node_->getMap()); + VarBits* liveness = next->getLiveness(); + + if (map != NULL && liveness != NULL) { + VarAttr* vaList = map->getVaList(); + uint32_t vaCount = map->getVaCount(); + + for (uint32_t i = 0; i < vaCount; i++) { + VarAttr* va = &vaList[i]; + VarData* vd = va->getVd(); + + if (!liveness->getBit(vd->getContextId())) + va->orFlags(kVarAttrUnuse); + } + } + } + + if (node_->getType() == kNodeTypeCall) { + ASMJIT_PROPAGATE_ERROR(cAlloc.run(static_cast(node_))); + break; + } + // ... Fall through ... + + case kNodeTypeHint: + case kNodeTypeRet: { + ASMJIT_PROPAGATE_ERROR(vAlloc.run(node_)); + + // Handle conditional/unconditional jump. + if (node_->isJmpOrJcc()) { + JumpNode* node = static_cast(node_); + TargetNode* jTarget = node->getTarget(); + + if (node->isJmp()) { + if (jTarget->hasState()) { + compiler->_setCursor(node->getPrev()); + switchState(jTarget->getState()); + + goto _NextGroup; + } + else { + next = jTarget; + } + } + else { + Node* jNext = node->getNext(); + + if (jTarget->isTranslated()) { + if (jNext->isTranslated()) { + ASMJIT_ASSERT(jNext->getType() == kNodeTypeTarget); + // TODO: [COMPILER] State - Do intersection of two states if possible. + } + + VarState* savedState = saveState(); + node->setState(savedState); + + X86Context_translateJump(this, node, jTarget); + next = jNext; + } + else if (jNext->isTranslated()) { + ASMJIT_ASSERT(jNext->getType() == kNodeTypeTarget); + + VarState* savedState = saveState(); + node->setState(savedState); + + compiler->_setCursor(node); + switchState(static_cast(jNext)->getState()); + + next = jTarget; + } + else { + node->setState(saveState()); + next = X86Context_getJccFlow(node); + } + } + } + else if (node_->isRet()) { + ASMJIT_PROPAGATE_ERROR( + X86Context_translateRet(this, static_cast(node_), func->getExitNode())); + } + break; + } + + // ---------------------------------------------------------------------- + // [Func] + // ---------------------------------------------------------------------- + + case kNodeTypeFunc: { + ASMJIT_ASSERT(node_ == func); + + X86FuncDecl* decl = func->getDecl(); + X86VarMap* map = func->getMap(); + + if (map != NULL) { + uint32_t i; + uint32_t argCount = func->_x86Decl.getArgCount(); + + for (i = 0; i < argCount; i++) { + const FuncInOut& arg = decl->getArg(i); + + VarData* vd = func->getArg(i); + VarAttr* va = map->findVa(vd); + ASMJIT_ASSERT(va != NULL); + + if (va->getFlags() & kVarAttrUnuse) + continue; + + uint32_t regIndex = va->getOutRegIndex(); + if (regIndex != kInvalidReg && (va->getFlags() & kVarAttrOutConv) == 0) { + switch (vd->getClass()) { + case kX86RegClassGp : attach(vd, regIndex, true); break; + case kX86RegClassMm : attach(vd, regIndex, true); break; + case kX86RegClassXyz: attach(vd, regIndex, true); break; + } + } + else if (va->hasFlag(kVarAttrOutConv)) { + // TODO: [COMPILER] Function Argument Conversion. + ASMJIT_ASSERT(!"Reached"); + } + else { + vd->_isMemArg = true; + vd->setMemOffset(arg.getStackOffset()); + vd->setState(kVarStateMem); + } + } + } + break; + } + + // ---------------------------------------------------------------------- + // [End] + // ---------------------------------------------------------------------- + + case kNodeTypeEnd: { + goto _NextGroup; + } + + default: + break; + } + + if (next == stop) + goto _NextGroup; + node_ = next; + } + +_Done: + ASMJIT_PROPAGATE_ERROR(X86Context_initFunc(this, func)); + ASMJIT_PROPAGATE_ERROR(X86Context_patchFuncMem(this, func, stop)); + ASMJIT_PROPAGATE_ERROR(X86Context_translatePrologEpilog(this, func)); + + ASMJIT_TLOG("[Translate] === Done ===\n\n"); + return kErrorOk; +} + +// ============================================================================ +// [asmjit::X86Context - Schedule] +// ============================================================================ + +Error X86Context::schedule() { + X86Compiler* compiler = getCompiler(); + X86Scheduler scheduler(compiler, + static_cast(compiler->getRuntime()->getCpuInfo())); + + Node* node_ = getFunc(); + Node* stop = getStop(); + + PodList::Link* jLink = _jccList.getFirst(); + + // -------------------------------------------------------------------------- + // [Loop] + // -------------------------------------------------------------------------- + +_Advance: + while (node_->isScheduled()) { +_NextGroup: + if (jLink == NULL) + goto _Done; + + // We always go to the next instruction in the main loop so we have to + // jump to the `jcc` target here. + node_ = static_cast(jLink->getValue())->getTarget(); + jLink = jLink->getNext(); + } + + // Find interval that can be passed to scheduler. + for (;;) { + Node* schedStart = node_; + + for (;;) { + Node* next = node_->getNext(); + node_->orFlags(kNodeFlagIsScheduled); + + // Shouldn't happen here, investigate if hit. + ASMJIT_ASSERT(node_ != stop); + + uint32_t nodeType = node_->getType(); + if (nodeType != kNodeTypeInst) { + // If we didn't reach any instruction node we simply advance. In this + // case no informative nodes will be removed and everything else just + // skipped. + if (schedStart == node_) { + node_ = next; + if (nodeType == kNodeTypeEnd || nodeType == kNodeTypeRet) + goto _NextGroup; + else + goto _Advance; + } + + // Remove informative nodes if we are in a middle of instruction stream. + // + // TODO: Shouldn't be there an option for this? Maybe it can be useful + // to stop if there is a comment or something. I'm not sure if it's + // good to always remove. + if (node_->isInformative()) { + compiler->removeNode(node_); + node_ = next; + continue; + } + + break; + } + + // Stop if `node_` is `jmp` or `jcc`. + if (node_->isJmpOrJcc()) + break; + + node_ = next; + } + + // If the stream is less than 3 instructions it will not be passed to + // scheduler. + if (schedStart != node_ && + schedStart->getNext() != node_ && + schedStart->getNext() != node_->getPrev()) { + + scheduler.run(schedStart, node_); + } + + // If node is `jmp` we follow it as well. + if (node_->isJmp()) { + node_ = static_cast(node_)->getTarget(); + goto _Advance; + } + + // Handle stop nodes. + { + uint32_t nodeType = node_->getType(); + if (nodeType == kNodeTypeEnd || nodeType == kNodeTypeRet) + goto _NextGroup; + } + + node_ = node_->getNext(); + goto _Advance; + } + +_Done: + return kErrorOk; +} + +// ============================================================================ +// [asmjit::X86Context - Serialize] +// ============================================================================ + +template +static ASMJIT_INLINE Error X86Context_serialize(X86Context* self, X86Assembler* assembler, Node* start, Node* stop) { + Node* node_ = start; + StringBuilder& sb = self->_stringBuilder; + +#if !defined(ASMJIT_DISABLE_LOGGER) + uint32_t vdCount; + uint32_t annotationLength; + + Logger* logger; + + if (LoggingEnabled) { + logger = assembler->getLogger(); + + vdCount = static_cast(self->_contextVd.getLength()); + annotationLength = self->_annotationLength; + } +#endif // !ASMJIT_DISABLE_LOGGER + + // Create labels on Assembler side. + ASMJIT_PROPAGATE_ERROR( + assembler->_registerIndexedLabels(self->getCompiler()->_targetList.getLength())); + + do { +#if !defined(ASMJIT_DISABLE_LOGGER) + if (LoggingEnabled) { + sb.clear(); + + if (node_->getComment()) { + sb.appendString(node_->getComment()); + } + + if (sb.getLength() < annotationLength) + sb.appendChars(' ', annotationLength - sb.getLength()); + + size_t offset = sb.getLength(); + sb.appendChars(' ', vdCount); + + if (node_->hasLiveness()) { + VarBits* liveness = node_->getLiveness(); + X86VarMap* map = static_cast(node_->getMap()); + + uint32_t i; + for (i = 0; i < vdCount; i++) { + if (liveness->getBit(i)) + sb.getData()[offset + i] = '.'; + } + + if (map != NULL) { + uint32_t vaCount = map->getVaCount(); + + for (i = 0; i < vaCount; i++) { + VarAttr* va = map->getVa(i); + VarData* vd = va->getVd(); + + uint32_t flags = va->getFlags(); + char c = 'u'; + + if ( (flags & kVarAttrInAll) && !(flags & kVarAttrOutAll)) c = 'r'; + if (!(flags & kVarAttrInAll) && (flags & kVarAttrOutAll)) c = 'w'; + if ( (flags & kVarAttrInAll) && (flags & kVarAttrOutAll)) c = 'x'; + + if ((flags & kVarAttrUnuse)) + c -= 'a' - 'A'; + + sb.getData()[offset + vd->getContextId()] = c; + } + } + } + + assembler->_comment = sb.getData(); + } +#endif // !ASMJIT_DISABLE_LOGGER + + switch (node_->getType()) { + case kNodeTypeAlign: { + AlignNode* node = static_cast(node_); + assembler->align(node->getMode(), node->getOffset()); + break; + } + + case kNodeTypeEmbed: { + EmbedNode* node = static_cast(node_); + assembler->embed(node->getData(), node->getSize()); + break; + } + + case kNodeTypeComment: { + CommentNode* node = static_cast(node_); + +#if !defined(ASMJIT_DISABLE_LOGGER) + if (LoggingEnabled) + logger->logFormat(kLoggerStyleComment, + "%s; %s\n", logger->getIndentation(), node->getComment()); +#endif // !ASMJIT_DISABLE_LOGGER + + break; + } + + case kNodeTypeHint: { + break; + } + + case kNodeTypeTarget: { + TargetNode* node = static_cast(node_); + + node->setOffset(assembler->getOffset()); + assembler->bind(node->getLabel()); + break; + } + + case kNodeTypeInst: { + InstNode* node = static_cast(node_); + + uint32_t instId = node->getInstId(); + uint32_t opCount = node->getOpCount(); + + const Operand* opList = node->getOpList(); + assembler->_instOptions = node->getOptions(); + + const Operand* o0 = &noOperand; + const Operand* o1 = &noOperand; + const Operand* o2 = &noOperand; + const Operand* o3 = &noOperand; + + if (node->isSpecial()) { + switch (instId) { + case kX86InstIdCpuid: + break; + + case kX86InstIdCbw: + case kX86InstIdCdq: + case kX86InstIdCdqe: + case kX86InstIdCwd: + case kX86InstIdCwde: + case kX86InstIdCqo: + break; + + case kX86InstIdCmpxchg: + o0 = &opList[1]; + o1 = &opList[2]; + break; + + case kX86InstIdCmpxchg8b : + case kX86InstIdCmpxchg16b: + o0 = &opList[4]; + break; + + case kX86InstIdDaa: + case kX86InstIdDas: + break; + + case kX86InstIdImul: + case kX86InstIdMul: + case kX86InstIdIdiv: + case kX86InstIdDiv: + // Assume "Mul/Div dst_hi (implicit), dst_lo (implicit), src (explicit)". + ASMJIT_ASSERT(opCount == 3); + o0 = &opList[2]; + break; + + case kX86InstIdMovPtr: + break; + + case kX86InstIdLahf: + case kX86InstIdSahf: + break; + + case kX86InstIdMaskmovq: + case kX86InstIdMaskmovdqu: + o0 = &opList[1]; + o1 = &opList[2]; + break; + + case kX86InstIdEnter: + o0 = &opList[0]; + o1 = &opList[1]; + break; + + case kX86InstIdLeave: + break; + + case kX86InstIdRet: + if (opCount > 0) + o0 = &opList[0]; + break; + + case kX86InstIdMonitor: + case kX86InstIdMwait: + break; + + case kX86InstIdPop: + o0 = &opList[0]; + break; + + case kX86InstIdPopa: + case kX86InstIdPopf: + break; + + case kX86InstIdPush: + o0 = &opList[0]; + break; + + case kX86InstIdPusha: + case kX86InstIdPushf: + break; + + case kX86InstIdRcl: + case kX86InstIdRcr: + case kX86InstIdRol: + case kX86InstIdRor: + case kX86InstIdSal: + case kX86InstIdSar: + case kX86InstIdShl: + case kX86InstIdShr: + o0 = &opList[0]; + o1 = &x86::cl; + break; + + case kX86InstIdShld: + case kX86InstIdShrd: + o0 = &opList[0]; + o1 = &opList[1]; + o2 = &x86::cl; + break; + + case kX86InstIdRdtsc: + case kX86InstIdRdtscp: + break; + + case kX86InstIdRepLodsB : case kX86InstIdRepLodsD : case kX86InstIdRepLodsQ : case kX86InstIdRepLodsW : + case kX86InstIdRepMovsB : case kX86InstIdRepMovsD : case kX86InstIdRepMovsQ : case kX86InstIdRepMovsW : + case kX86InstIdRepStosB : case kX86InstIdRepStosD : case kX86InstIdRepStosQ : case kX86InstIdRepStosW : + case kX86InstIdRepeCmpsB : case kX86InstIdRepeCmpsD : case kX86InstIdRepeCmpsQ : case kX86InstIdRepeCmpsW : + case kX86InstIdRepeScasB : case kX86InstIdRepeScasD : case kX86InstIdRepeScasQ : case kX86InstIdRepeScasW : + case kX86InstIdRepneCmpsB: case kX86InstIdRepneCmpsD: case kX86InstIdRepneCmpsQ: case kX86InstIdRepneCmpsW: + case kX86InstIdRepneScasB: case kX86InstIdRepneScasD: case kX86InstIdRepneScasQ: case kX86InstIdRepneScasW: + break; + + case kX86InstIdXrstor: + case kX86InstIdXrstor64: + case kX86InstIdXsave: + case kX86InstIdXsave64: + case kX86InstIdXsaveopt: + case kX86InstIdXsaveopt64: + o0 = &opList[0]; + break; + + case kX86InstIdXgetbv: + case kX86InstIdXsetbv: + break; + + default: + ASMJIT_ASSERT(!"Reached"); + } + } + else { + if (opCount > 0) o0 = &opList[0]; + if (opCount > 1) o1 = &opList[1]; + if (opCount > 2) o2 = &opList[2]; + if (opCount > 3) o3 = &opList[3]; + } + + // Should call _emit() directly as 4 operand form is the main form. + assembler->emit(instId, *o0, *o1, *o2, *o3); + break; + } + + // Function scope and return is translated to another nodes, no special + // handling is required at this point. + case kNodeTypeFunc: + case kNodeTypeEnd: + case kNodeTypeRet: { + break; + } + + // Function call adds nodes before and after, but it's required to emit + // the call instruction by itself. + case kNodeTypeCall: { + X86CallNode* node = static_cast(node_); + assembler->emit(kX86InstIdCall, node->_target, noOperand, noOperand); + break; + } + + default: + break; + } + + node_ = node_->getNext(); + } while (node_ != stop); + + return kErrorOk; +} + +Error X86Context::serialize(Assembler* assembler, Node* start, Node* stop) { +#if !defined(ASMJIT_DISABLE_LOGGER) + if (assembler->hasLogger()) + return X86Context_serialize<1>(this, static_cast(assembler), start, stop); +#endif // !ASMJIT_DISABLE_LOGGER + + return X86Context_serialize<0>(this, static_cast(assembler), start, stop); +} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // !ASMJIT_DISABLE_COMPILER && (ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64) diff --git a/third/Blackbone/src/3rd_party/AsmJit/x86/x86context_p.h b/third/Blackbone/src/3rd_party/AsmJit/x86/x86context_p.h new file mode 100644 index 0000000000000000000000000000000000000000..8c138f6863cae89e1cde02fe227720adda7e93f5 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/x86/x86context_p.h @@ -0,0 +1,523 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Guard] +#ifndef _ASMJIT_X86_X86CONTEXT_P_H +#define _ASMJIT_X86_X86CONTEXT_P_H + +#include "../build.h" +#if !defined(ASMJIT_DISABLE_COMPILER) + +// [Dependencies - AsmJit] +#include "../base/compiler.h" +#include "../base/context_p.h" +#include "../base/intutil.h" +#include "../x86/x86assembler.h" +#include "../x86/x86compiler.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +//! \addtogroup asmjit_x86_compiler +//! \{ + +// ============================================================================ +// [asmjit::X86Context] +// ============================================================================ + +#if defined(ASMJIT_DEBUG) +# define ASMJIT_X86_CHECK_STATE _checkState(); +#else +# define ASMJIT_X86_CHECK_STATE +#endif // ASMJIT_DEBUG + +//! \internal +//! +//! Compiler context is used by `X86Compiler`. +//! +//! Compiler context is used during compilation and normally developer doesn't +//! need access to it. The context is user per function (it's reset after each +//! function is generated). +struct X86Context : public Context { + ASMJIT_NO_COPY(X86Context) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a new `X86Context` instance. + X86Context(X86Compiler* compiler); + //! Destroy the `X86Context` instance. + virtual ~X86Context(); + + // -------------------------------------------------------------------------- + // [Reset] + // -------------------------------------------------------------------------- + + virtual void reset(bool releaseMemory = false); + + // -------------------------------------------------------------------------- + // [Arch] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE bool isX64() const { + return _zsp.getSize() == 16; + } + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get compiler as `X86Compiler`. + ASMJIT_INLINE X86Compiler* getCompiler() const { + return static_cast(_compiler); + } + + //! Get function as `X86FuncNode`. + ASMJIT_INLINE X86FuncNode* getFunc() const { + return reinterpret_cast(_func); + } + + //! Get clobbered registers (global). + ASMJIT_INLINE uint32_t getClobberedRegs(uint32_t c) { + return _clobberedRegs.get(c); + } + + // -------------------------------------------------------------------------- + // [Helpers] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE X86VarMap* newVarMap(uint32_t vaCount) { + return static_cast( + _baseZone.alloc(sizeof(X86VarMap) + vaCount * sizeof(VarAttr))); + } + + // -------------------------------------------------------------------------- + // [Emit] + // -------------------------------------------------------------------------- + + void emitLoad(VarData* vd, uint32_t regIndex, const char* reason); + void emitSave(VarData* vd, uint32_t regIndex, const char* reason); + void emitMove(VarData* vd, uint32_t toRegIndex, uint32_t fromRegIndex, const char* reason); + void emitSwapGp(VarData* aVd, VarData* bVd, uint32_t aIndex, uint32_t bIndex, const char* reason); + + void emitPushSequence(uint32_t regs); + void emitPopSequence(uint32_t regs); + + void emitConvertVarToVar(uint32_t dstType, uint32_t dstIndex, uint32_t srcType, uint32_t srcIndex); + void emitMoveVarOnStack(uint32_t dstType, const X86Mem* dst, uint32_t srcType, uint32_t srcIndex); + void emitMoveImmOnStack(uint32_t dstType, const X86Mem* dst, const Imm* src); + + void emitMoveImmToReg(uint32_t dstType, uint32_t dstIndex, const Imm* src); + + // -------------------------------------------------------------------------- + // [Register Management] + // -------------------------------------------------------------------------- + + void _checkState(); + + ASMJIT_INLINE uint32_t getRegSize() const { + return _zsp.getSize(); + } + + // -------------------------------------------------------------------------- + // [Attach / Detach] + // -------------------------------------------------------------------------- + + //! Attach. + //! + //! Attach a register to the 'VarData', changing 'VarData' members to show + //! that the variable is currently alive and linking variable with the + //! current 'X86VarState'. + template + ASMJIT_INLINE void attach(VarData* vd, uint32_t regIndex, bool modified) { + ASMJIT_ASSERT(vd->getClass() == C); + ASMJIT_ASSERT(regIndex != kInvalidReg); + + // Prevent Esp allocation if C==Gp. + ASMJIT_ASSERT(C != kX86RegClassGp || regIndex != kX86RegIndexSp); + + uint32_t regMask = IntUtil::mask(regIndex); + + vd->setState(kVarStateReg); + vd->setRegIndex(regIndex); + vd->addHomeIndex(regIndex); + vd->setModified(modified); + + _x86State.getListByClass(C)[regIndex] = vd; + _x86State._occupied.or_(C, regMask); + _x86State._modified.or_(C, static_cast(modified) << regIndex); + + ASMJIT_X86_CHECK_STATE + } + + //! Detach. + //! + //! The opposite of 'Attach'. Detach resets the members in 'VarData' + //! (regIndex, state and changed flags) and unlinks the variable with the + //! current 'X86VarState'. + template + ASMJIT_INLINE void detach(VarData* vd, uint32_t regIndex, uint32_t vState) { + ASMJIT_ASSERT(vd->getClass() == C); + ASMJIT_ASSERT(vd->getRegIndex() == regIndex); + ASMJIT_ASSERT(vState != kVarStateReg); + + uint32_t regMask = IntUtil::mask(regIndex); + + vd->setState(vState); + vd->resetRegIndex(); + vd->setModified(false); + + _x86State.getListByClass(C)[regIndex] = NULL; + _x86State._occupied.andNot(C, regMask); + _x86State._modified.andNot(C, regMask); + + ASMJIT_X86_CHECK_STATE + } + + // -------------------------------------------------------------------------- + // [Rebase] + // -------------------------------------------------------------------------- + + //! Rebase. + //! + //! Change the register of the 'VarData' changing also the current 'X86VarState'. + //! Rebase is nearly identical to 'Detach' and 'Attach' sequence, but doesn't + // change the 'VarData' modified flag. + template + ASMJIT_INLINE void rebase(VarData* vd, uint32_t newRegIndex, uint32_t oldRegIndex) { + ASMJIT_ASSERT(vd->getClass() == C); + + uint32_t newRegMask = IntUtil::mask(newRegIndex); + uint32_t oldRegMask = IntUtil::mask(oldRegIndex); + uint32_t bothRegMask = newRegMask ^ oldRegMask; + + vd->setRegIndex(newRegIndex); + + _x86State.getListByClass(C)[oldRegIndex] = NULL; + _x86State.getListByClass(C)[newRegIndex] = vd; + + _x86State._occupied.xor_(C, bothRegMask); + _x86State._modified.xor_(C, bothRegMask & -static_cast(vd->isModified())); + + ASMJIT_X86_CHECK_STATE + } + + // -------------------------------------------------------------------------- + // [Load / Save] + // -------------------------------------------------------------------------- + + //! Load. + //! + //! Load variable from its memory slot to a register, emitting 'Load' + //! instruction and changing the variable state to allocated. + template + ASMJIT_INLINE void load(VarData* vd, uint32_t regIndex) { + // Can be only called if variable is not allocated. + ASMJIT_ASSERT(vd->getClass() == C); + ASMJIT_ASSERT(vd->getState() != kVarStateReg); + ASMJIT_ASSERT(vd->getRegIndex() == kInvalidReg); + + emitLoad(vd, regIndex, "Load"); + attach(vd, regIndex, false); + + ASMJIT_X86_CHECK_STATE + } + + //! Save. + //! + //! Save the variable into its home location, but keep it as allocated. + template + ASMJIT_INLINE void save(VarData* vd) { + ASMJIT_ASSERT(vd->getClass() == C); + ASMJIT_ASSERT(vd->getState() == kVarStateReg); + ASMJIT_ASSERT(vd->getRegIndex() != kInvalidReg); + + uint32_t regIndex = vd->getRegIndex(); + uint32_t regMask = IntUtil::mask(regIndex); + + emitSave(vd, regIndex, "Save"); + + vd->setModified(false); + _x86State._modified.andNot(C, regMask); + + ASMJIT_X86_CHECK_STATE + } + + // -------------------------------------------------------------------------- + // [Move / Swap] + // -------------------------------------------------------------------------- + + //! Move a register. + //! + //! Move register from one index to another, emitting 'Move' if needed. This + //! function does nothing if register is already at the given index. + template + ASMJIT_INLINE void move(VarData* vd, uint32_t regIndex) { + ASMJIT_ASSERT(vd->getClass() == C); + ASMJIT_ASSERT(vd->getState() == kVarStateReg); + ASMJIT_ASSERT(vd->getRegIndex() != kInvalidReg); + + uint32_t oldIndex = vd->getRegIndex(); + if (regIndex != oldIndex) { + emitMove(vd, regIndex, oldIndex, "Move"); + rebase(vd, regIndex, oldIndex); + } + + ASMJIT_X86_CHECK_STATE + } + + //! Swap two registers + //! + //! It's only possible to swap Gp registers. + ASMJIT_INLINE void swapGp(VarData* aVd, VarData* bVd) { + ASMJIT_ASSERT(aVd != bVd); + + ASMJIT_ASSERT(aVd->getClass() == kX86RegClassGp); + ASMJIT_ASSERT(aVd->getState() == kVarStateReg); + ASMJIT_ASSERT(aVd->getRegIndex() != kInvalidReg); + + ASMJIT_ASSERT(bVd->getClass() == kX86RegClassGp); + ASMJIT_ASSERT(bVd->getState() == kVarStateReg); + ASMJIT_ASSERT(bVd->getRegIndex() != kInvalidReg); + + uint32_t aIndex = aVd->getRegIndex(); + uint32_t bIndex = bVd->getRegIndex(); + + emitSwapGp(aVd, bVd, aIndex, bIndex, "Swap"); + + aVd->setRegIndex(bIndex); + bVd->setRegIndex(aIndex); + + _x86State.getListByClass(kX86RegClassGp)[aIndex] = bVd; + _x86State.getListByClass(kX86RegClassGp)[bIndex] = aVd; + + uint32_t m = aVd->isModified() ^ bVd->isModified(); + _x86State._modified.xor_(kX86RegClassGp, (m << aIndex) | (m << bIndex)); + + ASMJIT_X86_CHECK_STATE + } + + // -------------------------------------------------------------------------- + // [Alloc / Spill] + // -------------------------------------------------------------------------- + + //! Alloc. + template + ASMJIT_INLINE void alloc(VarData* vd, uint32_t regIndex) { + ASMJIT_ASSERT(vd->getClass() == C); + ASMJIT_ASSERT(regIndex != kInvalidReg); + + uint32_t oldRegIndex = vd->getRegIndex(); + uint32_t oldState = vd->getState(); + uint32_t regMask = IntUtil::mask(regIndex); + + ASMJIT_ASSERT(_x86State.getListByClass(C)[regIndex] == NULL || regIndex == oldRegIndex); + + if (oldState != kVarStateReg) { + if (oldState == kVarStateMem) + emitLoad(vd, regIndex, "Alloc"); + vd->setModified(false); + } + else if (oldRegIndex != regIndex) { + emitMove(vd, regIndex, oldRegIndex, "Alloc"); + + _x86State.getListByClass(C)[oldRegIndex] = NULL; + regMask ^= IntUtil::mask(oldRegIndex); + } + else { + ASMJIT_X86_CHECK_STATE + return; + } + + vd->setState(kVarStateReg); + vd->setRegIndex(regIndex); + + _x86State.getListByClass(C)[regIndex] = vd; + _x86State._occupied.xor_(C, regMask); + _x86State._modified.xor_(C, regMask & -static_cast(vd->isModified())); + + ASMJIT_X86_CHECK_STATE + } + + //! Spill. + //! + //! Spill variable/register, saves the content to the memory-home if modified. + template + ASMJIT_INLINE void spill(VarData* vd) { + ASMJIT_ASSERT(vd->getClass() == C); + + if (vd->getState() != kVarStateReg) { + ASMJIT_X86_CHECK_STATE + return; + } + + uint32_t regIndex = vd->getRegIndex(); + + ASMJIT_ASSERT(regIndex != kInvalidReg); + ASMJIT_ASSERT(_x86State.getListByClass(C)[regIndex] == vd); + + if (vd->isModified()) + emitSave(vd, regIndex, "Spill"); + detach(vd, regIndex, kVarStateMem); + + ASMJIT_X86_CHECK_STATE + } + + // -------------------------------------------------------------------------- + // [Modify] + // -------------------------------------------------------------------------- + + template + ASMJIT_INLINE void modify(VarData* vd) { + ASMJIT_ASSERT(vd->getClass() == C); + + uint32_t regIndex = vd->getRegIndex(); + uint32_t regMask = IntUtil::mask(regIndex); + + vd->setModified(true); + _x86State._modified.or_(C, regMask); + + ASMJIT_X86_CHECK_STATE + } + + // -------------------------------------------------------------------------- + // [Unuse] + // -------------------------------------------------------------------------- + + //! Unuse. + //! + //! Unuse variable, it will be detached it if it's allocated then its state + //! will be changed to kVarStateUnused. + template + ASMJIT_INLINE void unuse(VarData* vd, uint32_t vState = kVarStateUnused) { + ASMJIT_ASSERT(vd->getClass() == C); + ASMJIT_ASSERT(vState != kVarStateReg); + + uint32_t regIndex = vd->getRegIndex(); + if (regIndex != kInvalidReg) + detach(vd, regIndex, vState); + else + vd->setState(vState); + + ASMJIT_X86_CHECK_STATE + } + + // -------------------------------------------------------------------------- + // [State] + // -------------------------------------------------------------------------- + + //! Get state as `X86VarState`. + ASMJIT_INLINE X86VarState* getState() const { + return const_cast(&_x86State); + } + + virtual void loadState(VarState* src); + virtual VarState* saveState(); + + virtual void switchState(VarState* src); + virtual void intersectStates(VarState* a, VarState* b); + + // -------------------------------------------------------------------------- + // [Memory] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE X86Mem getVarMem(VarData* vd) { + (void)getVarCell(vd); + + X86Mem mem(_memSlot); + mem.setBase(vd->getId()); + return mem; + } + + // -------------------------------------------------------------------------- + // [Fetch] + // -------------------------------------------------------------------------- + + virtual Error fetch(); + + // -------------------------------------------------------------------------- + // [Annotate] + // -------------------------------------------------------------------------- + + virtual Error annotate(); + + // -------------------------------------------------------------------------- + // [Translate] + // -------------------------------------------------------------------------- + + virtual Error translate(); + + // -------------------------------------------------------------------------- + // [Schedule] + // -------------------------------------------------------------------------- + + virtual Error schedule(); + + // -------------------------------------------------------------------------- + // [Serialize] + // -------------------------------------------------------------------------- + + virtual Error serialize(Assembler* assembler, Node* start, Node* stop); + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Count of X86/X64 registers. + X86RegCount _regCount; + //! X86/X64 stack-pointer (esp or rsp). + X86GpReg _zsp; + //! X86/X64 frame-pointer (ebp or rbp). + X86GpReg _zbp; + //! Temporary memory operand. + X86Mem _memSlot; + + //! X86/X64 specific compiler state, linked to `_state`. + X86VarState _x86State; + //! Clobbered registers (for the whole function). + X86RegMask _clobberedRegs; + + //! Memory cell where is stored address used to restore manually + //! aligned stack. + MemCell* _stackFrameCell; + + //! Global allocable registers mask. + uint32_t _gaRegs[kX86RegClassCount]; + + //! Function arguments base pointer (register). + uint8_t _argBaseReg; + //! Function variables base pointer (register). + uint8_t _varBaseReg; + //! Whether to emit comments. + uint8_t _emitComments; + + //! Function arguments base offset. + int32_t _argBaseOffset; + //! Function variables base offset. + int32_t _varBaseOffset; + + //! Function arguments displacement. + int32_t _argActualDisp; + //! Function variables displacement. + int32_t _varActualDisp; + + //! Temporary string builder used for logging. + StringBuilderT<256> _stringBuilder; +}; + +//! \} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // !ASMJIT_DISABLE_COMPILER +#endif // _ASMJIT_X86_X86CONTEXT_P_H diff --git a/third/Blackbone/src/3rd_party/AsmJit/x86/x86cpuinfo.cpp b/third/Blackbone/src/3rd_party/AsmJit/x86/x86cpuinfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d8ed57aa6d1532bc395d354870199d4fdf0732ec --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/x86/x86cpuinfo.cpp @@ -0,0 +1,402 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Guard] +#include "../build.h" +#if defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64) + +// [Dependencies - AsmJit] +#include "../base/intutil.h" +#include "../x86/x86cpuinfo.h" + +// 2009-02-05: Thanks to Mike Tajmajer for VC7.1 compiler support. It shouldn't +// affect x64 compilation, because x64 compiler starts with VS2005 (VC8.0). +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#include +#endif // _MSC_VER >= 1400 + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [asmjit::X86CpuVendor] +// ============================================================================ + +struct X86CpuVendor { + uint32_t id; + char text[12]; +}; + +static const X86CpuVendor x86CpuVendorList[] = { + { kCpuVendorIntel , { 'G', 'e', 'n', 'u', 'i', 'n', 'e', 'I', 'n', 't', 'e', 'l' } }, + { kCpuVendorAmd , { 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'A', 'M', 'D' } }, + { kCpuVendorVia , { 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 } }, + { kCpuVendorVia , { 'C', 'e', 'n', 't', 'a', 'u', 'r', 'H', 'a', 'u', 'l', 's' } } +}; + +static ASMJIT_INLINE bool x86CpuVendorEq(const X86CpuVendor& info, const char* vendorString) { + const uint32_t* a = reinterpret_cast(info.text); + const uint32_t* b = reinterpret_cast(vendorString); + + return (a[0] == b[0]) & (a[1] == b[1]) & (a[2] == b[2]); +} + +static ASMJIT_INLINE void x86SimplifyBrandString(char* s) { + // Always clear the current character in the buffer. It ensures that there + // is no garbage after the string NULL terminator. + char* d = s; + + char prev = 0; + char curr = s[0]; + s[0] = '\0'; + + for (;;) { + if (curr == 0) + break; + + if (curr == ' ') { + if (prev == '@' || s[1] == ' ' || s[1] == '@') + goto _Skip; + } + + d[0] = curr; + d++; + prev = curr; + +_Skip: + curr = *++s; + s[0] = '\0'; + } + + d[0] = '\0'; +} + +// ============================================================================ +// [asmjit::X86CpuUtil] +// ============================================================================ + +// This is messy, I know. Cpuid is implemented as intrinsic in VS2005, but +// we should support other compilers as well. Main problem is that MS compilers +// in 64-bit mode not allows to use inline assembler, so we need intrinsic and +// we need also asm version. + +union X86XCR { + uint64_t value; + + struct { + uint32_t eax; + uint32_t edx; + }; +}; + +// callCpuId() and detectCpuInfo() for x86 and x64 platforms begins here. +#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64) +void X86CpuUtil::callCpuId(uint32_t inEax, uint32_t inEcx, X86CpuId* result) { + +#if defined(_MSC_VER) +// 2009-02-05: Thanks to Mike Tajmajer for supporting VC7.1 compiler. +// ASMJIT_HOST_X64 is here only for readibility, only VS2005 can compile 64-bit code. +# if _MSC_VER >= 1400 || defined(ASMJIT_HOST_X64) + // Done by intrinsics. + __cpuidex(reinterpret_cast(result->i), inEax, inEcx); +# else // _MSC_VER < 1400 + uint32_t cpuid_eax = inEax; + uint32_t cpuid_ecx = inCax; + uint32_t* cpuid_out = result->i; + + __asm { + mov eax, cpuid_eax + mov ecx, cpuid_ecx + mov edi, cpuid_out + cpuid + mov dword ptr[edi + 0], eax + mov dword ptr[edi + 4], ebx + mov dword ptr[edi + 8], ecx + mov dword ptr[edi + 12], edx + } +# endif // _MSC_VER < 1400 + +#elif defined(__GNUC__) +// Note, patched to preserve ebx/rbx register which is used by GCC. +# if defined(ASMJIT_HOST_X86) +# define __myCpuId(inEax, inEcx, outEax, outEbx, outEcx, outEdx) \ + __asm__ __volatile__( \ + "mov %%ebx, %%edi\n" \ + "cpuid\n" \ + "xchg %%edi, %%ebx\n" \ + : "=a" (outEax), "=D" (outEbx), "=c" (outEcx), "=d" (outEdx) \ + : "a" (inEax), "c" (inEcx)) +# else +# define __myCpuId(inEax, inEcx, outEax, outEbx, outEcx, outEdx) \ + __asm__ __volatile__( \ + "mov %%rbx, %%rdi\n" \ + "cpuid\n" \ + "xchg %%rdi, %%rbx\n" \ + : "=a" (outEax), "=D" (outEbx), "=c" (outEcx), "=d" (outEdx) \ + : "a" (inEax), "c" (inEcx)) +# endif + __myCpuId(inEax, inEcx, result->eax, result->ebx, result->ecx, result->edx); +#endif // COMPILER +} + +static void callXGetBV(uint32_t inEcx, X86XCR* result) { + +#if defined(_MSC_VER) + +# if (_MSC_FULL_VER >= 160040219) // 2010SP1+ + result->value = _xgetbv(inEcx); +# else + result->value = 0; +# endif + +#elif defined(__GNUC__) + + unsigned int eax, edx; +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) + __asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(inEcx)); +# else + __asm__ __volatile__(".byte 0x0F, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(inEcx)); +# endif + result->eax = eax; + result->edx = edx; + +#else + + result->value = 0; + +#endif // COMPILER +} + +void X86CpuUtil::detect(X86CpuInfo* cpuInfo) { + X86CpuId regs; + + uint32_t i; + uint32_t maxBaseId; + + bool maybeMPX = false; + X86XCR xcr0; + xcr0.value = 0; + + // Clear everything except the '_size' member. + ::memset(reinterpret_cast(cpuInfo) + sizeof(uint32_t), + 0, sizeof(CpuInfo) - sizeof(uint32_t)); + + // Fill safe defaults. + cpuInfo->_hwThreadsCount = CpuInfo::detectHwThreadsCount(); + + // -------------------------------------------------------------------------- + // [CPUID EAX=0x0] + // -------------------------------------------------------------------------- + + // Get vendor string/id. + callCpuId(0x0, 0x0, ®s); + + maxBaseId = regs.eax; + ::memcpy(cpuInfo->_vendorString, ®s.ebx, 4); + ::memcpy(cpuInfo->_vendorString + 4, ®s.edx, 4); + ::memcpy(cpuInfo->_vendorString + 8, ®s.ecx, 4); + + for (i = 0; i < ASMJIT_ARRAY_SIZE(x86CpuVendorList); i++) { + if (x86CpuVendorEq(x86CpuVendorList[i], cpuInfo->_vendorString)) { + cpuInfo->_vendorId = x86CpuVendorList[i].id; + break; + } + } + + // -------------------------------------------------------------------------- + // [CPUID EAX=0x1] + // -------------------------------------------------------------------------- + + if (maxBaseId >= 0x1) { + // Get feature flags in ECX/EDX and family/model in EAX. + callCpuId(0x1, 0x0, ®s); + + // Fill family and model fields. + cpuInfo->_family = (regs.eax >> 8) & 0x0F; + cpuInfo->_model = (regs.eax >> 4) & 0x0F; + cpuInfo->_stepping = (regs.eax ) & 0x0F; + + // Use extended family and model fields. + if (cpuInfo->_family == 0x0F) { + cpuInfo->_family += ((regs.eax >> 20) & 0xFF); + cpuInfo->_model += ((regs.eax >> 16) & 0x0F) << 4; + } + + cpuInfo->_processorType = ((regs.eax >> 12) & 0x03); + cpuInfo->_brandIndex = ((regs.ebx ) & 0xFF); + cpuInfo->_flushCacheLineSize = ((regs.ebx >> 8) & 0xFF) * 8; + cpuInfo->_maxLogicalProcessors = ((regs.ebx >> 16) & 0xFF); + + if (regs.ecx & 0x00000001U) cpuInfo->addFeature(kX86CpuFeatureSSE3); + if (regs.ecx & 0x00000002U) cpuInfo->addFeature(kX86CpuFeaturePCLMULQDQ); + if (regs.ecx & 0x00000008U) cpuInfo->addFeature(kX86CpuFeatureMONITOR); + if (regs.ecx & 0x00000200U) cpuInfo->addFeature(kX86CpuFeatureSSSE3); + if (regs.ecx & 0x00002000U) cpuInfo->addFeature(kX86CpuFeatureCMPXCHG16B); + if (regs.ecx & 0x00080000U) cpuInfo->addFeature(kX86CpuFeatureSSE4_1); + if (regs.ecx & 0x00100000U) cpuInfo->addFeature(kX86CpuFeatureSSE4_2); + if (regs.ecx & 0x00400000U) cpuInfo->addFeature(kX86CpuFeatureMOVBE); + if (regs.ecx & 0x00800000U) cpuInfo->addFeature(kX86CpuFeaturePOPCNT); + if (regs.ecx & 0x02000000U) cpuInfo->addFeature(kX86CpuFeatureAESNI); + if (regs.ecx & 0x04000000U) cpuInfo->addFeature(kX86CpuFeatureXSave); + if (regs.ecx & 0x08000000U) cpuInfo->addFeature(kX86CpuFeatureXSaveOS); + if (regs.ecx & 0x40000000U) cpuInfo->addFeature(kX86CpuFeatureRDRAND); + + if (regs.edx & 0x00000010U) cpuInfo->addFeature(kX86CpuFeatureRDTSC); + if (regs.edx & 0x00000100U) cpuInfo->addFeature(kX86CpuFeatureCMPXCHG8B); + if (regs.edx & 0x00008000U) cpuInfo->addFeature(kX86CpuFeatureCMOV); + if (regs.edx & 0x00080000U) cpuInfo->addFeature(kX86CpuFeatureCLFLUSH); + if (regs.edx & 0x00800000U) cpuInfo->addFeature(kX86CpuFeatureMMX); + if (regs.edx & 0x01000000U) cpuInfo->addFeature(kX86CpuFeatureFXSR); + if (regs.edx & 0x02000000U) cpuInfo->addFeature(kX86CpuFeatureSSE).addFeature(kX86CpuFeatureMMX2); + if (regs.edx & 0x04000000U) cpuInfo->addFeature(kX86CpuFeatureSSE).addFeature(kX86CpuFeatureSSE2); + if (regs.edx & 0x10000000U) cpuInfo->addFeature(kX86CpuFeatureMT); + + // AMD sets Multithreading to ON if it has two or more cores. + if (cpuInfo->_hwThreadsCount == 1 && cpuInfo->_vendorId == kCpuVendorAmd && (regs.edx & 0x10000000U)) { + cpuInfo->_hwThreadsCount = 2; + } + + // Get the content of XCR0 if supported by CPU and enabled by OS. + if ((regs.ecx & 0x0C000000U) == 0x0C000000U) { + callXGetBV(0, &xcr0); + } + + // Detect AVX+. + if (regs.ecx & 0x10000000U) { + // - XCR0[2:1] == 11b + // XMM & YMM states are enabled by OS. + if ((xcr0.eax & 0x00000006U) == 0x00000006U) { + cpuInfo->addFeature(kX86CpuFeatureAVX); + + if (regs.ecx & 0x00000800U) cpuInfo->addFeature(kX86CpuFeatureXOP); + if (regs.ecx & 0x00004000U) cpuInfo->addFeature(kX86CpuFeatureFMA3); + if (regs.ecx & 0x00010000U) cpuInfo->addFeature(kX86CpuFeatureFMA4); + if (regs.ecx & 0x20000000U) cpuInfo->addFeature(kX86CpuFeatureF16C); + } + } + } + + // -------------------------------------------------------------------------- + // [CPUID EAX=0x7 ECX=0x0] + // -------------------------------------------------------------------------- + + // Detect new features if the processor supports CPUID-07. + if (maxBaseId >= 0x7) { + callCpuId(0x7, 0x0, ®s); + + if (regs.ebx & 0x00000001U) cpuInfo->addFeature(kX86CpuFeatureFSGSBase); + if (regs.ebx & 0x00000008U) cpuInfo->addFeature(kX86CpuFeatureBMI); + if (regs.ebx & 0x00000010U) cpuInfo->addFeature(kX86CpuFeatureHLE); + if (regs.ebx & 0x00000100U) cpuInfo->addFeature(kX86CpuFeatureBMI2); + if (regs.ebx & 0x00000200U) cpuInfo->addFeature(kX86CpuFeatureMOVSBSTOSBOpt); + if (regs.ebx & 0x00000800U) cpuInfo->addFeature(kX86CpuFeatureRTM); + if (regs.ebx & 0x00004000U) maybeMPX = true; + if (regs.ebx & 0x00040000U) cpuInfo->addFeature(kX86CpuFeatureRDSEED); + if (regs.ebx & 0x00080000U) cpuInfo->addFeature(kX86CpuFeatureADX); + if (regs.ebx & 0x00800000U) cpuInfo->addFeature(kX86CpuFeatureCLFLUSHOpt); + if (regs.ebx & 0x20000000U) cpuInfo->addFeature(kX86CpuFeatureSHA); + + if (regs.ecx & 0x00000001U) cpuInfo->addFeature(kX86CpuFeaturePREFETCHWT1); + + // Detect AVX2. + if (cpuInfo->hasFeature(kX86CpuFeatureAVX)) { + if (regs.ebx & 0x00000020U) cpuInfo->addFeature(kX86CpuFeatureAVX2); + } + + // Detect AVX-512+. + if (regs.ebx & 0x00010000U) { + // - XCR0[2:1] == 11b + // XMM & YMM states are enabled by OS. + // - XCR0[7:5] == 111b + // Upper 256-bit of ZMM0-XMM15 and ZMM16-ZMM31 state are enabled by OS. + if ((xcr0.eax & 0x00000076U) == 0x00000076U) { + cpuInfo->addFeature(kX86CpuFeatureAVX512F); + + if (regs.ebx & 0x00020000U) cpuInfo->addFeature(kX86CpuFeatureAVX512DQ); + if (regs.ebx & 0x04000000U) cpuInfo->addFeature(kX86CpuFeatureAVX512PF); + if (regs.ebx & 0x08000000U) cpuInfo->addFeature(kX86CpuFeatureAVX512ER); + if (regs.ebx & 0x10000000U) cpuInfo->addFeature(kX86CpuFeatureAVX512CD); + if (regs.ebx & 0x40000000U) cpuInfo->addFeature(kX86CpuFeatureAVX512BW); + if (regs.ebx & 0x80000000U) cpuInfo->addFeature(kX86CpuFeatureAVX512VL); + } + } + } + + // -------------------------------------------------------------------------- + // [CPUID EAX=0xD, ECX=0x0] + // -------------------------------------------------------------------------- + + if (maxBaseId >= 0xD && maybeMPX) { + callCpuId(0xD, 0x0, ®s); + + // Both CPUID result and XCR0 has to be enabled to have support for MPX. + if (((regs.eax & xcr0.eax) & 0x00000018U) == 0x00000018U) { + cpuInfo->addFeature(kX86CpuFeatureMPX); + } + } + + // -------------------------------------------------------------------------- + // [CPUID EAX=0x80000000] + // -------------------------------------------------------------------------- + + // Calling cpuid with 0x80000000 as the in argument gets the number of valid + // extended IDs. + callCpuId(0x80000000, 0x0, ®s); + + uint32_t maxExtId = IntUtil::iMin(regs.eax, 0x80000004); + uint32_t* brand = reinterpret_cast(cpuInfo->_brandString); + + for (i = 0x80000001; i <= maxExtId; i++) { + callCpuId(i, 0x0, ®s); + + switch (i) { + case 0x80000001: + if (regs.ecx & 0x00000001U) cpuInfo->addFeature(kX86CpuFeatureLahfSahf); + if (regs.ecx & 0x00000020U) cpuInfo->addFeature(kX86CpuFeatureLZCNT); + if (regs.ecx & 0x00000040U) cpuInfo->addFeature(kX86CpuFeatureSSE4A); + if (regs.ecx & 0x00000080U) cpuInfo->addFeature(kX86CpuFeatureMSSE); + if (regs.ecx & 0x00000100U) cpuInfo->addFeature(kX86CpuFeaturePREFETCH); + + if (regs.edx & 0x00100000U) cpuInfo->addFeature(kX86CpuFeatureNX); + if (regs.edx & 0x00200000U) cpuInfo->addFeature(kX86CpuFeatureFXSROpt); + if (regs.edx & 0x00400000U) cpuInfo->addFeature(kX86CpuFeatureMMX2); + if (regs.edx & 0x08000000U) cpuInfo->addFeature(kX86CpuFeatureRDTSCP); + if (regs.edx & 0x40000000U) cpuInfo->addFeature(kX86CpuFeature3DNOW2).addFeature(kX86CpuFeatureMMX2); + if (regs.edx & 0x80000000U) cpuInfo->addFeature(kX86CpuFeature3DNOW); + break; + + case 0x80000002: + case 0x80000003: + case 0x80000004: + *brand++ = regs.eax; + *brand++ = regs.ebx; + *brand++ = regs.ecx; + *brand++ = regs.edx; + break; + + default: + // Additional features can be detected in the future. + break; + } + } + + // Simplify the brand string (remove unnecessary spaces to make printing nicer). + x86SimplifyBrandString(cpuInfo->_brandString); +} +#endif + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64 diff --git a/third/Blackbone/src/3rd_party/AsmJit/x86/x86cpuinfo.h b/third/Blackbone/src/3rd_party/AsmJit/x86/x86cpuinfo.h new file mode 100644 index 0000000000000000000000000000000000000000..47c3e41ea150713c3ace9e311f370a498aa6cc15 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/x86/x86cpuinfo.h @@ -0,0 +1,263 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Guard] +#ifndef _ASMJIT_X86_X86CPUINFO_H +#define _ASMJIT_X86_X86CPUINFO_H + +// [Dependencies - AsmJit] +#include "../base/cpuinfo.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [Forward Declarations] +// ============================================================================ + +struct X86CpuInfo; + +//! \addtogroup asmjit_x86_general +//! \{ + +// ============================================================================ +// [asmjit::kX86CpuFeature] +// ============================================================================ + +//! X86 CPU features. +ASMJIT_ENUM(kX86CpuFeature) { + //! Cpu has Not-Execute-Bit. + kX86CpuFeatureNX = 0, + //! Cpu has multithreading. + kX86CpuFeatureMT, + //! Cpu has RDTSC. + kX86CpuFeatureRDTSC, + //! Cpu has RDTSCP. + kX86CpuFeatureRDTSCP, + //! Cpu has CMOV. + kX86CpuFeatureCMOV, + //! Cpu has CMPXCHG8B. + kX86CpuFeatureCMPXCHG8B, + //! Cpu has CMPXCHG16B (X64). + kX86CpuFeatureCMPXCHG16B, + //! Cpu has CLFUSH. + kX86CpuFeatureCLFLUSH, + //! Cpu has CLFUSH (Optimized). + kX86CpuFeatureCLFLUSHOpt, + //! Cpu has PREFETCH. + kX86CpuFeaturePREFETCH, + //! Cpu has PREFETCHWT1. + kX86CpuFeaturePREFETCHWT1, + //! Cpu has LAHF/SAHF. + kX86CpuFeatureLahfSahf, + //! Cpu has FXSAVE/FXRSTOR. + kX86CpuFeatureFXSR, + //! Cpu has FXSAVE/FXRSTOR (Optimized). + kX86CpuFeatureFXSROpt, + //! Cpu has MMX. + kX86CpuFeatureMMX, + //! Cpu has extended MMX. + kX86CpuFeatureMMX2, + //! Cpu has 3dNow! + kX86CpuFeature3DNOW, + //! Cpu has enchanced 3dNow! + kX86CpuFeature3DNOW2, + //! Cpu has SSE. + kX86CpuFeatureSSE, + //! Cpu has SSE2. + kX86CpuFeatureSSE2, + //! Cpu has SSE3. + kX86CpuFeatureSSE3, + //! Cpu has SSSE3. + kX86CpuFeatureSSSE3, + //! Cpu has SSE4.A. + kX86CpuFeatureSSE4A, + //! Cpu has SSE4.1. + kX86CpuFeatureSSE4_1, + //! Cpu has SSE4.2. + kX86CpuFeatureSSE4_2, + //! Cpu has Misaligned SSE (MSSE). + kX86CpuFeatureMSSE, + //! Cpu has MONITOR and MWAIT. + kX86CpuFeatureMONITOR, + //! Cpu has MOVBE. + kX86CpuFeatureMOVBE, + //! Cpu has POPCNT. + kX86CpuFeaturePOPCNT, + //! Cpu has LZCNT. + kX86CpuFeatureLZCNT, + //! Cpu has AESNI. + kX86CpuFeatureAESNI, + //! Cpu has PCLMULQDQ. + kX86CpuFeaturePCLMULQDQ, + //! Cpu has RDRAND. + kX86CpuFeatureRDRAND, + //! Cpu has RDSEED. + kX86CpuFeatureRDSEED, + //! Cpu has SHA-1 and SHA-256. + kX86CpuFeatureSHA, + //! Cpu has XSAVE support - XSAVE/XRSTOR, XSETBV/XGETBV, and XCR0. + kX86CpuFeatureXSave, + //! OS has enabled XSAVE, you can call XGETBV to get value of XCR0. + kX86CpuFeatureXSaveOS, + //! Cpu has AVX. + kX86CpuFeatureAVX, + //! Cpu has AVX2. + kX86CpuFeatureAVX2, + //! Cpu has F16C. + kX86CpuFeatureF16C, + //! Cpu has FMA3. + kX86CpuFeatureFMA3, + //! Cpu has FMA4. + kX86CpuFeatureFMA4, + //! Cpu has XOP. + kX86CpuFeatureXOP, + //! Cpu has BMI. + kX86CpuFeatureBMI, + //! Cpu has BMI2. + kX86CpuFeatureBMI2, + //! Cpu has HLE. + kX86CpuFeatureHLE, + //! Cpu has RTM. + kX86CpuFeatureRTM, + //! Cpu has ADX. + kX86CpuFeatureADX, + //! Cpu has MPX (Memory Protection Extensions). + kX86CpuFeatureMPX, + //! Cpu has FSGSBASE. + kX86CpuFeatureFSGSBase, + //! Cpu has optimized REP MOVSB/STOSB. + kX86CpuFeatureMOVSBSTOSBOpt, + + //! Cpu has AVX-512F (Foundation). + kX86CpuFeatureAVX512F, + //! Cpu has AVX-512CD (Conflict Detection). + kX86CpuFeatureAVX512CD, + //! Cpu has AVX-512PF (Prefetch Instructions). + kX86CpuFeatureAVX512PF, + //! Cpu has AVX-512ER (Exponential and Reciprocal Instructions). + kX86CpuFeatureAVX512ER, + //! Cpu has AVX-512DQ (DWord/QWord). + kX86CpuFeatureAVX512DQ, + //! Cpu has AVX-512BW (Byte/Word). + kX86CpuFeatureAVX512BW, + //! Cpu has AVX VL (Vector Length Excensions). + kX86CpuFeatureAVX512VL, + + //! Count of X86/X64 Cpu features. + kX86CpuFeatureCount +}; + +// ============================================================================ +// [asmjit::X86CpuId] +// ============================================================================ + +//! X86/X64 CPUID output. +union X86CpuId { + //! EAX/EBX/ECX/EDX output. + uint32_t i[4]; + + struct { + //! EAX output. + uint32_t eax; + //! EBX output. + uint32_t ebx; + //! ECX output. + uint32_t ecx; + //! EDX output. + uint32_t edx; + }; +}; + +// ============================================================================ +// [asmjit::X86CpuUtil] +// ============================================================================ + +#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64) +//! CPU utilities available only if the host processor is X86/X64. +struct X86CpuUtil { + //! Get the result of calling CPUID instruction to `out`. + ASMJIT_API static void callCpuId(uint32_t inEax, uint32_t inEcx, X86CpuId* out); + + //! Detect the Host CPU. + ASMJIT_API static void detect(X86CpuInfo* cpuInfo); +}; +#endif // ASMJIT_HOST_X86 || ASMJIT_HOST_X64 + +// ============================================================================ +// [asmjit::X86CpuInfo] +// ============================================================================ + +struct X86CpuInfo : public CpuInfo { + ASMJIT_NO_COPY(X86CpuInfo) + + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE X86CpuInfo(uint32_t size = sizeof(X86CpuInfo)) : + CpuInfo(size) {} + + // -------------------------------------------------------------------------- + // [Accessors] + // -------------------------------------------------------------------------- + + //! Get processor type. + ASMJIT_INLINE uint32_t getProcessorType() const { + return _processorType; + } + + //! Get brand index. + ASMJIT_INLINE uint32_t getBrandIndex() const { + return _brandIndex; + } + + //! Get flush cache line size. + ASMJIT_INLINE uint32_t getFlushCacheLineSize() const { + return _flushCacheLineSize; + } + + //! Get maximum logical processors count. + ASMJIT_INLINE uint32_t getMaxLogicalProcessors() const { + return _maxLogicalProcessors; + } + + // -------------------------------------------------------------------------- + // [Statics] + // -------------------------------------------------------------------------- + +#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64) + //! Get global instance of `X86CpuInfo`. + static ASMJIT_INLINE const X86CpuInfo* getHost() { + return static_cast(CpuInfo::getHost()); + } +#endif // ASMJIT_HOST_X86 || ASMJIT_HOST_X64 + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Processor type. + uint32_t _processorType; + //! Brand index. + uint32_t _brandIndex; + //! Flush cache line size in bytes. + uint32_t _flushCacheLineSize; + //! Maximum number of addressable IDs for logical processors. + uint32_t _maxLogicalProcessors; +}; + +//! \} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // _ASMJIT_X86_X86CPUINFO_H diff --git a/third/Blackbone/src/3rd_party/AsmJit/x86/x86inst.cpp b/third/Blackbone/src/3rd_party/AsmJit/x86/x86inst.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ddea978767714d4f4f44d0319640cfdbbf33115a --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/x86/x86inst.cpp @@ -0,0 +1,4971 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Guard] +#include "../build.h" +#if defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64) + +// [Dependencies - AsmJit] +#include "../x86/x86inst.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [Enums (Internal)] +// ============================================================================ + +//! \internal +enum { + kX86InstTable_L__ = (0) << kX86InstOpCode_L_Shift, + kX86InstTable_L_I = (0) << kX86InstOpCode_L_Shift, + kX86InstTable_L_0 = (0) << kX86InstOpCode_L_Shift, + kX86InstTable_L_L = (1) << kX86InstOpCode_L_Shift, + + kX86InstTable_W__ = (0) << kX86InstOpCode_W_Shift, + kX86InstTable_W_I = (0) << kX86InstOpCode_W_Shift, + kX86InstTable_W_0 = (0) << kX86InstOpCode_W_Shift, + kX86InstTable_W_1 = (1) << kX86InstOpCode_W_Shift, + kX86InstTable_W_W = (1) << kX86InstOpCode_W_Shift, + + kX86InstTable_E__ = (0) << kX86InstOpCode_EW_Shift, + kX86InstTable_E_I = (0) << kX86InstOpCode_EW_Shift, + kX86InstTable_E_0 = (0) << kX86InstOpCode_EW_Shift, + kX86InstTable_E_1 = (1) << kX86InstOpCode_EW_Shift +}; + +//! \internal +//! +//! Combined flags. +enum kX86InstOpInternal { + kX86InstOpI = kX86InstOpImm, + kX86InstOpL = kX86InstOpLabel, + kX86InstOpLbImm = kX86InstOpLabel | kX86InstOpImm, + + kX86InstOpGwb = kX86InstOpGw | kX86InstOpGb, + kX86InstOpGqd = kX86InstOpGq | kX86InstOpGd, + kX86InstOpGqdw = kX86InstOpGq | kX86InstOpGd | kX86InstOpGw, + kX86InstOpGqdwb = kX86InstOpGq | kX86InstOpGd | kX86InstOpGw | kX86InstOpGb, + + kX86InstOpGbMem = kX86InstOpGb | kX86InstOpMem, + kX86InstOpGwMem = kX86InstOpGw | kX86InstOpMem, + kX86InstOpGdMem = kX86InstOpGd | kX86InstOpMem, + kX86InstOpGqMem = kX86InstOpGq | kX86InstOpMem, + kX86InstOpGwbMem = kX86InstOpGwb | kX86InstOpMem, + kX86InstOpGqdMem = kX86InstOpGqd | kX86InstOpMem, + kX86InstOpGqdwMem = kX86InstOpGqdw | kX86InstOpMem, + kX86InstOpGqdwbMem = kX86InstOpGqdwb | kX86InstOpMem, + + kX86InstOpFpMem = kX86InstOpFp | kX86InstOpMem, + kX86InstOpMmMem = kX86InstOpMm | kX86InstOpMem, + kX86InstOpKMem = kX86InstOpK | kX86InstOpMem, + kX86InstOpXmmMem = kX86InstOpXmm | kX86InstOpMem, + kX86InstOpYmmMem = kX86InstOpYmm | kX86InstOpMem, + kX86InstOpZmmMem = kX86InstOpZmm | kX86InstOpMem, + + kX86InstOpMmXmm = kX86InstOpMm | kX86InstOpXmm, + kX86InstOpMmXmmMem = kX86InstOpMmXmm | kX86InstOpMem, + + kX86InstOpXy = kX86InstOpXmm | kX86InstOpYmm, + kX86InstOpXyMem = kX86InstOpXy | kX86InstOpMem, + + kX86InstOpXyz = kX86InstOpXy | kX86InstOpZmm, + kX86InstOpXyzMem = kX86InstOpXyz | kX86InstOpMem +}; + +//! \internal +//! +//! X86/X64 Instruction AVX-512 flags (combined). +ASMJIT_ENUM(kX86InstFlagsInternal) { + // FPU. + kX86InstFlagMem2_4 = kX86InstFlagMem2 | kX86InstFlagMem4, + kX86InstFlagMem2_4_8 = kX86InstFlagMem2_4 | kX86InstFlagMem8, + kX86InstFlagMem4_8 = kX86InstFlagMem4 | kX86InstFlagMem8, + kX86InstFlagMem4_8_10 = kX86InstFlagMem4_8 | kX86InstFlagMem10 +}; + +// ============================================================================ +// [Macros] +// ============================================================================ + +#if !defined(ASMJIT_DISABLE_NAMES) +# define INST_NAME_INDEX(_Code_) _Code_##_NameIndex +#else +# define INST_NAME_INDEX(_Code_) 0 +#endif + +// Undefined. Used to distinguish between zero and field that is not used. +#define U 0 + +// Instruction opcodes. +#define O_000000(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_00 | kX86InstOpCode_MM_00 | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_000F00(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_00 | kX86InstOpCode_MM_0F | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_000F01(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_00 | kX86InstOpCode_MM_0F01 | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_000F0F(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_00 | kX86InstOpCode_MM_0F | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_000F38(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_00 | kX86InstOpCode_MM_0F38 | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_000F3A(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_00 | kX86InstOpCode_MM_0F3A | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_660000(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_66 | kX86InstOpCode_MM_00 | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_660F00(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_66 | kX86InstOpCode_MM_0F | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_660F38(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_66 | kX86InstOpCode_MM_0F38 | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_660F3A(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_66 | kX86InstOpCode_MM_0F3A | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_9B0000(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_9B | kX86InstOpCode_MM_00 | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_F20000(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_F2 | kX86InstOpCode_MM_00 | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_F20F00(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_F2 | kX86InstOpCode_MM_0F | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_F20F38(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_F2 | kX86InstOpCode_MM_0F38 | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_F20F3A(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_F2 | kX86InstOpCode_MM_0F3A | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_F30000(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_F3 | kX86InstOpCode_MM_00 | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_F30F00(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_F3 | kX86InstOpCode_MM_0F | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_F30F38(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_F3 | kX86InstOpCode_MM_0F38 | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_F30F3A(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_F3 | kX86InstOpCode_MM_0F3A | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) + +#define O_00_M08(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_00 | kX86InstOpCode_MM_01000| (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_00_M09(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_00 | kX86InstOpCode_MM_01001| (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) +#define O_66_M03(_OpCode_, _O_, _L_, _W_, _EVEX_W_) (kX86InstOpCode_PP_66 | kX86InstOpCode_MM_00011| (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift) | kX86InstTable_L_##_L_ | kX86InstTable_W_##_W_ | kX86InstTable_E_##_EVEX_W_) + +#define O_00_X(_OpCode_, _O_) (kX86InstOpCode_PP_00 | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift)) +#define O_9B_X(_OpCode_, _O_) (kX86InstOpCode_PP_9B | (0x##_OpCode_) | ((_O_) << kX86InstOpCode_O_Shift)) + +// Instruction Encoding `Enc(...)`. +#define Enc(_Id_) kX86InstEncodingId##_Id_ + +// Instruction Flags `F(...)` and AVX-512 `AVX(...)`flags. +#define F(_Flags_) kX86InstFlag##_Flags_ + +#define A(_Flags_) kX86InstFlagAvx512##_Flags_ + +// Instruction EFLAGS `E(OSZAPCDX)`. +#define EF(_Flags_) 0 + +// Instruction Operands' Flags `O(...)`. +#define O(_Op_) kX86InstOp##_Op_ + +// Defines an X86/X64 instruction. +#define INST(_Id_, _Name_, _OpCode0_, _OpCode1_, _Encoding_, _IFlags_, _EFlags_, _WriteIndex_, _WriteSize_, _Op0_, _Op_, _Op2_, _Op3_, _Op4_) \ + { INST_NAME_INDEX(_Id_), _Id_##_ExtendedIndex, _OpCode0_ } + +// ============================================================================ +// [asmjit::X86Inst] +// ============================================================================ + +// ${X86InstData:Begin} +// Automatically generated, do not edit. +#if !defined(ASMJIT_DISABLE_NAMES) +const char _x86InstName[] = + "\0" + "adc\0" + "add\0" + "addpd\0" + "addps\0" + "addsd\0" + "addss\0" + "addsubpd\0" + "addsubps\0" + "aesdec\0" + "aesdeclast\0" + "aesenc\0" + "aesenclast\0" + "aesimc\0" + "aeskeygenassist\0" + "and\0" + "andn\0" + "andnpd\0" + "andnps\0" + "andpd\0" + "andps\0" + "bextr\0" + "blendpd\0" + "blendps\0" + "blendvpd\0" + "blendvps\0" + "blsi\0" + "blsmsk\0" + "blsr\0" + "bsf\0" + "bsr\0" + "bswap\0" + "bt\0" + "btc\0" + "btr\0" + "bts\0" + "bzhi\0" + "call\0" + "cbw\0" + "cdq\0" + "cdqe\0" + "clc\0" + "cld\0" + "clflush\0" + "cmc\0" + "cmova\0" + "cmovae\0" + "cmovb\0" + "cmovbe\0" + "cmovc\0" + "cmove\0" + "cmovg\0" + "cmovge\0" + "cmovl\0" + "cmovle\0" + "cmovna\0" + "cmovnae\0" + "cmovnb\0" + "cmovnbe\0" + "cmovnc\0" + "cmovne\0" + "cmovng\0" + "cmovnge\0" + "cmovnl\0" + "cmovnle\0" + "cmovno\0" + "cmovnp\0" + "cmovns\0" + "cmovnz\0" + "cmovo\0" + "cmovp\0" + "cmovpe\0" + "cmovpo\0" + "cmovs\0" + "cmovz\0" + "cmp\0" + "cmppd\0" + "cmpps\0" + "cmps_b\0" + "cmps_d\0" + "cmps_q\0" + "cmps_w\0" + "cmpsd\0" + "cmpss\0" + "cmpxchg\0" + "cmpxchg16b\0" + "cmpxchg8b\0" + "comisd\0" + "comiss\0" + "cpuid\0" + "cqo\0" + "crc32\0" + "cvtdq2pd\0" + "cvtdq2ps\0" + "cvtpd2dq\0" + "cvtpd2pi\0" + "cvtpd2ps\0" + "cvtpi2pd\0" + "cvtpi2ps\0" + "cvtps2dq\0" + "cvtps2pd\0" + "cvtps2pi\0" + "cvtsd2si\0" + "cvtsd2ss\0" + "cvtsi2sd\0" + "cvtsi2ss\0" + "cvtss2sd\0" + "cvtss2si\0" + "cvttpd2dq\0" + "cvttpd2pi\0" + "cvttps2dq\0" + "cvttps2pi\0" + "cvttsd2si\0" + "cvttss2si\0" + "cwd\0" + "cwde\0" + "daa\0" + "das\0" + "dec\0" + "div\0" + "divpd\0" + "divps\0" + "divsd\0" + "divss\0" + "dppd\0" + "dpps\0" + "emms\0" + "enter\0" + "extractps\0" + "extrq\0" + "f2xm1\0" + "fabs\0" + "fadd\0" + "faddp\0" + "fbld\0" + "fbstp\0" + "fchs\0" + "fclex\0" + "fcmovb\0" + "fcmovbe\0" + "fcmove\0" + "fcmovnb\0" + "fcmovnbe\0" + "fcmovne\0" + "fcmovnu\0" + "fcmovu\0" + "fcom\0" + "fcomi\0" + "fcomip\0" + "fcomp\0" + "fcompp\0" + "fcos\0" + "fdecstp\0" + "fdiv\0" + "fdivp\0" + "fdivr\0" + "fdivrp\0" + "femms\0" + "ffree\0" + "fiadd\0" + "ficom\0" + "ficomp\0" + "fidiv\0" + "fidivr\0" + "fild\0" + "fimul\0" + "fincstp\0" + "finit\0" + "fist\0" + "fistp\0" + "fisttp\0" + "fisub\0" + "fisubr\0" + "fld\0" + "fld1\0" + "fldcw\0" + "fldenv\0" + "fldl2e\0" + "fldl2t\0" + "fldlg2\0" + "fldln2\0" + "fldpi\0" + "fldz\0" + "fmul\0" + "fmulp\0" + "fnclex\0" + "fninit\0" + "fnop\0" + "fnsave\0" + "fnstcw\0" + "fnstenv\0" + "fnstsw\0" + "fpatan\0" + "fprem\0" + "fprem1\0" + "fptan\0" + "frndint\0" + "frstor\0" + "fsave\0" + "fscale\0" + "fsin\0" + "fsincos\0" + "fsqrt\0" + "fst\0" + "fstcw\0" + "fstenv\0" + "fstp\0" + "fstsw\0" + "fsub\0" + "fsubp\0" + "fsubr\0" + "fsubrp\0" + "ftst\0" + "fucom\0" + "fucomi\0" + "fucomip\0" + "fucomp\0" + "fucompp\0" + "fwait\0" + "fxam\0" + "fxch\0" + "fxrstor\0" + "fxsave\0" + "fxtract\0" + "fyl2x\0" + "fyl2xp1\0" + "haddpd\0" + "haddps\0" + "hsubpd\0" + "hsubps\0" + "idiv\0" + "imul\0" + "inc\0" + "insertps\0" + "insertq\0" + "int\0" + "ja\0" + "jae\0" + "jb\0" + "jbe\0" + "jc\0" + "je\0" + "jg\0" + "jge\0" + "jl\0" + "jle\0" + "jna\0" + "jnae\0" + "jnb\0" + "jnbe\0" + "jnc\0" + "jne\0" + "jng\0" + "jnge\0" + "jnl\0" + "jnle\0" + "jno\0" + "jnp\0" + "jns\0" + "jnz\0" + "jo\0" + "jp\0" + "jpe\0" + "jpo\0" + "js\0" + "jz\0" + "jecxz\0" + "jmp\0" + "lahf\0" + "lddqu\0" + "ldmxcsr\0" + "lea\0" + "leave\0" + "lfence\0" + "lods_b\0" + "lods_d\0" + "lods_q\0" + "lods_w\0" + "lzcnt\0" + "maskmovdqu\0" + "maskmovq\0" + "maxpd\0" + "maxps\0" + "maxsd\0" + "maxss\0" + "mfence\0" + "minpd\0" + "minps\0" + "minsd\0" + "minss\0" + "monitor\0" + "mov\0" + "mov_ptr\0" + "movapd\0" + "movaps\0" + "movbe\0" + "movd\0" + "movddup\0" + "movdq2q\0" + "movdqa\0" + "movdqu\0" + "movhlps\0" + "movhpd\0" + "movhps\0" + "movlhps\0" + "movlpd\0" + "movlps\0" + "movmskpd\0" + "movmskps\0" + "movntdq\0" + "movntdqa\0" + "movnti\0" + "movntpd\0" + "movntps\0" + "movntq\0" + "movntsd\0" + "movntss\0" + "movq\0" + "movq2dq\0" + "movs_b\0" + "movs_d\0" + "movs_q\0" + "movs_w\0" + "movsd\0" + "movshdup\0" + "movsldup\0" + "movss\0" + "movsx\0" + "movsxd\0" + "movupd\0" + "movups\0" + "movzx\0" + "mpsadbw\0" + "mul\0" + "mulpd\0" + "mulps\0" + "mulsd\0" + "mulss\0" + "mulx\0" + "mwait\0" + "neg\0" + "nop\0" + "not\0" + "or\0" + "orpd\0" + "orps\0" + "pabsb\0" + "pabsd\0" + "pabsw\0" + "packssdw\0" + "packsswb\0" + "packusdw\0" + "packuswb\0" + "paddb\0" + "paddd\0" + "paddq\0" + "paddsb\0" + "paddsw\0" + "paddusb\0" + "paddusw\0" + "paddw\0" + "palignr\0" + "pand\0" + "pandn\0" + "pause\0" + "pavgb\0" + "pavgw\0" + "pblendvb\0" + "pblendw\0" + "pclmulqdq\0" + "pcmpeqb\0" + "pcmpeqd\0" + "pcmpeqq\0" + "pcmpeqw\0" + "pcmpestri\0" + "pcmpestrm\0" + "pcmpgtb\0" + "pcmpgtd\0" + "pcmpgtq\0" + "pcmpgtw\0" + "pcmpistri\0" + "pcmpistrm\0" + "pdep\0" + "pext\0" + "pextrb\0" + "pextrd\0" + "pextrq\0" + "pextrw\0" + "pf2id\0" + "pf2iw\0" + "pfacc\0" + "pfadd\0" + "pfcmpeq\0" + "pfcmpge\0" + "pfcmpgt\0" + "pfmax\0" + "pfmin\0" + "pfmul\0" + "pfnacc\0" + "pfpnacc\0" + "pfrcp\0" + "pfrcpit1\0" + "pfrcpit2\0" + "pfrsqit1\0" + "pfrsqrt\0" + "pfsub\0" + "pfsubr\0" + "phaddd\0" + "phaddsw\0" + "phaddw\0" + "phminposuw\0" + "phsubd\0" + "phsubsw\0" + "phsubw\0" + "pi2fd\0" + "pi2fw\0" + "pinsrb\0" + "pinsrd\0" + "pinsrq\0" + "pinsrw\0" + "pmaddubsw\0" + "pmaddwd\0" + "pmaxsb\0" + "pmaxsd\0" + "pmaxsw\0" + "pmaxub\0" + "pmaxud\0" + "pmaxuw\0" + "pminsb\0" + "pminsd\0" + "pminsw\0" + "pminub\0" + "pminud\0" + "pminuw\0" + "pmovmskb\0" + "pmovsxbd\0" + "pmovsxbq\0" + "pmovsxbw\0" + "pmovsxdq\0" + "pmovsxwd\0" + "pmovsxwq\0" + "pmovzxbd\0" + "pmovzxbq\0" + "pmovzxbw\0" + "pmovzxdq\0" + "pmovzxwd\0" + "pmovzxwq\0" + "pmuldq\0" + "pmulhrsw\0" + "pmulhuw\0" + "pmulhw\0" + "pmulld\0" + "pmullw\0" + "pmuludq\0" + "pop\0" + "popa\0" + "popcnt\0" + "popf\0" + "por\0" + "prefetch\0" + "prefetch_3dnow\0" + "prefetchw_3dnow\0" + "psadbw\0" + "pshufb\0" + "pshufd\0" + "pshufhw\0" + "pshuflw\0" + "pshufw\0" + "psignb\0" + "psignd\0" + "psignw\0" + "pslld\0" + "pslldq\0" + "psllq\0" + "psllw\0" + "psrad\0" + "psraw\0" + "psrld\0" + "psrldq\0" + "psrlq\0" + "psrlw\0" + "psubb\0" + "psubd\0" + "psubq\0" + "psubsb\0" + "psubsw\0" + "psubusb\0" + "psubusw\0" + "psubw\0" + "pswapd\0" + "ptest\0" + "punpckhbw\0" + "punpckhdq\0" + "punpckhqdq\0" + "punpckhwd\0" + "punpcklbw\0" + "punpckldq\0" + "punpcklqdq\0" + "punpcklwd\0" + "push\0" + "pusha\0" + "pushf\0" + "pxor\0" + "rcl\0" + "rcpps\0" + "rcpss\0" + "rcr\0" + "rdfsbase\0" + "rdgsbase\0" + "rdrand\0" + "rdtsc\0" + "rdtscp\0" + "rep lods_b\0" + "rep lods_d\0" + "rep lods_q\0" + "rep lods_w\0" + "rep movs_b\0" + "rep movs_d\0" + "rep movs_q\0" + "rep movs_w\0" + "rep stos_b\0" + "rep stos_d\0" + "rep stos_q\0" + "rep stos_w\0" + "repe cmps_b\0" + "repe cmps_d\0" + "repe cmps_q\0" + "repe cmps_w\0" + "repe scas_b\0" + "repe scas_d\0" + "repe scas_q\0" + "repe scas_w\0" + "repne cmps_b\0" + "repne cmps_d\0" + "repne cmps_q\0" + "repne cmps_w\0" + "repne scas_b\0" + "repne scas_d\0" + "repne scas_q\0" + "repne scas_w\0" + "ret\0" + "rol\0" + "ror\0" + "rorx\0" + "roundpd\0" + "roundps\0" + "roundsd\0" + "roundss\0" + "rsqrtps\0" + "rsqrtss\0" + "sahf\0" + "sal\0" + "sar\0" + "sarx\0" + "sbb\0" + "scas_b\0" + "scas_d\0" + "scas_q\0" + "scas_w\0" + "seta\0" + "setae\0" + "setb\0" + "setbe\0" + "setc\0" + "sete\0" + "setg\0" + "setge\0" + "setl\0" + "setle\0" + "setna\0" + "setnae\0" + "setnb\0" + "setnbe\0" + "setnc\0" + "setne\0" + "setng\0" + "setnge\0" + "setnl\0" + "setnle\0" + "setno\0" + "setnp\0" + "setns\0" + "setnz\0" + "seto\0" + "setp\0" + "setpe\0" + "setpo\0" + "sets\0" + "setz\0" + "sfence\0" + "shl\0" + "shld\0" + "shlx\0" + "shr\0" + "shrd\0" + "shrx\0" + "shufpd\0" + "shufps\0" + "sqrtpd\0" + "sqrtps\0" + "sqrtsd\0" + "sqrtss\0" + "stc\0" + "std\0" + "stmxcsr\0" + "stos_b\0" + "stos_d\0" + "stos_q\0" + "stos_w\0" + "sub\0" + "subpd\0" + "subps\0" + "subsd\0" + "subss\0" + "test\0" + "tzcnt\0" + "ucomisd\0" + "ucomiss\0" + "ud2\0" + "unpckhpd\0" + "unpckhps\0" + "unpcklpd\0" + "unpcklps\0" + "vaddpd\0" + "vaddps\0" + "vaddsd\0" + "vaddss\0" + "vaddsubpd\0" + "vaddsubps\0" + "vaesdec\0" + "vaesdeclast\0" + "vaesenc\0" + "vaesenclast\0" + "vaesimc\0" + "vaeskeygenassist\0" + "vandnpd\0" + "vandnps\0" + "vandpd\0" + "vandps\0" + "vblendpd\0" + "vblendps\0" + "vblendvpd\0" + "vblendvps\0" + "vbroadcastf128\0" + "vbroadcasti128\0" + "vbroadcastsd\0" + "vbroadcastss\0" + "vcmppd\0" + "vcmpps\0" + "vcmpsd\0" + "vcmpss\0" + "vcomisd\0" + "vcomiss\0" + "vcvtdq2pd\0" + "vcvtdq2ps\0" + "vcvtpd2dq\0" + "vcvtpd2ps\0" + "vcvtph2ps\0" + "vcvtps2dq\0" + "vcvtps2pd\0" + "vcvtps2ph\0" + "vcvtsd2si\0" + "vcvtsd2ss\0" + "vcvtsi2sd\0" + "vcvtsi2ss\0" + "vcvtss2sd\0" + "vcvtss2si\0" + "vcvttpd2dq\0" + "vcvttps2dq\0" + "vcvttsd2si\0" + "vcvttss2si\0" + "vdivpd\0" + "vdivps\0" + "vdivsd\0" + "vdivss\0" + "vdppd\0" + "vdpps\0" + "vextractf128\0" + "vextracti128\0" + "vextractps\0" + "vfmadd132pd\0" + "vfmadd132ps\0" + "vfmadd132sd\0" + "vfmadd132ss\0" + "vfmadd213pd\0" + "vfmadd213ps\0" + "vfmadd213sd\0" + "vfmadd213ss\0" + "vfmadd231pd\0" + "vfmadd231ps\0" + "vfmadd231sd\0" + "vfmadd231ss\0" + "vfmaddpd\0" + "vfmaddps\0" + "vfmaddsd\0" + "vfmaddss\0" + "vfmaddsub132pd\0" + "vfmaddsub132ps\0" + "vfmaddsub213pd\0" + "vfmaddsub213ps\0" + "vfmaddsub231pd\0" + "vfmaddsub231ps\0" + "vfmaddsubpd\0" + "vfmaddsubps\0" + "vfmsub132pd\0" + "vfmsub132ps\0" + "vfmsub132sd\0" + "vfmsub132ss\0" + "vfmsub213pd\0" + "vfmsub213ps\0" + "vfmsub213sd\0" + "vfmsub213ss\0" + "vfmsub231pd\0" + "vfmsub231ps\0" + "vfmsub231sd\0" + "vfmsub231ss\0" + "vfmsubadd132pd\0" + "vfmsubadd132ps\0" + "vfmsubadd213pd\0" + "vfmsubadd213ps\0" + "vfmsubadd231pd\0" + "vfmsubadd231ps\0" + "vfmsubaddpd\0" + "vfmsubaddps\0" + "vfmsubpd\0" + "vfmsubps\0" + "vfmsubsd\0" + "vfmsubss\0" + "vfnmadd132pd\0" + "vfnmadd132ps\0" + "vfnmadd132sd\0" + "vfnmadd132ss\0" + "vfnmadd213pd\0" + "vfnmadd213ps\0" + "vfnmadd213sd\0" + "vfnmadd213ss\0" + "vfnmadd231pd\0" + "vfnmadd231ps\0" + "vfnmadd231sd\0" + "vfnmadd231ss\0" + "vfnmaddpd\0" + "vfnmaddps\0" + "vfnmaddsd\0" + "vfnmaddss\0" + "vfnmsub132pd\0" + "vfnmsub132ps\0" + "vfnmsub132sd\0" + "vfnmsub132ss\0" + "vfnmsub213pd\0" + "vfnmsub213ps\0" + "vfnmsub213sd\0" + "vfnmsub213ss\0" + "vfnmsub231pd\0" + "vfnmsub231ps\0" + "vfnmsub231sd\0" + "vfnmsub231ss\0" + "vfnmsubpd\0" + "vfnmsubps\0" + "vfnmsubsd\0" + "vfnmsubss\0" + "vfrczpd\0" + "vfrczps\0" + "vfrczsd\0" + "vfrczss\0" + "vgatherdpd\0" + "vgatherdps\0" + "vgatherqpd\0" + "vgatherqps\0" + "vhaddpd\0" + "vhaddps\0" + "vhsubpd\0" + "vhsubps\0" + "vinsertf128\0" + "vinserti128\0" + "vinsertps\0" + "vlddqu\0" + "vldmxcsr\0" + "vmaskmovdqu\0" + "vmaskmovpd\0" + "vmaskmovps\0" + "vmaxpd\0" + "vmaxps\0" + "vmaxsd\0" + "vmaxss\0" + "vminpd\0" + "vminps\0" + "vminsd\0" + "vminss\0" + "vmovapd\0" + "vmovaps\0" + "vmovd\0" + "vmovddup\0" + "vmovdqa\0" + "vmovdqu\0" + "vmovhlps\0" + "vmovhpd\0" + "vmovhps\0" + "vmovlhps\0" + "vmovlpd\0" + "vmovlps\0" + "vmovmskpd\0" + "vmovmskps\0" + "vmovntdq\0" + "vmovntdqa\0" + "vmovntpd\0" + "vmovntps\0" + "vmovq\0" + "vmovsd\0" + "vmovshdup\0" + "vmovsldup\0" + "vmovss\0" + "vmovupd\0" + "vmovups\0" + "vmpsadbw\0" + "vmulpd\0" + "vmulps\0" + "vmulsd\0" + "vmulss\0" + "vorpd\0" + "vorps\0" + "vpabsb\0" + "vpabsd\0" + "vpabsw\0" + "vpackssdw\0" + "vpacksswb\0" + "vpackusdw\0" + "vpackuswb\0" + "vpaddb\0" + "vpaddd\0" + "vpaddq\0" + "vpaddsb\0" + "vpaddsw\0" + "vpaddusb\0" + "vpaddusw\0" + "vpaddw\0" + "vpalignr\0" + "vpand\0" + "vpandn\0" + "vpavgb\0" + "vpavgw\0" + "vpblendd\0" + "vpblendvb\0" + "vpblendw\0" + "vpbroadcastb\0" + "vpbroadcastd\0" + "vpbroadcastq\0" + "vpbroadcastw\0" + "vpclmulqdq\0" + "vpcmov\0" + "vpcmpeqb\0" + "vpcmpeqd\0" + "vpcmpeqq\0" + "vpcmpeqw\0" + "vpcmpestri\0" + "vpcmpestrm\0" + "vpcmpgtb\0" + "vpcmpgtd\0" + "vpcmpgtq\0" + "vpcmpgtw\0" + "vpcmpistri\0" + "vpcmpistrm\0" + "vpcomb\0" + "vpcomd\0" + "vpcomq\0" + "vpcomub\0" + "vpcomud\0" + "vpcomuq\0" + "vpcomuw\0" + "vpcomw\0" + "vperm2f128\0" + "vperm2i128\0" + "vpermd\0" + "vpermil2pd\0" + "vpermil2ps\0" + "vpermilpd\0" + "vpermilps\0" + "vpermpd\0" + "vpermps\0" + "vpermq\0" + "vpextrb\0" + "vpextrd\0" + "vpextrq\0" + "vpextrw\0" + "vpgatherdd\0" + "vpgatherdq\0" + "vpgatherqd\0" + "vpgatherqq\0" + "vphaddbd\0" + "vphaddbq\0" + "vphaddbw\0" + "vphaddd\0" + "vphadddq\0" + "vphaddsw\0" + "vphaddubd\0" + "vphaddubq\0" + "vphaddubw\0" + "vphaddudq\0" + "vphadduwd\0" + "vphadduwq\0" + "vphaddw\0" + "vphaddwd\0" + "vphaddwq\0" + "vphminposuw\0" + "vphsubbw\0" + "vphsubd\0" + "vphsubdq\0" + "vphsubsw\0" + "vphsubw\0" + "vphsubwd\0" + "vpinsrb\0" + "vpinsrd\0" + "vpinsrq\0" + "vpinsrw\0" + "vpmacsdd\0" + "vpmacsdqh\0" + "vpmacsdql\0" + "vpmacssdd\0" + "vpmacssdqh\0" + "vpmacssdql\0" + "vpmacsswd\0" + "vpmacssww\0" + "vpmacswd\0" + "vpmacsww\0" + "vpmadcsswd\0" + "vpmadcswd\0" + "vpmaddubsw\0" + "vpmaddwd\0" + "vpmaskmovd\0" + "vpmaskmovq\0" + "vpmaxsb\0" + "vpmaxsd\0" + "vpmaxsw\0" + "vpmaxub\0" + "vpmaxud\0" + "vpmaxuw\0" + "vpminsb\0" + "vpminsd\0" + "vpminsw\0" + "vpminub\0" + "vpminud\0" + "vpminuw\0" + "vpmovmskb\0" + "vpmovsxbd\0" + "vpmovsxbq\0" + "vpmovsxbw\0" + "vpmovsxdq\0" + "vpmovsxwd\0" + "vpmovsxwq\0" + "vpmovzxbd\0" + "vpmovzxbq\0" + "vpmovzxbw\0" + "vpmovzxdq\0" + "vpmovzxwd\0" + "vpmovzxwq\0" + "vpmuldq\0" + "vpmulhrsw\0" + "vpmulhuw\0" + "vpmulhw\0" + "vpmulld\0" + "vpmullw\0" + "vpmuludq\0" + "vpor\0" + "vpperm\0" + "vprotb\0" + "vprotd\0" + "vprotq\0" + "vprotw\0" + "vpsadbw\0" + "vpshab\0" + "vpshad\0" + "vpshaq\0" + "vpshaw\0" + "vpshlb\0" + "vpshld\0" + "vpshlq\0" + "vpshlw\0" + "vpshufb\0" + "vpshufd\0" + "vpshufhw\0" + "vpshuflw\0" + "vpsignb\0" + "vpsignd\0" + "vpsignw\0" + "vpslld\0" + "vpslldq\0" + "vpsllq\0" + "vpsllvd\0" + "vpsllvq\0" + "vpsllw\0" + "vpsrad\0" + "vpsravd\0" + "vpsraw\0" + "vpsrld\0" + "vpsrldq\0" + "vpsrlq\0" + "vpsrlvd\0" + "vpsrlvq\0" + "vpsrlw\0" + "vpsubb\0" + "vpsubd\0" + "vpsubq\0" + "vpsubsb\0" + "vpsubsw\0" + "vpsubusb\0" + "vpsubusw\0" + "vpsubw\0" + "vptest\0" + "vpunpckhbw\0" + "vpunpckhdq\0" + "vpunpckhqdq\0" + "vpunpckhwd\0" + "vpunpcklbw\0" + "vpunpckldq\0" + "vpunpcklqdq\0" + "vpunpcklwd\0" + "vpxor\0" + "vrcpps\0" + "vrcpss\0" + "vroundpd\0" + "vroundps\0" + "vroundsd\0" + "vroundss\0" + "vrsqrtps\0" + "vrsqrtss\0" + "vshufpd\0" + "vshufps\0" + "vsqrtpd\0" + "vsqrtps\0" + "vsqrtsd\0" + "vsqrtss\0" + "vstmxcsr\0" + "vsubpd\0" + "vsubps\0" + "vsubsd\0" + "vsubss\0" + "vtestpd\0" + "vtestps\0" + "vucomisd\0" + "vucomiss\0" + "vunpckhpd\0" + "vunpckhps\0" + "vunpcklpd\0" + "vunpcklps\0" + "vxorpd\0" + "vxorps\0" + "vzeroall\0" + "vzeroupper\0" + "wrfsbase\0" + "wrgsbase\0" + "xadd\0" + "xchg\0" + "xgetbv\0" + "xor\0" + "xorpd\0" + "xorps\0" + "xrstor\0" + "xrstor64\0" + "xsave\0" + "xsave64\0" + "xsaveopt\0" + "xsaveopt64\0" + "xsetbv\0"; + +// Automatically generated, do not edit. +enum kX86InstAlphaIndex { + kX86InstAlphaIndexFirst = 'a', + kX86InstAlphaIndexLast = 'z', + kX86InstAlphaIndexInvalid = 0xFFFF +}; + +// Automatically generated, do not edit. +static const uint16_t _x86InstAlphaIndex[26] = { + kX86InstIdAdc, + kX86InstIdBextr, + kX86InstIdCall, + kX86InstIdDaa, + kX86InstIdEmms, + kX86InstIdF2xm1, + 0xFFFF, + kX86InstIdHaddpd, + kX86InstIdIdiv, + kX86InstIdJa, + 0xFFFF, + kX86InstIdLahf, + kX86InstIdMaskmovdqu, + kX86InstIdNeg, + kX86InstIdOr, + kX86InstIdPabsb, + 0xFFFF, + kX86InstIdRcl, + kX86InstIdSahf, + kX86InstIdTest, + kX86InstIdUcomisd, + kX86InstIdVaddpd, + kX86InstIdWrfsbase, + kX86InstIdXadd, + 0xFFFF, + 0xFFFF +}; + +// Automatically generated, do not edit. +enum kX86InstData_NameIndex { + kInstIdNone_NameIndex = 0, + kX86InstIdAdc_NameIndex = 1, + kX86InstIdAdd_NameIndex = 5, + kX86InstIdAddpd_NameIndex = 9, + kX86InstIdAddps_NameIndex = 15, + kX86InstIdAddsd_NameIndex = 21, + kX86InstIdAddss_NameIndex = 27, + kX86InstIdAddsubpd_NameIndex = 33, + kX86InstIdAddsubps_NameIndex = 42, + kX86InstIdAesdec_NameIndex = 51, + kX86InstIdAesdeclast_NameIndex = 58, + kX86InstIdAesenc_NameIndex = 69, + kX86InstIdAesenclast_NameIndex = 76, + kX86InstIdAesimc_NameIndex = 87, + kX86InstIdAeskeygenassist_NameIndex = 94, + kX86InstIdAnd_NameIndex = 110, + kX86InstIdAndn_NameIndex = 114, + kX86InstIdAndnpd_NameIndex = 119, + kX86InstIdAndnps_NameIndex = 126, + kX86InstIdAndpd_NameIndex = 133, + kX86InstIdAndps_NameIndex = 139, + kX86InstIdBextr_NameIndex = 145, + kX86InstIdBlendpd_NameIndex = 151, + kX86InstIdBlendps_NameIndex = 159, + kX86InstIdBlendvpd_NameIndex = 167, + kX86InstIdBlendvps_NameIndex = 176, + kX86InstIdBlsi_NameIndex = 185, + kX86InstIdBlsmsk_NameIndex = 190, + kX86InstIdBlsr_NameIndex = 197, + kX86InstIdBsf_NameIndex = 202, + kX86InstIdBsr_NameIndex = 206, + kX86InstIdBswap_NameIndex = 210, + kX86InstIdBt_NameIndex = 216, + kX86InstIdBtc_NameIndex = 219, + kX86InstIdBtr_NameIndex = 223, + kX86InstIdBts_NameIndex = 227, + kX86InstIdBzhi_NameIndex = 231, + kX86InstIdCall_NameIndex = 236, + kX86InstIdCbw_NameIndex = 241, + kX86InstIdCdq_NameIndex = 245, + kX86InstIdCdqe_NameIndex = 249, + kX86InstIdClc_NameIndex = 254, + kX86InstIdCld_NameIndex = 258, + kX86InstIdClflush_NameIndex = 262, + kX86InstIdCmc_NameIndex = 270, + kX86InstIdCmova_NameIndex = 274, + kX86InstIdCmovae_NameIndex = 280, + kX86InstIdCmovb_NameIndex = 287, + kX86InstIdCmovbe_NameIndex = 293, + kX86InstIdCmovc_NameIndex = 300, + kX86InstIdCmove_NameIndex = 306, + kX86InstIdCmovg_NameIndex = 312, + kX86InstIdCmovge_NameIndex = 318, + kX86InstIdCmovl_NameIndex = 325, + kX86InstIdCmovle_NameIndex = 331, + kX86InstIdCmovna_NameIndex = 338, + kX86InstIdCmovnae_NameIndex = 345, + kX86InstIdCmovnb_NameIndex = 353, + kX86InstIdCmovnbe_NameIndex = 360, + kX86InstIdCmovnc_NameIndex = 368, + kX86InstIdCmovne_NameIndex = 375, + kX86InstIdCmovng_NameIndex = 382, + kX86InstIdCmovnge_NameIndex = 389, + kX86InstIdCmovnl_NameIndex = 397, + kX86InstIdCmovnle_NameIndex = 404, + kX86InstIdCmovno_NameIndex = 412, + kX86InstIdCmovnp_NameIndex = 419, + kX86InstIdCmovns_NameIndex = 426, + kX86InstIdCmovnz_NameIndex = 433, + kX86InstIdCmovo_NameIndex = 440, + kX86InstIdCmovp_NameIndex = 446, + kX86InstIdCmovpe_NameIndex = 452, + kX86InstIdCmovpo_NameIndex = 459, + kX86InstIdCmovs_NameIndex = 466, + kX86InstIdCmovz_NameIndex = 472, + kX86InstIdCmp_NameIndex = 478, + kX86InstIdCmppd_NameIndex = 482, + kX86InstIdCmpps_NameIndex = 488, + kX86InstIdCmpsB_NameIndex = 494, + kX86InstIdCmpsD_NameIndex = 501, + kX86InstIdCmpsQ_NameIndex = 508, + kX86InstIdCmpsW_NameIndex = 515, + kX86InstIdCmpsd_NameIndex = 522, + kX86InstIdCmpss_NameIndex = 528, + kX86InstIdCmpxchg_NameIndex = 534, + kX86InstIdCmpxchg16b_NameIndex = 542, + kX86InstIdCmpxchg8b_NameIndex = 553, + kX86InstIdComisd_NameIndex = 563, + kX86InstIdComiss_NameIndex = 570, + kX86InstIdCpuid_NameIndex = 577, + kX86InstIdCqo_NameIndex = 583, + kX86InstIdCrc32_NameIndex = 587, + kX86InstIdCvtdq2pd_NameIndex = 593, + kX86InstIdCvtdq2ps_NameIndex = 602, + kX86InstIdCvtpd2dq_NameIndex = 611, + kX86InstIdCvtpd2pi_NameIndex = 620, + kX86InstIdCvtpd2ps_NameIndex = 629, + kX86InstIdCvtpi2pd_NameIndex = 638, + kX86InstIdCvtpi2ps_NameIndex = 647, + kX86InstIdCvtps2dq_NameIndex = 656, + kX86InstIdCvtps2pd_NameIndex = 665, + kX86InstIdCvtps2pi_NameIndex = 674, + kX86InstIdCvtsd2si_NameIndex = 683, + kX86InstIdCvtsd2ss_NameIndex = 692, + kX86InstIdCvtsi2sd_NameIndex = 701, + kX86InstIdCvtsi2ss_NameIndex = 710, + kX86InstIdCvtss2sd_NameIndex = 719, + kX86InstIdCvtss2si_NameIndex = 728, + kX86InstIdCvttpd2dq_NameIndex = 737, + kX86InstIdCvttpd2pi_NameIndex = 747, + kX86InstIdCvttps2dq_NameIndex = 757, + kX86InstIdCvttps2pi_NameIndex = 767, + kX86InstIdCvttsd2si_NameIndex = 777, + kX86InstIdCvttss2si_NameIndex = 787, + kX86InstIdCwd_NameIndex = 797, + kX86InstIdCwde_NameIndex = 801, + kX86InstIdDaa_NameIndex = 806, + kX86InstIdDas_NameIndex = 810, + kX86InstIdDec_NameIndex = 814, + kX86InstIdDiv_NameIndex = 818, + kX86InstIdDivpd_NameIndex = 822, + kX86InstIdDivps_NameIndex = 828, + kX86InstIdDivsd_NameIndex = 834, + kX86InstIdDivss_NameIndex = 840, + kX86InstIdDppd_NameIndex = 846, + kX86InstIdDpps_NameIndex = 851, + kX86InstIdEmms_NameIndex = 856, + kX86InstIdEnter_NameIndex = 861, + kX86InstIdExtractps_NameIndex = 867, + kX86InstIdExtrq_NameIndex = 877, + kX86InstIdF2xm1_NameIndex = 883, + kX86InstIdFabs_NameIndex = 889, + kX86InstIdFadd_NameIndex = 894, + kX86InstIdFaddp_NameIndex = 899, + kX86InstIdFbld_NameIndex = 905, + kX86InstIdFbstp_NameIndex = 910, + kX86InstIdFchs_NameIndex = 916, + kX86InstIdFclex_NameIndex = 921, + kX86InstIdFcmovb_NameIndex = 927, + kX86InstIdFcmovbe_NameIndex = 934, + kX86InstIdFcmove_NameIndex = 942, + kX86InstIdFcmovnb_NameIndex = 949, + kX86InstIdFcmovnbe_NameIndex = 957, + kX86InstIdFcmovne_NameIndex = 966, + kX86InstIdFcmovnu_NameIndex = 974, + kX86InstIdFcmovu_NameIndex = 982, + kX86InstIdFcom_NameIndex = 989, + kX86InstIdFcomi_NameIndex = 994, + kX86InstIdFcomip_NameIndex = 1000, + kX86InstIdFcomp_NameIndex = 1007, + kX86InstIdFcompp_NameIndex = 1013, + kX86InstIdFcos_NameIndex = 1020, + kX86InstIdFdecstp_NameIndex = 1025, + kX86InstIdFdiv_NameIndex = 1033, + kX86InstIdFdivp_NameIndex = 1038, + kX86InstIdFdivr_NameIndex = 1044, + kX86InstIdFdivrp_NameIndex = 1050, + kX86InstIdFemms_NameIndex = 1057, + kX86InstIdFfree_NameIndex = 1063, + kX86InstIdFiadd_NameIndex = 1069, + kX86InstIdFicom_NameIndex = 1075, + kX86InstIdFicomp_NameIndex = 1081, + kX86InstIdFidiv_NameIndex = 1088, + kX86InstIdFidivr_NameIndex = 1094, + kX86InstIdFild_NameIndex = 1101, + kX86InstIdFimul_NameIndex = 1106, + kX86InstIdFincstp_NameIndex = 1112, + kX86InstIdFinit_NameIndex = 1120, + kX86InstIdFist_NameIndex = 1126, + kX86InstIdFistp_NameIndex = 1131, + kX86InstIdFisttp_NameIndex = 1137, + kX86InstIdFisub_NameIndex = 1144, + kX86InstIdFisubr_NameIndex = 1150, + kX86InstIdFld_NameIndex = 1157, + kX86InstIdFld1_NameIndex = 1161, + kX86InstIdFldcw_NameIndex = 1166, + kX86InstIdFldenv_NameIndex = 1172, + kX86InstIdFldl2e_NameIndex = 1179, + kX86InstIdFldl2t_NameIndex = 1186, + kX86InstIdFldlg2_NameIndex = 1193, + kX86InstIdFldln2_NameIndex = 1200, + kX86InstIdFldpi_NameIndex = 1207, + kX86InstIdFldz_NameIndex = 1213, + kX86InstIdFmul_NameIndex = 1218, + kX86InstIdFmulp_NameIndex = 1223, + kX86InstIdFnclex_NameIndex = 1229, + kX86InstIdFninit_NameIndex = 1236, + kX86InstIdFnop_NameIndex = 1243, + kX86InstIdFnsave_NameIndex = 1248, + kX86InstIdFnstcw_NameIndex = 1255, + kX86InstIdFnstenv_NameIndex = 1262, + kX86InstIdFnstsw_NameIndex = 1270, + kX86InstIdFpatan_NameIndex = 1277, + kX86InstIdFprem_NameIndex = 1284, + kX86InstIdFprem1_NameIndex = 1290, + kX86InstIdFptan_NameIndex = 1297, + kX86InstIdFrndint_NameIndex = 1303, + kX86InstIdFrstor_NameIndex = 1311, + kX86InstIdFsave_NameIndex = 1318, + kX86InstIdFscale_NameIndex = 1324, + kX86InstIdFsin_NameIndex = 1331, + kX86InstIdFsincos_NameIndex = 1336, + kX86InstIdFsqrt_NameIndex = 1344, + kX86InstIdFst_NameIndex = 1350, + kX86InstIdFstcw_NameIndex = 1354, + kX86InstIdFstenv_NameIndex = 1360, + kX86InstIdFstp_NameIndex = 1367, + kX86InstIdFstsw_NameIndex = 1372, + kX86InstIdFsub_NameIndex = 1378, + kX86InstIdFsubp_NameIndex = 1383, + kX86InstIdFsubr_NameIndex = 1389, + kX86InstIdFsubrp_NameIndex = 1395, + kX86InstIdFtst_NameIndex = 1402, + kX86InstIdFucom_NameIndex = 1407, + kX86InstIdFucomi_NameIndex = 1413, + kX86InstIdFucomip_NameIndex = 1420, + kX86InstIdFucomp_NameIndex = 1428, + kX86InstIdFucompp_NameIndex = 1435, + kX86InstIdFwait_NameIndex = 1443, + kX86InstIdFxam_NameIndex = 1449, + kX86InstIdFxch_NameIndex = 1454, + kX86InstIdFxrstor_NameIndex = 1459, + kX86InstIdFxsave_NameIndex = 1467, + kX86InstIdFxtract_NameIndex = 1474, + kX86InstIdFyl2x_NameIndex = 1482, + kX86InstIdFyl2xp1_NameIndex = 1488, + kX86InstIdHaddpd_NameIndex = 1496, + kX86InstIdHaddps_NameIndex = 1503, + kX86InstIdHsubpd_NameIndex = 1510, + kX86InstIdHsubps_NameIndex = 1517, + kX86InstIdIdiv_NameIndex = 1524, + kX86InstIdImul_NameIndex = 1529, + kX86InstIdInc_NameIndex = 1534, + kX86InstIdInsertps_NameIndex = 1538, + kX86InstIdInsertq_NameIndex = 1547, + kX86InstIdInt_NameIndex = 1555, + kX86InstIdJa_NameIndex = 1559, + kX86InstIdJae_NameIndex = 1562, + kX86InstIdJb_NameIndex = 1566, + kX86InstIdJbe_NameIndex = 1569, + kX86InstIdJc_NameIndex = 1573, + kX86InstIdJe_NameIndex = 1576, + kX86InstIdJg_NameIndex = 1579, + kX86InstIdJge_NameIndex = 1582, + kX86InstIdJl_NameIndex = 1586, + kX86InstIdJle_NameIndex = 1589, + kX86InstIdJna_NameIndex = 1593, + kX86InstIdJnae_NameIndex = 1597, + kX86InstIdJnb_NameIndex = 1602, + kX86InstIdJnbe_NameIndex = 1606, + kX86InstIdJnc_NameIndex = 1611, + kX86InstIdJne_NameIndex = 1615, + kX86InstIdJng_NameIndex = 1619, + kX86InstIdJnge_NameIndex = 1623, + kX86InstIdJnl_NameIndex = 1628, + kX86InstIdJnle_NameIndex = 1632, + kX86InstIdJno_NameIndex = 1637, + kX86InstIdJnp_NameIndex = 1641, + kX86InstIdJns_NameIndex = 1645, + kX86InstIdJnz_NameIndex = 1649, + kX86InstIdJo_NameIndex = 1653, + kX86InstIdJp_NameIndex = 1656, + kX86InstIdJpe_NameIndex = 1659, + kX86InstIdJpo_NameIndex = 1663, + kX86InstIdJs_NameIndex = 1667, + kX86InstIdJz_NameIndex = 1670, + kX86InstIdJecxz_NameIndex = 1673, + kX86InstIdJmp_NameIndex = 1679, + kX86InstIdLahf_NameIndex = 1683, + kX86InstIdLddqu_NameIndex = 1688, + kX86InstIdLdmxcsr_NameIndex = 1694, + kX86InstIdLea_NameIndex = 1702, + kX86InstIdLeave_NameIndex = 1706, + kX86InstIdLfence_NameIndex = 1712, + kX86InstIdLodsB_NameIndex = 1719, + kX86InstIdLodsD_NameIndex = 1726, + kX86InstIdLodsQ_NameIndex = 1733, + kX86InstIdLodsW_NameIndex = 1740, + kX86InstIdLzcnt_NameIndex = 1747, + kX86InstIdMaskmovdqu_NameIndex = 1753, + kX86InstIdMaskmovq_NameIndex = 1764, + kX86InstIdMaxpd_NameIndex = 1773, + kX86InstIdMaxps_NameIndex = 1779, + kX86InstIdMaxsd_NameIndex = 1785, + kX86InstIdMaxss_NameIndex = 1791, + kX86InstIdMfence_NameIndex = 1797, + kX86InstIdMinpd_NameIndex = 1804, + kX86InstIdMinps_NameIndex = 1810, + kX86InstIdMinsd_NameIndex = 1816, + kX86InstIdMinss_NameIndex = 1822, + kX86InstIdMonitor_NameIndex = 1828, + kX86InstIdMov_NameIndex = 1836, + kX86InstIdMovPtr_NameIndex = 1840, + kX86InstIdMovapd_NameIndex = 1848, + kX86InstIdMovaps_NameIndex = 1855, + kX86InstIdMovbe_NameIndex = 1862, + kX86InstIdMovd_NameIndex = 1868, + kX86InstIdMovddup_NameIndex = 1873, + kX86InstIdMovdq2q_NameIndex = 1881, + kX86InstIdMovdqa_NameIndex = 1889, + kX86InstIdMovdqu_NameIndex = 1896, + kX86InstIdMovhlps_NameIndex = 1903, + kX86InstIdMovhpd_NameIndex = 1911, + kX86InstIdMovhps_NameIndex = 1918, + kX86InstIdMovlhps_NameIndex = 1925, + kX86InstIdMovlpd_NameIndex = 1933, + kX86InstIdMovlps_NameIndex = 1940, + kX86InstIdMovmskpd_NameIndex = 1947, + kX86InstIdMovmskps_NameIndex = 1956, + kX86InstIdMovntdq_NameIndex = 1965, + kX86InstIdMovntdqa_NameIndex = 1973, + kX86InstIdMovnti_NameIndex = 1982, + kX86InstIdMovntpd_NameIndex = 1989, + kX86InstIdMovntps_NameIndex = 1997, + kX86InstIdMovntq_NameIndex = 2005, + kX86InstIdMovntsd_NameIndex = 2012, + kX86InstIdMovntss_NameIndex = 2020, + kX86InstIdMovq_NameIndex = 2028, + kX86InstIdMovq2dq_NameIndex = 2033, + kX86InstIdMovsB_NameIndex = 2041, + kX86InstIdMovsD_NameIndex = 2048, + kX86InstIdMovsQ_NameIndex = 2055, + kX86InstIdMovsW_NameIndex = 2062, + kX86InstIdMovsd_NameIndex = 2069, + kX86InstIdMovshdup_NameIndex = 2075, + kX86InstIdMovsldup_NameIndex = 2084, + kX86InstIdMovss_NameIndex = 2093, + kX86InstIdMovsx_NameIndex = 2099, + kX86InstIdMovsxd_NameIndex = 2105, + kX86InstIdMovupd_NameIndex = 2112, + kX86InstIdMovups_NameIndex = 2119, + kX86InstIdMovzx_NameIndex = 2126, + kX86InstIdMpsadbw_NameIndex = 2132, + kX86InstIdMul_NameIndex = 2140, + kX86InstIdMulpd_NameIndex = 2144, + kX86InstIdMulps_NameIndex = 2150, + kX86InstIdMulsd_NameIndex = 2156, + kX86InstIdMulss_NameIndex = 2162, + kX86InstIdMulx_NameIndex = 2168, + kX86InstIdMwait_NameIndex = 2173, + kX86InstIdNeg_NameIndex = 2179, + kX86InstIdNop_NameIndex = 2183, + kX86InstIdNot_NameIndex = 2187, + kX86InstIdOr_NameIndex = 2191, + kX86InstIdOrpd_NameIndex = 2194, + kX86InstIdOrps_NameIndex = 2199, + kX86InstIdPabsb_NameIndex = 2204, + kX86InstIdPabsd_NameIndex = 2210, + kX86InstIdPabsw_NameIndex = 2216, + kX86InstIdPackssdw_NameIndex = 2222, + kX86InstIdPacksswb_NameIndex = 2231, + kX86InstIdPackusdw_NameIndex = 2240, + kX86InstIdPackuswb_NameIndex = 2249, + kX86InstIdPaddb_NameIndex = 2258, + kX86InstIdPaddd_NameIndex = 2264, + kX86InstIdPaddq_NameIndex = 2270, + kX86InstIdPaddsb_NameIndex = 2276, + kX86InstIdPaddsw_NameIndex = 2283, + kX86InstIdPaddusb_NameIndex = 2290, + kX86InstIdPaddusw_NameIndex = 2298, + kX86InstIdPaddw_NameIndex = 2306, + kX86InstIdPalignr_NameIndex = 2312, + kX86InstIdPand_NameIndex = 2320, + kX86InstIdPandn_NameIndex = 2325, + kX86InstIdPause_NameIndex = 2331, + kX86InstIdPavgb_NameIndex = 2337, + kX86InstIdPavgw_NameIndex = 2343, + kX86InstIdPblendvb_NameIndex = 2349, + kX86InstIdPblendw_NameIndex = 2358, + kX86InstIdPclmulqdq_NameIndex = 2366, + kX86InstIdPcmpeqb_NameIndex = 2376, + kX86InstIdPcmpeqd_NameIndex = 2384, + kX86InstIdPcmpeqq_NameIndex = 2392, + kX86InstIdPcmpeqw_NameIndex = 2400, + kX86InstIdPcmpestri_NameIndex = 2408, + kX86InstIdPcmpestrm_NameIndex = 2418, + kX86InstIdPcmpgtb_NameIndex = 2428, + kX86InstIdPcmpgtd_NameIndex = 2436, + kX86InstIdPcmpgtq_NameIndex = 2444, + kX86InstIdPcmpgtw_NameIndex = 2452, + kX86InstIdPcmpistri_NameIndex = 2460, + kX86InstIdPcmpistrm_NameIndex = 2470, + kX86InstIdPdep_NameIndex = 2480, + kX86InstIdPext_NameIndex = 2485, + kX86InstIdPextrb_NameIndex = 2490, + kX86InstIdPextrd_NameIndex = 2497, + kX86InstIdPextrq_NameIndex = 2504, + kX86InstIdPextrw_NameIndex = 2511, + kX86InstIdPf2id_NameIndex = 2518, + kX86InstIdPf2iw_NameIndex = 2524, + kX86InstIdPfacc_NameIndex = 2530, + kX86InstIdPfadd_NameIndex = 2536, + kX86InstIdPfcmpeq_NameIndex = 2542, + kX86InstIdPfcmpge_NameIndex = 2550, + kX86InstIdPfcmpgt_NameIndex = 2558, + kX86InstIdPfmax_NameIndex = 2566, + kX86InstIdPfmin_NameIndex = 2572, + kX86InstIdPfmul_NameIndex = 2578, + kX86InstIdPfnacc_NameIndex = 2584, + kX86InstIdPfpnacc_NameIndex = 2591, + kX86InstIdPfrcp_NameIndex = 2599, + kX86InstIdPfrcpit1_NameIndex = 2605, + kX86InstIdPfrcpit2_NameIndex = 2614, + kX86InstIdPfrsqit1_NameIndex = 2623, + kX86InstIdPfrsqrt_NameIndex = 2632, + kX86InstIdPfsub_NameIndex = 2640, + kX86InstIdPfsubr_NameIndex = 2646, + kX86InstIdPhaddd_NameIndex = 2653, + kX86InstIdPhaddsw_NameIndex = 2660, + kX86InstIdPhaddw_NameIndex = 2668, + kX86InstIdPhminposuw_NameIndex = 2675, + kX86InstIdPhsubd_NameIndex = 2686, + kX86InstIdPhsubsw_NameIndex = 2693, + kX86InstIdPhsubw_NameIndex = 2701, + kX86InstIdPi2fd_NameIndex = 2708, + kX86InstIdPi2fw_NameIndex = 2714, + kX86InstIdPinsrb_NameIndex = 2720, + kX86InstIdPinsrd_NameIndex = 2727, + kX86InstIdPinsrq_NameIndex = 2734, + kX86InstIdPinsrw_NameIndex = 2741, + kX86InstIdPmaddubsw_NameIndex = 2748, + kX86InstIdPmaddwd_NameIndex = 2758, + kX86InstIdPmaxsb_NameIndex = 2766, + kX86InstIdPmaxsd_NameIndex = 2773, + kX86InstIdPmaxsw_NameIndex = 2780, + kX86InstIdPmaxub_NameIndex = 2787, + kX86InstIdPmaxud_NameIndex = 2794, + kX86InstIdPmaxuw_NameIndex = 2801, + kX86InstIdPminsb_NameIndex = 2808, + kX86InstIdPminsd_NameIndex = 2815, + kX86InstIdPminsw_NameIndex = 2822, + kX86InstIdPminub_NameIndex = 2829, + kX86InstIdPminud_NameIndex = 2836, + kX86InstIdPminuw_NameIndex = 2843, + kX86InstIdPmovmskb_NameIndex = 2850, + kX86InstIdPmovsxbd_NameIndex = 2859, + kX86InstIdPmovsxbq_NameIndex = 2868, + kX86InstIdPmovsxbw_NameIndex = 2877, + kX86InstIdPmovsxdq_NameIndex = 2886, + kX86InstIdPmovsxwd_NameIndex = 2895, + kX86InstIdPmovsxwq_NameIndex = 2904, + kX86InstIdPmovzxbd_NameIndex = 2913, + kX86InstIdPmovzxbq_NameIndex = 2922, + kX86InstIdPmovzxbw_NameIndex = 2931, + kX86InstIdPmovzxdq_NameIndex = 2940, + kX86InstIdPmovzxwd_NameIndex = 2949, + kX86InstIdPmovzxwq_NameIndex = 2958, + kX86InstIdPmuldq_NameIndex = 2967, + kX86InstIdPmulhrsw_NameIndex = 2974, + kX86InstIdPmulhuw_NameIndex = 2983, + kX86InstIdPmulhw_NameIndex = 2991, + kX86InstIdPmulld_NameIndex = 2998, + kX86InstIdPmullw_NameIndex = 3005, + kX86InstIdPmuludq_NameIndex = 3012, + kX86InstIdPop_NameIndex = 3020, + kX86InstIdPopa_NameIndex = 3024, + kX86InstIdPopcnt_NameIndex = 3029, + kX86InstIdPopf_NameIndex = 3036, + kX86InstIdPor_NameIndex = 3041, + kX86InstIdPrefetch_NameIndex = 3045, + kX86InstIdPrefetch3dNow_NameIndex = 3054, + kX86InstIdPrefetchw3dNow_NameIndex = 3069, + kX86InstIdPsadbw_NameIndex = 3085, + kX86InstIdPshufb_NameIndex = 3092, + kX86InstIdPshufd_NameIndex = 3099, + kX86InstIdPshufhw_NameIndex = 3106, + kX86InstIdPshuflw_NameIndex = 3114, + kX86InstIdPshufw_NameIndex = 3122, + kX86InstIdPsignb_NameIndex = 3129, + kX86InstIdPsignd_NameIndex = 3136, + kX86InstIdPsignw_NameIndex = 3143, + kX86InstIdPslld_NameIndex = 3150, + kX86InstIdPslldq_NameIndex = 3156, + kX86InstIdPsllq_NameIndex = 3163, + kX86InstIdPsllw_NameIndex = 3169, + kX86InstIdPsrad_NameIndex = 3175, + kX86InstIdPsraw_NameIndex = 3181, + kX86InstIdPsrld_NameIndex = 3187, + kX86InstIdPsrldq_NameIndex = 3193, + kX86InstIdPsrlq_NameIndex = 3200, + kX86InstIdPsrlw_NameIndex = 3206, + kX86InstIdPsubb_NameIndex = 3212, + kX86InstIdPsubd_NameIndex = 3218, + kX86InstIdPsubq_NameIndex = 3224, + kX86InstIdPsubsb_NameIndex = 3230, + kX86InstIdPsubsw_NameIndex = 3237, + kX86InstIdPsubusb_NameIndex = 3244, + kX86InstIdPsubusw_NameIndex = 3252, + kX86InstIdPsubw_NameIndex = 3260, + kX86InstIdPswapd_NameIndex = 3266, + kX86InstIdPtest_NameIndex = 3273, + kX86InstIdPunpckhbw_NameIndex = 3279, + kX86InstIdPunpckhdq_NameIndex = 3289, + kX86InstIdPunpckhqdq_NameIndex = 3299, + kX86InstIdPunpckhwd_NameIndex = 3310, + kX86InstIdPunpcklbw_NameIndex = 3320, + kX86InstIdPunpckldq_NameIndex = 3330, + kX86InstIdPunpcklqdq_NameIndex = 3340, + kX86InstIdPunpcklwd_NameIndex = 3351, + kX86InstIdPush_NameIndex = 3361, + kX86InstIdPusha_NameIndex = 3366, + kX86InstIdPushf_NameIndex = 3372, + kX86InstIdPxor_NameIndex = 3378, + kX86InstIdRcl_NameIndex = 3383, + kX86InstIdRcpps_NameIndex = 3387, + kX86InstIdRcpss_NameIndex = 3393, + kX86InstIdRcr_NameIndex = 3399, + kX86InstIdRdfsbase_NameIndex = 3403, + kX86InstIdRdgsbase_NameIndex = 3412, + kX86InstIdRdrand_NameIndex = 3421, + kX86InstIdRdtsc_NameIndex = 3428, + kX86InstIdRdtscp_NameIndex = 3434, + kX86InstIdRepLodsB_NameIndex = 3441, + kX86InstIdRepLodsD_NameIndex = 3452, + kX86InstIdRepLodsQ_NameIndex = 3463, + kX86InstIdRepLodsW_NameIndex = 3474, + kX86InstIdRepMovsB_NameIndex = 3485, + kX86InstIdRepMovsD_NameIndex = 3496, + kX86InstIdRepMovsQ_NameIndex = 3507, + kX86InstIdRepMovsW_NameIndex = 3518, + kX86InstIdRepStosB_NameIndex = 3529, + kX86InstIdRepStosD_NameIndex = 3540, + kX86InstIdRepStosQ_NameIndex = 3551, + kX86InstIdRepStosW_NameIndex = 3562, + kX86InstIdRepeCmpsB_NameIndex = 3573, + kX86InstIdRepeCmpsD_NameIndex = 3585, + kX86InstIdRepeCmpsQ_NameIndex = 3597, + kX86InstIdRepeCmpsW_NameIndex = 3609, + kX86InstIdRepeScasB_NameIndex = 3621, + kX86InstIdRepeScasD_NameIndex = 3633, + kX86InstIdRepeScasQ_NameIndex = 3645, + kX86InstIdRepeScasW_NameIndex = 3657, + kX86InstIdRepneCmpsB_NameIndex = 3669, + kX86InstIdRepneCmpsD_NameIndex = 3682, + kX86InstIdRepneCmpsQ_NameIndex = 3695, + kX86InstIdRepneCmpsW_NameIndex = 3708, + kX86InstIdRepneScasB_NameIndex = 3721, + kX86InstIdRepneScasD_NameIndex = 3734, + kX86InstIdRepneScasQ_NameIndex = 3747, + kX86InstIdRepneScasW_NameIndex = 3760, + kX86InstIdRet_NameIndex = 3773, + kX86InstIdRol_NameIndex = 3777, + kX86InstIdRor_NameIndex = 3781, + kX86InstIdRorx_NameIndex = 3785, + kX86InstIdRoundpd_NameIndex = 3790, + kX86InstIdRoundps_NameIndex = 3798, + kX86InstIdRoundsd_NameIndex = 3806, + kX86InstIdRoundss_NameIndex = 3814, + kX86InstIdRsqrtps_NameIndex = 3822, + kX86InstIdRsqrtss_NameIndex = 3830, + kX86InstIdSahf_NameIndex = 3838, + kX86InstIdSal_NameIndex = 3843, + kX86InstIdSar_NameIndex = 3847, + kX86InstIdSarx_NameIndex = 3851, + kX86InstIdSbb_NameIndex = 3856, + kX86InstIdScasB_NameIndex = 3860, + kX86InstIdScasD_NameIndex = 3867, + kX86InstIdScasQ_NameIndex = 3874, + kX86InstIdScasW_NameIndex = 3881, + kX86InstIdSeta_NameIndex = 3888, + kX86InstIdSetae_NameIndex = 3893, + kX86InstIdSetb_NameIndex = 3899, + kX86InstIdSetbe_NameIndex = 3904, + kX86InstIdSetc_NameIndex = 3910, + kX86InstIdSete_NameIndex = 3915, + kX86InstIdSetg_NameIndex = 3920, + kX86InstIdSetge_NameIndex = 3925, + kX86InstIdSetl_NameIndex = 3931, + kX86InstIdSetle_NameIndex = 3936, + kX86InstIdSetna_NameIndex = 3942, + kX86InstIdSetnae_NameIndex = 3948, + kX86InstIdSetnb_NameIndex = 3955, + kX86InstIdSetnbe_NameIndex = 3961, + kX86InstIdSetnc_NameIndex = 3968, + kX86InstIdSetne_NameIndex = 3974, + kX86InstIdSetng_NameIndex = 3980, + kX86InstIdSetnge_NameIndex = 3986, + kX86InstIdSetnl_NameIndex = 3993, + kX86InstIdSetnle_NameIndex = 3999, + kX86InstIdSetno_NameIndex = 4006, + kX86InstIdSetnp_NameIndex = 4012, + kX86InstIdSetns_NameIndex = 4018, + kX86InstIdSetnz_NameIndex = 4024, + kX86InstIdSeto_NameIndex = 4030, + kX86InstIdSetp_NameIndex = 4035, + kX86InstIdSetpe_NameIndex = 4040, + kX86InstIdSetpo_NameIndex = 4046, + kX86InstIdSets_NameIndex = 4052, + kX86InstIdSetz_NameIndex = 4057, + kX86InstIdSfence_NameIndex = 4062, + kX86InstIdShl_NameIndex = 4069, + kX86InstIdShld_NameIndex = 4073, + kX86InstIdShlx_NameIndex = 4078, + kX86InstIdShr_NameIndex = 4083, + kX86InstIdShrd_NameIndex = 4087, + kX86InstIdShrx_NameIndex = 4092, + kX86InstIdShufpd_NameIndex = 4097, + kX86InstIdShufps_NameIndex = 4104, + kX86InstIdSqrtpd_NameIndex = 4111, + kX86InstIdSqrtps_NameIndex = 4118, + kX86InstIdSqrtsd_NameIndex = 4125, + kX86InstIdSqrtss_NameIndex = 4132, + kX86InstIdStc_NameIndex = 4139, + kX86InstIdStd_NameIndex = 4143, + kX86InstIdStmxcsr_NameIndex = 4147, + kX86InstIdStosB_NameIndex = 4155, + kX86InstIdStosD_NameIndex = 4162, + kX86InstIdStosQ_NameIndex = 4169, + kX86InstIdStosW_NameIndex = 4176, + kX86InstIdSub_NameIndex = 4183, + kX86InstIdSubpd_NameIndex = 4187, + kX86InstIdSubps_NameIndex = 4193, + kX86InstIdSubsd_NameIndex = 4199, + kX86InstIdSubss_NameIndex = 4205, + kX86InstIdTest_NameIndex = 4211, + kX86InstIdTzcnt_NameIndex = 4216, + kX86InstIdUcomisd_NameIndex = 4222, + kX86InstIdUcomiss_NameIndex = 4230, + kX86InstIdUd2_NameIndex = 4238, + kX86InstIdUnpckhpd_NameIndex = 4242, + kX86InstIdUnpckhps_NameIndex = 4251, + kX86InstIdUnpcklpd_NameIndex = 4260, + kX86InstIdUnpcklps_NameIndex = 4269, + kX86InstIdVaddpd_NameIndex = 4278, + kX86InstIdVaddps_NameIndex = 4285, + kX86InstIdVaddsd_NameIndex = 4292, + kX86InstIdVaddss_NameIndex = 4299, + kX86InstIdVaddsubpd_NameIndex = 4306, + kX86InstIdVaddsubps_NameIndex = 4316, + kX86InstIdVaesdec_NameIndex = 4326, + kX86InstIdVaesdeclast_NameIndex = 4334, + kX86InstIdVaesenc_NameIndex = 4346, + kX86InstIdVaesenclast_NameIndex = 4354, + kX86InstIdVaesimc_NameIndex = 4366, + kX86InstIdVaeskeygenassist_NameIndex = 4374, + kX86InstIdVandnpd_NameIndex = 4391, + kX86InstIdVandnps_NameIndex = 4399, + kX86InstIdVandpd_NameIndex = 4407, + kX86InstIdVandps_NameIndex = 4414, + kX86InstIdVblendpd_NameIndex = 4421, + kX86InstIdVblendps_NameIndex = 4430, + kX86InstIdVblendvpd_NameIndex = 4439, + kX86InstIdVblendvps_NameIndex = 4449, + kX86InstIdVbroadcastf128_NameIndex = 4459, + kX86InstIdVbroadcasti128_NameIndex = 4474, + kX86InstIdVbroadcastsd_NameIndex = 4489, + kX86InstIdVbroadcastss_NameIndex = 4502, + kX86InstIdVcmppd_NameIndex = 4515, + kX86InstIdVcmpps_NameIndex = 4522, + kX86InstIdVcmpsd_NameIndex = 4529, + kX86InstIdVcmpss_NameIndex = 4536, + kX86InstIdVcomisd_NameIndex = 4543, + kX86InstIdVcomiss_NameIndex = 4551, + kX86InstIdVcvtdq2pd_NameIndex = 4559, + kX86InstIdVcvtdq2ps_NameIndex = 4569, + kX86InstIdVcvtpd2dq_NameIndex = 4579, + kX86InstIdVcvtpd2ps_NameIndex = 4589, + kX86InstIdVcvtph2ps_NameIndex = 4599, + kX86InstIdVcvtps2dq_NameIndex = 4609, + kX86InstIdVcvtps2pd_NameIndex = 4619, + kX86InstIdVcvtps2ph_NameIndex = 4629, + kX86InstIdVcvtsd2si_NameIndex = 4639, + kX86InstIdVcvtsd2ss_NameIndex = 4649, + kX86InstIdVcvtsi2sd_NameIndex = 4659, + kX86InstIdVcvtsi2ss_NameIndex = 4669, + kX86InstIdVcvtss2sd_NameIndex = 4679, + kX86InstIdVcvtss2si_NameIndex = 4689, + kX86InstIdVcvttpd2dq_NameIndex = 4699, + kX86InstIdVcvttps2dq_NameIndex = 4710, + kX86InstIdVcvttsd2si_NameIndex = 4721, + kX86InstIdVcvttss2si_NameIndex = 4732, + kX86InstIdVdivpd_NameIndex = 4743, + kX86InstIdVdivps_NameIndex = 4750, + kX86InstIdVdivsd_NameIndex = 4757, + kX86InstIdVdivss_NameIndex = 4764, + kX86InstIdVdppd_NameIndex = 4771, + kX86InstIdVdpps_NameIndex = 4777, + kX86InstIdVextractf128_NameIndex = 4783, + kX86InstIdVextracti128_NameIndex = 4796, + kX86InstIdVextractps_NameIndex = 4809, + kX86InstIdVfmadd132pd_NameIndex = 4820, + kX86InstIdVfmadd132ps_NameIndex = 4832, + kX86InstIdVfmadd132sd_NameIndex = 4844, + kX86InstIdVfmadd132ss_NameIndex = 4856, + kX86InstIdVfmadd213pd_NameIndex = 4868, + kX86InstIdVfmadd213ps_NameIndex = 4880, + kX86InstIdVfmadd213sd_NameIndex = 4892, + kX86InstIdVfmadd213ss_NameIndex = 4904, + kX86InstIdVfmadd231pd_NameIndex = 4916, + kX86InstIdVfmadd231ps_NameIndex = 4928, + kX86InstIdVfmadd231sd_NameIndex = 4940, + kX86InstIdVfmadd231ss_NameIndex = 4952, + kX86InstIdVfmaddpd_NameIndex = 4964, + kX86InstIdVfmaddps_NameIndex = 4973, + kX86InstIdVfmaddsd_NameIndex = 4982, + kX86InstIdVfmaddss_NameIndex = 4991, + kX86InstIdVfmaddsub132pd_NameIndex = 5000, + kX86InstIdVfmaddsub132ps_NameIndex = 5015, + kX86InstIdVfmaddsub213pd_NameIndex = 5030, + kX86InstIdVfmaddsub213ps_NameIndex = 5045, + kX86InstIdVfmaddsub231pd_NameIndex = 5060, + kX86InstIdVfmaddsub231ps_NameIndex = 5075, + kX86InstIdVfmaddsubpd_NameIndex = 5090, + kX86InstIdVfmaddsubps_NameIndex = 5102, + kX86InstIdVfmsub132pd_NameIndex = 5114, + kX86InstIdVfmsub132ps_NameIndex = 5126, + kX86InstIdVfmsub132sd_NameIndex = 5138, + kX86InstIdVfmsub132ss_NameIndex = 5150, + kX86InstIdVfmsub213pd_NameIndex = 5162, + kX86InstIdVfmsub213ps_NameIndex = 5174, + kX86InstIdVfmsub213sd_NameIndex = 5186, + kX86InstIdVfmsub213ss_NameIndex = 5198, + kX86InstIdVfmsub231pd_NameIndex = 5210, + kX86InstIdVfmsub231ps_NameIndex = 5222, + kX86InstIdVfmsub231sd_NameIndex = 5234, + kX86InstIdVfmsub231ss_NameIndex = 5246, + kX86InstIdVfmsubadd132pd_NameIndex = 5258, + kX86InstIdVfmsubadd132ps_NameIndex = 5273, + kX86InstIdVfmsubadd213pd_NameIndex = 5288, + kX86InstIdVfmsubadd213ps_NameIndex = 5303, + kX86InstIdVfmsubadd231pd_NameIndex = 5318, + kX86InstIdVfmsubadd231ps_NameIndex = 5333, + kX86InstIdVfmsubaddpd_NameIndex = 5348, + kX86InstIdVfmsubaddps_NameIndex = 5360, + kX86InstIdVfmsubpd_NameIndex = 5372, + kX86InstIdVfmsubps_NameIndex = 5381, + kX86InstIdVfmsubsd_NameIndex = 5390, + kX86InstIdVfmsubss_NameIndex = 5399, + kX86InstIdVfnmadd132pd_NameIndex = 5408, + kX86InstIdVfnmadd132ps_NameIndex = 5421, + kX86InstIdVfnmadd132sd_NameIndex = 5434, + kX86InstIdVfnmadd132ss_NameIndex = 5447, + kX86InstIdVfnmadd213pd_NameIndex = 5460, + kX86InstIdVfnmadd213ps_NameIndex = 5473, + kX86InstIdVfnmadd213sd_NameIndex = 5486, + kX86InstIdVfnmadd213ss_NameIndex = 5499, + kX86InstIdVfnmadd231pd_NameIndex = 5512, + kX86InstIdVfnmadd231ps_NameIndex = 5525, + kX86InstIdVfnmadd231sd_NameIndex = 5538, + kX86InstIdVfnmadd231ss_NameIndex = 5551, + kX86InstIdVfnmaddpd_NameIndex = 5564, + kX86InstIdVfnmaddps_NameIndex = 5574, + kX86InstIdVfnmaddsd_NameIndex = 5584, + kX86InstIdVfnmaddss_NameIndex = 5594, + kX86InstIdVfnmsub132pd_NameIndex = 5604, + kX86InstIdVfnmsub132ps_NameIndex = 5617, + kX86InstIdVfnmsub132sd_NameIndex = 5630, + kX86InstIdVfnmsub132ss_NameIndex = 5643, + kX86InstIdVfnmsub213pd_NameIndex = 5656, + kX86InstIdVfnmsub213ps_NameIndex = 5669, + kX86InstIdVfnmsub213sd_NameIndex = 5682, + kX86InstIdVfnmsub213ss_NameIndex = 5695, + kX86InstIdVfnmsub231pd_NameIndex = 5708, + kX86InstIdVfnmsub231ps_NameIndex = 5721, + kX86InstIdVfnmsub231sd_NameIndex = 5734, + kX86InstIdVfnmsub231ss_NameIndex = 5747, + kX86InstIdVfnmsubpd_NameIndex = 5760, + kX86InstIdVfnmsubps_NameIndex = 5770, + kX86InstIdVfnmsubsd_NameIndex = 5780, + kX86InstIdVfnmsubss_NameIndex = 5790, + kX86InstIdVfrczpd_NameIndex = 5800, + kX86InstIdVfrczps_NameIndex = 5808, + kX86InstIdVfrczsd_NameIndex = 5816, + kX86InstIdVfrczss_NameIndex = 5824, + kX86InstIdVgatherdpd_NameIndex = 5832, + kX86InstIdVgatherdps_NameIndex = 5843, + kX86InstIdVgatherqpd_NameIndex = 5854, + kX86InstIdVgatherqps_NameIndex = 5865, + kX86InstIdVhaddpd_NameIndex = 5876, + kX86InstIdVhaddps_NameIndex = 5884, + kX86InstIdVhsubpd_NameIndex = 5892, + kX86InstIdVhsubps_NameIndex = 5900, + kX86InstIdVinsertf128_NameIndex = 5908, + kX86InstIdVinserti128_NameIndex = 5920, + kX86InstIdVinsertps_NameIndex = 5932, + kX86InstIdVlddqu_NameIndex = 5942, + kX86InstIdVldmxcsr_NameIndex = 5949, + kX86InstIdVmaskmovdqu_NameIndex = 5958, + kX86InstIdVmaskmovpd_NameIndex = 5970, + kX86InstIdVmaskmovps_NameIndex = 5981, + kX86InstIdVmaxpd_NameIndex = 5992, + kX86InstIdVmaxps_NameIndex = 5999, + kX86InstIdVmaxsd_NameIndex = 6006, + kX86InstIdVmaxss_NameIndex = 6013, + kX86InstIdVminpd_NameIndex = 6020, + kX86InstIdVminps_NameIndex = 6027, + kX86InstIdVminsd_NameIndex = 6034, + kX86InstIdVminss_NameIndex = 6041, + kX86InstIdVmovapd_NameIndex = 6048, + kX86InstIdVmovaps_NameIndex = 6056, + kX86InstIdVmovd_NameIndex = 6064, + kX86InstIdVmovddup_NameIndex = 6070, + kX86InstIdVmovdqa_NameIndex = 6079, + kX86InstIdVmovdqu_NameIndex = 6087, + kX86InstIdVmovhlps_NameIndex = 6095, + kX86InstIdVmovhpd_NameIndex = 6104, + kX86InstIdVmovhps_NameIndex = 6112, + kX86InstIdVmovlhps_NameIndex = 6120, + kX86InstIdVmovlpd_NameIndex = 6129, + kX86InstIdVmovlps_NameIndex = 6137, + kX86InstIdVmovmskpd_NameIndex = 6145, + kX86InstIdVmovmskps_NameIndex = 6155, + kX86InstIdVmovntdq_NameIndex = 6165, + kX86InstIdVmovntdqa_NameIndex = 6174, + kX86InstIdVmovntpd_NameIndex = 6184, + kX86InstIdVmovntps_NameIndex = 6193, + kX86InstIdVmovq_NameIndex = 6202, + kX86InstIdVmovsd_NameIndex = 6208, + kX86InstIdVmovshdup_NameIndex = 6215, + kX86InstIdVmovsldup_NameIndex = 6225, + kX86InstIdVmovss_NameIndex = 6235, + kX86InstIdVmovupd_NameIndex = 6242, + kX86InstIdVmovups_NameIndex = 6250, + kX86InstIdVmpsadbw_NameIndex = 6258, + kX86InstIdVmulpd_NameIndex = 6267, + kX86InstIdVmulps_NameIndex = 6274, + kX86InstIdVmulsd_NameIndex = 6281, + kX86InstIdVmulss_NameIndex = 6288, + kX86InstIdVorpd_NameIndex = 6295, + kX86InstIdVorps_NameIndex = 6301, + kX86InstIdVpabsb_NameIndex = 6307, + kX86InstIdVpabsd_NameIndex = 6314, + kX86InstIdVpabsw_NameIndex = 6321, + kX86InstIdVpackssdw_NameIndex = 6328, + kX86InstIdVpacksswb_NameIndex = 6338, + kX86InstIdVpackusdw_NameIndex = 6348, + kX86InstIdVpackuswb_NameIndex = 6358, + kX86InstIdVpaddb_NameIndex = 6368, + kX86InstIdVpaddd_NameIndex = 6375, + kX86InstIdVpaddq_NameIndex = 6382, + kX86InstIdVpaddsb_NameIndex = 6389, + kX86InstIdVpaddsw_NameIndex = 6397, + kX86InstIdVpaddusb_NameIndex = 6405, + kX86InstIdVpaddusw_NameIndex = 6414, + kX86InstIdVpaddw_NameIndex = 6423, + kX86InstIdVpalignr_NameIndex = 6430, + kX86InstIdVpand_NameIndex = 6439, + kX86InstIdVpandn_NameIndex = 6445, + kX86InstIdVpavgb_NameIndex = 6452, + kX86InstIdVpavgw_NameIndex = 6459, + kX86InstIdVpblendd_NameIndex = 6466, + kX86InstIdVpblendvb_NameIndex = 6475, + kX86InstIdVpblendw_NameIndex = 6485, + kX86InstIdVpbroadcastb_NameIndex = 6494, + kX86InstIdVpbroadcastd_NameIndex = 6507, + kX86InstIdVpbroadcastq_NameIndex = 6520, + kX86InstIdVpbroadcastw_NameIndex = 6533, + kX86InstIdVpclmulqdq_NameIndex = 6546, + kX86InstIdVpcmov_NameIndex = 6557, + kX86InstIdVpcmpeqb_NameIndex = 6564, + kX86InstIdVpcmpeqd_NameIndex = 6573, + kX86InstIdVpcmpeqq_NameIndex = 6582, + kX86InstIdVpcmpeqw_NameIndex = 6591, + kX86InstIdVpcmpestri_NameIndex = 6600, + kX86InstIdVpcmpestrm_NameIndex = 6611, + kX86InstIdVpcmpgtb_NameIndex = 6622, + kX86InstIdVpcmpgtd_NameIndex = 6631, + kX86InstIdVpcmpgtq_NameIndex = 6640, + kX86InstIdVpcmpgtw_NameIndex = 6649, + kX86InstIdVpcmpistri_NameIndex = 6658, + kX86InstIdVpcmpistrm_NameIndex = 6669, + kX86InstIdVpcomb_NameIndex = 6680, + kX86InstIdVpcomd_NameIndex = 6687, + kX86InstIdVpcomq_NameIndex = 6694, + kX86InstIdVpcomub_NameIndex = 6701, + kX86InstIdVpcomud_NameIndex = 6709, + kX86InstIdVpcomuq_NameIndex = 6717, + kX86InstIdVpcomuw_NameIndex = 6725, + kX86InstIdVpcomw_NameIndex = 6733, + kX86InstIdVperm2f128_NameIndex = 6740, + kX86InstIdVperm2i128_NameIndex = 6751, + kX86InstIdVpermd_NameIndex = 6762, + kX86InstIdVpermil2pd_NameIndex = 6769, + kX86InstIdVpermil2ps_NameIndex = 6780, + kX86InstIdVpermilpd_NameIndex = 6791, + kX86InstIdVpermilps_NameIndex = 6801, + kX86InstIdVpermpd_NameIndex = 6811, + kX86InstIdVpermps_NameIndex = 6819, + kX86InstIdVpermq_NameIndex = 6827, + kX86InstIdVpextrb_NameIndex = 6834, + kX86InstIdVpextrd_NameIndex = 6842, + kX86InstIdVpextrq_NameIndex = 6850, + kX86InstIdVpextrw_NameIndex = 6858, + kX86InstIdVpgatherdd_NameIndex = 6866, + kX86InstIdVpgatherdq_NameIndex = 6877, + kX86InstIdVpgatherqd_NameIndex = 6888, + kX86InstIdVpgatherqq_NameIndex = 6899, + kX86InstIdVphaddbd_NameIndex = 6910, + kX86InstIdVphaddbq_NameIndex = 6919, + kX86InstIdVphaddbw_NameIndex = 6928, + kX86InstIdVphaddd_NameIndex = 6937, + kX86InstIdVphadddq_NameIndex = 6945, + kX86InstIdVphaddsw_NameIndex = 6954, + kX86InstIdVphaddubd_NameIndex = 6963, + kX86InstIdVphaddubq_NameIndex = 6973, + kX86InstIdVphaddubw_NameIndex = 6983, + kX86InstIdVphaddudq_NameIndex = 6993, + kX86InstIdVphadduwd_NameIndex = 7003, + kX86InstIdVphadduwq_NameIndex = 7013, + kX86InstIdVphaddw_NameIndex = 7023, + kX86InstIdVphaddwd_NameIndex = 7031, + kX86InstIdVphaddwq_NameIndex = 7040, + kX86InstIdVphminposuw_NameIndex = 7049, + kX86InstIdVphsubbw_NameIndex = 7061, + kX86InstIdVphsubd_NameIndex = 7070, + kX86InstIdVphsubdq_NameIndex = 7078, + kX86InstIdVphsubsw_NameIndex = 7087, + kX86InstIdVphsubw_NameIndex = 7096, + kX86InstIdVphsubwd_NameIndex = 7104, + kX86InstIdVpinsrb_NameIndex = 7113, + kX86InstIdVpinsrd_NameIndex = 7121, + kX86InstIdVpinsrq_NameIndex = 7129, + kX86InstIdVpinsrw_NameIndex = 7137, + kX86InstIdVpmacsdd_NameIndex = 7145, + kX86InstIdVpmacsdqh_NameIndex = 7154, + kX86InstIdVpmacsdql_NameIndex = 7164, + kX86InstIdVpmacssdd_NameIndex = 7174, + kX86InstIdVpmacssdqh_NameIndex = 7184, + kX86InstIdVpmacssdql_NameIndex = 7195, + kX86InstIdVpmacsswd_NameIndex = 7206, + kX86InstIdVpmacssww_NameIndex = 7216, + kX86InstIdVpmacswd_NameIndex = 7226, + kX86InstIdVpmacsww_NameIndex = 7235, + kX86InstIdVpmadcsswd_NameIndex = 7244, + kX86InstIdVpmadcswd_NameIndex = 7255, + kX86InstIdVpmaddubsw_NameIndex = 7265, + kX86InstIdVpmaddwd_NameIndex = 7276, + kX86InstIdVpmaskmovd_NameIndex = 7285, + kX86InstIdVpmaskmovq_NameIndex = 7296, + kX86InstIdVpmaxsb_NameIndex = 7307, + kX86InstIdVpmaxsd_NameIndex = 7315, + kX86InstIdVpmaxsw_NameIndex = 7323, + kX86InstIdVpmaxub_NameIndex = 7331, + kX86InstIdVpmaxud_NameIndex = 7339, + kX86InstIdVpmaxuw_NameIndex = 7347, + kX86InstIdVpminsb_NameIndex = 7355, + kX86InstIdVpminsd_NameIndex = 7363, + kX86InstIdVpminsw_NameIndex = 7371, + kX86InstIdVpminub_NameIndex = 7379, + kX86InstIdVpminud_NameIndex = 7387, + kX86InstIdVpminuw_NameIndex = 7395, + kX86InstIdVpmovmskb_NameIndex = 7403, + kX86InstIdVpmovsxbd_NameIndex = 7413, + kX86InstIdVpmovsxbq_NameIndex = 7423, + kX86InstIdVpmovsxbw_NameIndex = 7433, + kX86InstIdVpmovsxdq_NameIndex = 7443, + kX86InstIdVpmovsxwd_NameIndex = 7453, + kX86InstIdVpmovsxwq_NameIndex = 7463, + kX86InstIdVpmovzxbd_NameIndex = 7473, + kX86InstIdVpmovzxbq_NameIndex = 7483, + kX86InstIdVpmovzxbw_NameIndex = 7493, + kX86InstIdVpmovzxdq_NameIndex = 7503, + kX86InstIdVpmovzxwd_NameIndex = 7513, + kX86InstIdVpmovzxwq_NameIndex = 7523, + kX86InstIdVpmuldq_NameIndex = 7533, + kX86InstIdVpmulhrsw_NameIndex = 7541, + kX86InstIdVpmulhuw_NameIndex = 7551, + kX86InstIdVpmulhw_NameIndex = 7560, + kX86InstIdVpmulld_NameIndex = 7568, + kX86InstIdVpmullw_NameIndex = 7576, + kX86InstIdVpmuludq_NameIndex = 7584, + kX86InstIdVpor_NameIndex = 7593, + kX86InstIdVpperm_NameIndex = 7598, + kX86InstIdVprotb_NameIndex = 7605, + kX86InstIdVprotd_NameIndex = 7612, + kX86InstIdVprotq_NameIndex = 7619, + kX86InstIdVprotw_NameIndex = 7626, + kX86InstIdVpsadbw_NameIndex = 7633, + kX86InstIdVpshab_NameIndex = 7641, + kX86InstIdVpshad_NameIndex = 7648, + kX86InstIdVpshaq_NameIndex = 7655, + kX86InstIdVpshaw_NameIndex = 7662, + kX86InstIdVpshlb_NameIndex = 7669, + kX86InstIdVpshld_NameIndex = 7676, + kX86InstIdVpshlq_NameIndex = 7683, + kX86InstIdVpshlw_NameIndex = 7690, + kX86InstIdVpshufb_NameIndex = 7697, + kX86InstIdVpshufd_NameIndex = 7705, + kX86InstIdVpshufhw_NameIndex = 7713, + kX86InstIdVpshuflw_NameIndex = 7722, + kX86InstIdVpsignb_NameIndex = 7731, + kX86InstIdVpsignd_NameIndex = 7739, + kX86InstIdVpsignw_NameIndex = 7747, + kX86InstIdVpslld_NameIndex = 7755, + kX86InstIdVpslldq_NameIndex = 7762, + kX86InstIdVpsllq_NameIndex = 7770, + kX86InstIdVpsllvd_NameIndex = 7777, + kX86InstIdVpsllvq_NameIndex = 7785, + kX86InstIdVpsllw_NameIndex = 7793, + kX86InstIdVpsrad_NameIndex = 7800, + kX86InstIdVpsravd_NameIndex = 7807, + kX86InstIdVpsraw_NameIndex = 7815, + kX86InstIdVpsrld_NameIndex = 7822, + kX86InstIdVpsrldq_NameIndex = 7829, + kX86InstIdVpsrlq_NameIndex = 7837, + kX86InstIdVpsrlvd_NameIndex = 7844, + kX86InstIdVpsrlvq_NameIndex = 7852, + kX86InstIdVpsrlw_NameIndex = 7860, + kX86InstIdVpsubb_NameIndex = 7867, + kX86InstIdVpsubd_NameIndex = 7874, + kX86InstIdVpsubq_NameIndex = 7881, + kX86InstIdVpsubsb_NameIndex = 7888, + kX86InstIdVpsubsw_NameIndex = 7896, + kX86InstIdVpsubusb_NameIndex = 7904, + kX86InstIdVpsubusw_NameIndex = 7913, + kX86InstIdVpsubw_NameIndex = 7922, + kX86InstIdVptest_NameIndex = 7929, + kX86InstIdVpunpckhbw_NameIndex = 7936, + kX86InstIdVpunpckhdq_NameIndex = 7947, + kX86InstIdVpunpckhqdq_NameIndex = 7958, + kX86InstIdVpunpckhwd_NameIndex = 7970, + kX86InstIdVpunpcklbw_NameIndex = 7981, + kX86InstIdVpunpckldq_NameIndex = 7992, + kX86InstIdVpunpcklqdq_NameIndex = 8003, + kX86InstIdVpunpcklwd_NameIndex = 8015, + kX86InstIdVpxor_NameIndex = 8026, + kX86InstIdVrcpps_NameIndex = 8032, + kX86InstIdVrcpss_NameIndex = 8039, + kX86InstIdVroundpd_NameIndex = 8046, + kX86InstIdVroundps_NameIndex = 8055, + kX86InstIdVroundsd_NameIndex = 8064, + kX86InstIdVroundss_NameIndex = 8073, + kX86InstIdVrsqrtps_NameIndex = 8082, + kX86InstIdVrsqrtss_NameIndex = 8091, + kX86InstIdVshufpd_NameIndex = 8100, + kX86InstIdVshufps_NameIndex = 8108, + kX86InstIdVsqrtpd_NameIndex = 8116, + kX86InstIdVsqrtps_NameIndex = 8124, + kX86InstIdVsqrtsd_NameIndex = 8132, + kX86InstIdVsqrtss_NameIndex = 8140, + kX86InstIdVstmxcsr_NameIndex = 8148, + kX86InstIdVsubpd_NameIndex = 8157, + kX86InstIdVsubps_NameIndex = 8164, + kX86InstIdVsubsd_NameIndex = 8171, + kX86InstIdVsubss_NameIndex = 8178, + kX86InstIdVtestpd_NameIndex = 8185, + kX86InstIdVtestps_NameIndex = 8193, + kX86InstIdVucomisd_NameIndex = 8201, + kX86InstIdVucomiss_NameIndex = 8210, + kX86InstIdVunpckhpd_NameIndex = 8219, + kX86InstIdVunpckhps_NameIndex = 8229, + kX86InstIdVunpcklpd_NameIndex = 8239, + kX86InstIdVunpcklps_NameIndex = 8249, + kX86InstIdVxorpd_NameIndex = 8259, + kX86InstIdVxorps_NameIndex = 8266, + kX86InstIdVzeroall_NameIndex = 8273, + kX86InstIdVzeroupper_NameIndex = 8282, + kX86InstIdWrfsbase_NameIndex = 8293, + kX86InstIdWrgsbase_NameIndex = 8302, + kX86InstIdXadd_NameIndex = 8311, + kX86InstIdXchg_NameIndex = 8316, + kX86InstIdXgetbv_NameIndex = 8321, + kX86InstIdXor_NameIndex = 8328, + kX86InstIdXorpd_NameIndex = 8332, + kX86InstIdXorps_NameIndex = 8338, + kX86InstIdXrstor_NameIndex = 8344, + kX86InstIdXrstor64_NameIndex = 8351, + kX86InstIdXsave_NameIndex = 8360, + kX86InstIdXsave64_NameIndex = 8366, + kX86InstIdXsaveopt_NameIndex = 8374, + kX86InstIdXsaveopt64_NameIndex = 8383, + kX86InstIdXsetbv_NameIndex = 8394 +}; +#endif // !ASMJIT_DISABLE_NAMES + +// Automatically generated, do not edit. +const X86InstExtendedInfo _x86InstExtendedInfo[] = { + { Enc(None) , 0 , 0 , 0x00, 0x00, 0, { U , U , U , U , U }, F(None) , U }, + { Enc(X86Arith) , 0 , 0 , 0x20, 0x3F, 0, { O(GqdwbMem) , O(GqdwbMem)|O(Imm), U , U , U }, F(Lock) , U }, + { Enc(X86Arith) , 0 , 0 , 0x00, 0x3F, 0, { O(GqdwbMem) , O(GqdwbMem)|O(Imm), U , U , U }, F(Lock) , U }, + { Enc(ExtRm) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , U , U , U }, F(None) , U }, + { Enc(ExtRmi) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , O(Imm) , U , U }, F(None) , U }, + { Enc(AvxRvm) , 0 , 0 , 0x00, 0x3F, 0, { O(Gqd) , O(Gqd) , O(GqdMem) , U , U }, F(None) , U }, + { Enc(AvxRmv) , 0 , 0 , 0x00, 0x3F, 0, { O(Gqd) , O(GqdMem) , O(Gqd) , U , U }, F(None) , U }, + { Enc(ExtRm) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , U , U , U }, F(None)|F(Special) , U }, + { Enc(AvxVm) , 0 , 0 , 0x00, 0x3F, 0, { O(Gqd) , O(GqdMem) , U , U , U }, F(None) , U }, + { Enc(X86RegRm) , 0 , 0 , 0x00, 0x3F, 0, { O(Gqdw) , O(GqdwMem) , U , U , U }, F(None) , U }, + { Enc(X86BSwap) , 0 , 0 , 0x00, 0x00, 0, { O(Gqd) , U , U , U , U }, F(None) , U }, + { Enc(X86BTest) , 0 , 0 , 0x00, 0x3B, 0, { O(GqdwMem) , O(Gqdw)|O(Imm) , U , U , U }, F(Test) , O_000F00(BA,4,_,_,_) }, + { Enc(X86BTest) , 0 , 0 , 0x00, 0x3B, 0, { O(GqdwMem) , O(Gqdw)|O(Imm) , U , U , U }, F(Lock) , O_000F00(BA,7,_,_,_) }, + { Enc(X86BTest) , 0 , 0 , 0x00, 0x3B, 0, { O(GqdwMem) , O(Gqdw)|O(Imm) , U , U , U }, F(Lock) , O_000F00(BA,6,_,_,_) }, + { Enc(X86BTest) , 0 , 0 , 0x00, 0x3B, 0, { O(GqdwMem) , O(Gqdw)|O(Imm) , U , U , U }, F(Lock) , O_000F00(BA,5,_,_,_) }, + { Enc(X86Call) , 0 , 0 , 0x00, 0x00, 0, { O(GqdMem)|O(LbImm), U , U , U , U }, F(Flow) , O_000000(E8,U,_,_,_) }, + { Enc(X86Op) , 0 , 0 , 0x00, 0x00, 0, { U , U , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86Op) , 0 , 0 , 0x00, 0x20, 0, { U , U , U , U , U }, F(None) , U }, + { Enc(X86Op) , 0 , 0 , 0x00, 0x40, 0, { U , U , U , U , U }, F(None) , U }, + { Enc(X86M) , 0 , 0 , 0x00, 0x00, 0, { O(Mem) , U , U , U , U }, F(None) , U }, + { Enc(X86Op) , 0 , 0 , 0x20, 0x20, 0, { U , U , U , U , U }, F(None) , U }, + { Enc(X86RegRm) , 0 , 0 , 0x24, 0x00, 0, { O(Gqdw) , O(GqdwMem) , U , U , U }, F(None) , U }, + { Enc(X86RegRm) , 0 , 0 , 0x20, 0x00, 0, { O(Gqdw) , O(GqdwMem) , U , U , U }, F(None) , U }, + { Enc(X86RegRm) , 0 , 0 , 0x04, 0x00, 0, { O(Gqdw) , O(GqdwMem) , U , U , U }, F(None) , U }, + { Enc(X86RegRm) , 0 , 0 , 0x07, 0x00, 0, { O(Gqdw) , O(GqdwMem) , U , U , U }, F(None) , U }, + { Enc(X86RegRm) , 0 , 0 , 0x03, 0x00, 0, { O(Gqdw) , O(GqdwMem) , U , U , U }, F(None) , U }, + { Enc(X86RegRm) , 0 , 0 , 0x01, 0x00, 0, { O(Gqdw) , O(GqdwMem) , U , U , U }, F(None) , U }, + { Enc(X86RegRm) , 0 , 0 , 0x10, 0x00, 0, { O(Gqdw) , O(GqdwMem) , U , U , U }, F(None) , U }, + { Enc(X86RegRm) , 0 , 0 , 0x02, 0x00, 0, { O(Gqdw) , O(GqdwMem) , U , U , U }, F(None) , U }, + { Enc(X86Arith) , 0 , 0 , 0x00, 0x3F, 0, { O(GqdwbMem) , O(GqdwbMem)|O(Imm), U , U , U }, F(Test) , U }, + { Enc(X86Op) , 0 , 0 , 0x40, 0x3F, 0, { U , U , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86Op_66H) , 0 , 0 , 0x40, 0x3F, 0, { U , U , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86RmReg) , 0 , 0 , 0x00, 0x3F, 0, { U , U , U , U , U }, F(Lock)|F(Special) , U }, + { Enc(X86M) , 0 , 0 , 0x00, 0x04, 0, { O(Mem) , U , U , U , U }, F(None)|F(Special) , U }, + { Enc(ExtRm) , 0 , 0 , 0x00, 0x3F, 0, { O(Xmm) , O(XmmMem) , U , U , U }, F(Test) , U }, + { Enc(ExtCrc) , 0 , 0 , 0x00, 0x00, 0, { O(Gqd) , O(GqdwbMem) , U , U , U }, F(None) , U }, + { Enc(ExtRm) , 0 , 16, 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , U , U , U }, F(Move) , U }, + { Enc(ExtRm) , 0 , 8 , 0x00, 0x00, 0, { O(Mm) , O(XmmMem) , U , U , U }, F(Move) , U }, + { Enc(ExtRm) , 0 , 16, 0x00, 0x00, 0, { O(Xmm) , O(MmMem) , U , U , U }, F(Move) , U }, + { Enc(ExtRm) , 0 , 8 , 0x00, 0x00, 0, { O(Xmm) , O(MmMem) , U , U , U }, F(Move) , U }, + { Enc(ExtRm_Q) , 0 , 8 , 0x00, 0x00, 0, { O(Gqd) , O(XmmMem) , U , U , U }, F(Move) , U }, + { Enc(ExtRm) , 0 , 4 , 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , U , U , U }, F(Move) , U }, + { Enc(ExtRm_Q) , 0 , 8 , 0x00, 0x00, 0, { O(Xmm) , O(GqdMem) , U , U , U }, F(Move) , U }, + { Enc(ExtRm_Q) , 0 , 4 , 0x00, 0x00, 0, { O(Xmm) , O(GqdMem) , U , U , U }, F(Move) , U }, + { Enc(ExtRm) , 0 , 8 , 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , U , U , U }, F(Move) , U }, + { Enc(X86Op) , 0 , 0 , 0x28, 0x3F, 0, { U , U , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86IncDec) , 0 , 0 , 0x00, 0x1F, 0, { O(GqdwbMem) , U , U , U , U }, F(Lock) , O_000000(48,U,_,_,_) }, + { Enc(X86Rm_B) , 0 , 0 , 0x00, 0x3F, 0, { U , U , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86Op) , 0 , 0 , 0x00, 0x00, 0, { U , U , U , U , U }, F(None) , U }, + { Enc(X86Enter) , 0 , 0 , 0x00, 0x00, 0, { U , U , U , U , U }, F(None)|F(Special) , U }, + { Enc(ExtExtract) , 0 , 8 , 0x00, 0x00, 0, { O(GqdMem) , O(Xmm) , U , U , U }, F(Move) , O_660F3A(17,U,_,_,_) }, + { Enc(ExtExtrq) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm)|O(Imm) , O(None)|O(Imm) , U , U }, F(None) , O_660F00(78,0,_,_,_) }, + { Enc(FpuOp) , 0 , 0 , 0x00, 0x00, 0, { U , U , U , U , U }, F(Fp) , U }, + { Enc(FpuArith) , 0 , 0 , 0x00, 0x00, 0, { O(FpMem) , O(Fp) , U , U , U }, F(Fp)|F(Mem4_8) , U }, + { Enc(FpuRDef) , 0 , 0 , 0x00, 0x00, 0, { O(Fp) , U , U , U , U }, F(Fp) , U }, + { Enc(X86M) , 0 , 0 , 0x00, 0x00, 0, { O(Mem) , U , U , U , U }, F(Fp) , U }, + { Enc(FpuR) , 0 , 0 , 0x20, 0x00, 0, { O(Fp) , U , U , U , U }, F(Fp) , U }, + { Enc(FpuR) , 0 , 0 , 0x24, 0x00, 0, { O(Fp) , U , U , U , U }, F(Fp) , U }, + { Enc(FpuR) , 0 , 0 , 0x04, 0x00, 0, { O(Fp) , U , U , U , U }, F(Fp) , U }, + { Enc(FpuR) , 0 , 0 , 0x10, 0x00, 0, { O(Fp) , U , U , U , U }, F(Fp) , U }, + { Enc(FpuCom) , 0 , 0 , 0x00, 0x00, 0, { O(Fp)|O(Mem) , O(Fp) , U , U , U }, F(Fp) , U }, + { Enc(FpuR) , 0 , 0 , 0x00, 0x3F, 0, { O(Fp) , U , U , U , U }, F(Fp) , U }, + { Enc(X86Op) , 0 , 0 , 0x00, 0x00, 0, { U , U , U , U , U }, F(Fp) , U }, + { Enc(FpuR) , 0 , 0 , 0x00, 0x00, 0, { O(Fp) , U , U , U , U }, F(Fp) , U }, + { Enc(FpuM) , 0 , 0 , 0x00, 0x00, 0, { O(Mem) , U , U , U , U }, F(Fp)|F(Mem2_4) , U }, + { Enc(FpuM) , 0 , 0 , 0x00, 0x00, 0, { O(Mem) , U , U , U , U }, F(Fp)|F(Mem2_4_8) , O_000000(DF,5,_,_,_) }, + { Enc(FpuM) , 0 , 0 , 0x00, 0x00, 0, { O(Mem) , U , U , U , U }, F(Fp)|F(Mem2_4_8) , O_000000(DF,7,_,_,_) }, + { Enc(FpuM) , 0 , 0 , 0x00, 0x00, 0, { O(Mem) , U , U , U , U }, F(Fp)|F(Mem2_4_8) , O_000000(DD,1,_,_,_) }, + { Enc(FpuFldFst) , 0 , 0 , 0x00, 0x00, 0, { O(Mem) , U , U , U , U }, F(Fp)|F(Mem4_8_10) , O_000000(DB,5,_,_,_) }, + { Enc(FpuStsw) , 0 , 0 , 0x00, 0x00, 0, { O(Mem) , U , U , U , U }, F(Fp) , O_00_X(DFE0,U) }, + { Enc(FpuFldFst) , 0 , 0 , 0x00, 0x00, 0, { O(Mem) , U , U , U , U }, F(Fp)|F(Mem4_8) , U }, + { Enc(FpuFldFst) , 0 , 0 , 0x00, 0x00, 0, { O(Mem) , U , U , U , U }, F(Fp)|F(Mem4_8_10) , O_000000(DB,7,_,_,_) }, + { Enc(FpuStsw) , 0 , 0 , 0x00, 0x00, 0, { O(Mem) , U , U , U , U }, F(Fp) , O_9B_X(DFE0,U) }, + { Enc(X86Rm_B) , 0 , 0 , 0x00, 0x3F, 0, { 0 , 0 , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86Imul) , 0 , 0 , 0x00, 0x3F, 0, { 0 , 0 , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86IncDec) , 0 , 0 , 0x00, 0x1F, 0, { O(GqdwbMem) , U , U , U , U }, F(Lock) , O_000000(40,U,_,_,_) }, + { Enc(ExtInsertq) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm) , O(None)|O(Imm) , O(None)|O(Imm) , U }, F(None) , O_F20F00(78,U,_,_,_) }, + { Enc(X86Int) , 0 , 0 , 0x00, 0x80, 0, { U , U , U , U , U }, F(None) , U }, + { Enc(X86Jcc) , 0 , 0 , 0x24, 0x00, 0, { O(Label) , U , U , U , U }, F(Flow) , U }, + { Enc(X86Jcc) , 0 , 0 , 0x20, 0x00, 0, { O(Label) , U , U , U , U }, F(Flow) , U }, + { Enc(X86Jcc) , 0 , 0 , 0x04, 0x00, 0, { O(Label) , U , U , U , U }, F(Flow) , U }, + { Enc(X86Jcc) , 0 , 0 , 0x07, 0x00, 0, { O(Label) , U , U , U , U }, F(Flow) , U }, + { Enc(X86Jcc) , 0 , 0 , 0x03, 0x00, 0, { O(Label) , U , U , U , U }, F(Flow) , U }, + { Enc(X86Jcc) , 0 , 0 , 0x01, 0x00, 0, { O(Label) , U , U , U , U }, F(Flow) , U }, + { Enc(X86Jcc) , 0 , 0 , 0x10, 0x00, 0, { O(Label) , U , U , U , U }, F(Flow) , U }, + { Enc(X86Jcc) , 0 , 0 , 0x02, 0x00, 0, { O(Label) , U , U , U , U }, F(Flow) , U }, + { Enc(X86Jecxz) , 0 , 0 , 0x00, 0x00, 0, { O(Gqdw) , O(Label) , U , U , U }, F(Flow)|F(Special) , U }, + { Enc(X86Jmp) , 0 , 0 , 0x00, 0x00, 0, { O(Label)|O(Imm) , U , U , U , U }, F(Flow) , O_000000(E9,U,_,_,_) }, + { Enc(X86Op) , 0 , 0 , 0x3E, 0x00, 0, { U , U , U , U , U }, F(None)|F(Special) , U }, + { Enc(ExtRm) , 0 , 16, 0x00, 0x00, 0, { O(Xmm) , O(Mem) , U , U , U }, F(Move) , U }, + { Enc(X86Lea) , 0 , 0 , 0x00, 0x00, 0, { O(Gqd) , O(Mem) , U , U , U }, F(Move) , U }, + { Enc(ExtFence) , 0 , 0 , 0x00, 0x00, 0, { U , U , U , U , U }, F(None) , U }, + { Enc(X86Op) , 0 , 1 , 0x40, 0x00, 0, { U , U , U , U , U }, F(Move)|F(Special) , U }, + { Enc(X86Op) , 0 , 4 , 0x40, 0x00, 0, { U , U , U , U , U }, F(Move)|F(Special) , U }, + { Enc(X86Op) , 0 , 8 , 0x40, 0x00, 0, { U , U , U , U , U }, F(Move)|F(Special) , U }, + { Enc(X86Op_66H) , 0 , 2 , 0x40, 0x00, 0, { U , U , U , U , U }, F(Move)|F(Special) , U }, + { Enc(ExtRm) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm) , U , U , U }, F(None)|F(Special) , U }, + { Enc(ExtRm) , 0 , 0 , 0x00, 0x00, 0, { O(Mm) , O(Mm) , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86Mov) , 0 , 0 , 0x00, 0x00, 0, { O(GqdwbMem) , O(GqdwbMem)|O(Imm), U , U , U }, F(Move) , U }, + { Enc(X86MovPtr) , 0 , 0 , 0x00, 0x00, 0, { O(Gqdwb) , O(Imm) , U , U , U }, F(Move)|F(Special) , O_000000(A2,U,_,_,_) }, + { Enc(ExtMov) , 0 , 16, 0x00, 0x00, 0, { O(XmmMem) , O(XmmMem) , U , U , U }, F(Move) , O_660F00(29,U,_,_,_) }, + { Enc(ExtMov) , 0 , 16, 0x00, 0x00, 0, { O(XmmMem) , O(XmmMem) , U , U , U }, F(Move) , O_000F00(29,U,_,_,_) }, + { Enc(ExtMovBe) , 0 , 0 , 0x00, 0x00, 0, { O(GqdwMem) , O(GqdwMem) , U , U , U }, F(Move) , O_000F38(F1,U,_,_,_) }, + { Enc(ExtMovD) , 0 , 16, 0x00, 0x00, 0, { O(Gd)|O(MmXmmMem) , O(Gd)|O(MmXmmMem) , U , U , U }, F(Move) , O_000F00(7E,U,_,_,_) }, + { Enc(ExtMov) , 0 , 16, 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , U , U , U }, F(Move) , U }, + { Enc(ExtMov) , 0 , 8 , 0x00, 0x00, 0, { O(Mm) , O(Xmm) , U , U , U }, F(Move) , U }, + { Enc(ExtMov) , 0 , 16, 0x00, 0x00, 0, { O(XmmMem) , O(XmmMem) , U , U , U }, F(Move) , O_660F00(7F,U,_,_,_) }, + { Enc(ExtMov) , 0 , 16, 0x00, 0x00, 0, { O(XmmMem) , O(XmmMem) , U , U , U }, F(Move) , O_F30F00(7F,U,_,_,_) }, + { Enc(ExtMov) , 0 , 8 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm) , U , U , U }, F(Move) , U }, + { Enc(ExtMov) , 8 , 8 , 0x00, 0x00, 0, { O(XmmMem) , O(XmmMem) , U , U , U }, F(None) , O_660F00(17,U,_,_,_) }, + { Enc(ExtMov) , 8 , 8 , 0x00, 0x00, 0, { O(XmmMem) , O(XmmMem) , U , U , U }, F(None) , O_000F00(17,U,_,_,_) }, + { Enc(ExtMov) , 8 , 8 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm) , U , U , U }, F(None) , U }, + { Enc(ExtMov) , 0 , 8 , 0x00, 0x00, 0, { O(XmmMem) , O(XmmMem) , U , U , U }, F(Move) , O_660F00(13,U,_,_,_) }, + { Enc(ExtMov) , 0 , 8 , 0x00, 0x00, 0, { O(XmmMem) , O(XmmMem) , U , U , U }, F(Move) , O_000F00(13,U,_,_,_) }, + { Enc(ExtMovNoRexW) , 0 , 8 , 0x00, 0x00, 0, { O(Gqd) , O(Xmm) , U , U , U }, F(Move) , U }, + { Enc(ExtMov) , 0 , 16, 0x00, 0x00, 0, { O(Mem) , O(Xmm) , U , U , U }, F(Move) , O_660F00(E7,U,_,_,_) }, + { Enc(ExtMov) , 0 , 16, 0x00, 0x00, 0, { O(Xmm) , O(Mem) , U , U , U }, F(Move) , U }, + { Enc(ExtMov) , 0 , 8 , 0x00, 0x00, 0, { O(Mem) , O(Gqd) , U , U , U }, F(Move) , O_000F00(C3,U,_,_,_) }, + { Enc(ExtMov) , 0 , 16, 0x00, 0x00, 0, { O(Mem) , O(Xmm) , U , U , U }, F(Move) , O_660F00(2B,U,_,_,_) }, + { Enc(ExtMov) , 0 , 16, 0x00, 0x00, 0, { O(Mem) , O(Xmm) , U , U , U }, F(Move) , O_000F00(2B,U,_,_,_) }, + { Enc(ExtMov) , 0 , 8 , 0x00, 0x00, 0, { O(Mem) , O(Mm) , U , U , U }, F(Move) , O_000F00(E7,U,_,_,_) }, + { Enc(ExtMov) , 0 , 8 , 0x00, 0x00, 0, { O(Mem) , O(Xmm) , U , U , U }, F(Move) , O_F20F00(2B,U,_,_,_) }, + { Enc(ExtMov) , 0 , 4 , 0x00, 0x00, 0, { O(Mem) , O(Xmm) , U , U , U }, F(Move) , O_F30F00(2B,U,_,_,_) }, + { Enc(ExtMovQ) , 0 , 16, 0x00, 0x00, 0, { O(Gq)|O(MmXmmMem) , O(Gq)|O(MmXmmMem) , U , U , U }, F(Move) , O_000F00(7E,U,_,W,_) }, + { Enc(ExtRm) , 0 , 16, 0x00, 0x00, 0, { O(Xmm) , O(Mm) , U , U , U }, F(Move) , U }, + { Enc(X86Op) , 0 , 0 , 0x00, 0x00, 0, { U , U , U , U , U }, F(Move)|F(Special) , U }, + { Enc(X86Op_66H) , 0 , 0 , 0x00, 0x00, 0, { U , U , U , U , U }, F(None)|F(Special) , U }, + { Enc(ExtMov) , 0 , 8 , 0x00, 0x00, 0, { O(XmmMem) , O(XmmMem) , U , U , U }, F(Move) |F(Z) , O_F20F00(11,U,_,_,_) }, + { Enc(ExtMov) , 0 , 4 , 0x00, 0x00, 0, { O(XmmMem) , O(XmmMem) , U , U , U }, F(Move) |F(Z) , O_F30F00(11,U,_,_,_) }, + { Enc(X86MovSxZx) , 0 , 0 , 0x00, 0x00, 0, { O(Gqdw) , O(GwbMem) , U , U , U }, F(Move) , U }, + { Enc(X86MovSxd) , 0 , 0 , 0x00, 0x00, 0, { O(Gq) , O(GdMem) , U , U , U }, F(Move) , U }, + { Enc(ExtMov) , 0 , 16, 0x00, 0x00, 0, { O(XmmMem) , O(XmmMem) , U , U , U }, F(Move) , O_660F00(11,U,_,_,_) }, + { Enc(ExtMov) , 0 , 16, 0x00, 0x00, 0, { O(XmmMem) , O(XmmMem) , U , U , U }, F(Move) , O_000F00(11,U,_,_,_) }, + { Enc(AvxRvm) , 0 , 0 , 0x00, 0x00, 0, { O(Gqd) , O(Gqd) , O(GqdMem) , U , U }, F(None) , U }, + { Enc(X86Rm_B) , 0 , 0 , 0x00, 0x3F, 0, { O(GqdwbMem) , U , U , U , U }, F(Lock) , U }, + { Enc(X86Rm_B) , 0 , 0 , 0x00, 0x00, 0, { O(GqdwbMem) , U , U , U , U }, F(Lock) , U }, + { Enc(ExtRm_P) , 0 , 0 , 0x00, 0x00, 0, { O(MmXmm) , O(MmXmmMem) , U , U , U }, F(None) , U }, + { Enc(ExtRmi_P) , 0 , 0 , 0x00, 0x00, 0, { O(MmXmm) , O(MmXmmMem) , O(Imm) , U , U }, F(None) , U }, + { Enc(ExtExtract) , 0 , 8 , 0x00, 0x00, 0, { O(Gd)|O(Gb)|O(Mem), O(Xmm) , U , U , U }, F(Move) , O_000F3A(14,U,_,_,_) }, + { Enc(ExtExtract) , 0 , 8 , 0x00, 0x00, 0, { O(GdMem) , O(Xmm) , U , U , U }, F(Move) , O_000F3A(16,U,_,_,_) }, + { Enc(ExtExtract) , 0 , 8 , 0x00, 0x00, 0, { O(GqdMem) , O(Xmm) , U , U , U }, F(Move) , O_000F3A(16,U,_,W,_) }, + { Enc(ExtExtract) , 0 , 8 , 0x00, 0x00, 0, { O(GdMem) , O(MmXmm) , U , U , U }, F(Move) , O_000F3A(15,U,_,_,_) }, + { Enc(3dNow) , 0 , 0 , 0x00, 0x00, 0, { O(Mm) , O(MmMem) , U , U , U }, F(None) , U }, + { Enc(ExtRmi) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(GdMem) , O(Imm) , U , U }, F(None) , U }, + { Enc(ExtRmi) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(GqMem) , O(Imm) , U , U }, F(None) , U }, + { Enc(ExtRmi_P) , 0 , 0 , 0x00, 0x00, 0, { O(MmXmm) , O(GdMem) , O(Imm) , U , U }, F(None) , U }, + { Enc(ExtRm_PQ) , 0 , 8 , 0x00, 0x00, 0, { O(Gqd) , O(MmXmm) , U , U , U }, F(Move) , U }, + { Enc(X86Pop) , 0 , 0 , 0x00, 0x00, 0, { 0 , U , U , U , U }, F(None)|F(Special) , O_000000(58,U,_,_,_) }, + { Enc(X86Op) , 0 , 0 , 0x00, 0xFF, 0, { U , U , U , U , U }, F(None)|F(Special) , U }, + { Enc(ExtPrefetch) , 0 , 0 , 0x00, 0x00, 0, { O(Mem) , O(Imm) , U , U , U }, F(None) , U }, + { Enc(ExtRmi) , 0 , 16, 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , O(Imm) , U , U }, F(Move) , U }, + { Enc(ExtRmi_P) , 0 , 8 , 0x00, 0x00, 0, { O(Mm) , O(MmMem) , O(Imm) , U , U }, F(Move) , U }, + { Enc(ExtRmRi_P) , 0 , 0 , 0x00, 0x00, 0, { O(MmXmm) , O(MmXmmMem)|O(Imm), U , U , U }, F(None) , O_000F00(72,6,_,_,_) }, + { Enc(ExtRmRi) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Imm) , U , U , U }, F(None) , O_660F00(73,7,_,_,_) }, + { Enc(ExtRmRi_P) , 0 , 0 , 0x00, 0x00, 0, { O(MmXmm) , O(MmXmmMem)|O(Imm), U , U , U }, F(None) , O_000F00(73,6,_,_,_) }, + { Enc(ExtRmRi_P) , 0 , 0 , 0x00, 0x00, 0, { O(MmXmm) , O(MmXmmMem)|O(Imm), U , U , U }, F(None) , O_000F00(71,6,_,_,_) }, + { Enc(ExtRmRi_P) , 0 , 0 , 0x00, 0x00, 0, { O(MmXmm) , O(MmXmmMem)|O(Imm), U , U , U }, F(None) , O_000F00(72,4,_,_,_) }, + { Enc(ExtRmRi_P) , 0 , 0 , 0x00, 0x00, 0, { O(MmXmm) , O(MmXmmMem)|O(Imm), U , U , U }, F(None) , O_000F00(71,4,_,_,_) }, + { Enc(ExtRmRi_P) , 0 , 0 , 0x00, 0x00, 0, { O(MmXmm) , O(MmXmmMem)|O(Imm), U , U , U }, F(None) , O_000F00(72,2,_,_,_) }, + { Enc(ExtRmRi) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Imm) , U , U , U }, F(None) , O_660F00(73,3,_,_,_) }, + { Enc(ExtRmRi_P) , 0 , 0 , 0x00, 0x00, 0, { O(MmXmm) , O(MmXmmMem)|O(Imm), U , U , U }, F(None) , O_000F00(73,2,_,_,_) }, + { Enc(ExtRmRi_P) , 0 , 0 , 0x00, 0x00, 0, { O(MmXmm) , O(MmXmmMem)|O(Imm), U , U , U }, F(None) , O_000F00(71,2,_,_,_) }, + { Enc(X86Push) , 0 , 0 , 0x00, 0x00, 0, { 0 , U , U , U , U }, F(None)|F(Special) , O_000000(50,U,_,_,_) }, + { Enc(X86Op) , 0 , 0 , 0xFF, 0x00, 0, { U , U , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86Rot) , 0 , 0 , 0x20, 0x21, 0, { O(GqdwbMem) , O(Gb)|O(Imm) , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86Rm) , 0 , 8 , 0x00, 0x00, 0, { O(Gqd) , U , U , U , U }, F(Move) , U }, + { Enc(X86Rm) , 0 , 8 , 0x00, 0x3F, 0, { O(Gqdw) , U , U , U , U }, F(Move) , U }, + { Enc(X86Rep) , 0 , 0 , 0x40, 0x00, 0, { O(Mem) , U , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86Rep) , 0 , 0 , 0x40, 0x00, 0, { O(Mem) , O(Mem) , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86Rep) , 0 , 0 , 0x40, 0x3F, 0, { O(Mem) , O(Mem) , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86Ret) , 0 , 0 , 0x00, 0x00, 0, { U , U , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86Rot) , 0 , 0 , 0x00, 0x21, 0, { O(GqdwbMem) , O(Gb)|O(Imm) , U , U , U }, F(None)|F(Special) , U }, + { Enc(AvxRmi) , 0 , 0 , 0x00, 0x00, 0, { O(Gqd) , O(GqdMem) , O(Imm) , U , U }, F(None) , U }, + { Enc(ExtRmi) , 0 , 8 , 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , O(Imm) , U , U }, F(Move) , U }, + { Enc(ExtRmi) , 0 , 4 , 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , O(Imm) , U , U }, F(Move) , U }, + { Enc(X86Op) , 0 , 0 , 0x00, 0x3E, 0, { U , U , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86Rot) , 0 , 0 , 0x00, 0x3F, 0, { O(GqdwbMem) , O(Gb)|O(Imm) , U , U , U }, F(None)|F(Special) , U }, + { Enc(AvxRmv) , 0 , 0 , 0x00, 0x00, 0, { O(Gqd) , O(GqdMem) , O(Gqd) , U , U }, F(None) , U }, + { Enc(X86Set) , 0 , 1 , 0x24, 0x00, 0, { O(GbMem) , U , U , U , U }, F(Move) , U }, + { Enc(X86Set) , 0 , 1 , 0x20, 0x00, 0, { O(GbMem) , U , U , U , U }, F(Move) , U }, + { Enc(X86Set) , 0 , 1 , 0x04, 0x00, 0, { O(GbMem) , U , U , U , U }, F(Move) , U }, + { Enc(X86Set) , 0 , 1 , 0x07, 0x00, 0, { O(GbMem) , U , U , U , U }, F(Move) , U }, + { Enc(X86Set) , 0 , 1 , 0x03, 0x00, 0, { O(GbMem) , U , U , U , U }, F(Move) , U }, + { Enc(X86Set) , 0 , 1 , 0x01, 0x00, 0, { O(GbMem) , U , U , U , U }, F(Move) , U }, + { Enc(X86Set) , 0 , 1 , 0x10, 0x00, 0, { O(GbMem) , U , U , U , U }, F(Move) , U }, + { Enc(X86Set) , 0 , 1 , 0x02, 0x00, 0, { O(GbMem) , U , U , U , U }, F(Move) , U }, + { Enc(X86Shlrd) , 0 , 0 , 0x00, 0x3F, 0, { O(GqdwbMem) , O(Gb) , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86Shlrd) , 0 , 0 , 0x00, 0x3F, 0, { O(GqdwbMem) , O(Gqdwb) , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86Op) , 0 , 0 , 0x40, 0x00, 0, { U , U , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86Op_66H) , 0 , 0 , 0x40, 0x00, 0, { U , U , U , U , U }, F(None)|F(Special) , U }, + { Enc(X86Test) , 0 , 0 , 0x00, 0x3F, 0, { O(GqdwbMem) , O(Gqdwb)|O(Imm) , U , U , U }, F(Test) , O_000000(F6,U,_,_,_) }, + { Enc(X86RegRm) , 0 , 0 , 0x00, 0x3F, 0, { O(Gqdw) , O(GqdwMem) , U , U , U }, F(Move) , U }, + { Enc(AvxRvm_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(Xy) , O(XyMem) , U , U }, F(Avx) , U }, + { Enc(AvxRvm) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm) , O(XmmMem) , U , U }, F(Avx) , U }, + { Enc(AvxRm) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , U , U , U }, F(Avx) , U }, + { Enc(AvxRmi) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , O(Imm) , U , U }, F(Avx) , U }, + { Enc(AvxRvmi_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(Xy) , O(XyMem) , O(Imm) , U }, F(Avx) , U }, + { Enc(AvxRvmr_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(Xy) , O(XyMem) , O(Xy) , U }, F(Avx) , U }, + { Enc(AvxRm) , 0 , 0 , 0x00, 0x00, 0, { O(Ymm) , O(Mem) , U , U , U }, F(Avx) , U }, + { Enc(AvxRm) , 0 , 0 , 0x00, 0x00, 0, { O(Ymm) , O(XmmMem) , U , U , U }, F(Avx) , U }, + { Enc(AvxRm) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(XmmMem) , U , U , U }, F(Avx) , U }, + { Enc(AvxRvmi) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm) , O(XmmMem) , O(Imm) , U }, F(Avx) , U }, + { Enc(AvxRm_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(XmmMem) , U , U , U }, F(Avx) , U }, + { Enc(AvxRm_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(XyMem) , U , U , U }, F(Avx) , U }, + { Enc(AvxRm) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(XyMem) , U , U , U }, F(Avx) , U }, + { Enc(AvxMri_P) , 0 , 0 , 0x00, 0x00, 0, { O(XmmMem) , O(Xy) , O(Imm) , U , U }, F(Avx) , U }, + { Enc(AvxRm) , 0 , 0 , 0x00, 0x00, 0, { O(Gqd) , O(XmmMem) , U , U , U }, F(Avx) , U }, + { Enc(AvxRvm) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm) , O(GqdMem) , U , U }, F(Avx) , U }, + { Enc(AvxRm_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(XyMem) , U , U , U }, F(Avx) , U }, + { Enc(AvxMri) , 0 , 0 , 0x00, 0x00, 0, { O(XmmMem) , O(Ymm) , O(Imm) , U , U }, F(Avx) , U }, + { Enc(AvxMri) , 0 , 0 , 0x00, 0x00, 0, { O(GqdMem) , O(Xmm) , O(Imm) , U , U }, F(Avx) , U }, + { Enc(Fma4_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U }, F(Avx) , U }, + { Enc(Fma4) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm) , O(XmmMem) , O(XmmMem) , U }, F(Avx) , U }, + { Enc(XopRm_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(XyMem) , U , U , U }, F(Avx) , U }, + { Enc(XopRm) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , U , U , U }, F(Avx) , U }, + { Enc(AvxGather) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(Mem) , O(Xy) , U , U }, F(Avx) , U }, + { Enc(AvxGatherEx) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Mem) , O(Xmm) , U , U }, F(Avx) , U }, + { Enc(AvxRvmi) , 0 , 0 , 0x00, 0x00, 0, { O(Ymm) , O(Ymm) , O(XmmMem) , O(Imm) , U }, F(Avx) , U }, + { Enc(AvxRm_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(Mem) , U , U , U }, F(Avx) , U }, + { Enc(AvxM) , 0 , 0 , 0x00, 0x00, 0, { O(Mem) , U , U , U , U }, F(Avx) , U }, + { Enc(AvxRm) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm) , U , U , U }, F(Avx) , U }, + { Enc(AvxRvmMvr_P) , 0 , 0 , 0x00, 0x00, 0, { O(XyMem) , O(Xy) , O(XyMem) , U , U }, F(Avx) , O_660F38(2F,U,_,_,_) }, + { Enc(AvxRvmMvr_P) , 0 , 0 , 0x00, 0x00, 0, { O(XyMem) , O(Xy) , O(XyMem) , U , U }, F(Avx) , O_660F38(2E,U,_,_,_) }, + { Enc(AvxRmMr_P) , 0 , 0 , 0x00, 0x00, 0, { O(XyMem) , O(XyMem) , U , U , U }, F(Avx) , O_660F00(29,U,_,_,_) }, + { Enc(AvxRmMr_P) , 0 , 0 , 0x00, 0x00, 0, { O(XyMem) , O(XyMem) , U , U , U }, F(Avx) , O_000F00(29,U,_,_,_) }, + { Enc(AvxRmMr) , 0 , 0 , 0x00, 0x00, 0, { O(XmmMem) , O(XmmMem) , U , U , U }, F(Avx) , O_660F00(7E,U,_,_,_) }, + { Enc(AvxRmMr_P) , 0 , 0 , 0x00, 0x00, 0, { O(XyMem) , O(XyMem) , U , U , U }, F(Avx) , O_660F00(7F,U,_,_,_) }, + { Enc(AvxRmMr_P) , 0 , 0 , 0x00, 0x00, 0, { O(XyMem) , O(XyMem) , U , U , U }, F(Avx) , O_F30F00(7F,U,_,_,_) }, + { Enc(AvxRvm) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm) , O(Xmm) , U , U }, F(Avx) , U }, + { Enc(AvxRvmMr) , 0 , 0 , 0x00, 0x00, 0, { O(XmmMem) , O(Xmm) , O(Mem) , U , U }, F(Avx) , O_660F00(17,U,_,_,_) }, + { Enc(AvxRvmMr) , 0 , 0 , 0x00, 0x00, 0, { O(XmmMem) , O(Xmm) , O(Mem) , U , U }, F(Avx) , O_000F00(17,U,_,_,_) }, + { Enc(AvxRvmMr) , 0 , 0 , 0x00, 0x00, 0, { O(XmmMem) , O(Xmm) , O(Mem) , U , U }, F(Avx) , O_660F00(13,U,_,_,_) }, + { Enc(AvxRvmMr) , 0 , 0 , 0x00, 0x00, 0, { O(XmmMem) , O(Xmm) , O(Mem) , U , U }, F(Avx) , O_000F00(13,U,_,_,_) }, + { Enc(AvxRm_P) , 0 , 0 , 0x00, 0x00, 0, { O(Gqd) , O(Xy) , U , U , U }, F(Avx) , U }, + { Enc(AvxMr) , 0 , 0 , 0x00, 0x00, 0, { O(Mem) , O(Xy) , U , U , U }, F(Avx) , U }, + { Enc(AvxMr_P) , 0 , 0 , 0x00, 0x00, 0, { O(Mem) , O(Xy) , U , U , U }, F(Avx) , U }, + { Enc(AvxMovSsSd) , 0 , 0 , 0x00, 0x00, 0, { O(XmmMem) , O(XmmMem) , O(Xmm) , U , U }, F(Avx) , O_F20F00(11,U,_,_,_) }, + { Enc(AvxMovSsSd) , 0 , 0 , 0x00, 0x00, 0, { O(XmmMem) , O(Xmm) , O(Xmm) , U , U }, F(Avx) , O_F30F00(11,U,_,_,_) }, + { Enc(AvxRmMr_P) , 0 , 0 , 0x00, 0x00, 0, { O(XyMem) , O(XyMem) , U , U , U }, F(Avx) , O_660F00(11,U,_,_,_) }, + { Enc(AvxRmMr_P) , 0 , 0 , 0x00, 0x00, 0, { O(XyMem) , O(XyMem) , U , U , U }, F(Avx) , O_000F00(11,U,_,_,_) }, + { Enc(AvxRvmr) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(Xy) , O(XyMem) , O(Xy) , U }, F(Avx) , U }, + { Enc(XopRvrmRvmr_P), 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U }, F(Avx) , U }, + { Enc(XopRvmi) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm) , O(XmmMem) , O(Imm) , U }, F(Avx) , U }, + { Enc(AvxRvmi) , 0 , 0 , 0x00, 0x00, 0, { O(Ymm) , O(Ymm) , O(YmmMem) , O(Imm) , U }, F(Avx) , U }, + { Enc(AvxRvm) , 0 , 0 , 0x00, 0x00, 0, { O(Ymm) , O(Ymm) , O(YmmMem) , U , U }, F(Avx) , U }, + { Enc(AvxRvrmRvmr_P), 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U }, F(Avx) , U }, + { Enc(AvxRvmRmi_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U }, F(Avx) , O_660F3A(05,U,_,_,_) }, + { Enc(AvxRvmRmi_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U }, F(Avx) , O_660F3A(04,U,_,_,_) }, + { Enc(AvxRmi) , 0 , 0 , 0x00, 0x00, 0, { O(Ymm) , O(YmmMem) , O(Imm) , U , U }, F(Avx) , U }, + { Enc(AvxMri) , 0 , 0 , 0x00, 0x00, 0, { O(GqdwbMem) , O(Xmm) , O(Imm) , U , U }, F(Avx) , U }, + { Enc(AvxMri) , 0 , 0 , 0x00, 0x00, 0, { O(GqMem) , O(Xmm) , O(Imm) , U , U }, F(Avx) , U }, + { Enc(AvxMri) , 0 , 0 , 0x00, 0x00, 0, { O(GqdwMem) , O(Xmm) , O(Imm) , U , U }, F(Avx) , U }, + { Enc(AvxRvmi) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm) , O(GqdwbMem) , O(Imm) , U }, F(Avx) , U }, + { Enc(AvxRvmi) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm) , O(GqdMem) , O(Imm) , U }, F(Avx) , U }, + { Enc(AvxRvmi) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm) , O(GqMem) , O(Imm) , U }, F(Avx) , U }, + { Enc(AvxRvmi) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm) , O(GqdwMem) , O(Imm) , U }, F(Avx) , U }, + { Enc(XopRvmr) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm) , O(XmmMem) , O(Xmm) , U }, F(Avx) , U }, + { Enc(AvxRvmMvr_P) , 0 , 0 , 0x00, 0x00, 0, { O(XyMem) , O(Xy) , O(XyMem) , U , U }, F(Avx) , O_660F38(8E,U,_,_,_) }, + { Enc(XopRvrmRvmr) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(Xmm) , O(XmmMem) , O(XmmMem) , U }, F(Avx) , U }, + { Enc(XopRvmRmi) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , O(XmmMem)|O(Imm) , U , U }, F(Avx) , O_00_M08(C0,U,_,_,_) }, + { Enc(XopRvmRmi) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , O(XmmMem)|O(Imm) , U , U }, F(Avx) , O_00_M08(C2,U,_,_,_) }, + { Enc(XopRvmRmi) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , O(XmmMem)|O(Imm) , U , U }, F(Avx) , O_00_M08(C3,U,_,_,_) }, + { Enc(XopRvmRmi) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , O(XmmMem)|O(Imm) , U , U }, F(Avx) , O_00_M08(C1,U,_,_,_) }, + { Enc(XopRvmRmv) , 0 , 0 , 0x00, 0x00, 0, { O(Xmm) , O(XmmMem) , O(XmmMem) , U , U }, F(Avx) , U }, + { Enc(AvxRmi_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(XyMem) , O(Imm) , U , U }, F(Avx) , U }, + { Enc(AvxRvmVmi_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U }, F(Avx) , O_660F00(72,6,_,_,_) }, + { Enc(AvxVmi_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(XyMem) , O(Imm) , U , U }, F(Avx) , U }, + { Enc(AvxRvmVmi_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U }, F(Avx) , O_660F00(73,6,_,_,_) }, + { Enc(AvxRvmVmi_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U }, F(Avx) , O_660F00(71,6,_,_,_) }, + { Enc(AvxRvmVmi_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U }, F(Avx) , O_660F00(72,4,_,_,_) }, + { Enc(AvxRvmVmi_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U }, F(Avx) , O_660F00(71,4,_,_,_) }, + { Enc(AvxRvmVmi_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U }, F(Avx) , O_660F00(72,2,_,_,_) }, + { Enc(AvxRvmVmi_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U }, F(Avx) , O_660F00(73,2,_,_,_) }, + { Enc(AvxRvmVmi_P) , 0 , 0 , 0x00, 0x00, 0, { O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U }, F(Avx) , O_660F00(71,2,_,_,_) }, + { Enc(AvxRm_P) , 0 , 0 , 0x00, 0x3F, 0, { O(Xy) , O(XyMem) , U , U , U }, F(Avx) , U }, + { Enc(AvxRm_P) , 0 , 0 , 0x00, 0x3F, 0, { O(Xy) , O(XyMem) , U , U , U }, F(Test) , U }, + { Enc(AvxRm) , 0 , 0 , 0x00, 0x3F, 0, { O(Xmm) , O(XmmMem) , U , U , U }, F(Avx) , U }, + { Enc(AvxOp) , 0 , 0 , 0x00, 0x00, 0, { U , U , U , U , U }, F(Avx) , U }, + { Enc(X86Rm) , 0 , 0 , 0x00, 0x00, 0, { O(Gqd) , U , U , U , U }, F(None) , U }, + { Enc(X86Xadd) , 0 , 0 , 0x00, 0x3F, 0, { O(GqdwbMem) , O(Gqdwb) , U , U , U }, F(Xchg)|F(Lock) , U }, + { Enc(X86Xchg) , 0 , 0 , 0x00, 0x00, 0, { O(GqdwbMem) , O(Gqdwb) , U , U , U }, F(Xchg)|F(Lock) , U }, + { Enc(X86M) , 0 , 0 , 0x00, 0x00, 0, { O(Mem) , U , U , U , U }, F(None)|F(Special) , U } +}; + +// Automatically generated, do not edit. +enum kX86InstData_ExtendedIndex { + kInstIdNone_ExtendedIndex = 0, + kX86InstIdAdc_ExtendedIndex = 1, + kX86InstIdAdd_ExtendedIndex = 2, + kX86InstIdAddpd_ExtendedIndex = 3, + kX86InstIdAddps_ExtendedIndex = 3, + kX86InstIdAddsd_ExtendedIndex = 3, + kX86InstIdAddss_ExtendedIndex = 3, + kX86InstIdAddsubpd_ExtendedIndex = 3, + kX86InstIdAddsubps_ExtendedIndex = 3, + kX86InstIdAesdec_ExtendedIndex = 3, + kX86InstIdAesdeclast_ExtendedIndex = 3, + kX86InstIdAesenc_ExtendedIndex = 3, + kX86InstIdAesenclast_ExtendedIndex = 3, + kX86InstIdAesimc_ExtendedIndex = 3, + kX86InstIdAeskeygenassist_ExtendedIndex = 4, + kX86InstIdAnd_ExtendedIndex = 2, + kX86InstIdAndn_ExtendedIndex = 5, + kX86InstIdAndnpd_ExtendedIndex = 3, + kX86InstIdAndnps_ExtendedIndex = 3, + kX86InstIdAndpd_ExtendedIndex = 3, + kX86InstIdAndps_ExtendedIndex = 3, + kX86InstIdBextr_ExtendedIndex = 6, + kX86InstIdBlendpd_ExtendedIndex = 4, + kX86InstIdBlendps_ExtendedIndex = 4, + kX86InstIdBlendvpd_ExtendedIndex = 7, + kX86InstIdBlendvps_ExtendedIndex = 7, + kX86InstIdBlsi_ExtendedIndex = 8, + kX86InstIdBlsmsk_ExtendedIndex = 8, + kX86InstIdBlsr_ExtendedIndex = 8, + kX86InstIdBsf_ExtendedIndex = 9, + kX86InstIdBsr_ExtendedIndex = 9, + kX86InstIdBswap_ExtendedIndex = 10, + kX86InstIdBt_ExtendedIndex = 11, + kX86InstIdBtc_ExtendedIndex = 12, + kX86InstIdBtr_ExtendedIndex = 13, + kX86InstIdBts_ExtendedIndex = 14, + kX86InstIdBzhi_ExtendedIndex = 6, + kX86InstIdCall_ExtendedIndex = 15, + kX86InstIdCbw_ExtendedIndex = 16, + kX86InstIdCdq_ExtendedIndex = 16, + kX86InstIdCdqe_ExtendedIndex = 16, + kX86InstIdClc_ExtendedIndex = 17, + kX86InstIdCld_ExtendedIndex = 18, + kX86InstIdClflush_ExtendedIndex = 19, + kX86InstIdCmc_ExtendedIndex = 20, + kX86InstIdCmova_ExtendedIndex = 21, + kX86InstIdCmovae_ExtendedIndex = 22, + kX86InstIdCmovb_ExtendedIndex = 22, + kX86InstIdCmovbe_ExtendedIndex = 21, + kX86InstIdCmovc_ExtendedIndex = 22, + kX86InstIdCmove_ExtendedIndex = 23, + kX86InstIdCmovg_ExtendedIndex = 24, + kX86InstIdCmovge_ExtendedIndex = 25, + kX86InstIdCmovl_ExtendedIndex = 25, + kX86InstIdCmovle_ExtendedIndex = 24, + kX86InstIdCmovna_ExtendedIndex = 21, + kX86InstIdCmovnae_ExtendedIndex = 22, + kX86InstIdCmovnb_ExtendedIndex = 22, + kX86InstIdCmovnbe_ExtendedIndex = 21, + kX86InstIdCmovnc_ExtendedIndex = 22, + kX86InstIdCmovne_ExtendedIndex = 23, + kX86InstIdCmovng_ExtendedIndex = 24, + kX86InstIdCmovnge_ExtendedIndex = 25, + kX86InstIdCmovnl_ExtendedIndex = 25, + kX86InstIdCmovnle_ExtendedIndex = 24, + kX86InstIdCmovno_ExtendedIndex = 26, + kX86InstIdCmovnp_ExtendedIndex = 27, + kX86InstIdCmovns_ExtendedIndex = 28, + kX86InstIdCmovnz_ExtendedIndex = 23, + kX86InstIdCmovo_ExtendedIndex = 26, + kX86InstIdCmovp_ExtendedIndex = 27, + kX86InstIdCmovpe_ExtendedIndex = 27, + kX86InstIdCmovpo_ExtendedIndex = 27, + kX86InstIdCmovs_ExtendedIndex = 28, + kX86InstIdCmovz_ExtendedIndex = 23, + kX86InstIdCmp_ExtendedIndex = 29, + kX86InstIdCmppd_ExtendedIndex = 4, + kX86InstIdCmpps_ExtendedIndex = 4, + kX86InstIdCmpsB_ExtendedIndex = 30, + kX86InstIdCmpsD_ExtendedIndex = 30, + kX86InstIdCmpsQ_ExtendedIndex = 30, + kX86InstIdCmpsW_ExtendedIndex = 31, + kX86InstIdCmpsd_ExtendedIndex = 4, + kX86InstIdCmpss_ExtendedIndex = 4, + kX86InstIdCmpxchg_ExtendedIndex = 32, + kX86InstIdCmpxchg16b_ExtendedIndex = 33, + kX86InstIdCmpxchg8b_ExtendedIndex = 33, + kX86InstIdComisd_ExtendedIndex = 34, + kX86InstIdComiss_ExtendedIndex = 34, + kX86InstIdCpuid_ExtendedIndex = 16, + kX86InstIdCqo_ExtendedIndex = 16, + kX86InstIdCrc32_ExtendedIndex = 35, + kX86InstIdCvtdq2pd_ExtendedIndex = 36, + kX86InstIdCvtdq2ps_ExtendedIndex = 36, + kX86InstIdCvtpd2dq_ExtendedIndex = 36, + kX86InstIdCvtpd2pi_ExtendedIndex = 37, + kX86InstIdCvtpd2ps_ExtendedIndex = 36, + kX86InstIdCvtpi2pd_ExtendedIndex = 38, + kX86InstIdCvtpi2ps_ExtendedIndex = 39, + kX86InstIdCvtps2dq_ExtendedIndex = 36, + kX86InstIdCvtps2pd_ExtendedIndex = 36, + kX86InstIdCvtps2pi_ExtendedIndex = 37, + kX86InstIdCvtsd2si_ExtendedIndex = 40, + kX86InstIdCvtsd2ss_ExtendedIndex = 41, + kX86InstIdCvtsi2sd_ExtendedIndex = 42, + kX86InstIdCvtsi2ss_ExtendedIndex = 43, + kX86InstIdCvtss2sd_ExtendedIndex = 44, + kX86InstIdCvtss2si_ExtendedIndex = 40, + kX86InstIdCvttpd2dq_ExtendedIndex = 36, + kX86InstIdCvttpd2pi_ExtendedIndex = 37, + kX86InstIdCvttps2dq_ExtendedIndex = 36, + kX86InstIdCvttps2pi_ExtendedIndex = 37, + kX86InstIdCvttsd2si_ExtendedIndex = 40, + kX86InstIdCvttss2si_ExtendedIndex = 40, + kX86InstIdCwd_ExtendedIndex = 16, + kX86InstIdCwde_ExtendedIndex = 16, + kX86InstIdDaa_ExtendedIndex = 45, + kX86InstIdDas_ExtendedIndex = 45, + kX86InstIdDec_ExtendedIndex = 46, + kX86InstIdDiv_ExtendedIndex = 47, + kX86InstIdDivpd_ExtendedIndex = 3, + kX86InstIdDivps_ExtendedIndex = 3, + kX86InstIdDivsd_ExtendedIndex = 3, + kX86InstIdDivss_ExtendedIndex = 3, + kX86InstIdDppd_ExtendedIndex = 4, + kX86InstIdDpps_ExtendedIndex = 4, + kX86InstIdEmms_ExtendedIndex = 48, + kX86InstIdEnter_ExtendedIndex = 49, + kX86InstIdExtractps_ExtendedIndex = 50, + kX86InstIdExtrq_ExtendedIndex = 51, + kX86InstIdF2xm1_ExtendedIndex = 52, + kX86InstIdFabs_ExtendedIndex = 52, + kX86InstIdFadd_ExtendedIndex = 53, + kX86InstIdFaddp_ExtendedIndex = 54, + kX86InstIdFbld_ExtendedIndex = 55, + kX86InstIdFbstp_ExtendedIndex = 55, + kX86InstIdFchs_ExtendedIndex = 52, + kX86InstIdFclex_ExtendedIndex = 52, + kX86InstIdFcmovb_ExtendedIndex = 56, + kX86InstIdFcmovbe_ExtendedIndex = 57, + kX86InstIdFcmove_ExtendedIndex = 58, + kX86InstIdFcmovnb_ExtendedIndex = 56, + kX86InstIdFcmovnbe_ExtendedIndex = 57, + kX86InstIdFcmovne_ExtendedIndex = 58, + kX86InstIdFcmovnu_ExtendedIndex = 59, + kX86InstIdFcmovu_ExtendedIndex = 59, + kX86InstIdFcom_ExtendedIndex = 60, + kX86InstIdFcomi_ExtendedIndex = 61, + kX86InstIdFcomip_ExtendedIndex = 61, + kX86InstIdFcomp_ExtendedIndex = 60, + kX86InstIdFcompp_ExtendedIndex = 52, + kX86InstIdFcos_ExtendedIndex = 52, + kX86InstIdFdecstp_ExtendedIndex = 52, + kX86InstIdFdiv_ExtendedIndex = 53, + kX86InstIdFdivp_ExtendedIndex = 54, + kX86InstIdFdivr_ExtendedIndex = 53, + kX86InstIdFdivrp_ExtendedIndex = 54, + kX86InstIdFemms_ExtendedIndex = 62, + kX86InstIdFfree_ExtendedIndex = 63, + kX86InstIdFiadd_ExtendedIndex = 64, + kX86InstIdFicom_ExtendedIndex = 64, + kX86InstIdFicomp_ExtendedIndex = 64, + kX86InstIdFidiv_ExtendedIndex = 64, + kX86InstIdFidivr_ExtendedIndex = 64, + kX86InstIdFild_ExtendedIndex = 65, + kX86InstIdFimul_ExtendedIndex = 64, + kX86InstIdFincstp_ExtendedIndex = 52, + kX86InstIdFinit_ExtendedIndex = 52, + kX86InstIdFist_ExtendedIndex = 64, + kX86InstIdFistp_ExtendedIndex = 66, + kX86InstIdFisttp_ExtendedIndex = 67, + kX86InstIdFisub_ExtendedIndex = 64, + kX86InstIdFisubr_ExtendedIndex = 64, + kX86InstIdFld_ExtendedIndex = 68, + kX86InstIdFld1_ExtendedIndex = 52, + kX86InstIdFldcw_ExtendedIndex = 55, + kX86InstIdFldenv_ExtendedIndex = 55, + kX86InstIdFldl2e_ExtendedIndex = 52, + kX86InstIdFldl2t_ExtendedIndex = 52, + kX86InstIdFldlg2_ExtendedIndex = 52, + kX86InstIdFldln2_ExtendedIndex = 52, + kX86InstIdFldpi_ExtendedIndex = 52, + kX86InstIdFldz_ExtendedIndex = 52, + kX86InstIdFmul_ExtendedIndex = 53, + kX86InstIdFmulp_ExtendedIndex = 54, + kX86InstIdFnclex_ExtendedIndex = 52, + kX86InstIdFninit_ExtendedIndex = 52, + kX86InstIdFnop_ExtendedIndex = 52, + kX86InstIdFnsave_ExtendedIndex = 55, + kX86InstIdFnstcw_ExtendedIndex = 55, + kX86InstIdFnstenv_ExtendedIndex = 55, + kX86InstIdFnstsw_ExtendedIndex = 69, + kX86InstIdFpatan_ExtendedIndex = 52, + kX86InstIdFprem_ExtendedIndex = 52, + kX86InstIdFprem1_ExtendedIndex = 52, + kX86InstIdFptan_ExtendedIndex = 52, + kX86InstIdFrndint_ExtendedIndex = 52, + kX86InstIdFrstor_ExtendedIndex = 55, + kX86InstIdFsave_ExtendedIndex = 55, + kX86InstIdFscale_ExtendedIndex = 52, + kX86InstIdFsin_ExtendedIndex = 52, + kX86InstIdFsincos_ExtendedIndex = 52, + kX86InstIdFsqrt_ExtendedIndex = 52, + kX86InstIdFst_ExtendedIndex = 70, + kX86InstIdFstcw_ExtendedIndex = 55, + kX86InstIdFstenv_ExtendedIndex = 55, + kX86InstIdFstp_ExtendedIndex = 71, + kX86InstIdFstsw_ExtendedIndex = 72, + kX86InstIdFsub_ExtendedIndex = 53, + kX86InstIdFsubp_ExtendedIndex = 54, + kX86InstIdFsubr_ExtendedIndex = 53, + kX86InstIdFsubrp_ExtendedIndex = 54, + kX86InstIdFtst_ExtendedIndex = 52, + kX86InstIdFucom_ExtendedIndex = 54, + kX86InstIdFucomi_ExtendedIndex = 61, + kX86InstIdFucomip_ExtendedIndex = 61, + kX86InstIdFucomp_ExtendedIndex = 54, + kX86InstIdFucompp_ExtendedIndex = 52, + kX86InstIdFwait_ExtendedIndex = 62, + kX86InstIdFxam_ExtendedIndex = 52, + kX86InstIdFxch_ExtendedIndex = 63, + kX86InstIdFxrstor_ExtendedIndex = 55, + kX86InstIdFxsave_ExtendedIndex = 55, + kX86InstIdFxtract_ExtendedIndex = 52, + kX86InstIdFyl2x_ExtendedIndex = 52, + kX86InstIdFyl2xp1_ExtendedIndex = 52, + kX86InstIdHaddpd_ExtendedIndex = 3, + kX86InstIdHaddps_ExtendedIndex = 3, + kX86InstIdHsubpd_ExtendedIndex = 3, + kX86InstIdHsubps_ExtendedIndex = 3, + kX86InstIdIdiv_ExtendedIndex = 73, + kX86InstIdImul_ExtendedIndex = 74, + kX86InstIdInc_ExtendedIndex = 75, + kX86InstIdInsertps_ExtendedIndex = 4, + kX86InstIdInsertq_ExtendedIndex = 76, + kX86InstIdInt_ExtendedIndex = 77, + kX86InstIdJa_ExtendedIndex = 78, + kX86InstIdJae_ExtendedIndex = 79, + kX86InstIdJb_ExtendedIndex = 79, + kX86InstIdJbe_ExtendedIndex = 78, + kX86InstIdJc_ExtendedIndex = 79, + kX86InstIdJe_ExtendedIndex = 80, + kX86InstIdJg_ExtendedIndex = 81, + kX86InstIdJge_ExtendedIndex = 82, + kX86InstIdJl_ExtendedIndex = 82, + kX86InstIdJle_ExtendedIndex = 81, + kX86InstIdJna_ExtendedIndex = 78, + kX86InstIdJnae_ExtendedIndex = 79, + kX86InstIdJnb_ExtendedIndex = 79, + kX86InstIdJnbe_ExtendedIndex = 78, + kX86InstIdJnc_ExtendedIndex = 79, + kX86InstIdJne_ExtendedIndex = 80, + kX86InstIdJng_ExtendedIndex = 81, + kX86InstIdJnge_ExtendedIndex = 82, + kX86InstIdJnl_ExtendedIndex = 82, + kX86InstIdJnle_ExtendedIndex = 81, + kX86InstIdJno_ExtendedIndex = 83, + kX86InstIdJnp_ExtendedIndex = 84, + kX86InstIdJns_ExtendedIndex = 85, + kX86InstIdJnz_ExtendedIndex = 80, + kX86InstIdJo_ExtendedIndex = 83, + kX86InstIdJp_ExtendedIndex = 84, + kX86InstIdJpe_ExtendedIndex = 84, + kX86InstIdJpo_ExtendedIndex = 84, + kX86InstIdJs_ExtendedIndex = 85, + kX86InstIdJz_ExtendedIndex = 80, + kX86InstIdJecxz_ExtendedIndex = 86, + kX86InstIdJmp_ExtendedIndex = 87, + kX86InstIdLahf_ExtendedIndex = 88, + kX86InstIdLddqu_ExtendedIndex = 89, + kX86InstIdLdmxcsr_ExtendedIndex = 19, + kX86InstIdLea_ExtendedIndex = 90, + kX86InstIdLeave_ExtendedIndex = 16, + kX86InstIdLfence_ExtendedIndex = 91, + kX86InstIdLodsB_ExtendedIndex = 92, + kX86InstIdLodsD_ExtendedIndex = 93, + kX86InstIdLodsQ_ExtendedIndex = 94, + kX86InstIdLodsW_ExtendedIndex = 95, + kX86InstIdLzcnt_ExtendedIndex = 9, + kX86InstIdMaskmovdqu_ExtendedIndex = 96, + kX86InstIdMaskmovq_ExtendedIndex = 97, + kX86InstIdMaxpd_ExtendedIndex = 3, + kX86InstIdMaxps_ExtendedIndex = 3, + kX86InstIdMaxsd_ExtendedIndex = 3, + kX86InstIdMaxss_ExtendedIndex = 3, + kX86InstIdMfence_ExtendedIndex = 91, + kX86InstIdMinpd_ExtendedIndex = 3, + kX86InstIdMinps_ExtendedIndex = 3, + kX86InstIdMinsd_ExtendedIndex = 3, + kX86InstIdMinss_ExtendedIndex = 3, + kX86InstIdMonitor_ExtendedIndex = 16, + kX86InstIdMov_ExtendedIndex = 98, + kX86InstIdMovPtr_ExtendedIndex = 99, + kX86InstIdMovapd_ExtendedIndex = 100, + kX86InstIdMovaps_ExtendedIndex = 101, + kX86InstIdMovbe_ExtendedIndex = 102, + kX86InstIdMovd_ExtendedIndex = 103, + kX86InstIdMovddup_ExtendedIndex = 104, + kX86InstIdMovdq2q_ExtendedIndex = 105, + kX86InstIdMovdqa_ExtendedIndex = 106, + kX86InstIdMovdqu_ExtendedIndex = 107, + kX86InstIdMovhlps_ExtendedIndex = 108, + kX86InstIdMovhpd_ExtendedIndex = 109, + kX86InstIdMovhps_ExtendedIndex = 110, + kX86InstIdMovlhps_ExtendedIndex = 111, + kX86InstIdMovlpd_ExtendedIndex = 112, + kX86InstIdMovlps_ExtendedIndex = 113, + kX86InstIdMovmskpd_ExtendedIndex = 114, + kX86InstIdMovmskps_ExtendedIndex = 114, + kX86InstIdMovntdq_ExtendedIndex = 115, + kX86InstIdMovntdqa_ExtendedIndex = 116, + kX86InstIdMovnti_ExtendedIndex = 117, + kX86InstIdMovntpd_ExtendedIndex = 118, + kX86InstIdMovntps_ExtendedIndex = 119, + kX86InstIdMovntq_ExtendedIndex = 120, + kX86InstIdMovntsd_ExtendedIndex = 121, + kX86InstIdMovntss_ExtendedIndex = 122, + kX86InstIdMovq_ExtendedIndex = 123, + kX86InstIdMovq2dq_ExtendedIndex = 124, + kX86InstIdMovsB_ExtendedIndex = 16, + kX86InstIdMovsD_ExtendedIndex = 125, + kX86InstIdMovsQ_ExtendedIndex = 16, + kX86InstIdMovsW_ExtendedIndex = 126, + kX86InstIdMovsd_ExtendedIndex = 127, + kX86InstIdMovshdup_ExtendedIndex = 36, + kX86InstIdMovsldup_ExtendedIndex = 36, + kX86InstIdMovss_ExtendedIndex = 128, + kX86InstIdMovsx_ExtendedIndex = 129, + kX86InstIdMovsxd_ExtendedIndex = 130, + kX86InstIdMovupd_ExtendedIndex = 131, + kX86InstIdMovups_ExtendedIndex = 132, + kX86InstIdMovzx_ExtendedIndex = 129, + kX86InstIdMpsadbw_ExtendedIndex = 4, + kX86InstIdMul_ExtendedIndex = 73, + kX86InstIdMulpd_ExtendedIndex = 3, + kX86InstIdMulps_ExtendedIndex = 3, + kX86InstIdMulsd_ExtendedIndex = 3, + kX86InstIdMulss_ExtendedIndex = 3, + kX86InstIdMulx_ExtendedIndex = 133, + kX86InstIdMwait_ExtendedIndex = 16, + kX86InstIdNeg_ExtendedIndex = 134, + kX86InstIdNop_ExtendedIndex = 48, + kX86InstIdNot_ExtendedIndex = 135, + kX86InstIdOr_ExtendedIndex = 2, + kX86InstIdOrpd_ExtendedIndex = 3, + kX86InstIdOrps_ExtendedIndex = 3, + kX86InstIdPabsb_ExtendedIndex = 136, + kX86InstIdPabsd_ExtendedIndex = 136, + kX86InstIdPabsw_ExtendedIndex = 136, + kX86InstIdPackssdw_ExtendedIndex = 136, + kX86InstIdPacksswb_ExtendedIndex = 136, + kX86InstIdPackusdw_ExtendedIndex = 3, + kX86InstIdPackuswb_ExtendedIndex = 136, + kX86InstIdPaddb_ExtendedIndex = 136, + kX86InstIdPaddd_ExtendedIndex = 136, + kX86InstIdPaddq_ExtendedIndex = 136, + kX86InstIdPaddsb_ExtendedIndex = 136, + kX86InstIdPaddsw_ExtendedIndex = 136, + kX86InstIdPaddusb_ExtendedIndex = 136, + kX86InstIdPaddusw_ExtendedIndex = 136, + kX86InstIdPaddw_ExtendedIndex = 136, + kX86InstIdPalignr_ExtendedIndex = 137, + kX86InstIdPand_ExtendedIndex = 136, + kX86InstIdPandn_ExtendedIndex = 136, + kX86InstIdPause_ExtendedIndex = 48, + kX86InstIdPavgb_ExtendedIndex = 136, + kX86InstIdPavgw_ExtendedIndex = 136, + kX86InstIdPblendvb_ExtendedIndex = 7, + kX86InstIdPblendw_ExtendedIndex = 4, + kX86InstIdPclmulqdq_ExtendedIndex = 4, + kX86InstIdPcmpeqb_ExtendedIndex = 136, + kX86InstIdPcmpeqd_ExtendedIndex = 136, + kX86InstIdPcmpeqq_ExtendedIndex = 3, + kX86InstIdPcmpeqw_ExtendedIndex = 136, + kX86InstIdPcmpestri_ExtendedIndex = 4, + kX86InstIdPcmpestrm_ExtendedIndex = 4, + kX86InstIdPcmpgtb_ExtendedIndex = 136, + kX86InstIdPcmpgtd_ExtendedIndex = 136, + kX86InstIdPcmpgtq_ExtendedIndex = 3, + kX86InstIdPcmpgtw_ExtendedIndex = 136, + kX86InstIdPcmpistri_ExtendedIndex = 4, + kX86InstIdPcmpistrm_ExtendedIndex = 4, + kX86InstIdPdep_ExtendedIndex = 133, + kX86InstIdPext_ExtendedIndex = 133, + kX86InstIdPextrb_ExtendedIndex = 138, + kX86InstIdPextrd_ExtendedIndex = 139, + kX86InstIdPextrq_ExtendedIndex = 140, + kX86InstIdPextrw_ExtendedIndex = 141, + kX86InstIdPf2id_ExtendedIndex = 142, + kX86InstIdPf2iw_ExtendedIndex = 142, + kX86InstIdPfacc_ExtendedIndex = 142, + kX86InstIdPfadd_ExtendedIndex = 142, + kX86InstIdPfcmpeq_ExtendedIndex = 142, + kX86InstIdPfcmpge_ExtendedIndex = 142, + kX86InstIdPfcmpgt_ExtendedIndex = 142, + kX86InstIdPfmax_ExtendedIndex = 142, + kX86InstIdPfmin_ExtendedIndex = 142, + kX86InstIdPfmul_ExtendedIndex = 142, + kX86InstIdPfnacc_ExtendedIndex = 142, + kX86InstIdPfpnacc_ExtendedIndex = 142, + kX86InstIdPfrcp_ExtendedIndex = 142, + kX86InstIdPfrcpit1_ExtendedIndex = 142, + kX86InstIdPfrcpit2_ExtendedIndex = 142, + kX86InstIdPfrsqit1_ExtendedIndex = 142, + kX86InstIdPfrsqrt_ExtendedIndex = 142, + kX86InstIdPfsub_ExtendedIndex = 142, + kX86InstIdPfsubr_ExtendedIndex = 142, + kX86InstIdPhaddd_ExtendedIndex = 136, + kX86InstIdPhaddsw_ExtendedIndex = 136, + kX86InstIdPhaddw_ExtendedIndex = 136, + kX86InstIdPhminposuw_ExtendedIndex = 3, + kX86InstIdPhsubd_ExtendedIndex = 136, + kX86InstIdPhsubsw_ExtendedIndex = 136, + kX86InstIdPhsubw_ExtendedIndex = 136, + kX86InstIdPi2fd_ExtendedIndex = 142, + kX86InstIdPi2fw_ExtendedIndex = 142, + kX86InstIdPinsrb_ExtendedIndex = 143, + kX86InstIdPinsrd_ExtendedIndex = 143, + kX86InstIdPinsrq_ExtendedIndex = 144, + kX86InstIdPinsrw_ExtendedIndex = 145, + kX86InstIdPmaddubsw_ExtendedIndex = 136, + kX86InstIdPmaddwd_ExtendedIndex = 136, + kX86InstIdPmaxsb_ExtendedIndex = 3, + kX86InstIdPmaxsd_ExtendedIndex = 3, + kX86InstIdPmaxsw_ExtendedIndex = 136, + kX86InstIdPmaxub_ExtendedIndex = 136, + kX86InstIdPmaxud_ExtendedIndex = 3, + kX86InstIdPmaxuw_ExtendedIndex = 3, + kX86InstIdPminsb_ExtendedIndex = 3, + kX86InstIdPminsd_ExtendedIndex = 3, + kX86InstIdPminsw_ExtendedIndex = 136, + kX86InstIdPminub_ExtendedIndex = 136, + kX86InstIdPminud_ExtendedIndex = 3, + kX86InstIdPminuw_ExtendedIndex = 3, + kX86InstIdPmovmskb_ExtendedIndex = 146, + kX86InstIdPmovsxbd_ExtendedIndex = 36, + kX86InstIdPmovsxbq_ExtendedIndex = 36, + kX86InstIdPmovsxbw_ExtendedIndex = 36, + kX86InstIdPmovsxdq_ExtendedIndex = 36, + kX86InstIdPmovsxwd_ExtendedIndex = 36, + kX86InstIdPmovsxwq_ExtendedIndex = 36, + kX86InstIdPmovzxbd_ExtendedIndex = 36, + kX86InstIdPmovzxbq_ExtendedIndex = 36, + kX86InstIdPmovzxbw_ExtendedIndex = 36, + kX86InstIdPmovzxdq_ExtendedIndex = 36, + kX86InstIdPmovzxwd_ExtendedIndex = 36, + kX86InstIdPmovzxwq_ExtendedIndex = 36, + kX86InstIdPmuldq_ExtendedIndex = 3, + kX86InstIdPmulhrsw_ExtendedIndex = 136, + kX86InstIdPmulhuw_ExtendedIndex = 136, + kX86InstIdPmulhw_ExtendedIndex = 136, + kX86InstIdPmulld_ExtendedIndex = 3, + kX86InstIdPmullw_ExtendedIndex = 136, + kX86InstIdPmuludq_ExtendedIndex = 136, + kX86InstIdPop_ExtendedIndex = 147, + kX86InstIdPopa_ExtendedIndex = 16, + kX86InstIdPopcnt_ExtendedIndex = 9, + kX86InstIdPopf_ExtendedIndex = 148, + kX86InstIdPor_ExtendedIndex = 136, + kX86InstIdPrefetch_ExtendedIndex = 149, + kX86InstIdPrefetch3dNow_ExtendedIndex = 19, + kX86InstIdPrefetchw3dNow_ExtendedIndex = 19, + kX86InstIdPsadbw_ExtendedIndex = 136, + kX86InstIdPshufb_ExtendedIndex = 136, + kX86InstIdPshufd_ExtendedIndex = 150, + kX86InstIdPshufhw_ExtendedIndex = 150, + kX86InstIdPshuflw_ExtendedIndex = 150, + kX86InstIdPshufw_ExtendedIndex = 151, + kX86InstIdPsignb_ExtendedIndex = 136, + kX86InstIdPsignd_ExtendedIndex = 136, + kX86InstIdPsignw_ExtendedIndex = 136, + kX86InstIdPslld_ExtendedIndex = 152, + kX86InstIdPslldq_ExtendedIndex = 153, + kX86InstIdPsllq_ExtendedIndex = 154, + kX86InstIdPsllw_ExtendedIndex = 155, + kX86InstIdPsrad_ExtendedIndex = 156, + kX86InstIdPsraw_ExtendedIndex = 157, + kX86InstIdPsrld_ExtendedIndex = 158, + kX86InstIdPsrldq_ExtendedIndex = 159, + kX86InstIdPsrlq_ExtendedIndex = 160, + kX86InstIdPsrlw_ExtendedIndex = 161, + kX86InstIdPsubb_ExtendedIndex = 136, + kX86InstIdPsubd_ExtendedIndex = 136, + kX86InstIdPsubq_ExtendedIndex = 136, + kX86InstIdPsubsb_ExtendedIndex = 136, + kX86InstIdPsubsw_ExtendedIndex = 136, + kX86InstIdPsubusb_ExtendedIndex = 136, + kX86InstIdPsubusw_ExtendedIndex = 136, + kX86InstIdPsubw_ExtendedIndex = 136, + kX86InstIdPswapd_ExtendedIndex = 142, + kX86InstIdPtest_ExtendedIndex = 34, + kX86InstIdPunpckhbw_ExtendedIndex = 136, + kX86InstIdPunpckhdq_ExtendedIndex = 136, + kX86InstIdPunpckhqdq_ExtendedIndex = 3, + kX86InstIdPunpckhwd_ExtendedIndex = 136, + kX86InstIdPunpcklbw_ExtendedIndex = 136, + kX86InstIdPunpckldq_ExtendedIndex = 136, + kX86InstIdPunpcklqdq_ExtendedIndex = 3, + kX86InstIdPunpcklwd_ExtendedIndex = 136, + kX86InstIdPush_ExtendedIndex = 162, + kX86InstIdPusha_ExtendedIndex = 16, + kX86InstIdPushf_ExtendedIndex = 163, + kX86InstIdPxor_ExtendedIndex = 136, + kX86InstIdRcl_ExtendedIndex = 164, + kX86InstIdRcpps_ExtendedIndex = 36, + kX86InstIdRcpss_ExtendedIndex = 41, + kX86InstIdRcr_ExtendedIndex = 164, + kX86InstIdRdfsbase_ExtendedIndex = 165, + kX86InstIdRdgsbase_ExtendedIndex = 165, + kX86InstIdRdrand_ExtendedIndex = 166, + kX86InstIdRdtsc_ExtendedIndex = 16, + kX86InstIdRdtscp_ExtendedIndex = 16, + kX86InstIdRepLodsB_ExtendedIndex = 167, + kX86InstIdRepLodsD_ExtendedIndex = 167, + kX86InstIdRepLodsQ_ExtendedIndex = 167, + kX86InstIdRepLodsW_ExtendedIndex = 167, + kX86InstIdRepMovsB_ExtendedIndex = 168, + kX86InstIdRepMovsD_ExtendedIndex = 168, + kX86InstIdRepMovsQ_ExtendedIndex = 168, + kX86InstIdRepMovsW_ExtendedIndex = 168, + kX86InstIdRepStosB_ExtendedIndex = 167, + kX86InstIdRepStosD_ExtendedIndex = 167, + kX86InstIdRepStosQ_ExtendedIndex = 167, + kX86InstIdRepStosW_ExtendedIndex = 167, + kX86InstIdRepeCmpsB_ExtendedIndex = 169, + kX86InstIdRepeCmpsD_ExtendedIndex = 169, + kX86InstIdRepeCmpsQ_ExtendedIndex = 169, + kX86InstIdRepeCmpsW_ExtendedIndex = 169, + kX86InstIdRepeScasB_ExtendedIndex = 169, + kX86InstIdRepeScasD_ExtendedIndex = 169, + kX86InstIdRepeScasQ_ExtendedIndex = 169, + kX86InstIdRepeScasW_ExtendedIndex = 169, + kX86InstIdRepneCmpsB_ExtendedIndex = 169, + kX86InstIdRepneCmpsD_ExtendedIndex = 169, + kX86InstIdRepneCmpsQ_ExtendedIndex = 169, + kX86InstIdRepneCmpsW_ExtendedIndex = 169, + kX86InstIdRepneScasB_ExtendedIndex = 169, + kX86InstIdRepneScasD_ExtendedIndex = 169, + kX86InstIdRepneScasQ_ExtendedIndex = 169, + kX86InstIdRepneScasW_ExtendedIndex = 169, + kX86InstIdRet_ExtendedIndex = 170, + kX86InstIdRol_ExtendedIndex = 171, + kX86InstIdRor_ExtendedIndex = 171, + kX86InstIdRorx_ExtendedIndex = 172, + kX86InstIdRoundpd_ExtendedIndex = 150, + kX86InstIdRoundps_ExtendedIndex = 150, + kX86InstIdRoundsd_ExtendedIndex = 173, + kX86InstIdRoundss_ExtendedIndex = 174, + kX86InstIdRsqrtps_ExtendedIndex = 36, + kX86InstIdRsqrtss_ExtendedIndex = 41, + kX86InstIdSahf_ExtendedIndex = 175, + kX86InstIdSal_ExtendedIndex = 176, + kX86InstIdSar_ExtendedIndex = 176, + kX86InstIdSarx_ExtendedIndex = 177, + kX86InstIdSbb_ExtendedIndex = 1, + kX86InstIdScasB_ExtendedIndex = 30, + kX86InstIdScasD_ExtendedIndex = 30, + kX86InstIdScasQ_ExtendedIndex = 30, + kX86InstIdScasW_ExtendedIndex = 31, + kX86InstIdSeta_ExtendedIndex = 178, + kX86InstIdSetae_ExtendedIndex = 179, + kX86InstIdSetb_ExtendedIndex = 179, + kX86InstIdSetbe_ExtendedIndex = 178, + kX86InstIdSetc_ExtendedIndex = 179, + kX86InstIdSete_ExtendedIndex = 180, + kX86InstIdSetg_ExtendedIndex = 181, + kX86InstIdSetge_ExtendedIndex = 182, + kX86InstIdSetl_ExtendedIndex = 182, + kX86InstIdSetle_ExtendedIndex = 181, + kX86InstIdSetna_ExtendedIndex = 178, + kX86InstIdSetnae_ExtendedIndex = 179, + kX86InstIdSetnb_ExtendedIndex = 179, + kX86InstIdSetnbe_ExtendedIndex = 178, + kX86InstIdSetnc_ExtendedIndex = 179, + kX86InstIdSetne_ExtendedIndex = 180, + kX86InstIdSetng_ExtendedIndex = 181, + kX86InstIdSetnge_ExtendedIndex = 182, + kX86InstIdSetnl_ExtendedIndex = 182, + kX86InstIdSetnle_ExtendedIndex = 181, + kX86InstIdSetno_ExtendedIndex = 183, + kX86InstIdSetnp_ExtendedIndex = 184, + kX86InstIdSetns_ExtendedIndex = 185, + kX86InstIdSetnz_ExtendedIndex = 180, + kX86InstIdSeto_ExtendedIndex = 183, + kX86InstIdSetp_ExtendedIndex = 184, + kX86InstIdSetpe_ExtendedIndex = 184, + kX86InstIdSetpo_ExtendedIndex = 184, + kX86InstIdSets_ExtendedIndex = 185, + kX86InstIdSetz_ExtendedIndex = 180, + kX86InstIdSfence_ExtendedIndex = 91, + kX86InstIdShl_ExtendedIndex = 176, + kX86InstIdShld_ExtendedIndex = 186, + kX86InstIdShlx_ExtendedIndex = 177, + kX86InstIdShr_ExtendedIndex = 176, + kX86InstIdShrd_ExtendedIndex = 187, + kX86InstIdShrx_ExtendedIndex = 177, + kX86InstIdShufpd_ExtendedIndex = 4, + kX86InstIdShufps_ExtendedIndex = 4, + kX86InstIdSqrtpd_ExtendedIndex = 36, + kX86InstIdSqrtps_ExtendedIndex = 36, + kX86InstIdSqrtsd_ExtendedIndex = 44, + kX86InstIdSqrtss_ExtendedIndex = 41, + kX86InstIdStc_ExtendedIndex = 17, + kX86InstIdStd_ExtendedIndex = 18, + kX86InstIdStmxcsr_ExtendedIndex = 19, + kX86InstIdStosB_ExtendedIndex = 188, + kX86InstIdStosD_ExtendedIndex = 188, + kX86InstIdStosQ_ExtendedIndex = 188, + kX86InstIdStosW_ExtendedIndex = 189, + kX86InstIdSub_ExtendedIndex = 2, + kX86InstIdSubpd_ExtendedIndex = 3, + kX86InstIdSubps_ExtendedIndex = 3, + kX86InstIdSubsd_ExtendedIndex = 3, + kX86InstIdSubss_ExtendedIndex = 3, + kX86InstIdTest_ExtendedIndex = 190, + kX86InstIdTzcnt_ExtendedIndex = 191, + kX86InstIdUcomisd_ExtendedIndex = 34, + kX86InstIdUcomiss_ExtendedIndex = 34, + kX86InstIdUd2_ExtendedIndex = 48, + kX86InstIdUnpckhpd_ExtendedIndex = 3, + kX86InstIdUnpckhps_ExtendedIndex = 3, + kX86InstIdUnpcklpd_ExtendedIndex = 3, + kX86InstIdUnpcklps_ExtendedIndex = 3, + kX86InstIdVaddpd_ExtendedIndex = 192, + kX86InstIdVaddps_ExtendedIndex = 192, + kX86InstIdVaddsd_ExtendedIndex = 193, + kX86InstIdVaddss_ExtendedIndex = 193, + kX86InstIdVaddsubpd_ExtendedIndex = 192, + kX86InstIdVaddsubps_ExtendedIndex = 192, + kX86InstIdVaesdec_ExtendedIndex = 193, + kX86InstIdVaesdeclast_ExtendedIndex = 193, + kX86InstIdVaesenc_ExtendedIndex = 193, + kX86InstIdVaesenclast_ExtendedIndex = 193, + kX86InstIdVaesimc_ExtendedIndex = 194, + kX86InstIdVaeskeygenassist_ExtendedIndex = 195, + kX86InstIdVandnpd_ExtendedIndex = 192, + kX86InstIdVandnps_ExtendedIndex = 192, + kX86InstIdVandpd_ExtendedIndex = 192, + kX86InstIdVandps_ExtendedIndex = 192, + kX86InstIdVblendpd_ExtendedIndex = 196, + kX86InstIdVblendps_ExtendedIndex = 196, + kX86InstIdVblendvpd_ExtendedIndex = 197, + kX86InstIdVblendvps_ExtendedIndex = 197, + kX86InstIdVbroadcastf128_ExtendedIndex = 198, + kX86InstIdVbroadcasti128_ExtendedIndex = 198, + kX86InstIdVbroadcastsd_ExtendedIndex = 199, + kX86InstIdVbroadcastss_ExtendedIndex = 200, + kX86InstIdVcmppd_ExtendedIndex = 196, + kX86InstIdVcmpps_ExtendedIndex = 196, + kX86InstIdVcmpsd_ExtendedIndex = 201, + kX86InstIdVcmpss_ExtendedIndex = 201, + kX86InstIdVcomisd_ExtendedIndex = 194, + kX86InstIdVcomiss_ExtendedIndex = 194, + kX86InstIdVcvtdq2pd_ExtendedIndex = 202, + kX86InstIdVcvtdq2ps_ExtendedIndex = 203, + kX86InstIdVcvtpd2dq_ExtendedIndex = 204, + kX86InstIdVcvtpd2ps_ExtendedIndex = 204, + kX86InstIdVcvtph2ps_ExtendedIndex = 202, + kX86InstIdVcvtps2dq_ExtendedIndex = 203, + kX86InstIdVcvtps2pd_ExtendedIndex = 202, + kX86InstIdVcvtps2ph_ExtendedIndex = 205, + kX86InstIdVcvtsd2si_ExtendedIndex = 206, + kX86InstIdVcvtsd2ss_ExtendedIndex = 193, + kX86InstIdVcvtsi2sd_ExtendedIndex = 207, + kX86InstIdVcvtsi2ss_ExtendedIndex = 207, + kX86InstIdVcvtss2sd_ExtendedIndex = 193, + kX86InstIdVcvtss2si_ExtendedIndex = 206, + kX86InstIdVcvttpd2dq_ExtendedIndex = 208, + kX86InstIdVcvttps2dq_ExtendedIndex = 203, + kX86InstIdVcvttsd2si_ExtendedIndex = 206, + kX86InstIdVcvttss2si_ExtendedIndex = 206, + kX86InstIdVdivpd_ExtendedIndex = 192, + kX86InstIdVdivps_ExtendedIndex = 192, + kX86InstIdVdivsd_ExtendedIndex = 193, + kX86InstIdVdivss_ExtendedIndex = 193, + kX86InstIdVdppd_ExtendedIndex = 201, + kX86InstIdVdpps_ExtendedIndex = 196, + kX86InstIdVextractf128_ExtendedIndex = 209, + kX86InstIdVextracti128_ExtendedIndex = 209, + kX86InstIdVextractps_ExtendedIndex = 210, + kX86InstIdVfmadd132pd_ExtendedIndex = 192, + kX86InstIdVfmadd132ps_ExtendedIndex = 192, + kX86InstIdVfmadd132sd_ExtendedIndex = 193, + kX86InstIdVfmadd132ss_ExtendedIndex = 193, + kX86InstIdVfmadd213pd_ExtendedIndex = 192, + kX86InstIdVfmadd213ps_ExtendedIndex = 192, + kX86InstIdVfmadd213sd_ExtendedIndex = 193, + kX86InstIdVfmadd213ss_ExtendedIndex = 193, + kX86InstIdVfmadd231pd_ExtendedIndex = 192, + kX86InstIdVfmadd231ps_ExtendedIndex = 192, + kX86InstIdVfmadd231sd_ExtendedIndex = 193, + kX86InstIdVfmadd231ss_ExtendedIndex = 193, + kX86InstIdVfmaddpd_ExtendedIndex = 211, + kX86InstIdVfmaddps_ExtendedIndex = 211, + kX86InstIdVfmaddsd_ExtendedIndex = 212, + kX86InstIdVfmaddss_ExtendedIndex = 212, + kX86InstIdVfmaddsub132pd_ExtendedIndex = 192, + kX86InstIdVfmaddsub132ps_ExtendedIndex = 192, + kX86InstIdVfmaddsub213pd_ExtendedIndex = 192, + kX86InstIdVfmaddsub213ps_ExtendedIndex = 192, + kX86InstIdVfmaddsub231pd_ExtendedIndex = 192, + kX86InstIdVfmaddsub231ps_ExtendedIndex = 192, + kX86InstIdVfmaddsubpd_ExtendedIndex = 211, + kX86InstIdVfmaddsubps_ExtendedIndex = 211, + kX86InstIdVfmsub132pd_ExtendedIndex = 192, + kX86InstIdVfmsub132ps_ExtendedIndex = 192, + kX86InstIdVfmsub132sd_ExtendedIndex = 193, + kX86InstIdVfmsub132ss_ExtendedIndex = 193, + kX86InstIdVfmsub213pd_ExtendedIndex = 192, + kX86InstIdVfmsub213ps_ExtendedIndex = 192, + kX86InstIdVfmsub213sd_ExtendedIndex = 193, + kX86InstIdVfmsub213ss_ExtendedIndex = 193, + kX86InstIdVfmsub231pd_ExtendedIndex = 192, + kX86InstIdVfmsub231ps_ExtendedIndex = 192, + kX86InstIdVfmsub231sd_ExtendedIndex = 193, + kX86InstIdVfmsub231ss_ExtendedIndex = 193, + kX86InstIdVfmsubadd132pd_ExtendedIndex = 192, + kX86InstIdVfmsubadd132ps_ExtendedIndex = 192, + kX86InstIdVfmsubadd213pd_ExtendedIndex = 192, + kX86InstIdVfmsubadd213ps_ExtendedIndex = 192, + kX86InstIdVfmsubadd231pd_ExtendedIndex = 192, + kX86InstIdVfmsubadd231ps_ExtendedIndex = 192, + kX86InstIdVfmsubaddpd_ExtendedIndex = 211, + kX86InstIdVfmsubaddps_ExtendedIndex = 211, + kX86InstIdVfmsubpd_ExtendedIndex = 211, + kX86InstIdVfmsubps_ExtendedIndex = 211, + kX86InstIdVfmsubsd_ExtendedIndex = 212, + kX86InstIdVfmsubss_ExtendedIndex = 212, + kX86InstIdVfnmadd132pd_ExtendedIndex = 192, + kX86InstIdVfnmadd132ps_ExtendedIndex = 192, + kX86InstIdVfnmadd132sd_ExtendedIndex = 193, + kX86InstIdVfnmadd132ss_ExtendedIndex = 193, + kX86InstIdVfnmadd213pd_ExtendedIndex = 192, + kX86InstIdVfnmadd213ps_ExtendedIndex = 192, + kX86InstIdVfnmadd213sd_ExtendedIndex = 193, + kX86InstIdVfnmadd213ss_ExtendedIndex = 193, + kX86InstIdVfnmadd231pd_ExtendedIndex = 192, + kX86InstIdVfnmadd231ps_ExtendedIndex = 192, + kX86InstIdVfnmadd231sd_ExtendedIndex = 193, + kX86InstIdVfnmadd231ss_ExtendedIndex = 193, + kX86InstIdVfnmaddpd_ExtendedIndex = 211, + kX86InstIdVfnmaddps_ExtendedIndex = 211, + kX86InstIdVfnmaddsd_ExtendedIndex = 212, + kX86InstIdVfnmaddss_ExtendedIndex = 212, + kX86InstIdVfnmsub132pd_ExtendedIndex = 192, + kX86InstIdVfnmsub132ps_ExtendedIndex = 192, + kX86InstIdVfnmsub132sd_ExtendedIndex = 193, + kX86InstIdVfnmsub132ss_ExtendedIndex = 193, + kX86InstIdVfnmsub213pd_ExtendedIndex = 192, + kX86InstIdVfnmsub213ps_ExtendedIndex = 192, + kX86InstIdVfnmsub213sd_ExtendedIndex = 193, + kX86InstIdVfnmsub213ss_ExtendedIndex = 193, + kX86InstIdVfnmsub231pd_ExtendedIndex = 192, + kX86InstIdVfnmsub231ps_ExtendedIndex = 192, + kX86InstIdVfnmsub231sd_ExtendedIndex = 193, + kX86InstIdVfnmsub231ss_ExtendedIndex = 193, + kX86InstIdVfnmsubpd_ExtendedIndex = 211, + kX86InstIdVfnmsubps_ExtendedIndex = 211, + kX86InstIdVfnmsubsd_ExtendedIndex = 212, + kX86InstIdVfnmsubss_ExtendedIndex = 212, + kX86InstIdVfrczpd_ExtendedIndex = 213, + kX86InstIdVfrczps_ExtendedIndex = 213, + kX86InstIdVfrczsd_ExtendedIndex = 214, + kX86InstIdVfrczss_ExtendedIndex = 214, + kX86InstIdVgatherdpd_ExtendedIndex = 215, + kX86InstIdVgatherdps_ExtendedIndex = 215, + kX86InstIdVgatherqpd_ExtendedIndex = 215, + kX86InstIdVgatherqps_ExtendedIndex = 216, + kX86InstIdVhaddpd_ExtendedIndex = 192, + kX86InstIdVhaddps_ExtendedIndex = 192, + kX86InstIdVhsubpd_ExtendedIndex = 192, + kX86InstIdVhsubps_ExtendedIndex = 192, + kX86InstIdVinsertf128_ExtendedIndex = 217, + kX86InstIdVinserti128_ExtendedIndex = 217, + kX86InstIdVinsertps_ExtendedIndex = 201, + kX86InstIdVlddqu_ExtendedIndex = 218, + kX86InstIdVldmxcsr_ExtendedIndex = 219, + kX86InstIdVmaskmovdqu_ExtendedIndex = 220, + kX86InstIdVmaskmovpd_ExtendedIndex = 221, + kX86InstIdVmaskmovps_ExtendedIndex = 222, + kX86InstIdVmaxpd_ExtendedIndex = 192, + kX86InstIdVmaxps_ExtendedIndex = 192, + kX86InstIdVmaxsd_ExtendedIndex = 192, + kX86InstIdVmaxss_ExtendedIndex = 192, + kX86InstIdVminpd_ExtendedIndex = 192, + kX86InstIdVminps_ExtendedIndex = 192, + kX86InstIdVminsd_ExtendedIndex = 192, + kX86InstIdVminss_ExtendedIndex = 192, + kX86InstIdVmovapd_ExtendedIndex = 223, + kX86InstIdVmovaps_ExtendedIndex = 224, + kX86InstIdVmovd_ExtendedIndex = 225, + kX86InstIdVmovddup_ExtendedIndex = 203, + kX86InstIdVmovdqa_ExtendedIndex = 226, + kX86InstIdVmovdqu_ExtendedIndex = 227, + kX86InstIdVmovhlps_ExtendedIndex = 228, + kX86InstIdVmovhpd_ExtendedIndex = 229, + kX86InstIdVmovhps_ExtendedIndex = 230, + kX86InstIdVmovlhps_ExtendedIndex = 228, + kX86InstIdVmovlpd_ExtendedIndex = 231, + kX86InstIdVmovlps_ExtendedIndex = 232, + kX86InstIdVmovmskpd_ExtendedIndex = 233, + kX86InstIdVmovmskps_ExtendedIndex = 233, + kX86InstIdVmovntdq_ExtendedIndex = 234, + kX86InstIdVmovntdqa_ExtendedIndex = 218, + kX86InstIdVmovntpd_ExtendedIndex = 235, + kX86InstIdVmovntps_ExtendedIndex = 235, + kX86InstIdVmovq_ExtendedIndex = 225, + kX86InstIdVmovsd_ExtendedIndex = 236, + kX86InstIdVmovshdup_ExtendedIndex = 203, + kX86InstIdVmovsldup_ExtendedIndex = 203, + kX86InstIdVmovss_ExtendedIndex = 237, + kX86InstIdVmovupd_ExtendedIndex = 238, + kX86InstIdVmovups_ExtendedIndex = 239, + kX86InstIdVmpsadbw_ExtendedIndex = 196, + kX86InstIdVmulpd_ExtendedIndex = 192, + kX86InstIdVmulps_ExtendedIndex = 192, + kX86InstIdVmulsd_ExtendedIndex = 192, + kX86InstIdVmulss_ExtendedIndex = 192, + kX86InstIdVorpd_ExtendedIndex = 192, + kX86InstIdVorps_ExtendedIndex = 192, + kX86InstIdVpabsb_ExtendedIndex = 203, + kX86InstIdVpabsd_ExtendedIndex = 203, + kX86InstIdVpabsw_ExtendedIndex = 203, + kX86InstIdVpackssdw_ExtendedIndex = 192, + kX86InstIdVpacksswb_ExtendedIndex = 192, + kX86InstIdVpackusdw_ExtendedIndex = 192, + kX86InstIdVpackuswb_ExtendedIndex = 192, + kX86InstIdVpaddb_ExtendedIndex = 192, + kX86InstIdVpaddd_ExtendedIndex = 192, + kX86InstIdVpaddq_ExtendedIndex = 192, + kX86InstIdVpaddsb_ExtendedIndex = 192, + kX86InstIdVpaddsw_ExtendedIndex = 192, + kX86InstIdVpaddusb_ExtendedIndex = 192, + kX86InstIdVpaddusw_ExtendedIndex = 192, + kX86InstIdVpaddw_ExtendedIndex = 192, + kX86InstIdVpalignr_ExtendedIndex = 196, + kX86InstIdVpand_ExtendedIndex = 192, + kX86InstIdVpandn_ExtendedIndex = 192, + kX86InstIdVpavgb_ExtendedIndex = 192, + kX86InstIdVpavgw_ExtendedIndex = 192, + kX86InstIdVpblendd_ExtendedIndex = 196, + kX86InstIdVpblendvb_ExtendedIndex = 240, + kX86InstIdVpblendw_ExtendedIndex = 196, + kX86InstIdVpbroadcastb_ExtendedIndex = 202, + kX86InstIdVpbroadcastd_ExtendedIndex = 202, + kX86InstIdVpbroadcastq_ExtendedIndex = 202, + kX86InstIdVpbroadcastw_ExtendedIndex = 202, + kX86InstIdVpclmulqdq_ExtendedIndex = 201, + kX86InstIdVpcmov_ExtendedIndex = 241, + kX86InstIdVpcmpeqb_ExtendedIndex = 192, + kX86InstIdVpcmpeqd_ExtendedIndex = 192, + kX86InstIdVpcmpeqq_ExtendedIndex = 192, + kX86InstIdVpcmpeqw_ExtendedIndex = 192, + kX86InstIdVpcmpestri_ExtendedIndex = 195, + kX86InstIdVpcmpestrm_ExtendedIndex = 195, + kX86InstIdVpcmpgtb_ExtendedIndex = 192, + kX86InstIdVpcmpgtd_ExtendedIndex = 192, + kX86InstIdVpcmpgtq_ExtendedIndex = 192, + kX86InstIdVpcmpgtw_ExtendedIndex = 192, + kX86InstIdVpcmpistri_ExtendedIndex = 195, + kX86InstIdVpcmpistrm_ExtendedIndex = 195, + kX86InstIdVpcomb_ExtendedIndex = 242, + kX86InstIdVpcomd_ExtendedIndex = 242, + kX86InstIdVpcomq_ExtendedIndex = 242, + kX86InstIdVpcomub_ExtendedIndex = 242, + kX86InstIdVpcomud_ExtendedIndex = 242, + kX86InstIdVpcomuq_ExtendedIndex = 242, + kX86InstIdVpcomuw_ExtendedIndex = 242, + kX86InstIdVpcomw_ExtendedIndex = 242, + kX86InstIdVperm2f128_ExtendedIndex = 243, + kX86InstIdVperm2i128_ExtendedIndex = 243, + kX86InstIdVpermd_ExtendedIndex = 244, + kX86InstIdVpermil2pd_ExtendedIndex = 245, + kX86InstIdVpermil2ps_ExtendedIndex = 245, + kX86InstIdVpermilpd_ExtendedIndex = 246, + kX86InstIdVpermilps_ExtendedIndex = 247, + kX86InstIdVpermpd_ExtendedIndex = 248, + kX86InstIdVpermps_ExtendedIndex = 244, + kX86InstIdVpermq_ExtendedIndex = 248, + kX86InstIdVpextrb_ExtendedIndex = 249, + kX86InstIdVpextrd_ExtendedIndex = 210, + kX86InstIdVpextrq_ExtendedIndex = 250, + kX86InstIdVpextrw_ExtendedIndex = 251, + kX86InstIdVpgatherdd_ExtendedIndex = 215, + kX86InstIdVpgatherdq_ExtendedIndex = 215, + kX86InstIdVpgatherqd_ExtendedIndex = 216, + kX86InstIdVpgatherqq_ExtendedIndex = 215, + kX86InstIdVphaddbd_ExtendedIndex = 214, + kX86InstIdVphaddbq_ExtendedIndex = 214, + kX86InstIdVphaddbw_ExtendedIndex = 214, + kX86InstIdVphaddd_ExtendedIndex = 192, + kX86InstIdVphadddq_ExtendedIndex = 214, + kX86InstIdVphaddsw_ExtendedIndex = 192, + kX86InstIdVphaddubd_ExtendedIndex = 214, + kX86InstIdVphaddubq_ExtendedIndex = 214, + kX86InstIdVphaddubw_ExtendedIndex = 214, + kX86InstIdVphaddudq_ExtendedIndex = 214, + kX86InstIdVphadduwd_ExtendedIndex = 214, + kX86InstIdVphadduwq_ExtendedIndex = 214, + kX86InstIdVphaddw_ExtendedIndex = 192, + kX86InstIdVphaddwd_ExtendedIndex = 214, + kX86InstIdVphaddwq_ExtendedIndex = 214, + kX86InstIdVphminposuw_ExtendedIndex = 194, + kX86InstIdVphsubbw_ExtendedIndex = 214, + kX86InstIdVphsubd_ExtendedIndex = 192, + kX86InstIdVphsubdq_ExtendedIndex = 214, + kX86InstIdVphsubsw_ExtendedIndex = 192, + kX86InstIdVphsubw_ExtendedIndex = 192, + kX86InstIdVphsubwd_ExtendedIndex = 214, + kX86InstIdVpinsrb_ExtendedIndex = 252, + kX86InstIdVpinsrd_ExtendedIndex = 253, + kX86InstIdVpinsrq_ExtendedIndex = 254, + kX86InstIdVpinsrw_ExtendedIndex = 255, + kX86InstIdVpmacsdd_ExtendedIndex = 256, + kX86InstIdVpmacsdqh_ExtendedIndex = 256, + kX86InstIdVpmacsdql_ExtendedIndex = 256, + kX86InstIdVpmacssdd_ExtendedIndex = 256, + kX86InstIdVpmacssdqh_ExtendedIndex = 256, + kX86InstIdVpmacssdql_ExtendedIndex = 256, + kX86InstIdVpmacsswd_ExtendedIndex = 256, + kX86InstIdVpmacssww_ExtendedIndex = 256, + kX86InstIdVpmacswd_ExtendedIndex = 256, + kX86InstIdVpmacsww_ExtendedIndex = 256, + kX86InstIdVpmadcsswd_ExtendedIndex = 256, + kX86InstIdVpmadcswd_ExtendedIndex = 256, + kX86InstIdVpmaddubsw_ExtendedIndex = 192, + kX86InstIdVpmaddwd_ExtendedIndex = 192, + kX86InstIdVpmaskmovd_ExtendedIndex = 257, + kX86InstIdVpmaskmovq_ExtendedIndex = 257, + kX86InstIdVpmaxsb_ExtendedIndex = 192, + kX86InstIdVpmaxsd_ExtendedIndex = 192, + kX86InstIdVpmaxsw_ExtendedIndex = 192, + kX86InstIdVpmaxub_ExtendedIndex = 192, + kX86InstIdVpmaxud_ExtendedIndex = 192, + kX86InstIdVpmaxuw_ExtendedIndex = 192, + kX86InstIdVpminsb_ExtendedIndex = 192, + kX86InstIdVpminsd_ExtendedIndex = 192, + kX86InstIdVpminsw_ExtendedIndex = 192, + kX86InstIdVpminub_ExtendedIndex = 192, + kX86InstIdVpminud_ExtendedIndex = 192, + kX86InstIdVpminuw_ExtendedIndex = 192, + kX86InstIdVpmovmskb_ExtendedIndex = 233, + kX86InstIdVpmovsxbd_ExtendedIndex = 203, + kX86InstIdVpmovsxbq_ExtendedIndex = 203, + kX86InstIdVpmovsxbw_ExtendedIndex = 203, + kX86InstIdVpmovsxdq_ExtendedIndex = 203, + kX86InstIdVpmovsxwd_ExtendedIndex = 203, + kX86InstIdVpmovsxwq_ExtendedIndex = 203, + kX86InstIdVpmovzxbd_ExtendedIndex = 203, + kX86InstIdVpmovzxbq_ExtendedIndex = 203, + kX86InstIdVpmovzxbw_ExtendedIndex = 203, + kX86InstIdVpmovzxdq_ExtendedIndex = 203, + kX86InstIdVpmovzxwd_ExtendedIndex = 203, + kX86InstIdVpmovzxwq_ExtendedIndex = 203, + kX86InstIdVpmuldq_ExtendedIndex = 192, + kX86InstIdVpmulhrsw_ExtendedIndex = 192, + kX86InstIdVpmulhuw_ExtendedIndex = 192, + kX86InstIdVpmulhw_ExtendedIndex = 192, + kX86InstIdVpmulld_ExtendedIndex = 192, + kX86InstIdVpmullw_ExtendedIndex = 192, + kX86InstIdVpmuludq_ExtendedIndex = 192, + kX86InstIdVpor_ExtendedIndex = 192, + kX86InstIdVpperm_ExtendedIndex = 258, + kX86InstIdVprotb_ExtendedIndex = 259, + kX86InstIdVprotd_ExtendedIndex = 260, + kX86InstIdVprotq_ExtendedIndex = 261, + kX86InstIdVprotw_ExtendedIndex = 262, + kX86InstIdVpsadbw_ExtendedIndex = 192, + kX86InstIdVpshab_ExtendedIndex = 263, + kX86InstIdVpshad_ExtendedIndex = 263, + kX86InstIdVpshaq_ExtendedIndex = 263, + kX86InstIdVpshaw_ExtendedIndex = 263, + kX86InstIdVpshlb_ExtendedIndex = 263, + kX86InstIdVpshld_ExtendedIndex = 263, + kX86InstIdVpshlq_ExtendedIndex = 263, + kX86InstIdVpshlw_ExtendedIndex = 263, + kX86InstIdVpshufb_ExtendedIndex = 192, + kX86InstIdVpshufd_ExtendedIndex = 264, + kX86InstIdVpshufhw_ExtendedIndex = 264, + kX86InstIdVpshuflw_ExtendedIndex = 264, + kX86InstIdVpsignb_ExtendedIndex = 192, + kX86InstIdVpsignd_ExtendedIndex = 192, + kX86InstIdVpsignw_ExtendedIndex = 192, + kX86InstIdVpslld_ExtendedIndex = 265, + kX86InstIdVpslldq_ExtendedIndex = 266, + kX86InstIdVpsllq_ExtendedIndex = 267, + kX86InstIdVpsllvd_ExtendedIndex = 192, + kX86InstIdVpsllvq_ExtendedIndex = 192, + kX86InstIdVpsllw_ExtendedIndex = 268, + kX86InstIdVpsrad_ExtendedIndex = 269, + kX86InstIdVpsravd_ExtendedIndex = 192, + kX86InstIdVpsraw_ExtendedIndex = 270, + kX86InstIdVpsrld_ExtendedIndex = 271, + kX86InstIdVpsrldq_ExtendedIndex = 266, + kX86InstIdVpsrlq_ExtendedIndex = 272, + kX86InstIdVpsrlvd_ExtendedIndex = 192, + kX86InstIdVpsrlvq_ExtendedIndex = 192, + kX86InstIdVpsrlw_ExtendedIndex = 273, + kX86InstIdVpsubb_ExtendedIndex = 192, + kX86InstIdVpsubd_ExtendedIndex = 192, + kX86InstIdVpsubq_ExtendedIndex = 192, + kX86InstIdVpsubsb_ExtendedIndex = 192, + kX86InstIdVpsubsw_ExtendedIndex = 192, + kX86InstIdVpsubusb_ExtendedIndex = 192, + kX86InstIdVpsubusw_ExtendedIndex = 192, + kX86InstIdVpsubw_ExtendedIndex = 192, + kX86InstIdVptest_ExtendedIndex = 274, + kX86InstIdVpunpckhbw_ExtendedIndex = 192, + kX86InstIdVpunpckhdq_ExtendedIndex = 192, + kX86InstIdVpunpckhqdq_ExtendedIndex = 192, + kX86InstIdVpunpckhwd_ExtendedIndex = 192, + kX86InstIdVpunpcklbw_ExtendedIndex = 192, + kX86InstIdVpunpckldq_ExtendedIndex = 192, + kX86InstIdVpunpcklqdq_ExtendedIndex = 192, + kX86InstIdVpunpcklwd_ExtendedIndex = 192, + kX86InstIdVpxor_ExtendedIndex = 192, + kX86InstIdVrcpps_ExtendedIndex = 203, + kX86InstIdVrcpss_ExtendedIndex = 193, + kX86InstIdVroundpd_ExtendedIndex = 264, + kX86InstIdVroundps_ExtendedIndex = 264, + kX86InstIdVroundsd_ExtendedIndex = 201, + kX86InstIdVroundss_ExtendedIndex = 201, + kX86InstIdVrsqrtps_ExtendedIndex = 203, + kX86InstIdVrsqrtss_ExtendedIndex = 193, + kX86InstIdVshufpd_ExtendedIndex = 196, + kX86InstIdVshufps_ExtendedIndex = 196, + kX86InstIdVsqrtpd_ExtendedIndex = 203, + kX86InstIdVsqrtps_ExtendedIndex = 203, + kX86InstIdVsqrtsd_ExtendedIndex = 193, + kX86InstIdVsqrtss_ExtendedIndex = 193, + kX86InstIdVstmxcsr_ExtendedIndex = 219, + kX86InstIdVsubpd_ExtendedIndex = 192, + kX86InstIdVsubps_ExtendedIndex = 192, + kX86InstIdVsubsd_ExtendedIndex = 193, + kX86InstIdVsubss_ExtendedIndex = 193, + kX86InstIdVtestpd_ExtendedIndex = 275, + kX86InstIdVtestps_ExtendedIndex = 275, + kX86InstIdVucomisd_ExtendedIndex = 276, + kX86InstIdVucomiss_ExtendedIndex = 276, + kX86InstIdVunpckhpd_ExtendedIndex = 192, + kX86InstIdVunpckhps_ExtendedIndex = 192, + kX86InstIdVunpcklpd_ExtendedIndex = 192, + kX86InstIdVunpcklps_ExtendedIndex = 192, + kX86InstIdVxorpd_ExtendedIndex = 192, + kX86InstIdVxorps_ExtendedIndex = 192, + kX86InstIdVzeroall_ExtendedIndex = 277, + kX86InstIdVzeroupper_ExtendedIndex = 277, + kX86InstIdWrfsbase_ExtendedIndex = 278, + kX86InstIdWrgsbase_ExtendedIndex = 278, + kX86InstIdXadd_ExtendedIndex = 279, + kX86InstIdXchg_ExtendedIndex = 280, + kX86InstIdXgetbv_ExtendedIndex = 16, + kX86InstIdXor_ExtendedIndex = 2, + kX86InstIdXorpd_ExtendedIndex = 3, + kX86InstIdXorps_ExtendedIndex = 3, + kX86InstIdXrstor_ExtendedIndex = 281, + kX86InstIdXrstor64_ExtendedIndex = 281, + kX86InstIdXsave_ExtendedIndex = 281, + kX86InstIdXsave64_ExtendedIndex = 281, + kX86InstIdXsaveopt_ExtendedIndex = 281, + kX86InstIdXsaveopt64_ExtendedIndex = 281, + kX86InstIdXsetbv_ExtendedIndex = 16 +}; +// ${X86InstData:End} + +// Please run tools/src-gendefs.js (by using just node.js, without any dependencies) to regenerate the code above. +const X86InstInfo _x86InstInfo[] = { + // <----------------------------+--------------------+-------------------------------------------+-------------------+------------------------------------+-------------+-------+---------------------------------------------------------------------------------------------------+ + // | | Instruction Opcodes | | Instruction Flags | E-FLAGS | Write | Operands (Gp/Fp/Mm/K/Xmm/Ymm/Zmm Regs, Mem, Imm, Label, None/Undefined) | + // Instruction Id | Instruction Name +---------------------+---------------------+ Instruction Enc. +---------------+--------------------+-------------+---+---+-------------------+-------------------+-------------------+-------------------+-------------------+ + // | | 0:PP-MMM OP/O L/W/EW| 1:PP-MMM OP/O L/W/EW| | Global Flags |A512(ID|VL|kz|rnd|b)| EF:OSZAPCDX |Idx| Sz| [0] 1st Operand | [1] 2nd Operand | [2] 3rd Operand | [3] 4th Operand | [4] 5th Operand | + // <----------------------------+--------------------+---------------------+---------------------+-------------------+---------------+--------------------+-------------+---+---+-------------------+-------------------+-------------------+-------------------+-------------------+ + INST(kInstIdNone , "" , U , U , Enc(None) , F(None) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdAdc , "adc" , O_000000(10,2,_,_,_), U , Enc(X86Arith) , F(Lock) , EF(WWWWWX__), 0 , 0 , O(GqdwbMem) , O(GqdwbMem)|O(Imm), U , U , U ), + INST(kX86InstIdAdd , "add" , O_000000(00,0,_,_,_), U , Enc(X86Arith) , F(Lock) , EF(WWWWWW__), 0 , 0 , O(GqdwbMem) , O(GqdwbMem)|O(Imm), U , U , U ), + INST(kX86InstIdAddpd , "addpd" , O_660F00(58,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdAddps , "addps" , O_000F00(58,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdAddsd , "addsd" , O_F20F00(58,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdAddss , "addss" , O_F30F00(58,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdAddsubpd , "addsubpd" , O_660F00(D0,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdAddsubps , "addsubps" , O_F20F00(D0,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdAesdec , "aesdec" , O_660F38(DE,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdAesdeclast , "aesdeclast" , O_660F38(DF,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdAesenc , "aesenc" , O_660F38(DC,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdAesenclast , "aesenclast" , O_660F38(DD,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdAesimc , "aesimc" , O_660F38(DB,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdAeskeygenassist , "aeskeygenassist" , O_660F3A(DF,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdAnd , "and" , O_000000(20,4,_,_,_), U , Enc(X86Arith) , F(Lock) , EF(WWWUWW__), 0 , 0 , O(GqdwbMem) , O(GqdwbMem)|O(Imm), U , U , U ), + INST(kX86InstIdAndn , "andn" , O_000F38(F2,U,_,_,_), U , Enc(AvxRvm) , F(None) , EF(WWWUUW__), 0 , 0 , O(Gqd) , O(Gqd) , O(GqdMem) , U , U ), + INST(kX86InstIdAndnpd , "andnpd" , O_660F00(55,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdAndnps , "andnps" , O_000F00(55,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdAndpd , "andpd" , O_660F00(54,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdAndps , "andps" , O_000F00(54,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdBextr , "bextr" , O_000F38(F7,U,_,_,_), U , Enc(AvxRmv) , F(None) , EF(WUWUUW__), 0 , 0 , O(Gqd) , O(GqdMem) , O(Gqd) , U , U ), + INST(kX86InstIdBlendpd , "blendpd" , O_660F3A(0D,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdBlendps , "blendps" , O_660F3A(0C,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdBlendvpd , "blendvpd" , O_660F38(15,U,_,_,_), U , Enc(ExtRm) , F(None)|F(Special) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdBlendvps , "blendvps" , O_660F38(14,U,_,_,_), U , Enc(ExtRm) , F(None)|F(Special) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdBlsi , "blsi" , O_000F38(F3,3,_,_,_), U , Enc(AvxVm) , F(None) , EF(WWWUUW__), 0 , 0 , O(Gqd) , O(GqdMem) , U , U , U ), + INST(kX86InstIdBlsmsk , "blsmsk" , O_000F38(F3,2,_,_,_), U , Enc(AvxVm) , F(None) , EF(WWWUUW__), 0 , 0 , O(Gqd) , O(GqdMem) , U , U , U ), + INST(kX86InstIdBlsr , "blsr" , O_000F38(F3,1,_,_,_), U , Enc(AvxVm) , F(None) , EF(WWWUUW__), 0 , 0 , O(Gqd) , O(GqdMem) , U , U , U ), + INST(kX86InstIdBsf , "bsf" , O_000F00(BC,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(UUWUUU__), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdBsr , "bsr" , O_000F00(BD,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(UUWUUU__), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdBswap , "bswap" , O_000F00(C8,U,_,_,_), U , Enc(X86BSwap) , F(None) , EF(________), 0 , 0 , O(Gqd) , U , U , U , U ), + INST(kX86InstIdBt , "bt" , O_000F00(A3,U,_,_,_), O_000F00(BA,4,_,_,_), Enc(X86BTest) , F(Test) , EF(UU_UUW__), 0 , 0 , O(GqdwMem) , O(Gqdw)|O(Imm) , U , U , U ), + INST(kX86InstIdBtc , "btc" , O_000F00(BB,U,_,_,_), O_000F00(BA,7,_,_,_), Enc(X86BTest) , F(Lock) , EF(UU_UUW__), 0 , 0 , O(GqdwMem) , O(Gqdw)|O(Imm) , U , U , U ), + INST(kX86InstIdBtr , "btr" , O_000F00(B3,U,_,_,_), O_000F00(BA,6,_,_,_), Enc(X86BTest) , F(Lock) , EF(UU_UUW__), 0 , 0 , O(GqdwMem) , O(Gqdw)|O(Imm) , U , U , U ), + INST(kX86InstIdBts , "bts" , O_000F00(AB,U,_,_,_), O_000F00(BA,5,_,_,_), Enc(X86BTest) , F(Lock) , EF(UU_UUW__), 0 , 0 , O(GqdwMem) , O(Gqdw)|O(Imm) , U , U , U ), + INST(kX86InstIdBzhi , "bzhi" , O_000F38(F5,U,_,_,_), U , Enc(AvxRmv) , F(None) , EF(WWWUUW__), 0 , 0 , O(Gqd) , O(GqdMem) , O(Gqd) , U , U ), + INST(kX86InstIdCall , "call" , O_000000(FF,2,_,_,_), O_000000(E8,U,_,_,_), Enc(X86Call) , F(Flow) , EF(________), 0 , 0 , O(GqdMem)|O(LbImm), U , U , U , U ), + INST(kX86InstIdCbw , "cbw" , O_660000(98,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdCdq , "cdq" , O_000000(99,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdCdqe , "cdqe" , O_000000(98,U,_,W,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdClc , "clc" , O_000000(F8,U,_,_,_), U , Enc(X86Op) , F(None) , EF(_____W__), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdCld , "cld" , O_000000(FC,U,_,_,_), U , Enc(X86Op) , F(None) , EF(______W_), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdClflush , "clflush" , O_000F00(AE,7,_,_,_), U , Enc(X86M) , F(None) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdCmc , "cmc" , O_000000(F5,U,_,_,_), U , Enc(X86Op) , F(None) , EF(_____X__), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdCmova , "cmova" , O_000F00(47,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(__R__R__), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovae , "cmovae" , O_000F00(43,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(_____R__), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovb , "cmovb" , O_000F00(42,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(_____R__), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovbe , "cmovbe" , O_000F00(46,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(__R__R__), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovc , "cmovc" , O_000F00(42,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(_____R__), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmove , "cmove" , O_000F00(44,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(__R_____), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovg , "cmovg" , O_000F00(4F,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(RRR_____), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovge , "cmovge" , O_000F00(4D,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(RR______), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovl , "cmovl" , O_000F00(4C,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(RR______), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovle , "cmovle" , O_000F00(4E,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(RRR_____), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovna , "cmovna" , O_000F00(46,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(__R__R__), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovnae , "cmovnae" , O_000F00(42,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(_____R__), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovnb , "cmovnb" , O_000F00(43,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(_____R__), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovnbe , "cmovnbe" , O_000F00(47,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(__R__R__), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovnc , "cmovnc" , O_000F00(43,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(_____R__), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovne , "cmovne" , O_000F00(45,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(__R_____), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovng , "cmovng" , O_000F00(4E,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(RRR_____), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovnge , "cmovnge" , O_000F00(4C,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(RR______), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovnl , "cmovnl" , O_000F00(4D,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(RR______), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovnle , "cmovnle" , O_000F00(4F,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(RRR_____), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovno , "cmovno" , O_000F00(41,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(R_______), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovnp , "cmovnp" , O_000F00(4B,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(____R___), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovns , "cmovns" , O_000F00(49,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(_R______), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovnz , "cmovnz" , O_000F00(45,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(__R_____), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovo , "cmovo" , O_000F00(40,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(R_______), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovp , "cmovp" , O_000F00(4A,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(____R___), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovpe , "cmovpe" , O_000F00(4A,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(____R___), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovpo , "cmovpo" , O_000F00(4B,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(____R___), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovs , "cmovs" , O_000F00(48,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(_R______), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmovz , "cmovz" , O_000F00(44,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(__R_____), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdCmp , "cmp" , O_000000(38,7,_,_,_), U , Enc(X86Arith) , F(Test) , EF(WWWWWW__), 0 , 0 , O(GqdwbMem) , O(GqdwbMem)|O(Imm), U , U , U ), + INST(kX86InstIdCmppd , "cmppd" , O_660F00(C2,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdCmpps , "cmpps" , O_000F00(C2,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdCmpsB , "cmps_b" , O_000000(A6,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdCmpsD , "cmps_d" , O_000000(A7,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdCmpsQ , "cmps_q" , O_000000(A7,U,_,W,_), U , Enc(X86Op) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdCmpsW , "cmps_w" , O_000000(A7,U,_,_,_), U , Enc(X86Op_66H) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdCmpsd , "cmpsd" , O_F20F00(C2,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdCmpss , "cmpss" , O_F30F00(C2,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdCmpxchg , "cmpxchg" , O_000F00(B0,U,_,_,_), U , Enc(X86RmReg) , F(Lock)|F(Special) , EF(WWWWWW__), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdCmpxchg16b , "cmpxchg16b" , O_000F00(C7,1,_,W,_), U , Enc(X86M) , F(None)|F(Special) , EF(__W_____), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdCmpxchg8b , "cmpxchg8b" , O_000F00(C7,1,_,_,_), U , Enc(X86M) , F(None)|F(Special) , EF(__W_____), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdComisd , "comisd" , O_660F00(2F,U,_,_,_), U , Enc(ExtRm) , F(Test) , EF(WWWWWW__), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdComiss , "comiss" , O_000F00(2F,U,_,_,_), U , Enc(ExtRm) , F(Test) , EF(WWWWWW__), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCpuid , "cpuid" , O_000F00(A2,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdCqo , "cqo" , O_000000(99,U,_,W,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdCrc32 , "crc32" , O_F20F38(F0,U,_,_,_), U , Enc(ExtCrc) , F(None) , EF(________), 0 , 0 , O(Gqd) , O(GqdwbMem) , U , U , U ), + INST(kX86InstIdCvtdq2pd , "cvtdq2pd" , O_F30F00(E6,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCvtdq2ps , "cvtdq2ps" , O_000F00(5B,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCvtpd2dq , "cvtpd2dq" , O_F20F00(E6,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCvtpd2pi , "cvtpd2pi" , O_660F00(2D,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 8 , O(Mm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCvtpd2ps , "cvtpd2ps" , O_660F00(5A,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCvtpi2pd , "cvtpi2pd" , O_660F00(2A,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(MmMem) , U , U , U ), + INST(kX86InstIdCvtpi2ps , "cvtpi2ps" , O_000F00(2A,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 8 , O(Xmm) , O(MmMem) , U , U , U ), + INST(kX86InstIdCvtps2dq , "cvtps2dq" , O_660F00(5B,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCvtps2pd , "cvtps2pd" , O_000F00(5A,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCvtps2pi , "cvtps2pi" , O_000F00(2D,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 8 , O(Mm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCvtsd2si , "cvtsd2si" , O_F20F00(2D,U,_,_,_), U , Enc(ExtRm_Q) , F(Move) , EF(________), 0 , 8 , O(Gqd) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCvtsd2ss , "cvtsd2ss" , O_F20F00(5A,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 4 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCvtsi2sd , "cvtsi2sd" , O_F20F00(2A,U,_,_,_), U , Enc(ExtRm_Q) , F(Move) , EF(________), 0 , 8 , O(Xmm) , O(GqdMem) , U , U , U ), + INST(kX86InstIdCvtsi2ss , "cvtsi2ss" , O_F30F00(2A,U,_,_,_), U , Enc(ExtRm_Q) , F(Move) , EF(________), 0 , 4 , O(Xmm) , O(GqdMem) , U , U , U ), + INST(kX86InstIdCvtss2sd , "cvtss2sd" , O_F30F00(5A,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 8 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCvtss2si , "cvtss2si" , O_F30F00(2D,U,_,_,_), U , Enc(ExtRm_Q) , F(Move) , EF(________), 0 , 8 , O(Gqd) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCvttpd2dq , "cvttpd2dq" , O_660F00(E6,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCvttpd2pi , "cvttpd2pi" , O_660F00(2C,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 8 , O(Mm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCvttps2dq , "cvttps2dq" , O_F30F00(5B,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCvttps2pi , "cvttps2pi" , O_000F00(2C,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 8 , O(Mm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCvttsd2si , "cvttsd2si" , O_F20F00(2C,U,_,_,_), U , Enc(ExtRm_Q) , F(Move) , EF(________), 0 , 8 , O(Gqd) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCvttss2si , "cvttss2si" , O_F30F00(2C,U,_,_,_), U , Enc(ExtRm_Q) , F(Move) , EF(________), 0 , 8 , O(Gqd) , O(XmmMem) , U , U , U ), + INST(kX86InstIdCwd , "cwd" , O_660000(99,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdCwde , "cwde" , O_000000(98,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdDaa , "daa" , O_000000(27,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(UWWXWX__), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdDas , "das" , O_000000(2F,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(UWWXWX__), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdDec , "dec" , O_000000(FE,1,_,_,_), O_000000(48,U,_,_,_), Enc(X86IncDec) , F(Lock) , EF(WWWWW___), 0 , 0 , O(GqdwbMem) , U , U , U , U ), + INST(kX86InstIdDiv , "div" , O_000000(F6,6,_,_,_), U , Enc(X86Rm_B) , F(None)|F(Special) , EF(UUUUUU__), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdDivpd , "divpd" , O_660F00(5E,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdDivps , "divps" , O_000F00(5E,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdDivsd , "divsd" , O_F20F00(5E,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdDivss , "divss" , O_F30F00(5E,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdDppd , "dppd" , O_660F3A(41,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdDpps , "dpps" , O_660F3A(40,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdEmms , "emms" , O_000F00(77,U,_,_,_), U , Enc(X86Op) , F(None) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdEnter , "enter" , O_000000(C8,U,_,_,_), U , Enc(X86Enter) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdExtractps , "extractps" , O_660F3A(17,U,_,_,_), O_660F3A(17,U,_,_,_), Enc(ExtExtract) , F(Move) , EF(________), 0 , 8 , O(GqdMem) , O(Xmm) , U , U , U ), + INST(kX86InstIdExtrq , "extrq" , O_660F00(79,U,_,_,_), O_660F00(78,0,_,_,_), Enc(ExtExtrq) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(Xmm)|O(Imm) , O(None)|O(Imm) , U , U ), + INST(kX86InstIdF2xm1 , "f2xm1" , O_00_X(D9F0,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFabs , "fabs" , O_00_X(D9E1,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFadd , "fadd" , O_00_X(C0C0,0) , U , Enc(FpuArith) , F(Fp)|F(Mem4_8) , EF(________), 0 , 0 , O(FpMem) , O(Fp) , U , U , U ), + INST(kX86InstIdFaddp , "faddp" , O_00_X(DEC0,U) , U , Enc(FpuRDef) , F(Fp) , EF(________), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFbld , "fbld" , O_000000(DF,4,_,_,_), U , Enc(X86M) , F(Fp) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFbstp , "fbstp" , O_000000(DF,6,_,_,_), U , Enc(X86M) , F(Fp) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFchs , "fchs" , O_00_X(D9E0,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFclex , "fclex" , O_9B_X(DBE2,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFcmovb , "fcmovb" , O_00_X(DAC0,U) , U , Enc(FpuR) , F(Fp) , EF(_____R__), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFcmovbe , "fcmovbe" , O_00_X(DAD0,U) , U , Enc(FpuR) , F(Fp) , EF(__R__R__), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFcmove , "fcmove" , O_00_X(DAC8,U) , U , Enc(FpuR) , F(Fp) , EF(__R_____), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFcmovnb , "fcmovnb" , O_00_X(DBC0,U) , U , Enc(FpuR) , F(Fp) , EF(_____R__), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFcmovnbe , "fcmovnbe" , O_00_X(DBD0,U) , U , Enc(FpuR) , F(Fp) , EF(__R__R__), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFcmovne , "fcmovne" , O_00_X(DBC8,U) , U , Enc(FpuR) , F(Fp) , EF(__R_____), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFcmovnu , "fcmovnu" , O_00_X(DBD8,U) , U , Enc(FpuR) , F(Fp) , EF(____R___), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFcmovu , "fcmovu" , O_00_X(DAD8,U) , U , Enc(FpuR) , F(Fp) , EF(____R___), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFcom , "fcom" , O_00_X(D0D0,2) , U , Enc(FpuCom) , F(Fp) , EF(________), 0 , 0 , O(Fp)|O(Mem) , O(Fp) , U , U , U ), + INST(kX86InstIdFcomi , "fcomi" , O_00_X(DBF0,U) , U , Enc(FpuR) , F(Fp) , EF(WWWWWW__), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFcomip , "fcomip" , O_00_X(DFF0,U) , U , Enc(FpuR) , F(Fp) , EF(WWWWWW__), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFcomp , "fcomp" , O_00_X(D8D8,3) , U , Enc(FpuCom) , F(Fp) , EF(________), 0 , 0 , O(Fp)|O(Mem) , O(Fp) , U , U , U ), + INST(kX86InstIdFcompp , "fcompp" , O_00_X(DED9,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFcos , "fcos" , O_00_X(D9FF,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFdecstp , "fdecstp" , O_00_X(D9F6,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFdiv , "fdiv" , O_00_X(F0F8,6) , U , Enc(FpuArith) , F(Fp)|F(Mem4_8) , EF(________), 0 , 0 , O(FpMem) , O(Fp) , U , U , U ), + INST(kX86InstIdFdivp , "fdivp" , O_00_X(DEF8,U) , U , Enc(FpuRDef) , F(Fp) , EF(________), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFdivr , "fdivr" , O_00_X(F8F0,7) , U , Enc(FpuArith) , F(Fp)|F(Mem4_8) , EF(________), 0 , 0 , O(FpMem) , O(Fp) , U , U , U ), + INST(kX86InstIdFdivrp , "fdivrp" , O_00_X(DEF0,U) , U , Enc(FpuRDef) , F(Fp) , EF(________), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFemms , "femms" , O_000F00(0E,U,_,_,_), U , Enc(X86Op) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFfree , "ffree" , O_00_X(DDC0,U) , U , Enc(FpuR) , F(Fp) , EF(________), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFiadd , "fiadd" , O_000000(DA,0,_,_,_), U , Enc(FpuM) , F(Fp)|F(Mem2_4) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFicom , "ficom" , O_000000(DA,2,_,_,_), U , Enc(FpuM) , F(Fp)|F(Mem2_4) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFicomp , "ficomp" , O_000000(DA,3,_,_,_), U , Enc(FpuM) , F(Fp)|F(Mem2_4) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFidiv , "fidiv" , O_000000(DA,6,_,_,_), U , Enc(FpuM) , F(Fp)|F(Mem2_4) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFidivr , "fidivr" , O_000000(DA,7,_,_,_), U , Enc(FpuM) , F(Fp)|F(Mem2_4) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFild , "fild" , O_000000(DB,0,_,_,_), O_000000(DF,5,_,_,_), Enc(FpuM) , F(Fp)|F(Mem2_4_8) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFimul , "fimul" , O_000000(DA,1,_,_,_), U , Enc(FpuM) , F(Fp)|F(Mem2_4) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFincstp , "fincstp" , O_00_X(D9F7,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFinit , "finit" , O_9B_X(DBE3,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFist , "fist" , O_000000(DB,2,_,_,_), U , Enc(FpuM) , F(Fp)|F(Mem2_4) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFistp , "fistp" , O_000000(DB,3,_,_,_), O_000000(DF,7,_,_,_), Enc(FpuM) , F(Fp)|F(Mem2_4_8) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFisttp , "fisttp" , O_000000(DB,1,_,_,_), O_000000(DD,1,_,_,_), Enc(FpuM) , F(Fp)|F(Mem2_4_8) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFisub , "fisub" , O_000000(DA,4,_,_,_), U , Enc(FpuM) , F(Fp)|F(Mem2_4) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFisubr , "fisubr" , O_000000(DA,5,_,_,_), U , Enc(FpuM) , F(Fp)|F(Mem2_4) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFld , "fld" , O_000000(D9,0,_,_,_), O_000000(DB,5,_,_,_), Enc(FpuFldFst) , F(Fp)|F(Mem4_8_10) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFld1 , "fld1" , O_00_X(D9E8,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFldcw , "fldcw" , O_000000(D9,5,_,_,_), U , Enc(X86M) , F(Fp) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFldenv , "fldenv" , O_000000(D9,4,_,_,_), U , Enc(X86M) , F(Fp) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFldl2e , "fldl2e" , O_00_X(D9EA,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFldl2t , "fldl2t" , O_00_X(D9E9,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFldlg2 , "fldlg2" , O_00_X(D9EC,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFldln2 , "fldln2" , O_00_X(D9ED,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFldpi , "fldpi" , O_00_X(D9EB,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFldz , "fldz" , O_00_X(D9EE,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFmul , "fmul" , O_00_X(C8C8,1) , U , Enc(FpuArith) , F(Fp)|F(Mem4_8) , EF(________), 0 , 0 , O(FpMem) , O(Fp) , U , U , U ), + INST(kX86InstIdFmulp , "fmulp" , O_00_X(DEC8,U) , U , Enc(FpuRDef) , F(Fp) , EF(________), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFnclex , "fnclex" , O_00_X(DBE2,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFninit , "fninit" , O_00_X(DBE3,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFnop , "fnop" , O_00_X(D9D0,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFnsave , "fnsave" , O_000000(DD,6,_,_,_), U , Enc(X86M) , F(Fp) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFnstcw , "fnstcw" , O_000000(D9,7,_,_,_), U , Enc(X86M) , F(Fp) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFnstenv , "fnstenv" , O_000000(D9,6,_,_,_), U , Enc(X86M) , F(Fp) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFnstsw , "fnstsw" , O_000000(DD,7,_,_,_), O_00_X(DFE0,U) , Enc(FpuStsw) , F(Fp) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFpatan , "fpatan" , O_00_X(D9F3,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFprem , "fprem" , O_00_X(D9F8,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFprem1 , "fprem1" , O_00_X(D9F5,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFptan , "fptan" , O_00_X(D9F2,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFrndint , "frndint" , O_00_X(D9FC,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFrstor , "frstor" , O_000000(DD,4,_,_,_), U , Enc(X86M) , F(Fp) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFsave , "fsave" , O_9B0000(DD,6,_,_,_), U , Enc(X86M) , F(Fp) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFscale , "fscale" , O_00_X(D9FD,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFsin , "fsin" , O_00_X(D9FE,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFsincos , "fsincos" , O_00_X(D9FB,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFsqrt , "fsqrt" , O_00_X(D9FA,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFst , "fst" , O_000000(D9,2,_,_,_), U , Enc(FpuFldFst) , F(Fp)|F(Mem4_8) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFstcw , "fstcw" , O_9B0000(D9,7,_,_,_), U , Enc(X86M) , F(Fp) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFstenv , "fstenv" , O_9B0000(D9,6,_,_,_), U , Enc(X86M) , F(Fp) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFstp , "fstp" , O_000000(D9,3,_,_,_), O_000000(DB,7,_,_,_), Enc(FpuFldFst) , F(Fp)|F(Mem4_8_10) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFstsw , "fstsw" , O_9B0000(DD,7,_,_,_), O_9B_X(DFE0,U) , Enc(FpuStsw) , F(Fp) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFsub , "fsub" , O_00_X(E0E8,4) , U , Enc(FpuArith) , F(Fp)|F(Mem4_8) , EF(________), 0 , 0 , O(FpMem) , O(Fp) , U , U , U ), + INST(kX86InstIdFsubp , "fsubp" , O_00_X(DEE8,U) , U , Enc(FpuRDef) , F(Fp) , EF(________), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFsubr , "fsubr" , O_00_X(E8E0,5) , U , Enc(FpuArith) , F(Fp)|F(Mem4_8) , EF(________), 0 , 0 , O(FpMem) , O(Fp) , U , U , U ), + INST(kX86InstIdFsubrp , "fsubrp" , O_00_X(DEE0,U) , U , Enc(FpuRDef) , F(Fp) , EF(________), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFtst , "ftst" , O_00_X(D9E4,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFucom , "fucom" , O_00_X(DDE0,U) , U , Enc(FpuRDef) , F(Fp) , EF(________), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFucomi , "fucomi" , O_00_X(DBE8,U) , U , Enc(FpuR) , F(Fp) , EF(WWWWWW__), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFucomip , "fucomip" , O_00_X(DFE8,U) , U , Enc(FpuR) , F(Fp) , EF(WWWWWW__), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFucomp , "fucomp" , O_00_X(DDE8,U) , U , Enc(FpuRDef) , F(Fp) , EF(________), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFucompp , "fucompp" , O_00_X(DAE9,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFwait , "fwait" , O_000000(DB,U,_,_,_), U , Enc(X86Op) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFxam , "fxam" , O_00_X(D9E5,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFxch , "fxch" , O_00_X(D9C8,U) , U , Enc(FpuR) , F(Fp) , EF(________), 0 , 0 , O(Fp) , U , U , U , U ), + INST(kX86InstIdFxrstor , "fxrstor" , O_000F00(AE,1,_,_,_), U , Enc(X86M) , F(Fp) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFxsave , "fxsave" , O_000F00(AE,0,_,_,_), U , Enc(X86M) , F(Fp) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdFxtract , "fxtract" , O_00_X(D9F4,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFyl2x , "fyl2x" , O_00_X(D9F1,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdFyl2xp1 , "fyl2xp1" , O_00_X(D9F9,U) , U , Enc(FpuOp) , F(Fp) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdHaddpd , "haddpd" , O_660F00(7C,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdHaddps , "haddps" , O_F20F00(7C,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdHsubpd , "hsubpd" , O_660F00(7D,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdHsubps , "hsubps" , O_F20F00(7D,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdIdiv , "idiv" , O_000000(F6,7,_,_,_), U , Enc(X86Rm_B) , F(None)|F(Special) , EF(UUUUUU__), 0 , 0 , 0 , 0 , U , U , U ), + INST(kX86InstIdImul , "imul" , U , U , Enc(X86Imul) , F(None)|F(Special) , EF(WUUUUW__), 0 , 0 , 0 , 0 , U , U , U ), + INST(kX86InstIdInc , "inc" , O_000000(FE,0,_,_,_), O_000000(40,U,_,_,_), Enc(X86IncDec) , F(Lock) , EF(WWWWW___), 0 , 0 , O(GqdwbMem) , U , U , U , U ), + INST(kX86InstIdInsertps , "insertps" , O_660F3A(21,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdInsertq , "insertq" , O_F20F00(79,U,_,_,_), O_F20F00(78,U,_,_,_), Enc(ExtInsertq) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(None)|O(Imm) , O(None)|O(Imm) , U ), + INST(kX86InstIdInt , "int" , O_000000(CC,U,_,_,_), U , Enc(X86Int) , F(None) , EF(_______W), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdJa , "ja" , O_000000(77,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(__R__R__), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJae , "jae" , O_000000(73,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(_____R__), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJb , "jb" , O_000000(72,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(_____R__), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJbe , "jbe" , O_000000(76,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(__R__R__), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJc , "jc" , O_000000(72,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(_____R__), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJe , "je" , O_000000(74,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(__R_____), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJg , "jg" , O_000000(7F,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(RRR_____), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJge , "jge" , O_000000(7D,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(RR______), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJl , "jl" , O_000000(7C,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(RR______), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJle , "jle" , O_000000(7E,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(RRR_____), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJna , "jna" , O_000000(76,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(__R__R__), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJnae , "jnae" , O_000000(72,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(_____R__), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJnb , "jnb" , O_000000(73,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(_____R__), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJnbe , "jnbe" , O_000000(77,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(__R__R__), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJnc , "jnc" , O_000000(73,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(_____R__), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJne , "jne" , O_000000(75,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(__R_____), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJng , "jng" , O_000000(7E,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(RRR_____), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJnge , "jnge" , O_000000(7C,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(RR______), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJnl , "jnl" , O_000000(7D,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(RR______), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJnle , "jnle" , O_000000(7F,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(RRR_____), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJno , "jno" , O_000000(71,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(R_______), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJnp , "jnp" , O_000000(7B,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(____R___), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJns , "jns" , O_000000(79,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(_R______), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJnz , "jnz" , O_000000(75,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(__R_____), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJo , "jo" , O_000000(70,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(R_______), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJp , "jp" , O_000000(7A,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(____R___), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJpe , "jpe" , O_000000(7A,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(____R___), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJpo , "jpo" , O_000000(7B,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(____R___), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJs , "js" , O_000000(78,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(_R______), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJz , "jz" , O_000000(74,U,_,_,_), U , Enc(X86Jcc) , F(Flow) , EF(__R_____), 0 , 0 , O(Label) , U , U , U , U ), + INST(kX86InstIdJecxz , "jecxz" , O_000000(E3,U,_,_,_), U , Enc(X86Jecxz) , F(Flow)|F(Special) , EF(________), 0 , 0 , O(Gqdw) , O(Label) , U , U , U ), + INST(kX86InstIdJmp , "jmp" , O_000000(FF,4,_,_,_), O_000000(E9,U,_,_,_), Enc(X86Jmp) , F(Flow) , EF(________), 0 , 0 , O(Label)|O(Imm) , U , U , U , U ), + INST(kX86InstIdLahf , "lahf" , O_000000(9F,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(_RRRRR__), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdLddqu , "lddqu" , O_F20F00(F0,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(Mem) , U , U , U ), + INST(kX86InstIdLdmxcsr , "ldmxcsr" , O_000F00(AE,2,_,_,_), U , Enc(X86M) , F(None) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdLea , "lea" , O_000000(8D,U,_,_,_), U , Enc(X86Lea) , F(Move) , EF(________), 0 , 0 , O(Gqd) , O(Mem) , U , U , U ), + INST(kX86InstIdLeave , "leave" , O_000000(C9,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdLfence , "lfence" , O_000F00(AE,5,_,_,_), U , Enc(ExtFence) , F(None) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdLodsB , "lods_b" , O_000000(AC,U,_,_,_), U , Enc(X86Op) , F(Move)|F(Special) , EF(______R_), 0 , 1 , U , U , U , U , U ), + INST(kX86InstIdLodsD , "lods_d" , O_000000(AD,U,_,_,_), U , Enc(X86Op) , F(Move)|F(Special) , EF(______R_), 0 , 4 , U , U , U , U , U ), + INST(kX86InstIdLodsQ , "lods_q" , O_000000(AD,U,_,W,_), U , Enc(X86Op) , F(Move)|F(Special) , EF(______R_), 0 , 8 , U , U , U , U , U ), + INST(kX86InstIdLodsW , "lods_w" , O_000000(AD,U,_,_,_), U , Enc(X86Op_66H) , F(Move)|F(Special) , EF(______R_), 0 , 2 , U , U , U , U , U ), + INST(kX86InstIdLzcnt , "lzcnt" , O_F30F00(BD,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(UUWUUW__), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdMaskmovdqu , "maskmovdqu" , O_660F00(57,U,_,_,_), U , Enc(ExtRm) , F(None)|F(Special) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , U , U , U ), + INST(kX86InstIdMaskmovq , "maskmovq" , O_000F00(F7,U,_,_,_), U , Enc(ExtRm) , F(None)|F(Special) , EF(________), 0 , 0 , O(Mm) , O(Mm) , U , U , U ), + INST(kX86InstIdMaxpd , "maxpd" , O_660F00(5F,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMaxps , "maxps" , O_000F00(5F,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMaxsd , "maxsd" , O_F20F00(5F,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMaxss , "maxss" , O_F30F00(5F,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMfence , "mfence" , O_000F00(AE,6,_,_,_), U , Enc(ExtFence) , F(None) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdMinpd , "minpd" , O_660F00(5D,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMinps , "minps" , O_000F00(5D,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMinsd , "minsd" , O_F20F00(5D,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMinss , "minss" , O_F30F00(5D,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMonitor , "monitor" , O_000F01(C8,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdMov , "mov" , U , U , Enc(X86Mov) , F(Move) , EF(________), 0 , 0 , O(GqdwbMem) , O(GqdwbMem)|O(Imm), U , U , U ), + INST(kX86InstIdMovPtr , "mov_ptr" , O_000000(A0,U,_,_,_), O_000000(A2,U,_,_,_), Enc(X86MovPtr) , F(Move)|F(Special) , EF(________), 0 , 0 , O(Gqdwb) , O(Imm) , U , U , U ), + INST(kX86InstIdMovapd , "movapd" , O_660F00(28,U,_,_,_), O_660F00(29,U,_,_,_), Enc(ExtMov) , F(Move) , EF(________), 0 , 16, O(XmmMem) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMovaps , "movaps" , O_000F00(28,U,_,_,_), O_000F00(29,U,_,_,_), Enc(ExtMov) , F(Move) , EF(________), 0 , 16, O(XmmMem) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMovbe , "movbe" , O_000F38(F0,U,_,_,_), O_000F38(F1,U,_,_,_), Enc(ExtMovBe) , F(Move) , EF(________), 0 , 0 , O(GqdwMem) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdMovd , "movd" , O_000F00(6E,U,_,_,_), O_000F00(7E,U,_,_,_), Enc(ExtMovD) , F(Move) , EF(________), 0 , 16, O(Gd)|O(MmXmmMem) , O(Gd)|O(MmXmmMem) , U , U , U ), + INST(kX86InstIdMovddup , "movddup" , O_F20F00(12,U,_,_,_), U , Enc(ExtMov) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMovdq2q , "movdq2q" , O_F20F00(D6,U,_,_,_), U , Enc(ExtMov) , F(Move) , EF(________), 0 , 8 , O(Mm) , O(Xmm) , U , U , U ), + INST(kX86InstIdMovdqa , "movdqa" , O_660F00(6F,U,_,_,_), O_660F00(7F,U,_,_,_), Enc(ExtMov) , F(Move) , EF(________), 0 , 16, O(XmmMem) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMovdqu , "movdqu" , O_F30F00(6F,U,_,_,_), O_F30F00(7F,U,_,_,_), Enc(ExtMov) , F(Move) , EF(________), 0 , 16, O(XmmMem) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMovhlps , "movhlps" , O_000F00(12,U,_,_,_), U , Enc(ExtMov) , F(Move) , EF(________), 0 , 8 , O(Xmm) , O(Xmm) , U , U , U ), + INST(kX86InstIdMovhpd , "movhpd" , O_660F00(16,U,_,_,_), O_660F00(17,U,_,_,_), Enc(ExtMov) , F(None) , EF(________), 8 , 8 , O(XmmMem) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMovhps , "movhps" , O_000F00(16,U,_,_,_), O_000F00(17,U,_,_,_), Enc(ExtMov) , F(None) , EF(________), 8 , 8 , O(XmmMem) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMovlhps , "movlhps" , O_000F00(16,U,_,_,_), U , Enc(ExtMov) , F(None) , EF(________), 8 , 8 , O(Xmm) , O(Xmm) , U , U , U ), + INST(kX86InstIdMovlpd , "movlpd" , O_660F00(12,U,_,_,_), O_660F00(13,U,_,_,_), Enc(ExtMov) , F(Move) , EF(________), 0 , 8 , O(XmmMem) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMovlps , "movlps" , O_000F00(12,U,_,_,_), O_000F00(13,U,_,_,_), Enc(ExtMov) , F(Move) , EF(________), 0 , 8 , O(XmmMem) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMovmskpd , "movmskpd" , O_660F00(50,U,_,_,_), U , Enc(ExtMovNoRexW) , F(Move) , EF(________), 0 , 8 , O(Gqd) , O(Xmm) , U , U , U ), + INST(kX86InstIdMovmskps , "movmskps" , O_000F00(50,U,_,_,_), U , Enc(ExtMovNoRexW) , F(Move) , EF(________), 0 , 8 , O(Gqd) , O(Xmm) , U , U , U ), + INST(kX86InstIdMovntdq , "movntdq" , U , O_660F00(E7,U,_,_,_), Enc(ExtMov) , F(Move) , EF(________), 0 , 16, O(Mem) , O(Xmm) , U , U , U ), + INST(kX86InstIdMovntdqa , "movntdqa" , O_660F38(2A,U,_,_,_), U , Enc(ExtMov) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(Mem) , U , U , U ), + INST(kX86InstIdMovnti , "movnti" , U , O_000F00(C3,U,_,_,_), Enc(ExtMov) , F(Move) , EF(________), 0 , 8 , O(Mem) , O(Gqd) , U , U , U ), + INST(kX86InstIdMovntpd , "movntpd" , U , O_660F00(2B,U,_,_,_), Enc(ExtMov) , F(Move) , EF(________), 0 , 16, O(Mem) , O(Xmm) , U , U , U ), + INST(kX86InstIdMovntps , "movntps" , U , O_000F00(2B,U,_,_,_), Enc(ExtMov) , F(Move) , EF(________), 0 , 16, O(Mem) , O(Xmm) , U , U , U ), + INST(kX86InstIdMovntq , "movntq" , U , O_000F00(E7,U,_,_,_), Enc(ExtMov) , F(Move) , EF(________), 0 , 8 , O(Mem) , O(Mm) , U , U , U ), + INST(kX86InstIdMovntsd , "movntsd" , U , O_F20F00(2B,U,_,_,_), Enc(ExtMov) , F(Move) , EF(________), 0 , 8 , O(Mem) , O(Xmm) , U , U , U ), + INST(kX86InstIdMovntss , "movntss" , U , O_F30F00(2B,U,_,_,_), Enc(ExtMov) , F(Move) , EF(________), 0 , 4 , O(Mem) , O(Xmm) , U , U , U ), + INST(kX86InstIdMovq , "movq" , O_000F00(6E,U,_,W,_), O_000F00(7E,U,_,W,_), Enc(ExtMovQ) , F(Move) , EF(________), 0 , 16, O(Gq)|O(MmXmmMem) , O(Gq)|O(MmXmmMem) , U , U , U ), + INST(kX86InstIdMovq2dq , "movq2dq" , O_F30F00(D6,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(Mm) , U , U , U ), + INST(kX86InstIdMovsB , "movs_b" , O_000000(A4,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdMovsD , "movs_d" , O_000000(A5,U,_,_,_), U , Enc(X86Op) , F(Move)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdMovsQ , "movs_q" , O_000000(A5,U,_,W,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdMovsW , "movs_w" , O_000000(A5,U,_,_,_), U , Enc(X86Op_66H) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdMovsd , "movsd" , O_F20F00(10,U,_,_,_), O_F20F00(11,U,_,_,_), Enc(ExtMov) , F(Move) |F(Z) , EF(________), 0 , 8 , O(XmmMem) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMovshdup , "movshdup" , O_F30F00(16,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMovsldup , "movsldup" , O_F30F00(12,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMovss , "movss" , O_F30F00(10,U,_,_,_), O_F30F00(11,U,_,_,_), Enc(ExtMov) , F(Move) |F(Z) , EF(________), 0 , 4 , O(XmmMem) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMovsx , "movsx" , O_000F00(BE,U,_,_,_), U , Enc(X86MovSxZx) , F(Move) , EF(________), 0 , 0 , O(Gqdw) , O(GwbMem) , U , U , U ), + INST(kX86InstIdMovsxd , "movsxd" , O_000000(63,U,_,_,_), U , Enc(X86MovSxd) , F(Move) , EF(________), 0 , 0 , O(Gq) , O(GdMem) , U , U , U ), + INST(kX86InstIdMovupd , "movupd" , O_660F00(10,U,_,_,_), O_660F00(11,U,_,_,_), Enc(ExtMov) , F(Move) , EF(________), 0 , 16, O(XmmMem) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMovups , "movups" , O_000F00(10,U,_,_,_), O_000F00(11,U,_,_,_), Enc(ExtMov) , F(Move) , EF(________), 0 , 16, O(XmmMem) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMovzx , "movzx" , O_000F00(B6,U,_,_,_), U , Enc(X86MovSxZx) , F(Move) , EF(________), 0 , 0 , O(Gqdw) , O(GwbMem) , U , U , U ), + INST(kX86InstIdMpsadbw , "mpsadbw" , O_660F3A(42,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdMul , "mul" , O_000000(F6,4,_,_,_), U , Enc(X86Rm_B) , F(None)|F(Special) , EF(WUUUUW__), 0 , 0 , 0 , 0 , U , U , U ), + INST(kX86InstIdMulpd , "mulpd" , O_660F00(59,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMulps , "mulps" , O_000F00(59,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMulsd , "mulsd" , O_F20F00(59,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMulss , "mulss" , O_F30F00(59,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdMulx , "mulx" , O_F20F38(F6,U,_,_,_), U , Enc(AvxRvm) , F(None) , EF(________), 0 , 0 , O(Gqd) , O(Gqd) , O(GqdMem) , U , U ), + INST(kX86InstIdMwait , "mwait" , O_000F01(C9,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdNeg , "neg" , O_000000(F6,3,_,_,_), U , Enc(X86Rm_B) , F(Lock) , EF(WWWWWW__), 0 , 0 , O(GqdwbMem) , U , U , U , U ), + INST(kX86InstIdNop , "nop" , O_000000(90,U,_,_,_), U , Enc(X86Op) , F(None) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdNot , "not" , O_000000(F6,2,_,_,_), U , Enc(X86Rm_B) , F(Lock) , EF(________), 0 , 0 , O(GqdwbMem) , U , U , U , U ), + INST(kX86InstIdOr , "or" , O_000000(08,1,_,_,_), U , Enc(X86Arith) , F(Lock) , EF(WWWUWW__), 0 , 0 , O(GqdwbMem) , O(GqdwbMem)|O(Imm), U , U , U ), + INST(kX86InstIdOrpd , "orpd" , O_660F00(56,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdOrps , "orps" , O_000F00(56,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPabsb , "pabsb" , O_000F38(1C,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPabsd , "pabsd" , O_000F38(1E,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPabsw , "pabsw" , O_000F38(1D,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPackssdw , "packssdw" , O_000F00(6B,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPacksswb , "packsswb" , O_000F00(63,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPackusdw , "packusdw" , O_660F38(2B,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPackuswb , "packuswb" , O_000F00(67,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPaddb , "paddb" , O_000F00(FC,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPaddd , "paddd" , O_000F00(FE,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPaddq , "paddq" , O_000F00(D4,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPaddsb , "paddsb" , O_000F00(EC,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPaddsw , "paddsw" , O_000F00(ED,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPaddusb , "paddusb" , O_000F00(DC,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPaddusw , "paddusw" , O_000F00(DD,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPaddw , "paddw" , O_000F00(FD,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPalignr , "palignr" , O_000F3A(0F,U,_,_,_), U , Enc(ExtRmi_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , O(Imm) , U , U ), + INST(kX86InstIdPand , "pand" , O_000F00(DB,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPandn , "pandn" , O_000F00(DF,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPause , "pause" , O_F30000(90,U,_,_,_), U , Enc(X86Op) , F(None) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdPavgb , "pavgb" , O_000F00(E0,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPavgw , "pavgw" , O_000F00(E3,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPblendvb , "pblendvb" , O_660F38(10,U,_,_,_), U , Enc(ExtRm) , F(None)|F(Special) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPblendw , "pblendw" , O_660F3A(0E,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdPclmulqdq , "pclmulqdq" , O_660F3A(44,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdPcmpeqb , "pcmpeqb" , O_000F00(74,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPcmpeqd , "pcmpeqd" , O_000F00(76,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPcmpeqq , "pcmpeqq" , O_660F38(29,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPcmpeqw , "pcmpeqw" , O_000F00(75,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPcmpestri , "pcmpestri" , O_660F3A(61,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdPcmpestrm , "pcmpestrm" , O_660F3A(60,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdPcmpgtb , "pcmpgtb" , O_000F00(64,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPcmpgtd , "pcmpgtd" , O_000F00(66,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPcmpgtq , "pcmpgtq" , O_660F38(37,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPcmpgtw , "pcmpgtw" , O_000F00(65,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPcmpistri , "pcmpistri" , O_660F3A(63,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdPcmpistrm , "pcmpistrm" , O_660F3A(62,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdPdep , "pdep" , O_F20F38(F5,U,_,_,_), U , Enc(AvxRvm) , F(None) , EF(________), 0 , 0 , O(Gqd) , O(Gqd) , O(GqdMem) , U , U ), + INST(kX86InstIdPext , "pext" , O_F30F38(F5,U,_,_,_), U , Enc(AvxRvm) , F(None) , EF(________), 0 , 0 , O(Gqd) , O(Gqd) , O(GqdMem) , U , U ), + INST(kX86InstIdPextrb , "pextrb" , O_000F3A(14,U,_,_,_), O_000F3A(14,U,_,_,_), Enc(ExtExtract) , F(Move) , EF(________), 0 , 8 , O(Gd)|O(Gb)|O(Mem), O(Xmm) , U , U , U ), + INST(kX86InstIdPextrd , "pextrd" , O_000F3A(16,U,_,_,_), O_000F3A(16,U,_,_,_), Enc(ExtExtract) , F(Move) , EF(________), 0 , 8 , O(GdMem) , O(Xmm) , U , U , U ), + INST(kX86InstIdPextrq , "pextrq" , O_000F3A(16,U,_,W,_), O_000F3A(16,U,_,W,_), Enc(ExtExtract) , F(Move) , EF(________), 0 , 8 , O(GqdMem) , O(Xmm) , U , U , U ), + INST(kX86InstIdPextrw , "pextrw" , O_000F00(C5,U,_,_,_), O_000F3A(15,U,_,_,_), Enc(ExtExtract) , F(Move) , EF(________), 0 , 8 , O(GdMem) , O(MmXmm) , U , U , U ), + INST(kX86InstIdPf2id , "pf2id" , O_000F0F(1D,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPf2iw , "pf2iw" , O_000F0F(1C,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPfacc , "pfacc" , O_000F0F(AE,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPfadd , "pfadd" , O_000F0F(9E,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPfcmpeq , "pfcmpeq" , O_000F0F(B0,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPfcmpge , "pfcmpge" , O_000F0F(90,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPfcmpgt , "pfcmpgt" , O_000F0F(A0,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPfmax , "pfmax" , O_000F0F(A4,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPfmin , "pfmin" , O_000F0F(94,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPfmul , "pfmul" , O_000F0F(B4,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPfnacc , "pfnacc" , O_000F0F(8A,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPfpnacc , "pfpnacc" , O_000F0F(8E,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPfrcp , "pfrcp" , O_000F0F(96,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPfrcpit1 , "pfrcpit1" , O_000F0F(A6,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPfrcpit2 , "pfrcpit2" , O_000F0F(B6,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPfrsqit1 , "pfrsqit1" , O_000F0F(A7,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPfrsqrt , "pfrsqrt" , O_000F0F(97,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPfsub , "pfsub" , O_000F0F(9A,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPfsubr , "pfsubr" , O_000F0F(AA,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPhaddd , "phaddd" , O_000F38(02,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPhaddsw , "phaddsw" , O_000F38(03,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPhaddw , "phaddw" , O_000F38(01,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPhminposuw , "phminposuw" , O_660F38(41,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPhsubd , "phsubd" , O_000F38(06,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPhsubsw , "phsubsw" , O_000F38(07,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPhsubw , "phsubw" , O_000F38(05,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPi2fd , "pi2fd" , O_000F0F(0D,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPi2fw , "pi2fw" , O_000F0F(0C,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPinsrb , "pinsrb" , O_660F3A(20,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(GdMem) , O(Imm) , U , U ), + INST(kX86InstIdPinsrd , "pinsrd" , O_660F3A(22,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(GdMem) , O(Imm) , U , U ), + INST(kX86InstIdPinsrq , "pinsrq" , O_660F3A(22,U,_,W,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(GqMem) , O(Imm) , U , U ), + INST(kX86InstIdPinsrw , "pinsrw" , O_000F00(C4,U,_,_,_), U , Enc(ExtRmi_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(GdMem) , O(Imm) , U , U ), + INST(kX86InstIdPmaddubsw , "pmaddubsw" , O_000F38(04,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPmaddwd , "pmaddwd" , O_000F00(F5,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPmaxsb , "pmaxsb" , O_660F38(3C,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmaxsd , "pmaxsd" , O_660F38(3D,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmaxsw , "pmaxsw" , O_000F00(EE,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPmaxub , "pmaxub" , O_000F00(DE,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPmaxud , "pmaxud" , O_660F38(3F,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmaxuw , "pmaxuw" , O_660F38(3E,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPminsb , "pminsb" , O_660F38(38,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPminsd , "pminsd" , O_660F38(39,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPminsw , "pminsw" , O_000F00(EA,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPminub , "pminub" , O_000F00(DA,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPminud , "pminud" , O_660F38(3B,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPminuw , "pminuw" , O_660F38(3A,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmovmskb , "pmovmskb" , O_000F00(D7,U,_,_,_), U , Enc(ExtRm_PQ) , F(Move) , EF(________), 0 , 8 , O(Gqd) , O(MmXmm) , U , U , U ), + INST(kX86InstIdPmovsxbd , "pmovsxbd" , O_660F38(21,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmovsxbq , "pmovsxbq" , O_660F38(22,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmovsxbw , "pmovsxbw" , O_660F38(20,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmovsxdq , "pmovsxdq" , O_660F38(25,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmovsxwd , "pmovsxwd" , O_660F38(23,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmovsxwq , "pmovsxwq" , O_660F38(24,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmovzxbd , "pmovzxbd" , O_660F38(31,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmovzxbq , "pmovzxbq" , O_660F38(32,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmovzxbw , "pmovzxbw" , O_660F38(30,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmovzxdq , "pmovzxdq" , O_660F38(35,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmovzxwd , "pmovzxwd" , O_660F38(33,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmovzxwq , "pmovzxwq" , O_660F38(34,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmuldq , "pmuldq" , O_660F38(28,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmulhrsw , "pmulhrsw" , O_000F38(0B,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPmulhuw , "pmulhuw" , O_000F00(E4,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPmulhw , "pmulhw" , O_000F00(E5,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPmulld , "pmulld" , O_660F38(40,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPmullw , "pmullw" , O_000F00(D5,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPmuludq , "pmuludq" , O_000F00(F4,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPop , "pop" , O_000000(8F,0,_,_,_), O_000000(58,U,_,_,_), Enc(X86Pop) , F(None)|F(Special) , EF(________), 0 , 0 , 0 , U , U , U , U ), + INST(kX86InstIdPopa , "popa" , O_000000(61,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdPopcnt , "popcnt" , O_F30F00(B8,U,_,_,_), U , Enc(X86RegRm) , F(None) , EF(WWWWWW__), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdPopf , "popf" , O_000000(9D,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(WWWWWWWW), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdPor , "por" , O_000F00(EB,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPrefetch , "prefetch" , O_000F00(18,U,_,_,_), U , Enc(ExtPrefetch) , F(None) , EF(________), 0 , 0 , O(Mem) , O(Imm) , U , U , U ), + INST(kX86InstIdPrefetch3dNow , "prefetch_3dnow" , O_000F00(0D,0,_,_,_), U , Enc(X86M) , F(None) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdPrefetchw3dNow , "prefetchw_3dnow" , O_000F00(0D,1,_,_,_), U , Enc(X86M) , F(None) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdPsadbw , "psadbw" , O_000F00(F6,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPshufb , "pshufb" , O_000F38(00,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPshufd , "pshufd" , O_660F00(70,U,_,_,_), U , Enc(ExtRmi) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdPshufhw , "pshufhw" , O_F30F00(70,U,_,_,_), U , Enc(ExtRmi) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdPshuflw , "pshuflw" , O_F20F00(70,U,_,_,_), U , Enc(ExtRmi) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdPshufw , "pshufw" , O_000F00(70,U,_,_,_), U , Enc(ExtRmi_P) , F(Move) , EF(________), 0 , 8 , O(Mm) , O(MmMem) , O(Imm) , U , U ), + INST(kX86InstIdPsignb , "psignb" , O_000F38(08,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPsignd , "psignd" , O_000F38(0A,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPsignw , "psignw" , O_000F38(09,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPslld , "pslld" , O_000F00(F2,U,_,_,_), O_000F00(72,6,_,_,_), Enc(ExtRmRi_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem)|O(Imm), U , U , U ), + INST(kX86InstIdPslldq , "pslldq" , U , O_660F00(73,7,_,_,_), Enc(ExtRmRi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(Imm) , U , U , U ), + INST(kX86InstIdPsllq , "psllq" , O_000F00(F3,U,_,_,_), O_000F00(73,6,_,_,_), Enc(ExtRmRi_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem)|O(Imm), U , U , U ), + INST(kX86InstIdPsllw , "psllw" , O_000F00(F1,U,_,_,_), O_000F00(71,6,_,_,_), Enc(ExtRmRi_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem)|O(Imm), U , U , U ), + INST(kX86InstIdPsrad , "psrad" , O_000F00(E2,U,_,_,_), O_000F00(72,4,_,_,_), Enc(ExtRmRi_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem)|O(Imm), U , U , U ), + INST(kX86InstIdPsraw , "psraw" , O_000F00(E1,U,_,_,_), O_000F00(71,4,_,_,_), Enc(ExtRmRi_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem)|O(Imm), U , U , U ), + INST(kX86InstIdPsrld , "psrld" , O_000F00(D2,U,_,_,_), O_000F00(72,2,_,_,_), Enc(ExtRmRi_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem)|O(Imm), U , U , U ), + INST(kX86InstIdPsrldq , "psrldq" , U , O_660F00(73,3,_,_,_), Enc(ExtRmRi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(Imm) , U , U , U ), + INST(kX86InstIdPsrlq , "psrlq" , O_000F00(D3,U,_,_,_), O_000F00(73,2,_,_,_), Enc(ExtRmRi_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem)|O(Imm), U , U , U ), + INST(kX86InstIdPsrlw , "psrlw" , O_000F00(D1,U,_,_,_), O_000F00(71,2,_,_,_), Enc(ExtRmRi_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem)|O(Imm), U , U , U ), + INST(kX86InstIdPsubb , "psubb" , O_000F00(F8,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPsubd , "psubd" , O_000F00(FA,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPsubq , "psubq" , O_000F00(FB,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPsubsb , "psubsb" , O_000F00(E8,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPsubsw , "psubsw" , O_000F00(E9,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPsubusb , "psubusb" , O_000F00(D8,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPsubusw , "psubusw" , O_000F00(D9,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPsubw , "psubw" , O_000F00(F9,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPswapd , "pswapd" , O_000F0F(BB,U,_,_,_), U , Enc(3dNow) , F(None) , EF(________), 0 , 0 , O(Mm) , O(MmMem) , U , U , U ), + INST(kX86InstIdPtest , "ptest" , O_660F38(17,U,_,_,_), U , Enc(ExtRm) , F(Test) , EF(WWWWWW__), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPunpckhbw , "punpckhbw" , O_000F00(68,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPunpckhdq , "punpckhdq" , O_000F00(6A,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPunpckhqdq , "punpckhqdq" , O_660F00(6D,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPunpckhwd , "punpckhwd" , O_000F00(69,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPunpcklbw , "punpcklbw" , O_000F00(60,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPunpckldq , "punpckldq" , O_000F00(62,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPunpcklqdq , "punpcklqdq" , O_660F00(6C,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdPunpcklwd , "punpcklwd" , O_000F00(61,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdPush , "push" , O_000000(FF,6,_,_,_), O_000000(50,U,_,_,_), Enc(X86Push) , F(None)|F(Special) , EF(________), 0 , 0 , 0 , U , U , U , U ), + INST(kX86InstIdPusha , "pusha" , O_000000(60,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdPushf , "pushf" , O_000000(9C,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(RRRRRRRR), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdPxor , "pxor" , O_000F00(EF,U,_,_,_), U , Enc(ExtRm_P) , F(None) , EF(________), 0 , 0 , O(MmXmm) , O(MmXmmMem) , U , U , U ), + INST(kX86InstIdRcl , "rcl" , O_000000(D0,2,_,_,_), U , Enc(X86Rot) , F(None)|F(Special) , EF(W____X__), 0 , 0 , O(GqdwbMem) , O(Gb)|O(Imm) , U , U , U ), + INST(kX86InstIdRcpps , "rcpps" , O_000F00(53,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdRcpss , "rcpss" , O_F30F00(53,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 4 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdRcr , "rcr" , O_000000(D0,3,_,_,_), U , Enc(X86Rot) , F(None)|F(Special) , EF(W____X__), 0 , 0 , O(GqdwbMem) , O(Gb)|O(Imm) , U , U , U ), + INST(kX86InstIdRdfsbase , "rdfsbase" , O_F30F00(AE,0,_,_,_), U , Enc(X86Rm) , F(Move) , EF(________), 0 , 8 , O(Gqd) , U , U , U , U ), + INST(kX86InstIdRdgsbase , "rdgsbase" , O_F30F00(AE,1,_,_,_), U , Enc(X86Rm) , F(Move) , EF(________), 0 , 8 , O(Gqd) , U , U , U , U ), + INST(kX86InstIdRdrand , "rdrand" , O_000F00(C7,6,_,_,_), U , Enc(X86Rm) , F(Move) , EF(WWWWWW__), 0 , 8 , O(Gqdw) , U , U , U , U ), + INST(kX86InstIdRdtsc , "rdtsc" , O_000F00(31,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdRdtscp , "rdtscp" , O_000F01(F9,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdRepLodsB , "rep lods_b" , O_000000(AC,1,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(______R_), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdRepLodsD , "rep lods_d" , O_000000(AD,1,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(______R_), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdRepLodsQ , "rep lods_q" , O_000000(AD,1,_,W,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(______R_), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdRepLodsW , "rep lods_w" , O_660000(AD,1,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(______R_), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdRepMovsB , "rep movs_b" , O_000000(A4,1,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(______R_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepMovsD , "rep movs_d" , O_000000(A5,1,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(______R_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepMovsQ , "rep movs_q" , O_000000(A5,1,_,W,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(______R_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepMovsW , "rep movs_w" , O_660000(A5,1,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(______R_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepStosB , "rep stos_b" , O_000000(AA,1,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(______R_), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdRepStosD , "rep stos_d" , O_000000(AB,1,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(______R_), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdRepStosQ , "rep stos_q" , O_000000(AB,1,_,W,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(______R_), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdRepStosW , "rep stos_w" , O_660000(AB,1,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(______R_), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdRepeCmpsB , "repe cmps_b" , O_000000(A6,1,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepeCmpsD , "repe cmps_d" , O_000000(A7,1,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepeCmpsQ , "repe cmps_q" , O_000000(A7,1,_,W,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepeCmpsW , "repe cmps_w" , O_660000(A7,1,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepeScasB , "repe scas_b" , O_000000(AE,1,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepeScasD , "repe scas_d" , O_000000(AF,1,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepeScasQ , "repe scas_q" , O_000000(AF,1,_,W,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepeScasW , "repe scas_w" , O_660000(AF,1,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepneCmpsB , "repne cmps_b" , O_000000(A6,0,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepneCmpsD , "repne cmps_d" , O_000000(A7,0,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepneCmpsQ , "repne cmps_q" , O_000000(A7,0,_,W,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepneCmpsW , "repne cmps_w" , O_660000(A7,0,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepneScasB , "repne scas_b" , O_000000(AE,0,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepneScasD , "repne scas_d" , O_000000(AF,0,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepneScasQ , "repne scas_q" , O_000000(AF,0,_,W,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRepneScasW , "repne scas_w" , O_660000(AF,0,_,_,_), U , Enc(X86Rep) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , O(Mem) , O(Mem) , U , U , U ), + INST(kX86InstIdRet , "ret" , O_000000(C2,U,_,_,_), U , Enc(X86Ret) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdRol , "rol" , O_000000(D0,0,_,_,_), U , Enc(X86Rot) , F(None)|F(Special) , EF(W____W__), 0 , 0 , O(GqdwbMem) , O(Gb)|O(Imm) , U , U , U ), + INST(kX86InstIdRor , "ror" , O_000000(D0,1,_,_,_), U , Enc(X86Rot) , F(None)|F(Special) , EF(W____W__), 0 , 0 , O(GqdwbMem) , O(Gb)|O(Imm) , U , U , U ), + INST(kX86InstIdRorx , "rorx" , O_F20F3A(F0,U,_,_,_), U , Enc(AvxRmi) , F(None) , EF(________), 0 , 0 , O(Gqd) , O(GqdMem) , O(Imm) , U , U ), + INST(kX86InstIdRoundpd , "roundpd" , O_660F3A(09,U,_,_,_), U , Enc(ExtRmi) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdRoundps , "roundps" , O_660F3A(08,U,_,_,_), U , Enc(ExtRmi) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdRoundsd , "roundsd" , O_660F3A(0B,U,_,_,_), U , Enc(ExtRmi) , F(Move) , EF(________), 0 , 8 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdRoundss , "roundss" , O_660F3A(0A,U,_,_,_), U , Enc(ExtRmi) , F(Move) , EF(________), 0 , 4 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdRsqrtps , "rsqrtps" , O_000F00(52,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdRsqrtss , "rsqrtss" , O_F30F00(52,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 4 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdSahf , "sahf" , O_000000(9E,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(_WWWWW__), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdSal , "sal" , O_000000(D0,4,_,_,_), U , Enc(X86Rot) , F(None)|F(Special) , EF(WWWUWW__), 0 , 0 , O(GqdwbMem) , O(Gb)|O(Imm) , U , U , U ), + INST(kX86InstIdSar , "sar" , O_000000(D0,7,_,_,_), U , Enc(X86Rot) , F(None)|F(Special) , EF(WWWUWW__), 0 , 0 , O(GqdwbMem) , O(Gb)|O(Imm) , U , U , U ), + INST(kX86InstIdSarx , "sarx" , O_F30F38(F7,U,_,_,_), U , Enc(AvxRmv) , F(None) , EF(________), 0 , 0 , O(Gqd) , O(GqdMem) , O(Gqd) , U , U ), + INST(kX86InstIdSbb , "sbb" , O_000000(18,3,_,_,_), U , Enc(X86Arith) , F(Lock) , EF(WWWWWX__), 0 , 0 , O(GqdwbMem) , O(GqdwbMem)|O(Imm), U , U , U ), + INST(kX86InstIdScasB , "scas_b" , O_000000(AE,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdScasD , "scas_d" , O_000000(AF,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdScasQ , "scas_q" , O_000000(AF,U,_,W,_), U , Enc(X86Op) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdScasW , "scas_w" , O_000000(AF,U,_,_,_), U , Enc(X86Op_66H) , F(None)|F(Special) , EF(WWWWWWR_), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdSeta , "seta" , O_000F00(97,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(__R__R__), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetae , "setae" , O_000F00(93,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(_____R__), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetb , "setb" , O_000F00(92,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(_____R__), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetbe , "setbe" , O_000F00(96,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(__R__R__), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetc , "setc" , O_000F00(92,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(_____R__), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSete , "sete" , O_000F00(94,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(__R_____), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetg , "setg" , O_000F00(9F,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(RRR_____), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetge , "setge" , O_000F00(9D,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(RR______), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetl , "setl" , O_000F00(9C,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(RR______), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetle , "setle" , O_000F00(9E,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(RRR_____), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetna , "setna" , O_000F00(96,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(__R__R__), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetnae , "setnae" , O_000F00(92,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(_____R__), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetnb , "setnb" , O_000F00(93,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(_____R__), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetnbe , "setnbe" , O_000F00(97,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(__R__R__), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetnc , "setnc" , O_000F00(93,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(_____R__), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetne , "setne" , O_000F00(95,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(__R_____), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetng , "setng" , O_000F00(9E,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(RRR_____), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetnge , "setnge" , O_000F00(9C,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(RR______), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetnl , "setnl" , O_000F00(9D,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(RR______), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetnle , "setnle" , O_000F00(9F,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(RRR_____), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetno , "setno" , O_000F00(91,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(R_______), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetnp , "setnp" , O_000F00(9B,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(____R___), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetns , "setns" , O_000F00(99,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(_R______), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetnz , "setnz" , O_000F00(95,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(__R_____), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSeto , "seto" , O_000F00(90,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(R_______), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetp , "setp" , O_000F00(9A,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(____R___), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetpe , "setpe" , O_000F00(9A,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(____R___), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetpo , "setpo" , O_000F00(9B,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(____R___), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSets , "sets" , O_000F00(98,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(_R______), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSetz , "setz" , O_000F00(94,U,_,_,_), U , Enc(X86Set) , F(Move) , EF(__R_____), 0 , 1 , O(GbMem) , U , U , U , U ), + INST(kX86InstIdSfence , "sfence" , O_000F00(AE,7,_,_,_), U , Enc(ExtFence) , F(None) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdShl , "shl" , O_000000(D0,4,_,_,_), U , Enc(X86Rot) , F(None)|F(Special) , EF(WWWUWW__), 0 , 0 , O(GqdwbMem) , O(Gb)|O(Imm) , U , U , U ), + INST(kX86InstIdShld , "shld" , O_000F00(A4,U,_,_,_), U , Enc(X86Shlrd) , F(None)|F(Special) , EF(UWWUWW__), 0 , 0 , O(GqdwbMem) , O(Gb) , U , U , U ), + INST(kX86InstIdShlx , "shlx" , O_660F38(F7,U,_,_,_), U , Enc(AvxRmv) , F(None) , EF(________), 0 , 0 , O(Gqd) , O(GqdMem) , O(Gqd) , U , U ), + INST(kX86InstIdShr , "shr" , O_000000(D0,5,_,_,_), U , Enc(X86Rot) , F(None)|F(Special) , EF(WWWUWW__), 0 , 0 , O(GqdwbMem) , O(Gb)|O(Imm) , U , U , U ), + INST(kX86InstIdShrd , "shrd" , O_000F00(AC,U,_,_,_), U , Enc(X86Shlrd) , F(None)|F(Special) , EF(UWWUWW__), 0 , 0 , O(GqdwbMem) , O(Gqdwb) , U , U , U ), + INST(kX86InstIdShrx , "shrx" , O_F20F38(F7,U,_,_,_), U , Enc(AvxRmv) , F(None) , EF(________), 0 , 0 , O(Gqd) , O(GqdMem) , O(Gqd) , U , U ), + INST(kX86InstIdShufpd , "shufpd" , O_660F00(C6,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdShufps , "shufps" , O_000F00(C6,U,_,_,_), U , Enc(ExtRmi) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdSqrtpd , "sqrtpd" , O_660F00(51,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdSqrtps , "sqrtps" , O_000F00(51,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 16, O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdSqrtsd , "sqrtsd" , O_F20F00(51,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 8 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdSqrtss , "sqrtss" , O_F30F00(51,U,_,_,_), U , Enc(ExtRm) , F(Move) , EF(________), 0 , 4 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdStc , "stc" , O_000000(F9,U,_,_,_), U , Enc(X86Op) , F(None) , EF(_____W__), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdStd , "std" , O_000000(FD,U,_,_,_), U , Enc(X86Op) , F(None) , EF(______W_), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdStmxcsr , "stmxcsr" , O_000F00(AE,3,_,_,_), U , Enc(X86M) , F(None) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdStosB , "stos_b" , O_000000(AA,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(______R_), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdStosD , "stos_d" , O_000000(AB,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(______R_), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdStosQ , "stos_q" , O_000000(AB,U,_,W,_), U , Enc(X86Op) , F(None)|F(Special) , EF(______R_), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdStosW , "stos_w" , O_000000(AB,U,_,_,_), U , Enc(X86Op_66H) , F(None)|F(Special) , EF(______R_), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdSub , "sub" , O_000000(28,5,_,_,_), U , Enc(X86Arith) , F(Lock) , EF(WWWWWW__), 0 , 0 , O(GqdwbMem) , O(GqdwbMem)|O(Imm), U , U , U ), + INST(kX86InstIdSubpd , "subpd" , O_660F00(5C,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdSubps , "subps" , O_000F00(5C,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdSubsd , "subsd" , O_F20F00(5C,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdSubss , "subss" , O_F30F00(5C,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdTest , "test" , O_000000(84,U,_,_,_), O_000000(F6,U,_,_,_), Enc(X86Test) , F(Test) , EF(WWWUWW__), 0 , 0 , O(GqdwbMem) , O(Gqdwb)|O(Imm) , U , U , U ), + INST(kX86InstIdTzcnt , "tzcnt" , O_F30F00(BC,U,_,_,_), U , Enc(X86RegRm) , F(Move) , EF(UUWUUW__), 0 , 0 , O(Gqdw) , O(GqdwMem) , U , U , U ), + INST(kX86InstIdUcomisd , "ucomisd" , O_660F00(2E,U,_,_,_), U , Enc(ExtRm) , F(Test) , EF(WWWWWW__), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdUcomiss , "ucomiss" , O_000F00(2E,U,_,_,_), U , Enc(ExtRm) , F(Test) , EF(WWWWWW__), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdUd2 , "ud2" , O_000F00(0B,U,_,_,_), U , Enc(X86Op) , F(None) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdUnpckhpd , "unpckhpd" , O_660F00(15,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdUnpckhps , "unpckhps" , O_000F00(15,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdUnpcklpd , "unpcklpd" , O_660F00(14,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdUnpcklps , "unpcklps" , O_000F00(14,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVaddpd , "vaddpd" , O_660F00(58,U,_,I,1), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVaddps , "vaddps" , O_000F00(58,U,_,I,0), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVaddsd , "vaddsd" , O_F20F00(58,U,0,I,1), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVaddss , "vaddss" , O_F30F00(58,U,0,I,0), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVaddsubpd , "vaddsubpd" , O_660F00(D0,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVaddsubps , "vaddsubps" , O_F20F00(D0,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVaesdec , "vaesdec" , O_660F38(DE,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVaesdeclast , "vaesdeclast" , O_660F38(DF,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVaesenc , "vaesenc" , O_660F38(DC,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVaesenclast , "vaesenclast" , O_660F38(DD,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVaesimc , "vaesimc" , O_660F38(DB,U,_,_,_), U , Enc(AvxRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVaeskeygenassist , "vaeskeygenassist" , O_660F3A(DF,U,_,_,_), U , Enc(AvxRmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdVandnpd , "vandnpd" , O_660F00(55,U,_,_,1), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVandnps , "vandnps" , O_000F00(55,U,_,_,0), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVandpd , "vandpd" , O_660F00(54,U,_,_,1), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVandps , "vandps" , O_000F00(54,U,_,_,0), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVblendpd , "vblendpd" , O_660F3A(0D,U,_,_,_), U , Enc(AvxRvmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(Imm) , U ), + INST(kX86InstIdVblendps , "vblendps" , O_660F3A(0C,U,_,_,_), U , Enc(AvxRvmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(Imm) , U ), + INST(kX86InstIdVblendvpd , "vblendvpd" , O_660F3A(4B,U,_,_,_), U , Enc(AvxRvmr_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(Xy) , U ), + INST(kX86InstIdVblendvps , "vblendvps" , O_660F3A(4A,U,_,_,_), U , Enc(AvxRvmr_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(Xy) , U ), + INST(kX86InstIdVbroadcastf128 , "vbroadcastf128" , O_660F38(1A,U,L,_,_), U , Enc(AvxRm) , F(Avx) , EF(________), 0 , 0 , O(Ymm) , O(Mem) , U , U , U ), + INST(kX86InstIdVbroadcasti128 , "vbroadcasti128" , O_660F38(5A,U,L,_,_), U , Enc(AvxRm) , F(Avx) , EF(________), 0 , 0 , O(Ymm) , O(Mem) , U , U , U ), + INST(kX86InstIdVbroadcastsd , "vbroadcastsd" , O_660F38(19,U,L,0,1), U , Enc(AvxRm) , F(Avx) , EF(________), 0 , 0 , O(Ymm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVbroadcastss , "vbroadcastss" , O_660F38(18,U,_,0,0), U , Enc(AvxRm) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVcmppd , "vcmppd" , O_660F00(C2,U,_,_,_), U , Enc(AvxRvmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(Imm) , U ), + INST(kX86InstIdVcmpps , "vcmpps" , O_000F00(C2,U,_,_,_), U , Enc(AvxRvmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(Imm) , U ), + INST(kX86InstIdVcmpsd , "vcmpsd" , O_F20F00(C2,U,_,_,_), U , Enc(AvxRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Imm) , U ), + INST(kX86InstIdVcmpss , "vcmpss" , O_F30F00(C2,U,_,_,_), U , Enc(AvxRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Imm) , U ), + INST(kX86InstIdVcomisd , "vcomisd" , O_660F00(2F,U,_,_,_), U , Enc(AvxRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVcomiss , "vcomiss" , O_000F00(2F,U,_,_,_), U , Enc(AvxRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVcvtdq2pd , "vcvtdq2pd" , O_F30F00(E6,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVcvtdq2ps , "vcvtdq2ps" , O_000F00(5B,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVcvtpd2dq , "vcvtpd2dq" , O_F20F00(E6,U,_,_,_), U , Enc(AvxRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XyMem) , U , U , U ), + INST(kX86InstIdVcvtpd2ps , "vcvtpd2ps" , O_660F00(5A,U,_,_,_), U , Enc(AvxRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XyMem) , U , U , U ), + INST(kX86InstIdVcvtph2ps , "vcvtph2ps" , O_660F38(13,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVcvtps2dq , "vcvtps2dq" , O_660F00(5B,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVcvtps2pd , "vcvtps2pd" , O_000F00(5A,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVcvtps2ph , "vcvtps2ph" , O_660F3A(1D,U,_,_,_), U , Enc(AvxMri_P) , F(Avx) , EF(________), 0 , 0 , O(XmmMem) , O(Xy) , O(Imm) , U , U ), + INST(kX86InstIdVcvtsd2si , "vcvtsd2si" , O_F20F00(2D,U,_,_,_), U , Enc(AvxRm) , F(Avx) , EF(________), 0 , 0 , O(Gqd) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVcvtsd2ss , "vcvtsd2ss" , O_F20F00(5A,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVcvtsi2sd , "vcvtsi2sd" , O_F20F00(2A,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(GqdMem) , U , U ), + INST(kX86InstIdVcvtsi2ss , "vcvtsi2ss" , O_F30F00(2A,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(GqdMem) , U , U ), + INST(kX86InstIdVcvtss2sd , "vcvtss2sd" , O_F30F00(5A,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVcvtss2si , "vcvtss2si" , O_F20F00(2D,U,_,_,_), U , Enc(AvxRm) , F(Avx) , EF(________), 0 , 0 , O(Gqd) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVcvttpd2dq , "vcvttpd2dq" , O_660F00(E6,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XyMem) , U , U , U ), + INST(kX86InstIdVcvttps2dq , "vcvttps2dq" , O_F30F00(5B,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVcvttsd2si , "vcvttsd2si" , O_F20F00(2C,U,_,_,_), U , Enc(AvxRm) , F(Avx) , EF(________), 0 , 0 , O(Gqd) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVcvttss2si , "vcvttss2si" , O_F30F00(2C,U,_,_,_), U , Enc(AvxRm) , F(Avx) , EF(________), 0 , 0 , O(Gqd) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVdivpd , "vdivpd" , O_660F00(5E,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVdivps , "vdivps" , O_000F00(5E,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVdivsd , "vdivsd" , O_F20F00(5E,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVdivss , "vdivss" , O_F30F00(5E,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVdppd , "vdppd" , O_660F3A(41,U,_,_,_), U , Enc(AvxRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Imm) , U ), + INST(kX86InstIdVdpps , "vdpps" , O_660F3A(40,U,_,_,_), U , Enc(AvxRvmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(Imm) , U ), + INST(kX86InstIdVextractf128 , "vextractf128" , O_660F3A(19,U,L,_,_), U , Enc(AvxMri) , F(Avx) , EF(________), 0 , 0 , O(XmmMem) , O(Ymm) , O(Imm) , U , U ), + INST(kX86InstIdVextracti128 , "vextracti128" , O_660F3A(39,U,L,_,_), U , Enc(AvxMri) , F(Avx) , EF(________), 0 , 0 , O(XmmMem) , O(Ymm) , O(Imm) , U , U ), + INST(kX86InstIdVextractps , "vextractps" , O_660F3A(17,U,_,_,_), U , Enc(AvxMri) , F(Avx) , EF(________), 0 , 0 , O(GqdMem) , O(Xmm) , O(Imm) , U , U ), + INST(kX86InstIdVfmadd132pd , "vfmadd132pd" , O_660F38(98,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmadd132ps , "vfmadd132ps" , O_660F38(98,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmadd132sd , "vfmadd132sd" , O_660F38(99,U,_,W,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfmadd132ss , "vfmadd132ss" , O_660F38(99,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfmadd213pd , "vfmadd213pd" , O_660F38(A8,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmadd213ps , "vfmadd213ps" , O_660F38(A8,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmadd213sd , "vfmadd213sd" , O_660F38(A9,U,_,W,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfmadd213ss , "vfmadd213ss" , O_660F38(A9,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfmadd231pd , "vfmadd231pd" , O_660F38(B8,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmadd231ps , "vfmadd231ps" , O_660F38(B8,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmadd231sd , "vfmadd231sd" , O_660F38(B9,U,_,W,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfmadd231ss , "vfmadd231ss" , O_660F38(B9,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfmaddpd , "vfmaddpd" , O_660F3A(69,U,_,_,_), U , Enc(Fma4_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U ), + INST(kX86InstIdVfmaddps , "vfmaddps" , O_660F3A(68,U,_,_,_), U , Enc(Fma4_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U ), + INST(kX86InstIdVfmaddsd , "vfmaddsd" , O_660F3A(6B,U,_,_,_), U , Enc(Fma4) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(XmmMem) , U ), + INST(kX86InstIdVfmaddss , "vfmaddss" , O_660F3A(6A,U,_,_,_), U , Enc(Fma4) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(XmmMem) , U ), + INST(kX86InstIdVfmaddsub132pd , "vfmaddsub132pd" , O_660F38(96,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmaddsub132ps , "vfmaddsub132ps" , O_660F38(96,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmaddsub213pd , "vfmaddsub213pd" , O_660F38(A6,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmaddsub213ps , "vfmaddsub213ps" , O_660F38(A6,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmaddsub231pd , "vfmaddsub231pd" , O_660F38(B6,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmaddsub231ps , "vfmaddsub231ps" , O_660F38(B6,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmaddsubpd , "vfmaddsubpd" , O_660F3A(5D,U,_,_,_), U , Enc(Fma4_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U ), + INST(kX86InstIdVfmaddsubps , "vfmaddsubps" , O_660F3A(5C,U,_,_,_), U , Enc(Fma4_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U ), + INST(kX86InstIdVfmsub132pd , "vfmsub132pd" , O_660F38(9A,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmsub132ps , "vfmsub132ps" , O_660F38(9A,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmsub132sd , "vfmsub132sd" , O_660F38(9B,U,_,W,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfmsub132ss , "vfmsub132ss" , O_660F38(9B,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfmsub213pd , "vfmsub213pd" , O_660F38(AA,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmsub213ps , "vfmsub213ps" , O_660F38(AA,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmsub213sd , "vfmsub213sd" , O_660F38(AB,U,_,W,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfmsub213ss , "vfmsub213ss" , O_660F38(AB,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfmsub231pd , "vfmsub231pd" , O_660F38(BA,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmsub231ps , "vfmsub231ps" , O_660F38(BA,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmsub231sd , "vfmsub231sd" , O_660F38(BB,U,_,W,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfmsub231ss , "vfmsub231ss" , O_660F38(BB,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfmsubadd132pd , "vfmsubadd132pd" , O_660F38(97,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmsubadd132ps , "vfmsubadd132ps" , O_660F38(97,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmsubadd213pd , "vfmsubadd213pd" , O_660F38(A7,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmsubadd213ps , "vfmsubadd213ps" , O_660F38(A7,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmsubadd231pd , "vfmsubadd231pd" , O_660F38(B7,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmsubadd231ps , "vfmsubadd231ps" , O_660F38(B7,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfmsubaddpd , "vfmsubaddpd" , O_660F3A(5F,U,_,_,_), U , Enc(Fma4_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U ), + INST(kX86InstIdVfmsubaddps , "vfmsubaddps" , O_660F3A(5E,U,_,_,_), U , Enc(Fma4_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U ), + INST(kX86InstIdVfmsubpd , "vfmsubpd" , O_660F3A(6D,U,_,_,_), U , Enc(Fma4_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U ), + INST(kX86InstIdVfmsubps , "vfmsubps" , O_660F3A(6C,U,_,_,_), U , Enc(Fma4_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U ), + INST(kX86InstIdVfmsubsd , "vfmsubsd" , O_660F3A(6F,U,_,_,_), U , Enc(Fma4) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(XmmMem) , U ), + INST(kX86InstIdVfmsubss , "vfmsubss" , O_660F3A(6E,U,_,_,_), U , Enc(Fma4) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(XmmMem) , U ), + INST(kX86InstIdVfnmadd132pd , "vfnmadd132pd" , O_660F38(9C,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfnmadd132ps , "vfnmadd132ps" , O_660F38(9C,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfnmadd132sd , "vfnmadd132sd" , O_660F38(9D,U,_,W,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfnmadd132ss , "vfnmadd132ss" , O_660F38(9D,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfnmadd213pd , "vfnmadd213pd" , O_660F38(AC,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfnmadd213ps , "vfnmadd213ps" , O_660F38(AC,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfnmadd213sd , "vfnmadd213sd" , O_660F38(AD,U,_,W,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfnmadd213ss , "vfnmadd213ss" , O_660F38(AD,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfnmadd231pd , "vfnmadd231pd" , O_660F38(BC,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfnmadd231ps , "vfnmadd231ps" , O_660F38(BC,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfnmadd231sd , "vfnmadd231sd" , O_660F38(BC,U,_,W,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfnmadd231ss , "vfnmadd231ss" , O_660F38(BC,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfnmaddpd , "vfnmaddpd" , O_660F3A(79,U,_,_,_), U , Enc(Fma4_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U ), + INST(kX86InstIdVfnmaddps , "vfnmaddps" , O_660F3A(78,U,_,_,_), U , Enc(Fma4_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U ), + INST(kX86InstIdVfnmaddsd , "vfnmaddsd" , O_660F3A(7B,U,_,_,_), U , Enc(Fma4) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(XmmMem) , U ), + INST(kX86InstIdVfnmaddss , "vfnmaddss" , O_660F3A(7A,U,_,_,_), U , Enc(Fma4) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(XmmMem) , U ), + INST(kX86InstIdVfnmsub132pd , "vfnmsub132pd" , O_660F38(9E,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfnmsub132ps , "vfnmsub132ps" , O_660F38(9E,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfnmsub132sd , "vfnmsub132sd" , O_660F38(9F,U,_,W,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfnmsub132ss , "vfnmsub132ss" , O_660F38(9F,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfnmsub213pd , "vfnmsub213pd" , O_660F38(AE,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfnmsub213ps , "vfnmsub213ps" , O_660F38(AE,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfnmsub213sd , "vfnmsub213sd" , O_660F38(AF,U,_,W,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfnmsub213ss , "vfnmsub213ss" , O_660F38(AF,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfnmsub231pd , "vfnmsub231pd" , O_660F38(BE,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfnmsub231ps , "vfnmsub231ps" , O_660F38(BE,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVfnmsub231sd , "vfnmsub231sd" , O_660F38(BF,U,_,W,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfnmsub231ss , "vfnmsub231ss" , O_660F38(BF,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVfnmsubpd , "vfnmsubpd" , O_660F3A(7D,U,_,_,_), U , Enc(Fma4_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U ), + INST(kX86InstIdVfnmsubps , "vfnmsubps" , O_660F3A(7C,U,_,_,_), U , Enc(Fma4_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U ), + INST(kX86InstIdVfnmsubsd , "vfnmsubsd" , O_660F3A(7F,U,_,_,_), U , Enc(Fma4) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(XmmMem) , U ), + INST(kX86InstIdVfnmsubss , "vfnmsubss" , O_660F3A(7E,U,_,_,_), U , Enc(Fma4) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(XmmMem) , U ), + INST(kX86InstIdVfrczpd , "vfrczpd" , O_00_M09(81,U,_,_,_), U , Enc(XopRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVfrczps , "vfrczps" , O_00_M09(80,U,_,_,_), U , Enc(XopRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVfrczsd , "vfrczsd" , O_00_M09(83,U,_,_,_), U , Enc(XopRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVfrczss , "vfrczss" , O_00_M09(82,U,_,_,_), U , Enc(XopRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVgatherdpd , "vgatherdpd" , O_660F38(92,U,_,W,_), U , Enc(AvxGather) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Mem) , O(Xy) , U , U ), + INST(kX86InstIdVgatherdps , "vgatherdps" , O_660F38(92,U,_,_,_), U , Enc(AvxGather) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Mem) , O(Xy) , U , U ), + INST(kX86InstIdVgatherqpd , "vgatherqpd" , O_660F38(93,U,_,W,_), U , Enc(AvxGather) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Mem) , O(Xy) , U , U ), + INST(kX86InstIdVgatherqps , "vgatherqps" , O_660F38(93,U,_,_,_), U , Enc(AvxGatherEx) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Mem) , O(Xmm) , U , U ), + INST(kX86InstIdVhaddpd , "vhaddpd" , O_660F00(7C,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVhaddps , "vhaddps" , O_F20F00(7C,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVhsubpd , "vhsubpd" , O_660F00(7D,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVhsubps , "vhsubps" , O_F20F00(7D,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVinsertf128 , "vinsertf128" , O_660F3A(18,U,L,_,_), U , Enc(AvxRvmi) , F(Avx) , EF(________), 0 , 0 , O(Ymm) , O(Ymm) , O(XmmMem) , O(Imm) , U ), + INST(kX86InstIdVinserti128 , "vinserti128" , O_660F3A(38,U,L,_,_), U , Enc(AvxRvmi) , F(Avx) , EF(________), 0 , 0 , O(Ymm) , O(Ymm) , O(XmmMem) , O(Imm) , U ), + INST(kX86InstIdVinsertps , "vinsertps" , O_660F3A(21,U,_,_,_), U , Enc(AvxRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Imm) , U ), + INST(kX86InstIdVlddqu , "vlddqu" , O_F20F00(F0,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Mem) , U , U , U ), + INST(kX86InstIdVldmxcsr , "vldmxcsr" , O_000F00(AE,2,_,_,_), U , Enc(AvxM) , F(Avx) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdVmaskmovdqu , "vmaskmovdqu" , O_660F00(F7,U,_,_,_), U , Enc(AvxRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , U , U , U ), + INST(kX86InstIdVmaskmovpd , "vmaskmovpd" , O_660F38(2D,U,_,_,_), O_660F38(2F,U,_,_,_), Enc(AvxRvmMvr_P) , F(Avx) , EF(________), 0 , 0 , O(XyMem) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVmaskmovps , "vmaskmovps" , O_660F38(2C,U,_,_,_), O_660F38(2E,U,_,_,_), Enc(AvxRvmMvr_P) , F(Avx) , EF(________), 0 , 0 , O(XyMem) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVmaxpd , "vmaxpd" , O_660F00(5F,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVmaxps , "vmaxps" , O_000F00(5F,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVmaxsd , "vmaxsd" , O_F20F00(5F,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVmaxss , "vmaxss" , O_F30F00(5F,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVminpd , "vminpd" , O_660F00(5D,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVminps , "vminps" , O_000F00(5D,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVminsd , "vminsd" , O_F20F00(5D,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVminss , "vminss" , O_F30F00(5D,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVmovapd , "vmovapd" , O_660F00(28,U,_,_,_), O_660F00(29,U,_,_,_), Enc(AvxRmMr_P) , F(Avx) , EF(________), 0 , 0 , O(XyMem) , O(XyMem) , U , U , U ), + INST(kX86InstIdVmovaps , "vmovaps" , O_000F00(28,U,_,_,_), O_000F00(29,U,_,_,_), Enc(AvxRmMr_P) , F(Avx) , EF(________), 0 , 0 , O(XyMem) , O(XyMem) , U , U , U ), + INST(kX86InstIdVmovd , "vmovd" , O_660F00(6E,U,_,_,_), O_660F00(7E,U,_,_,_), Enc(AvxRmMr) , F(Avx) , EF(________), 0 , 0 , O(XmmMem) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVmovddup , "vmovddup" , O_F20F00(12,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVmovdqa , "vmovdqa" , O_660F00(6F,U,_,_,_), O_660F00(7F,U,_,_,_), Enc(AvxRmMr_P) , F(Avx) , EF(________), 0 , 0 , O(XyMem) , O(XyMem) , U , U , U ), + INST(kX86InstIdVmovdqu , "vmovdqu" , O_F30F00(6F,U,_,_,_), O_F30F00(7F,U,_,_,_), Enc(AvxRmMr_P) , F(Avx) , EF(________), 0 , 0 , O(XyMem) , O(XyMem) , U , U , U ), + INST(kX86InstIdVmovhlps , "vmovhlps" , O_000F00(12,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(Xmm) , U , U ), + INST(kX86InstIdVmovhpd , "vmovhpd" , O_660F00(16,U,_,_,_), O_660F00(17,U,_,_,_), Enc(AvxRvmMr) , F(Avx) , EF(________), 0 , 0 , O(XmmMem) , O(Xmm) , O(Mem) , U , U ), + INST(kX86InstIdVmovhps , "vmovhps" , O_000F00(16,U,_,_,_), O_000F00(17,U,_,_,_), Enc(AvxRvmMr) , F(Avx) , EF(________), 0 , 0 , O(XmmMem) , O(Xmm) , O(Mem) , U , U ), + INST(kX86InstIdVmovlhps , "vmovlhps" , O_000F00(16,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(Xmm) , U , U ), + INST(kX86InstIdVmovlpd , "vmovlpd" , O_660F00(12,U,_,_,_), O_660F00(13,U,_,_,_), Enc(AvxRvmMr) , F(Avx) , EF(________), 0 , 0 , O(XmmMem) , O(Xmm) , O(Mem) , U , U ), + INST(kX86InstIdVmovlps , "vmovlps" , O_000F00(12,U,_,_,_), O_000F00(13,U,_,_,_), Enc(AvxRvmMr) , F(Avx) , EF(________), 0 , 0 , O(XmmMem) , O(Xmm) , O(Mem) , U , U ), + INST(kX86InstIdVmovmskpd , "vmovmskpd" , O_660F00(50,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Gqd) , O(Xy) , U , U , U ), + INST(kX86InstIdVmovmskps , "vmovmskps" , O_000F00(50,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Gqd) , O(Xy) , U , U , U ), + INST(kX86InstIdVmovntdq , "vmovntdq" , O_660F00(E7,U,_,_,_), U , Enc(AvxMr) , F(Avx) , EF(________), 0 , 0 , O(Mem) , O(Xy) , U , U , U ), + INST(kX86InstIdVmovntdqa , "vmovntdqa" , O_660F38(2A,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Mem) , U , U , U ), + INST(kX86InstIdVmovntpd , "vmovntpd" , O_660F00(2B,U,_,_,_), U , Enc(AvxMr_P) , F(Avx) , EF(________), 0 , 0 , O(Mem) , O(Xy) , U , U , U ), + INST(kX86InstIdVmovntps , "vmovntps" , O_000F00(2B,U,_,_,_), U , Enc(AvxMr_P) , F(Avx) , EF(________), 0 , 0 , O(Mem) , O(Xy) , U , U , U ), + INST(kX86InstIdVmovq , "vmovq" , O_660F00(6E,U,_,W,_), O_660F00(7E,U,_,_,_), Enc(AvxRmMr) , F(Avx) , EF(________), 0 , 0 , O(XmmMem) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVmovsd , "vmovsd" , O_F20F00(10,U,_,_,_), O_F20F00(11,U,_,_,_), Enc(AvxMovSsSd) , F(Avx) , EF(________), 0 , 0 , O(XmmMem) , O(XmmMem) , O(Xmm) , U , U ), + INST(kX86InstIdVmovshdup , "vmovshdup" , O_F30F00(16,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVmovsldup , "vmovsldup" , O_F30F00(12,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVmovss , "vmovss" , O_F30F00(10,U,_,_,_), O_F30F00(11,U,_,_,_), Enc(AvxMovSsSd) , F(Avx) , EF(________), 0 , 0 , O(XmmMem) , O(Xmm) , O(Xmm) , U , U ), + INST(kX86InstIdVmovupd , "vmovupd" , O_660F00(10,U,_,_,_), O_660F00(11,U,_,_,_), Enc(AvxRmMr_P) , F(Avx) , EF(________), 0 , 0 , O(XyMem) , O(XyMem) , U , U , U ), + INST(kX86InstIdVmovups , "vmovups" , O_000F00(10,U,_,_,_), O_000F00(11,U,_,_,_), Enc(AvxRmMr_P) , F(Avx) , EF(________), 0 , 0 , O(XyMem) , O(XyMem) , U , U , U ), + INST(kX86InstIdVmpsadbw , "vmpsadbw" , O_660F3A(42,U,_,_,_), U , Enc(AvxRvmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(Imm) , U ), + INST(kX86InstIdVmulpd , "vmulpd" , O_660F00(59,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVmulps , "vmulps" , O_000F00(59,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVmulsd , "vmulsd" , O_F20F00(59,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVmulss , "vmulss" , O_F30F00(59,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVorpd , "vorpd" , O_660F00(56,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVorps , "vorps" , O_000F00(56,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpabsb , "vpabsb" , O_660F38(1C,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVpabsd , "vpabsd" , O_660F38(1E,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVpabsw , "vpabsw" , O_660F38(1D,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVpackssdw , "vpackssdw" , O_660F00(6B,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpacksswb , "vpacksswb" , O_660F00(63,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpackusdw , "vpackusdw" , O_660F38(2B,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpackuswb , "vpackuswb" , O_660F00(67,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpaddb , "vpaddb" , O_660F00(FC,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpaddd , "vpaddd" , O_660F00(FE,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpaddq , "vpaddq" , O_660F00(D4,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpaddsb , "vpaddsb" , O_660F00(EC,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpaddsw , "vpaddsw" , O_660F00(ED,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpaddusb , "vpaddusb" , O_660F00(DC,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpaddusw , "vpaddusw" , O_660F00(DD,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpaddw , "vpaddw" , O_660F00(FD,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpalignr , "vpalignr" , O_660F3A(0F,U,_,_,_), U , Enc(AvxRvmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(Imm) , U ), + INST(kX86InstIdVpand , "vpand" , O_660F00(DB,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpandn , "vpandn" , O_660F00(DF,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpavgb , "vpavgb" , O_660F00(E0,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpavgw , "vpavgw" , O_660F00(E3,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpblendd , "vpblendd" , O_660F3A(02,U,_,_,_), U , Enc(AvxRvmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(Imm) , U ), + INST(kX86InstIdVpblendvb , "vpblendvb" , O_660F3A(4C,U,_,_,_), U , Enc(AvxRvmr) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(Xy) , U ), + INST(kX86InstIdVpblendw , "vpblendw" , O_660F3A(0E,U,_,_,_), U , Enc(AvxRvmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(Imm) , U ), + INST(kX86InstIdVpbroadcastb , "vpbroadcastb" , O_660F38(78,U,_,_,0), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVpbroadcastd , "vpbroadcastd" , O_660F38(58,U,_,_,0), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVpbroadcastq , "vpbroadcastq" , O_660F38(59,U,_,_,1), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVpbroadcastw , "vpbroadcastw" , O_660F38(79,U,_,_,0), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVpclmulqdq , "vpclmulqdq" , O_660F3A(44,U,_,_,_), U , Enc(AvxRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Imm) , U ), + INST(kX86InstIdVpcmov , "vpcmov" , O_00_M08(A2,U,_,_,_), U , Enc(XopRvrmRvmr_P), F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U ), + INST(kX86InstIdVpcmpeqb , "vpcmpeqb" , O_660F00(74,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpcmpeqd , "vpcmpeqd" , O_660F00(76,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpcmpeqq , "vpcmpeqq" , O_660F38(29,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpcmpeqw , "vpcmpeqw" , O_660F00(75,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpcmpestri , "vpcmpestri" , O_660F3A(61,U,_,_,_), U , Enc(AvxRmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdVpcmpestrm , "vpcmpestrm" , O_660F3A(60,U,_,_,_), U , Enc(AvxRmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdVpcmpgtb , "vpcmpgtb" , O_660F00(64,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpcmpgtd , "vpcmpgtd" , O_660F00(66,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpcmpgtq , "vpcmpgtq" , O_660F38(37,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpcmpgtw , "vpcmpgtw" , O_660F00(65,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpcmpistri , "vpcmpistri" , O_660F3A(63,U,_,_,_), U , Enc(AvxRmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdVpcmpistrm , "vpcmpistrm" , O_660F3A(62,U,_,_,_), U , Enc(AvxRmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(Imm) , U , U ), + INST(kX86InstIdVpcomb , "vpcomb" , O_00_M08(CC,U,_,_,_), U , Enc(XopRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Imm) , U ), + INST(kX86InstIdVpcomd , "vpcomd" , O_00_M08(CE,U,_,_,_), U , Enc(XopRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Imm) , U ), + INST(kX86InstIdVpcomq , "vpcomq" , O_00_M08(CF,U,_,_,_), U , Enc(XopRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Imm) , U ), + INST(kX86InstIdVpcomub , "vpcomub" , O_00_M08(EC,U,_,_,_), U , Enc(XopRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Imm) , U ), + INST(kX86InstIdVpcomud , "vpcomud" , O_00_M08(EE,U,_,_,_), U , Enc(XopRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Imm) , U ), + INST(kX86InstIdVpcomuq , "vpcomuq" , O_00_M08(EF,U,_,_,_), U , Enc(XopRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Imm) , U ), + INST(kX86InstIdVpcomuw , "vpcomuw" , O_00_M08(ED,U,_,_,_), U , Enc(XopRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Imm) , U ), + INST(kX86InstIdVpcomw , "vpcomw" , O_00_M08(CD,U,_,_,_), U , Enc(XopRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Imm) , U ), + INST(kX86InstIdVperm2f128 , "vperm2f128" , O_660F3A(06,U,L,_,_), U , Enc(AvxRvmi) , F(Avx) , EF(________), 0 , 0 , O(Ymm) , O(Ymm) , O(YmmMem) , O(Imm) , U ), + INST(kX86InstIdVperm2i128 , "vperm2i128" , O_660F3A(46,U,L,_,_), U , Enc(AvxRvmi) , F(Avx) , EF(________), 0 , 0 , O(Ymm) , O(Ymm) , O(YmmMem) , O(Imm) , U ), + INST(kX86InstIdVpermd , "vpermd" , O_660F38(36,U,L,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Ymm) , O(Ymm) , O(YmmMem) , U , U ), + INST(kX86InstIdVpermil2pd , "vpermil2pd" , O_66_M03(49,U,_,_,_), U , Enc(AvxRvrmRvmr_P), F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U ), + INST(kX86InstIdVpermil2ps , "vpermil2ps" , O_66_M03(48,U,_,_,_), U , Enc(AvxRvrmRvmr_P), F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(XyMem) , U ), + INST(kX86InstIdVpermilpd , "vpermilpd" , O_660F38(0D,U,_,_,_), O_660F3A(05,U,_,_,_), Enc(AvxRvmRmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U ), + INST(kX86InstIdVpermilps , "vpermilps" , O_660F38(0C,U,_,_,_), O_660F3A(04,U,_,_,_), Enc(AvxRvmRmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U ), + INST(kX86InstIdVpermpd , "vpermpd" , O_660F3A(01,U,L,W,_), U , Enc(AvxRmi) , F(Avx) , EF(________), 0 , 0 , O(Ymm) , O(YmmMem) , O(Imm) , U , U ), + INST(kX86InstIdVpermps , "vpermps" , O_660F38(16,U,L,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Ymm) , O(Ymm) , O(YmmMem) , U , U ), + INST(kX86InstIdVpermq , "vpermq" , O_660F3A(00,U,L,W,_), U , Enc(AvxRmi) , F(Avx) , EF(________), 0 , 0 , O(Ymm) , O(YmmMem) , O(Imm) , U , U ), + INST(kX86InstIdVpextrb , "vpextrb" , O_660F3A(14,U,_,_,_), U , Enc(AvxMri) , F(Avx) , EF(________), 0 , 0 , O(GqdwbMem) , O(Xmm) , O(Imm) , U , U ), + INST(kX86InstIdVpextrd , "vpextrd" , O_660F3A(16,U,_,_,_), U , Enc(AvxMri) , F(Avx) , EF(________), 0 , 0 , O(GqdMem) , O(Xmm) , O(Imm) , U , U ), + INST(kX86InstIdVpextrq , "vpextrq" , O_660F3A(16,U,_,W,_), U , Enc(AvxMri) , F(Avx) , EF(________), 0 , 0 , O(GqMem) , O(Xmm) , O(Imm) , U , U ), + INST(kX86InstIdVpextrw , "vpextrw" , O_660F3A(15,U,_,_,_), U , Enc(AvxMri) , F(Avx) , EF(________), 0 , 0 , O(GqdwMem) , O(Xmm) , O(Imm) , U , U ), + INST(kX86InstIdVpgatherdd , "vpgatherdd" , O_660F38(90,U,_,_,_), U , Enc(AvxGather) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Mem) , O(Xy) , U , U ), + INST(kX86InstIdVpgatherdq , "vpgatherdq" , O_660F38(90,U,_,W,_), U , Enc(AvxGather) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Mem) , O(Xy) , U , U ), + INST(kX86InstIdVpgatherqd , "vpgatherqd" , O_660F38(91,U,_,_,_), U , Enc(AvxGatherEx) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Mem) , O(Xmm) , U , U ), + INST(kX86InstIdVpgatherqq , "vpgatherqq" , O_660F38(91,U,_,W,_), U , Enc(AvxGather) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Mem) , O(Xy) , U , U ), + INST(kX86InstIdVphaddbd , "vphaddbd" , O_00_M09(C2,U,_,_,_), U , Enc(XopRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVphaddbq , "vphaddbq" , O_00_M09(C3,U,_,_,_), U , Enc(XopRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVphaddbw , "vphaddbw" , O_00_M09(C1,U,_,_,_), U , Enc(XopRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVphaddd , "vphaddd" , O_660F38(02,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVphadddq , "vphadddq" , O_00_M09(CB,U,_,_,_), U , Enc(XopRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVphaddsw , "vphaddsw" , O_660F38(03,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVphaddubd , "vphaddubd" , O_00_M09(D2,U,_,_,_), U , Enc(XopRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVphaddubq , "vphaddubq" , O_00_M09(D3,U,_,_,_), U , Enc(XopRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVphaddubw , "vphaddubw" , O_00_M09(D1,U,_,_,_), U , Enc(XopRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVphaddudq , "vphaddudq" , O_00_M09(DB,U,_,_,_), U , Enc(XopRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVphadduwd , "vphadduwd" , O_00_M09(D6,U,_,_,_), U , Enc(XopRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVphadduwq , "vphadduwq" , O_00_M09(D7,U,_,_,_), U , Enc(XopRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVphaddw , "vphaddw" , O_660F38(01,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVphaddwd , "vphaddwd" , O_00_M09(C6,U,_,_,_), U , Enc(XopRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVphaddwq , "vphaddwq" , O_00_M09(C7,U,_,_,_), U , Enc(XopRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVphminposuw , "vphminposuw" , O_660F38(41,U,_,_,_), U , Enc(AvxRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVphsubbw , "vphsubbw" , O_00_M09(E1,U,_,_,_), U , Enc(XopRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVphsubd , "vphsubd" , O_660F38(06,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVphsubdq , "vphsubdq" , O_00_M09(E3,U,_,_,_), U , Enc(XopRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVphsubsw , "vphsubsw" , O_660F38(07,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVphsubw , "vphsubw" , O_660F38(05,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVphsubwd , "vphsubwd" , O_00_M09(E2,U,_,_,_), U , Enc(XopRm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVpinsrb , "vpinsrb" , O_660F3A(20,U,_,_,_), U , Enc(AvxRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(GqdwbMem) , O(Imm) , U ), + INST(kX86InstIdVpinsrd , "vpinsrd" , O_660F3A(22,U,_,_,_), U , Enc(AvxRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(GqdMem) , O(Imm) , U ), + INST(kX86InstIdVpinsrq , "vpinsrq" , O_660F3A(22,U,_,W,_), U , Enc(AvxRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(GqMem) , O(Imm) , U ), + INST(kX86InstIdVpinsrw , "vpinsrw" , O_660F00(C4,U,_,_,_), U , Enc(AvxRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(GqdwMem) , O(Imm) , U ), + INST(kX86InstIdVpmacsdd , "vpmacsdd" , O_00_M08(9E,U,_,_,_), U , Enc(XopRvmr) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Xmm) , U ), + INST(kX86InstIdVpmacsdqh , "vpmacsdqh" , O_00_M08(9F,U,_,_,_), U , Enc(XopRvmr) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Xmm) , U ), + INST(kX86InstIdVpmacsdql , "vpmacsdql" , O_00_M08(97,U,_,_,_), U , Enc(XopRvmr) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Xmm) , U ), + INST(kX86InstIdVpmacssdd , "vpmacssdd" , O_00_M08(8E,U,_,_,_), U , Enc(XopRvmr) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Xmm) , U ), + INST(kX86InstIdVpmacssdqh , "vpmacssdqh" , O_00_M08(8F,U,_,_,_), U , Enc(XopRvmr) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Xmm) , U ), + INST(kX86InstIdVpmacssdql , "vpmacssdql" , O_00_M08(87,U,_,_,_), U , Enc(XopRvmr) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Xmm) , U ), + INST(kX86InstIdVpmacsswd , "vpmacsswd" , O_00_M08(86,U,_,_,_), U , Enc(XopRvmr) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Xmm) , U ), + INST(kX86InstIdVpmacssww , "vpmacssww" , O_00_M08(85,U,_,_,_), U , Enc(XopRvmr) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Xmm) , U ), + INST(kX86InstIdVpmacswd , "vpmacswd" , O_00_M08(96,U,_,_,_), U , Enc(XopRvmr) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Xmm) , U ), + INST(kX86InstIdVpmacsww , "vpmacsww" , O_00_M08(95,U,_,_,_), U , Enc(XopRvmr) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Xmm) , U ), + INST(kX86InstIdVpmadcsswd , "vpmadcsswd" , O_00_M08(A6,U,_,_,_), U , Enc(XopRvmr) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Xmm) , U ), + INST(kX86InstIdVpmadcswd , "vpmadcswd" , O_00_M08(B6,U,_,_,_), U , Enc(XopRvmr) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Xmm) , U ), + INST(kX86InstIdVpmaddubsw , "vpmaddubsw" , O_660F38(04,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpmaddwd , "vpmaddwd" , O_660F00(F5,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpmaskmovd , "vpmaskmovd" , O_660F38(8C,U,_,_,_), O_660F38(8E,U,_,_,_), Enc(AvxRvmMvr_P) , F(Avx) , EF(________), 0 , 0 , O(XyMem) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpmaskmovq , "vpmaskmovq" , O_660F38(8C,U,_,W,_), O_660F38(8E,U,_,_,_), Enc(AvxRvmMvr_P) , F(Avx) , EF(________), 0 , 0 , O(XyMem) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpmaxsb , "vpmaxsb" , O_660F38(3C,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpmaxsd , "vpmaxsd" , O_660F38(3D,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpmaxsw , "vpmaxsw" , O_660F00(EE,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpmaxub , "vpmaxub" , O_660F00(DE,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpmaxud , "vpmaxud" , O_660F38(3F,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpmaxuw , "vpmaxuw" , O_660F38(3E,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpminsb , "vpminsb" , O_660F38(38,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpminsd , "vpminsd" , O_660F38(39,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpminsw , "vpminsw" , O_660F00(EA,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpminub , "vpminub" , O_660F00(DA,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpminud , "vpminud" , O_660F38(3B,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpminuw , "vpminuw" , O_660F38(3A,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpmovmskb , "vpmovmskb" , O_660F00(D7,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Gqd) , O(Xy) , U , U , U ), + INST(kX86InstIdVpmovsxbd , "vpmovsxbd" , O_660F38(21,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVpmovsxbq , "vpmovsxbq" , O_660F38(22,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVpmovsxbw , "vpmovsxbw" , O_660F38(20,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVpmovsxdq , "vpmovsxdq" , O_660F38(25,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVpmovsxwd , "vpmovsxwd" , O_660F38(23,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVpmovsxwq , "vpmovsxwq" , O_660F38(24,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVpmovzxbd , "vpmovzxbd" , O_660F38(31,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVpmovzxbq , "vpmovzxbq" , O_660F38(32,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVpmovzxbw , "vpmovzxbw" , O_660F38(30,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVpmovzxdq , "vpmovzxdq" , O_660F38(35,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVpmovzxwd , "vpmovzxwd" , O_660F38(33,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVpmovzxwq , "vpmovzxwq" , O_660F38(34,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVpmuldq , "vpmuldq" , O_660F38(28,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpmulhrsw , "vpmulhrsw" , O_660F38(0B,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpmulhuw , "vpmulhuw" , O_660F00(E4,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpmulhw , "vpmulhw" , O_660F00(E5,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpmulld , "vpmulld" , O_660F38(40,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpmullw , "vpmullw" , O_660F00(D5,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpmuludq , "vpmuludq" , O_660F00(F4,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpor , "vpor" , O_660F00(EB,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpperm , "vpperm" , O_00_M08(A3,U,_,_,_), U , Enc(XopRvrmRvmr) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(XmmMem) , U ), + INST(kX86InstIdVprotb , "vprotb" , O_00_M09(90,U,_,_,_), O_00_M08(C0,U,_,_,_), Enc(XopRvmRmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(XmmMem)|O(Imm) , U , U ), + INST(kX86InstIdVprotd , "vprotd" , O_00_M09(92,U,_,_,_), O_00_M08(C2,U,_,_,_), Enc(XopRvmRmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(XmmMem)|O(Imm) , U , U ), + INST(kX86InstIdVprotq , "vprotq" , O_00_M09(93,U,_,_,_), O_00_M08(C3,U,_,_,_), Enc(XopRvmRmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(XmmMem)|O(Imm) , U , U ), + INST(kX86InstIdVprotw , "vprotw" , O_00_M09(91,U,_,_,_), O_00_M08(C1,U,_,_,_), Enc(XopRvmRmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(XmmMem)|O(Imm) , U , U ), + INST(kX86InstIdVpsadbw , "vpsadbw" , O_660F00(F6,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpshab , "vpshab" , O_00_M09(98,U,_,_,_), U , Enc(XopRvmRmv) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(XmmMem) , U , U ), + INST(kX86InstIdVpshad , "vpshad" , O_00_M09(9A,U,_,_,_), U , Enc(XopRvmRmv) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(XmmMem) , U , U ), + INST(kX86InstIdVpshaq , "vpshaq" , O_00_M09(9B,U,_,_,_), U , Enc(XopRvmRmv) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(XmmMem) , U , U ), + INST(kX86InstIdVpshaw , "vpshaw" , O_00_M09(99,U,_,_,_), U , Enc(XopRvmRmv) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(XmmMem) , U , U ), + INST(kX86InstIdVpshlb , "vpshlb" , O_00_M09(94,U,_,_,_), U , Enc(XopRvmRmv) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(XmmMem) , U , U ), + INST(kX86InstIdVpshld , "vpshld" , O_00_M09(96,U,_,_,_), U , Enc(XopRvmRmv) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(XmmMem) , U , U ), + INST(kX86InstIdVpshlq , "vpshlq" , O_00_M09(97,U,_,_,_), U , Enc(XopRvmRmv) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(XmmMem) , U , U ), + INST(kX86InstIdVpshlw , "vpshlw" , O_00_M09(95,U,_,_,_), U , Enc(XopRvmRmv) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , O(XmmMem) , U , U ), + INST(kX86InstIdVpshufb , "vpshufb" , O_660F38(00,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpshufd , "vpshufd" , O_660F00(70,U,_,_,_), U , Enc(AvxRmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , O(Imm) , U , U ), + INST(kX86InstIdVpshufhw , "vpshufhw" , O_F30F00(70,U,_,_,_), U , Enc(AvxRmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , O(Imm) , U , U ), + INST(kX86InstIdVpshuflw , "vpshuflw" , O_F20F00(70,U,_,_,_), U , Enc(AvxRmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , O(Imm) , U , U ), + INST(kX86InstIdVpsignb , "vpsignb" , O_660F38(08,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpsignd , "vpsignd" , O_660F38(0A,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpsignw , "vpsignw" , O_660F38(09,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpslld , "vpslld" , O_660F00(F2,U,_,_,_), O_660F00(72,6,_,_,_), Enc(AvxRvmVmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U ), + INST(kX86InstIdVpslldq , "vpslldq" , O_660F00(73,7,_,_,_), U , Enc(AvxVmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , O(Imm) , U , U ), + INST(kX86InstIdVpsllq , "vpsllq" , O_660F00(F3,U,_,_,_), O_660F00(73,6,_,_,_), Enc(AvxRvmVmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U ), + INST(kX86InstIdVpsllvd , "vpsllvd" , O_660F38(47,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpsllvq , "vpsllvq" , O_660F38(47,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpsllw , "vpsllw" , O_660F00(F1,U,_,_,_), O_660F00(71,6,_,_,_), Enc(AvxRvmVmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U ), + INST(kX86InstIdVpsrad , "vpsrad" , O_660F00(E2,U,_,_,_), O_660F00(72,4,_,_,_), Enc(AvxRvmVmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U ), + INST(kX86InstIdVpsravd , "vpsravd" , O_660F38(46,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpsraw , "vpsraw" , O_660F00(E1,U,_,_,_), O_660F00(71,4,_,_,_), Enc(AvxRvmVmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U ), + INST(kX86InstIdVpsrld , "vpsrld" , O_660F00(D2,U,_,_,_), O_660F00(72,2,_,_,_), Enc(AvxRvmVmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U ), + INST(kX86InstIdVpsrldq , "vpsrldq" , O_660F00(73,3,_,_,_), U , Enc(AvxVmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , O(Imm) , U , U ), + INST(kX86InstIdVpsrlq , "vpsrlq" , O_660F00(D3,U,_,_,_), O_660F00(73,2,_,_,_), Enc(AvxRvmVmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U ), + INST(kX86InstIdVpsrlvd , "vpsrlvd" , O_660F38(45,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpsrlvq , "vpsrlvq" , O_660F38(45,U,_,W,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpsrlw , "vpsrlw" , O_660F00(D1,U,_,_,_), O_660F00(71,2,_,_,_), Enc(AvxRvmVmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , O(XyMem)|O(Imm) , U , U ), + INST(kX86InstIdVpsubb , "vpsubb" , O_660F00(F8,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpsubd , "vpsubd" , O_660F00(FA,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpsubq , "vpsubq" , O_660F00(FB,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpsubsb , "vpsubsb" , O_660F00(E8,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpsubsw , "vpsubsw" , O_660F00(E9,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpsubusb , "vpsubusb" , O_660F00(D8,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpsubusw , "vpsubusw" , O_660F00(D9,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpsubw , "vpsubw" , O_660F00(F9,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVptest , "vptest" , O_660F38(17,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(WWWWWW__), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVpunpckhbw , "vpunpckhbw" , O_660F00(68,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpunpckhdq , "vpunpckhdq" , O_660F00(6A,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpunpckhqdq , "vpunpckhqdq" , O_660F00(6D,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpunpckhwd , "vpunpckhwd" , O_660F00(69,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpunpcklbw , "vpunpcklbw" , O_660F00(60,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpunpckldq , "vpunpckldq" , O_660F00(62,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpunpcklqdq , "vpunpcklqdq" , O_660F00(6C,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpunpcklwd , "vpunpcklwd" , O_660F00(61,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVpxor , "vpxor" , O_660F00(EF,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVrcpps , "vrcpps" , O_000F00(53,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVrcpss , "vrcpss" , O_F30F00(53,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVroundpd , "vroundpd" , O_660F3A(09,U,_,_,_), U , Enc(AvxRmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , O(Imm) , U , U ), + INST(kX86InstIdVroundps , "vroundps" , O_660F3A(08,U,_,_,_), U , Enc(AvxRmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , O(Imm) , U , U ), + INST(kX86InstIdVroundsd , "vroundsd" , O_660F3A(0B,U,_,_,_), U , Enc(AvxRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Imm) , U ), + INST(kX86InstIdVroundss , "vroundss" , O_660F3A(0A,U,_,_,_), U , Enc(AvxRvmi) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , O(Imm) , U ), + INST(kX86InstIdVrsqrtps , "vrsqrtps" , O_000F00(52,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVrsqrtss , "vrsqrtss" , O_F30F00(52,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVshufpd , "vshufpd" , O_660F00(C6,U,_,_,_), U , Enc(AvxRvmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(Imm) , U ), + INST(kX86InstIdVshufps , "vshufps" , O_000F00(C6,U,_,_,_), U , Enc(AvxRvmi_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , O(Imm) , U ), + INST(kX86InstIdVsqrtpd , "vsqrtpd" , O_660F00(51,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVsqrtps , "vsqrtps" , O_000F00(51,U,_,_,_), U , Enc(AvxRm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVsqrtsd , "vsqrtsd" , O_F20F00(51,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVsqrtss , "vsqrtss" , O_F30F00(51,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVstmxcsr , "vstmxcsr" , O_000F00(AE,3,_,_,_), U , Enc(AvxM) , F(Avx) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdVsubpd , "vsubpd" , O_660F00(5C,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVsubps , "vsubps" , O_000F00(5C,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVsubsd , "vsubsd" , O_F20F00(5C,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVsubss , "vsubss" , O_F30F00(5C,U,_,_,_), U , Enc(AvxRvm) , F(Avx) , EF(________), 0 , 0 , O(Xmm) , O(Xmm) , O(XmmMem) , U , U ), + INST(kX86InstIdVtestpd , "vtestpd" , O_660F38(0F,U,_,_,_), U , Enc(AvxRm_P) , F(Test) , EF(WWWWWW__), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVtestps , "vtestps" , O_660F38(0E,U,_,_,_), U , Enc(AvxRm_P) , F(Test) , EF(WWWWWW__), 0 , 0 , O(Xy) , O(XyMem) , U , U , U ), + INST(kX86InstIdVucomisd , "vucomisd" , O_660F00(2E,U,_,_,_), U , Enc(AvxRm) , F(Avx) , EF(WWWWWW__), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVucomiss , "vucomiss" , O_000F00(2E,U,_,_,_), U , Enc(AvxRm) , F(Avx) , EF(WWWWWW__), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdVunpckhpd , "vunpckhpd" , O_660F00(15,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVunpckhps , "vunpckhps" , O_000F00(15,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVunpcklpd , "vunpcklpd" , O_660F00(14,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVunpcklps , "vunpcklps" , O_000F00(14,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVxorpd , "vxorpd" , O_660F00(57,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVxorps , "vxorps" , O_000F00(57,U,_,_,_), U , Enc(AvxRvm_P) , F(Avx) , EF(________), 0 , 0 , O(Xy) , O(Xy) , O(XyMem) , U , U ), + INST(kX86InstIdVzeroall , "vzeroall" , O_000F00(77,U,L,_,_), U , Enc(AvxOp) , F(Avx) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdVzeroupper , "vzeroupper" , O_000F00(77,U,_,_,_), U , Enc(AvxOp) , F(Avx) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdWrfsbase , "wrfsbase" , O_F30F00(AE,2,_,_,_), U , Enc(X86Rm) , F(None) , EF(________), 0 , 0 , O(Gqd) , U , U , U , U ), + INST(kX86InstIdWrgsbase , "wrgsbase" , O_F30F00(AE,3,_,_,_), U , Enc(X86Rm) , F(None) , EF(________), 0 , 0 , O(Gqd) , U , U , U , U ), + INST(kX86InstIdXadd , "xadd" , O_000F00(C0,U,_,_,_), U , Enc(X86Xadd) , F(Xchg)|F(Lock) , EF(WWWWWW__), 0 , 0 , O(GqdwbMem) , O(Gqdwb) , U , U , U ), + INST(kX86InstIdXchg , "xchg" , O_000000(86,U,_,_,_), U , Enc(X86Xchg) , F(Xchg)|F(Lock) , EF(________), 0 , 0 , O(GqdwbMem) , O(Gqdwb) , U , U , U ), + INST(kX86InstIdXgetbv , "xgetbv" , O_000F01(D0,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ), + INST(kX86InstIdXor , "xor" , O_000000(30,6,_,_,_), U , Enc(X86Arith) , F(Lock) , EF(WWWUWW__), 0 , 0 , O(GqdwbMem) , O(GqdwbMem)|O(Imm), U , U , U ), + INST(kX86InstIdXorpd , "xorpd" , O_660F00(57,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdXorps , "xorps" , O_000F00(57,U,_,_,_), U , Enc(ExtRm) , F(None) , EF(________), 0 , 0 , O(Xmm) , O(XmmMem) , U , U , U ), + INST(kX86InstIdXrstor , "xrstor" , O_000F00(AE,5,_,_,_), U , Enc(X86M) , F(None)|F(Special) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdXrstor64 , "xrstor64" , O_000F00(AE,5,_,W,_), U , Enc(X86M) , F(None)|F(Special) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdXsave , "xsave" , O_000F00(AE,4,_,_,_), U , Enc(X86M) , F(None)|F(Special) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdXsave64 , "xsave64" , O_000F00(AE,4,_,W,_), U , Enc(X86M) , F(None)|F(Special) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdXsaveopt , "xsaveopt" , O_000F00(AE,6,_,_,_), U , Enc(X86M) , F(None)|F(Special) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdXsaveopt64 , "xsaveopt64" , O_000F00(AE,6,_,W,_), U , Enc(X86M) , F(None)|F(Special) , EF(________), 0 , 0 , O(Mem) , U , U , U , U ), + INST(kX86InstIdXsetbv , "xsetbv" , O_000F01(D1,U,_,_,_), U , Enc(X86Op) , F(None)|F(Special) , EF(________), 0 , 0 , U , U , U , U , U ) +}; + +#undef INST + +#undef O_00_X +#undef O_9B_X + +#undef O_66_M03 +#undef O_00_M09 +#undef O_00_M08 + +#undef O_F30F3A +#undef O_F30F38 +#undef O_F30F00 +#undef O_F30000 +#undef O_F20F3A +#undef O_F20F38 +#undef O_F20F00 +#undef O_F20000 +#undef O_9B0000 +#undef O_660F3A +#undef O_660F38 +#undef O_660F00 +#undef O_660000 +#undef O_000F3A +#undef O_000F38 +#undef O_000F0F +#undef O_000F01 +#undef O_000F00 +#undef O_000000 + +#undef O +#undef EF +#undef A +#undef F +#undef Enc + +#undef U + +// ============================================================================ +// [asmjit::X86Cond] +// ============================================================================ + +#define CC_TO_INST(_Inst_) { \ + _Inst_##o, \ + _Inst_##no, \ + _Inst_##b, \ + _Inst_##ae, \ + _Inst_##e, \ + _Inst_##ne, \ + _Inst_##be, \ + _Inst_##a, \ + _Inst_##s, \ + _Inst_##ns, \ + _Inst_##pe, \ + _Inst_##po, \ + _Inst_##l, \ + _Inst_##ge, \ + _Inst_##le, \ + _Inst_##g, \ + \ + kInstIdNone, \ + kInstIdNone, \ + kInstIdNone, \ + kInstIdNone \ +} + +const uint32_t _x86ReverseCond[20] = { + /* kX86CondO -> */ kX86CondO, + /* kX86CondNO -> */ kX86CondNO, + /* kX86CondB -> */ kX86CondA, + /* kX86CondAE -> */ kX86CondBE, + /* kX86CondE -> */ kX86CondE, + /* kX86CondNE -> */ kX86CondNE, + /* kX86CondBE -> */ kX86CondAE, + /* kX86CondA -> */ kX86CondB, + /* kX86CondS -> */ kX86CondS, + /* kX86CondNS -> */ kX86CondNS, + /* kX86CondPE -> */ kX86CondPE, + /* kX86CondPO -> */ kX86CondPO, + /* kX86CondL -> */ kX86CondG, + /* kX86CondGE -> */ kX86CondLE, + /* kX86CondLE -> */ kX86CondGE, + /* kX86CondG -> */ kX86CondL, + + /* kX86CondFpuUnordered -> */ kX86CondFpuUnordered, + /* kX86CondFpuNotUnordered -> */ kX86CondFpuNotUnordered, + + 0x12, + 0x13 +}; + +const uint32_t _x86CondToCmovcc[20] = CC_TO_INST(kX86InstIdCmov); +const uint32_t _x86CondToJcc [20] = CC_TO_INST(kX86InstIdJ ); +const uint32_t _x86CondToSetcc [20] = CC_TO_INST(kX86InstIdSet ); + +#undef CC_TO_INST + +// ============================================================================ +// [asmjit::X86Util] +// ============================================================================ + +#if !defined(ASMJIT_DISABLE_NAMES) +// Compare two instruction names. +// +// `a` is null terminated instruction name from `_x86InstName[]` table. +// `b` is non-null terminated instruction name passed to `getInstIdByName()`. +static ASMJIT_INLINE int X86Util_cmpInstName(const char* a, const char* b, size_t len) { + for (size_t i = 0; i < len; i++) { + int c = static_cast(static_cast(a[i])) - + static_cast(static_cast(b[i])) ; + if (c != 0) + return c; + } + + return static_cast(a[len]); +} + +uint32_t X86Util::getInstIdByName(const char* name, size_t len) { + if (name == NULL) + return kInstIdNone; + + if (len == kInvalidIndex) + len = ::strlen(name); + + if (len == 0) + return kInstIdNone; + + uint32_t prefix = name[0] - kX86InstAlphaIndexFirst; + if (prefix > kX86InstAlphaIndexLast - kX86InstAlphaIndexFirst) + return kInstIdNone; + + uint32_t index = _x86InstAlphaIndex[prefix]; + if (index == kX86InstAlphaIndexInvalid) + return kInstIdNone; + + const X86InstInfo* base = _x86InstInfo + index; + const X86InstInfo* end = _x86InstInfo + _kX86InstIdCount; + + // Handle instructions starting with 'j' specially. `jcc` instruction breaks + // the sorting, because of the suffixes (it's considered as one instruction), + // so basically `jecxz` and `jmp` are stored after all `jcc` instructions. + bool linearSearch = prefix == ('j' - kX86InstAlphaIndexFirst); + + while (++prefix <= kX86InstAlphaIndexLast - kX86InstAlphaIndexFirst) { + index = _x86InstAlphaIndex[prefix]; + if (index == kX86InstAlphaIndexInvalid) + continue; + end = _x86InstInfo + index; + break; + } + + if (linearSearch) { + while (base != end) { + if (X86Util_cmpInstName(base->getInstName(), name, len) == 0) + return static_cast((size_t)(base - _x86InstInfo)); + base++; + } + } + else { + for (size_t lim = (size_t)(end - base); lim != 0; lim >>= 1) { + const X86InstInfo* cur = base + (lim >> 1); + int result = X86Util_cmpInstName(cur->getInstName(), name, len); + + if (result < 0) { + base = cur + 1; + lim--; + continue; + } + + if (result > 0) + continue; + + return static_cast((size_t)(cur - _x86InstInfo)); + } + } + + return kInstIdNone; +} +#endif // ASMJIT_DISABLE_NAMES + +// ============================================================================ +// [asmjit::X86Util - Test] +// ============================================================================ + +#if defined(ASMJIT_TEST) && !defined(ASMJIT_DISABLE_NAMES) +UNIT(x86_inst_name) { + // All known instructions should be matched. + INFO("Matching all X86/X64 instructions."); + for (uint32_t a = 0; a < _kX86InstIdCount; a++) { + uint32_t b = X86Util::getInstIdByName(_x86InstInfo[a].getInstName()); + + EXPECT(a == b, + "Should match existing instruction \"%s\" {id:%u} != \"%s\" {id:%u}.", + _x86InstInfo[a].getInstName(), a, + _x86InstInfo[b].getInstName(), b); + } + + // Everything else should return kInstIdNone + INFO("Trying to look-up instructions that don't exist."); + EXPECT(X86Util::getInstIdByName(NULL) == kInstIdNone, + "Should return kInstIdNone for NULL input."); + + EXPECT(X86Util::getInstIdByName("") == kInstIdNone, + "Should return kInstIdNone for empty string."); + + EXPECT(X86Util::getInstIdByName("_") == kInstIdNone, + "Should return kInstIdNone for unknown instruction."); + + EXPECT(X86Util::getInstIdByName("123xyz") == kInstIdNone, + "Should return kInstIdNone for unknown instruction."); +} +#endif // ASMJIT_TEST && !ASMJIT_DISABLE_NAMES + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64 diff --git a/third/Blackbone/src/3rd_party/AsmJit/x86/x86inst.h b/third/Blackbone/src/3rd_party/AsmJit/x86/x86inst.h new file mode 100644 index 0000000000000000000000000000000000000000..e36b791988966151637bcde84e20366508f0d79f --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/x86/x86inst.h @@ -0,0 +1,2410 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Guard] +#ifndef _ASMJIT_X86_X86INST_H +#define _ASMJIT_X86_X86INST_H + +// [Dependencies - AsmJit] +#include "../base/assembler.h" +#include "../base/compiler.h" +#include "../base/globals.h" +#include "../base/intutil.h" +#include "../base/operand.h" +#include "../base/vectypes.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [Forward Declarations] +// ============================================================================ + +struct X86InstInfo; +struct X86InstExtendedInfo; + +//! \addtogroup asmjit_x86_inst +//! \{ + +// ============================================================================ +// [asmjit::X86Inst/X86Cond - Globals] +// ============================================================================ + +#if !defined(ASMJIT_DISABLE_NAMES) +//! \internal +//! +//! X86/X64 instructions' names, accessible through `X86InstInfo`. +ASMJIT_VAR const char _x86InstName[]; +#endif // !ASMJIT_DISABLE_NAMES + +//! \internal +//! +//! X86/X64 instructions' extended information, accessible through `X86InstInfo`. +ASMJIT_VAR const X86InstExtendedInfo _x86InstExtendedInfo[]; + +//! \internal +//! +//! X86/X64 instructions' information. +ASMJIT_VAR const X86InstInfo _x86InstInfo[]; + +//! \internal +//! +//! X86/X64 condition codes to reversed condition codes map. +ASMJIT_VAR const uint32_t _x86ReverseCond[20]; + +//! \internal +//! +//! X86/X64 condition codes to "cmovcc" group map. +ASMJIT_VAR const uint32_t _x86CondToCmovcc[20]; + +//! \internal +//! +//! X86/X64 condition codes to "jcc" group map. +ASMJIT_VAR const uint32_t _x86CondToJcc[20]; + +//! \internal +//! +//! X86/X64 condition codes to "setcc" group map. +ASMJIT_VAR const uint32_t _x86CondToSetcc[20]; + +// ============================================================================ +// [asmjit::kX86InstId] +// ============================================================================ + +//! X86/X64 instruction IDs. +//! +//! Note that these instruction codes are AsmJit specific. Each instruction has +//! a unique ID that is used as an index to AsmJit instruction table. The list +//! is sorted alphabetically except instructions starting with `j`, because the +//! `jcc` instruction is composition of an opcode and condition code. It means +//! that these instructions are sorted as `jcc`, `jecxz` and `jmp`. Please use +//! \ref X86Util::getInstIdByName() if you need instruction name to ID mapping +//! and are not aware on how to handle such case. +ASMJIT_ENUM(kX86InstId) { + kX86InstIdAdc = 1, // X86/X64 + kX86InstIdAdd, // X86/X64 + kX86InstIdAddpd, // SSE2 + kX86InstIdAddps, // SSE + kX86InstIdAddsd, // SSE2 + kX86InstIdAddss, // SSE + kX86InstIdAddsubpd, // SSE3 + kX86InstIdAddsubps, // SSE3 + kX86InstIdAesdec, // AESNI + kX86InstIdAesdeclast, // AESNI + kX86InstIdAesenc, // AESNI + kX86InstIdAesenclast, // AESNI + kX86InstIdAesimc, // AESNI + kX86InstIdAeskeygenassist, // AESNI + kX86InstIdAnd, // X86/X64 + kX86InstIdAndn, // BMI + kX86InstIdAndnpd, // SSE2 + kX86InstIdAndnps, // SSE + kX86InstIdAndpd, // SSE2 + kX86InstIdAndps, // SSE + kX86InstIdBextr, // BMI + kX86InstIdBlendpd, // SSE4.1 + kX86InstIdBlendps, // SSE4.1 + kX86InstIdBlendvpd, // SSE4.1 + kX86InstIdBlendvps, // SSE4.1 + kX86InstIdBlsi, // BMI + kX86InstIdBlsmsk, // BMI + kX86InstIdBlsr, // BMI + kX86InstIdBsf, // X86/X64 + kX86InstIdBsr, // X86/X64 + kX86InstIdBswap, // X86/X64 (i486+) + kX86InstIdBt, // X86/X64 + kX86InstIdBtc, // X86/X64 + kX86InstIdBtr, // X86/X64 + kX86InstIdBts, // X86/X64 + kX86InstIdBzhi, // BMI2 + kX86InstIdCall, // X86/X64 + kX86InstIdCbw, // X86/X64 + kX86InstIdCdq, // X86/X64 + kX86InstIdCdqe, // X64 only + kX86InstIdClc, // X86/X64 + kX86InstIdCld, // X86/X64 + kX86InstIdClflush, // SSE2 + kX86InstIdCmc, // X86/X64 + kX86InstIdCmova, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovae, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovb, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovbe, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovc, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmove, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovg, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovge, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovl, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovle, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovna, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovnae, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovnb, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovnbe, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovnc, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovne, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovng, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovnge, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovnl, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovnle, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovno, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovnp, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovns, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovnz, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovo, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovp, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovpe, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovpo, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovs, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmovz, // X86/X64 (cmovcc) (i586+) + kX86InstIdCmp, // X86/X64 + kX86InstIdCmppd, // SSE2 + kX86InstIdCmpps, // SSE + kX86InstIdCmpsB, // CMPS - X86/X64 + kX86InstIdCmpsD, // CMPS - X86/X64 + kX86InstIdCmpsQ, // CMPS - X64 + kX86InstIdCmpsW, // CMPS - X86/X64 + kX86InstIdCmpsd, // SSE2 + kX86InstIdCmpss, // SSE + kX86InstIdCmpxchg, // X86/X64 (i486+) + kX86InstIdCmpxchg16b, // X64 only + kX86InstIdCmpxchg8b, // X86/X64 (i586+) + kX86InstIdComisd, // SSE2 + kX86InstIdComiss, // SSE + kX86InstIdCpuid, // X86/X64 (i486/i586+) + kX86InstIdCqo, // X64 only + kX86InstIdCrc32, // SSE4.2 + kX86InstIdCvtdq2pd, // SSE2 + kX86InstIdCvtdq2ps, // SSE2 + kX86InstIdCvtpd2dq, // SSE2 + kX86InstIdCvtpd2pi, // SSE2 + kX86InstIdCvtpd2ps, // SSE2 + kX86InstIdCvtpi2pd, // SSE2 + kX86InstIdCvtpi2ps, // SSE + kX86InstIdCvtps2dq, // SSE2 + kX86InstIdCvtps2pd, // SSE2 + kX86InstIdCvtps2pi, // SSE + kX86InstIdCvtsd2si, // SSE2 + kX86InstIdCvtsd2ss, // SSE2 + kX86InstIdCvtsi2sd, // SSE2 + kX86InstIdCvtsi2ss, // SSE + kX86InstIdCvtss2sd, // SSE2 + kX86InstIdCvtss2si, // SSE + kX86InstIdCvttpd2dq, // SSE2 + kX86InstIdCvttpd2pi, // SSE2 + kX86InstIdCvttps2dq, // SSE2 + kX86InstIdCvttps2pi, // SSE + kX86InstIdCvttsd2si, // SSE2 + kX86InstIdCvttss2si, // SSE + kX86InstIdCwd, // X86/X64 + kX86InstIdCwde, // X86/X64 + kX86InstIdDaa, // X86 only + kX86InstIdDas, // X86 only + kX86InstIdDec, // X86/X64 + kX86InstIdDiv, // X86/X64 + kX86InstIdDivpd, // SSE2 + kX86InstIdDivps, // SSE + kX86InstIdDivsd, // SSE2 + kX86InstIdDivss, // SSE + kX86InstIdDppd, // SSE4.1 + kX86InstIdDpps, // SSE4.1 + kX86InstIdEmms, // MMX + kX86InstIdEnter, // X86/X64 + kX86InstIdExtractps, // SSE4.1 + kX86InstIdExtrq, // SSE4a + kX86InstIdF2xm1, // FPU + kX86InstIdFabs, // FPU + kX86InstIdFadd, // FPU + kX86InstIdFaddp, // FPU + kX86InstIdFbld, // FPU + kX86InstIdFbstp, // FPU + kX86InstIdFchs, // FPU + kX86InstIdFclex, // FPU + kX86InstIdFcmovb, // FPU + kX86InstIdFcmovbe, // FPU + kX86InstIdFcmove, // FPU + kX86InstIdFcmovnb, // FPU + kX86InstIdFcmovnbe, // FPU + kX86InstIdFcmovne, // FPU + kX86InstIdFcmovnu, // FPU + kX86InstIdFcmovu, // FPU + kX86InstIdFcom, // FPU + kX86InstIdFcomi, // FPU + kX86InstIdFcomip, // FPU + kX86InstIdFcomp, // FPU + kX86InstIdFcompp, // FPU + kX86InstIdFcos, // FPU + kX86InstIdFdecstp, // FPU + kX86InstIdFdiv, // FPU + kX86InstIdFdivp, // FPU + kX86InstIdFdivr, // FPU + kX86InstIdFdivrp, // FPU + kX86InstIdFemms, // 3dNow! + kX86InstIdFfree, // FPU + kX86InstIdFiadd, // FPU + kX86InstIdFicom, // FPU + kX86InstIdFicomp, // FPU + kX86InstIdFidiv, // FPU + kX86InstIdFidivr, // FPU + kX86InstIdFild, // FPU + kX86InstIdFimul, // FPU + kX86InstIdFincstp, // FPU + kX86InstIdFinit, // FPU + kX86InstIdFist, // FPU + kX86InstIdFistp, // FPU + kX86InstIdFisttp, // SSE3 + kX86InstIdFisub, // FPU + kX86InstIdFisubr, // FPU + kX86InstIdFld, // FPU + kX86InstIdFld1, // FPU + kX86InstIdFldcw, // FPU + kX86InstIdFldenv, // FPU + kX86InstIdFldl2e, // FPU + kX86InstIdFldl2t, // FPU + kX86InstIdFldlg2, // FPU + kX86InstIdFldln2, // FPU + kX86InstIdFldpi, // FPU + kX86InstIdFldz, // FPU + kX86InstIdFmul, // FPU + kX86InstIdFmulp, // FPU + kX86InstIdFnclex, // FPU + kX86InstIdFninit, // FPU + kX86InstIdFnop, // FPU + kX86InstIdFnsave, // FPU + kX86InstIdFnstcw, // FPU + kX86InstIdFnstenv, // FPU + kX86InstIdFnstsw, // FPU + kX86InstIdFpatan, // FPU + kX86InstIdFprem, // FPU + kX86InstIdFprem1, // FPU + kX86InstIdFptan, // FPU + kX86InstIdFrndint, // FPU + kX86InstIdFrstor, // FPU + kX86InstIdFsave, // FPU + kX86InstIdFscale, // FPU + kX86InstIdFsin, // FPU + kX86InstIdFsincos, // FPU + kX86InstIdFsqrt, // FPU + kX86InstIdFst, // FPU + kX86InstIdFstcw, // FPU + kX86InstIdFstenv, // FPU + kX86InstIdFstp, // FPU + kX86InstIdFstsw, // FPU + kX86InstIdFsub, // FPU + kX86InstIdFsubp, // FPU + kX86InstIdFsubr, // FPU + kX86InstIdFsubrp, // FPU + kX86InstIdFtst, // FPU + kX86InstIdFucom, // FPU + kX86InstIdFucomi, // FPU + kX86InstIdFucomip, // FPU + kX86InstIdFucomp, // FPU + kX86InstIdFucompp, // FPU + kX86InstIdFwait, // FPU + kX86InstIdFxam, // FPU + kX86InstIdFxch, // FPU + kX86InstIdFxrstor, // FPU + kX86InstIdFxsave, // FPU + kX86InstIdFxtract, // FPU + kX86InstIdFyl2x, // FPU + kX86InstIdFyl2xp1, // FPU + kX86InstIdHaddpd, // SSE3 + kX86InstIdHaddps, // SSE3 + kX86InstIdHsubpd, // SSE3 + kX86InstIdHsubps, // SSE3 + kX86InstIdIdiv, // X86/X64 + kX86InstIdImul, // X86/X64 + kX86InstIdInc, // X86/X64 + kX86InstIdInsertps, // SSE4.1 + kX86InstIdInsertq, // SSE4a + kX86InstIdInt, // X86/X64 + kX86InstIdJa, // X86/X64 (jcc) + kX86InstIdJae, // X86/X64 (jcc) + kX86InstIdJb, // X86/X64 (jcc) + kX86InstIdJbe, // X86/X64 (jcc) + kX86InstIdJc, // X86/X64 (jcc) + kX86InstIdJe, // X86/X64 (jcc) + kX86InstIdJg, // X86/X64 (jcc) + kX86InstIdJge, // X86/X64 (jcc) + kX86InstIdJl, // X86/X64 (jcc) + kX86InstIdJle, // X86/X64 (jcc) + kX86InstIdJna, // X86/X64 (jcc) + kX86InstIdJnae, // X86/X64 (jcc) + kX86InstIdJnb, // X86/X64 (jcc) + kX86InstIdJnbe, // X86/X64 (jcc) + kX86InstIdJnc, // X86/X64 (jcc) + kX86InstIdJne, // X86/X64 (jcc) + kX86InstIdJng, // X86/X64 (jcc) + kX86InstIdJnge, // X86/X64 (jcc) + kX86InstIdJnl, // X86/X64 (jcc) + kX86InstIdJnle, // X86/X64 (jcc) + kX86InstIdJno, // X86/X64 (jcc) + kX86InstIdJnp, // X86/X64 (jcc) + kX86InstIdJns, // X86/X64 (jcc) + kX86InstIdJnz, // X86/X64 (jcc) + kX86InstIdJo, // X86/X64 (jcc) + kX86InstIdJp, // X86/X64 (jcc) + kX86InstIdJpe, // X86/X64 (jcc) + kX86InstIdJpo, // X86/X64 (jcc) + kX86InstIdJs, // X86/X64 (jcc) + kX86InstIdJz, // X86/X64 (jcc) + kX86InstIdJecxz, // X86/X64 (jcxz/jecxz/jrcxz) + kX86InstIdJmp, // X86/X64 (jmp) + kX86InstIdLahf, // X86/X64 (CPUID NEEDED) + kX86InstIdLddqu, // SSE3 + kX86InstIdLdmxcsr, // SSE + kX86InstIdLea, // X86/X64 + kX86InstIdLeave, // X86/X64 + kX86InstIdLfence, // SSE2 + kX86InstIdLodsB, // LODS - X86/X64 + kX86InstIdLodsD, // LODS - X86/X64 + kX86InstIdLodsQ, // LODS - X86/X64 + kX86InstIdLodsW, // LODS - X86/X64 + kX86InstIdLzcnt, // LZCNT + kX86InstIdMaskmovdqu, // SSE2 + kX86InstIdMaskmovq, // MMX-Ext + kX86InstIdMaxpd, // SSE2 + kX86InstIdMaxps, // SSE + kX86InstIdMaxsd, // SSE2 + kX86InstIdMaxss, // SSE + kX86InstIdMfence, // SSE2 + kX86InstIdMinpd, // SSE2 + kX86InstIdMinps, // SSE + kX86InstIdMinsd, // SSE2 + kX86InstIdMinss, // SSE + kX86InstIdMonitor, // SSE3 + kX86InstIdMov, // X86/X64 + kX86InstIdMovPtr, // X86/X64 + kX86InstIdMovapd, // SSE2 + kX86InstIdMovaps, // SSE + kX86InstIdMovbe, // SSE3 - Intel-Atom + kX86InstIdMovd, // MMX/SSE2 + kX86InstIdMovddup, // SSE3 + kX86InstIdMovdq2q, // SSE2 + kX86InstIdMovdqa, // SSE2 + kX86InstIdMovdqu, // SSE2 + kX86InstIdMovhlps, // SSE + kX86InstIdMovhpd, // SSE2 + kX86InstIdMovhps, // SSE + kX86InstIdMovlhps, // SSE + kX86InstIdMovlpd, // SSE2 + kX86InstIdMovlps, // SSE + kX86InstIdMovmskpd, // SSE2 + kX86InstIdMovmskps, // SSE2 + kX86InstIdMovntdq, // SSE2 + kX86InstIdMovntdqa, // SSE4.1 + kX86InstIdMovnti, // SSE2 + kX86InstIdMovntpd, // SSE2 + kX86InstIdMovntps, // SSE + kX86InstIdMovntq, // MMX-Ext + kX86InstIdMovntsd, // SSE4a + kX86InstIdMovntss, // SSE4a + kX86InstIdMovq, // MMX/SSE/SSE2 + kX86InstIdMovq2dq, // SSE2 + kX86InstIdMovsB, // MOVS - X86/X64 + kX86InstIdMovsD, // MOVS - X86/X64 + kX86InstIdMovsQ, // MOVS - X64 + kX86InstIdMovsW, // MOVS - X86/X64 + kX86InstIdMovsd, // SSE2 + kX86InstIdMovshdup, // SSE3 + kX86InstIdMovsldup, // SSE3 + kX86InstIdMovss, // SSE + kX86InstIdMovsx, // X86/X64 + kX86InstIdMovsxd, // X86/X64 + kX86InstIdMovupd, // SSE2 + kX86InstIdMovups, // SSE + kX86InstIdMovzx, // X86/X64 + kX86InstIdMpsadbw, // SSE4.1 + kX86InstIdMul, // X86/X64 + kX86InstIdMulpd, // SSE2 + kX86InstIdMulps, // SSE + kX86InstIdMulsd, // SSE2 + kX86InstIdMulss, // SSE + kX86InstIdMulx, // BMI2 + kX86InstIdMwait, // SSE3 + kX86InstIdNeg, // X86/X64 + kX86InstIdNop, // X86/X64 + kX86InstIdNot, // X86/X64 + kX86InstIdOr, // X86/X64 + kX86InstIdOrpd, // SSE2 + kX86InstIdOrps, // SSE + kX86InstIdPabsb, // SSSE3 + kX86InstIdPabsd, // SSSE3 + kX86InstIdPabsw, // SSSE3 + kX86InstIdPackssdw, // MMX/SSE2 + kX86InstIdPacksswb, // MMX/SSE2 + kX86InstIdPackusdw, // SSE4.1 + kX86InstIdPackuswb, // MMX/SSE2 + kX86InstIdPaddb, // MMX/SSE2 + kX86InstIdPaddd, // MMX/SSE2 + kX86InstIdPaddq, // SSE2 + kX86InstIdPaddsb, // MMX/SSE2 + kX86InstIdPaddsw, // MMX/SSE2 + kX86InstIdPaddusb, // MMX/SSE2 + kX86InstIdPaddusw, // MMX/SSE2 + kX86InstIdPaddw, // MMX/SSE2 + kX86InstIdPalignr, // SSSE3 + kX86InstIdPand, // MMX/SSE2 + kX86InstIdPandn, // MMX/SSE2 + kX86InstIdPause, // SSE2. + kX86InstIdPavgb, // MMX-Ext + kX86InstIdPavgw, // MMX-Ext + kX86InstIdPblendvb, // SSE4.1 + kX86InstIdPblendw, // SSE4.1 + kX86InstIdPclmulqdq, // PCLMULQDQ + kX86InstIdPcmpeqb, // MMX/SSE2 + kX86InstIdPcmpeqd, // MMX/SSE2 + kX86InstIdPcmpeqq, // SSE4.1 + kX86InstIdPcmpeqw, // MMX/SSE2 + kX86InstIdPcmpestri, // SSE4.2 + kX86InstIdPcmpestrm, // SSE4.2 + kX86InstIdPcmpgtb, // MMX/SSE2 + kX86InstIdPcmpgtd, // MMX/SSE2 + kX86InstIdPcmpgtq, // SSE4.2 + kX86InstIdPcmpgtw, // MMX/SSE2 + kX86InstIdPcmpistri, // SSE4.2 + kX86InstIdPcmpistrm, // SSE4.2 + kX86InstIdPdep, // BMI2 + kX86InstIdPext, // BMI2 + kX86InstIdPextrb, // SSE4.1 + kX86InstIdPextrd, // SSE4.1 + kX86InstIdPextrq, // SSE4.1 + kX86InstIdPextrw, // MMX-Ext/SSE2 + kX86InstIdPf2id, // 3dNow! + kX86InstIdPf2iw, // Enhanced 3dNow! + kX86InstIdPfacc, // 3dNow! + kX86InstIdPfadd, // 3dNow! + kX86InstIdPfcmpeq, // 3dNow! + kX86InstIdPfcmpge, // 3dNow! + kX86InstIdPfcmpgt, // 3dNow! + kX86InstIdPfmax, // 3dNow! + kX86InstIdPfmin, // 3dNow! + kX86InstIdPfmul, // 3dNow! + kX86InstIdPfnacc, // Enhanced 3dNow! + kX86InstIdPfpnacc, // Enhanced 3dNow! + kX86InstIdPfrcp, // 3dNow! + kX86InstIdPfrcpit1, // 3dNow! + kX86InstIdPfrcpit2, // 3dNow! + kX86InstIdPfrsqit1, // 3dNow! + kX86InstIdPfrsqrt, // 3dNow! + kX86InstIdPfsub, // 3dNow! + kX86InstIdPfsubr, // 3dNow! + kX86InstIdPhaddd, // SSSE3 + kX86InstIdPhaddsw, // SSSE3 + kX86InstIdPhaddw, // SSSE3 + kX86InstIdPhminposuw, // SSE4.1 + kX86InstIdPhsubd, // SSSE3 + kX86InstIdPhsubsw, // SSSE3 + kX86InstIdPhsubw, // SSSE3 + kX86InstIdPi2fd, // 3dNow! + kX86InstIdPi2fw, // Enhanced 3dNow! + kX86InstIdPinsrb, // SSE4.1 + kX86InstIdPinsrd, // SSE4.1 + kX86InstIdPinsrq, // SSE4.1 + kX86InstIdPinsrw, // MMX-Ext + kX86InstIdPmaddubsw, // SSSE3 + kX86InstIdPmaddwd, // MMX/SSE2 + kX86InstIdPmaxsb, // SSE4.1 + kX86InstIdPmaxsd, // SSE4.1 + kX86InstIdPmaxsw, // MMX-Ext + kX86InstIdPmaxub, // MMX-Ext + kX86InstIdPmaxud, // SSE4.1 + kX86InstIdPmaxuw, // SSE4.1 + kX86InstIdPminsb, // SSE4.1 + kX86InstIdPminsd, // SSE4.1 + kX86InstIdPminsw, // MMX-Ext + kX86InstIdPminub, // MMX-Ext + kX86InstIdPminud, // SSE4.1 + kX86InstIdPminuw, // SSE4.1 + kX86InstIdPmovmskb, // MMX-Ext + kX86InstIdPmovsxbd, // SSE4.1 + kX86InstIdPmovsxbq, // SSE4.1 + kX86InstIdPmovsxbw, // SSE4.1 + kX86InstIdPmovsxdq, // SSE4.1 + kX86InstIdPmovsxwd, // SSE4.1 + kX86InstIdPmovsxwq, // SSE4.1 + kX86InstIdPmovzxbd, // SSE4.1 + kX86InstIdPmovzxbq, // SSE4.1 + kX86InstIdPmovzxbw, // SSE4.1 + kX86InstIdPmovzxdq, // SSE4.1 + kX86InstIdPmovzxwd, // SSE4.1 + kX86InstIdPmovzxwq, // SSE4.1 + kX86InstIdPmuldq, // SSE4.1 + kX86InstIdPmulhrsw, // SSSE3 + kX86InstIdPmulhuw, // MMX-Ext + kX86InstIdPmulhw, // MMX/SSE2 + kX86InstIdPmulld, // SSE4.1 + kX86InstIdPmullw, // MMX/SSE2 + kX86InstIdPmuludq, // SSE2 + kX86InstIdPop, // X86/X64 + kX86InstIdPopa, // X86 only + kX86InstIdPopcnt, // SSE4.2 + kX86InstIdPopf, // X86/X64 + kX86InstIdPor, // MMX/SSE2 + kX86InstIdPrefetch, // MMX-Ext/SSE + kX86InstIdPrefetch3dNow, // 3dNow! + kX86InstIdPrefetchw3dNow, // 3dNow! + kX86InstIdPsadbw, // MMX-Ext + kX86InstIdPshufb, // SSSE3 + kX86InstIdPshufd, // SSE2 + kX86InstIdPshufhw, // SSE2 + kX86InstIdPshuflw, // SSE2 + kX86InstIdPshufw, // MMX-Ext + kX86InstIdPsignb, // SSSE3 + kX86InstIdPsignd, // SSSE3 + kX86InstIdPsignw, // SSSE3 + kX86InstIdPslld, // MMX/SSE2 + kX86InstIdPslldq, // SSE2 + kX86InstIdPsllq, // MMX/SSE2 + kX86InstIdPsllw, // MMX/SSE2 + kX86InstIdPsrad, // MMX/SSE2 + kX86InstIdPsraw, // MMX/SSE2 + kX86InstIdPsrld, // MMX/SSE2 + kX86InstIdPsrldq, // SSE2 + kX86InstIdPsrlq, // MMX/SSE2 + kX86InstIdPsrlw, // MMX/SSE2 + kX86InstIdPsubb, // MMX/SSE2 + kX86InstIdPsubd, // MMX/SSE2 + kX86InstIdPsubq, // SSE2 + kX86InstIdPsubsb, // MMX/SSE2 + kX86InstIdPsubsw, // MMX/SSE2 + kX86InstIdPsubusb, // MMX/SSE2 + kX86InstIdPsubusw, // MMX/SSE2 + kX86InstIdPsubw, // MMX/SSE2 + kX86InstIdPswapd, // Enhanced 3dNow! + kX86InstIdPtest, // SSE4.1 + kX86InstIdPunpckhbw, // MMX/SSE2 + kX86InstIdPunpckhdq, // MMX/SSE2 + kX86InstIdPunpckhqdq, // SSE2 + kX86InstIdPunpckhwd, // MMX/SSE2 + kX86InstIdPunpcklbw, // MMX/SSE2 + kX86InstIdPunpckldq, // MMX/SSE2 + kX86InstIdPunpcklqdq, // SSE2 + kX86InstIdPunpcklwd, // MMX/SSE2 + kX86InstIdPush, // X86/X64 + kX86InstIdPusha, // X86 only + kX86InstIdPushf, // X86/X64 + kX86InstIdPxor, // MMX/SSE2 + kX86InstIdRcl, // X86/X64 + kX86InstIdRcpps, // SSE + kX86InstIdRcpss, // SSE + kX86InstIdRcr, // X86/X64 + kX86InstIdRdfsbase, // FSGSBASE (x64) + kX86InstIdRdgsbase, // FSGSBASE (x64) + kX86InstIdRdrand, // RDRAND + kX86InstIdRdtsc, // X86/X64 + kX86InstIdRdtscp, // X86/X64 + kX86InstIdRepLodsB, // X86/X64 (REP) + kX86InstIdRepLodsD, // X86/X64 (REP) + kX86InstIdRepLodsQ, // X64 only (REP) + kX86InstIdRepLodsW, // X86/X64 (REP) + kX86InstIdRepMovsB, // X86/X64 (REP) + kX86InstIdRepMovsD, // X86/X64 (REP) + kX86InstIdRepMovsQ, // X64 only (REP) + kX86InstIdRepMovsW, // X86/X64 (REP) + kX86InstIdRepStosB, // X86/X64 (REP) + kX86InstIdRepStosD, // X86/X64 (REP) + kX86InstIdRepStosQ, // X64 only (REP) + kX86InstIdRepStosW, // X86/X64 (REP) + kX86InstIdRepeCmpsB, // X86/X64 (REP) + kX86InstIdRepeCmpsD, // X86/X64 (REP) + kX86InstIdRepeCmpsQ, // X64 only (REP) + kX86InstIdRepeCmpsW, // X86/X64 (REP) + kX86InstIdRepeScasB, // X86/X64 (REP) + kX86InstIdRepeScasD, // X86/X64 (REP) + kX86InstIdRepeScasQ, // X64 only (REP) + kX86InstIdRepeScasW, // X86/X64 (REP) + kX86InstIdRepneCmpsB, // X86/X64 (REP) + kX86InstIdRepneCmpsD, // X86/X64 (REP) + kX86InstIdRepneCmpsQ, // X64 only (REP) + kX86InstIdRepneCmpsW, // X86/X64 (REP) + kX86InstIdRepneScasB, // X86/X64 (REP) + kX86InstIdRepneScasD, // X86/X64 (REP) + kX86InstIdRepneScasQ, // X64 only (REP) + kX86InstIdRepneScasW, // X86/X64 (REP) + kX86InstIdRet, // X86/X64 + kX86InstIdRol, // X86/X64 + kX86InstIdRor, // X86/X64 + kX86InstIdRorx, // BMI2 + kX86InstIdRoundpd, // SSE4.1 + kX86InstIdRoundps, // SSE4.1 + kX86InstIdRoundsd, // SSE4.1 + kX86InstIdRoundss, // SSE4.1 + kX86InstIdRsqrtps, // SSE + kX86InstIdRsqrtss, // SSE + kX86InstIdSahf, // X86/X64 (CPUID NEEDED) + kX86InstIdSal, // X86/X64 + kX86InstIdSar, // X86/X64 + kX86InstIdSarx, // BMI2 + kX86InstIdSbb, // X86/X64 + kX86InstIdScasB, // SCAS - X86/X64 + kX86InstIdScasD, // SCAS - X86/X64 + kX86InstIdScasQ, // SCAS - X64 + kX86InstIdScasW, // SCAS - X86/X64 + kX86InstIdSeta, // X86/X64 (setcc) + kX86InstIdSetae, // X86/X64 (setcc) + kX86InstIdSetb, // X86/X64 (setcc) + kX86InstIdSetbe, // X86/X64 (setcc) + kX86InstIdSetc, // X86/X64 (setcc) + kX86InstIdSete, // X86/X64 (setcc) + kX86InstIdSetg, // X86/X64 (setcc) + kX86InstIdSetge, // X86/X64 (setcc) + kX86InstIdSetl, // X86/X64 (setcc) + kX86InstIdSetle, // X86/X64 (setcc) + kX86InstIdSetna, // X86/X64 (setcc) + kX86InstIdSetnae, // X86/X64 (setcc) + kX86InstIdSetnb, // X86/X64 (setcc) + kX86InstIdSetnbe, // X86/X64 (setcc) + kX86InstIdSetnc, // X86/X64 (setcc) + kX86InstIdSetne, // X86/X64 (setcc) + kX86InstIdSetng, // X86/X64 (setcc) + kX86InstIdSetnge, // X86/X64 (setcc) + kX86InstIdSetnl, // X86/X64 (setcc) + kX86InstIdSetnle, // X86/X64 (setcc) + kX86InstIdSetno, // X86/X64 (setcc) + kX86InstIdSetnp, // X86/X64 (setcc) + kX86InstIdSetns, // X86/X64 (setcc) + kX86InstIdSetnz, // X86/X64 (setcc) + kX86InstIdSeto, // X86/X64 (setcc) + kX86InstIdSetp, // X86/X64 (setcc) + kX86InstIdSetpe, // X86/X64 (setcc) + kX86InstIdSetpo, // X86/X64 (setcc) + kX86InstIdSets, // X86/X64 (setcc) + kX86InstIdSetz, // X86/X64 (setcc) + kX86InstIdSfence, // MMX-Ext/SSE + kX86InstIdShl, // X86/X64 + kX86InstIdShld, // X86/X64 + kX86InstIdShlx, // BMI2 + kX86InstIdShr, // X86/X64 + kX86InstIdShrd, // X86/X64 + kX86InstIdShrx, // BMI2 + kX86InstIdShufpd, // SSE2 + kX86InstIdShufps, // SSE + kX86InstIdSqrtpd, // SSE2 + kX86InstIdSqrtps, // SSE + kX86InstIdSqrtsd, // SSE2 + kX86InstIdSqrtss, // SSE + kX86InstIdStc, // X86/X64 + kX86InstIdStd, // X86/X64 + kX86InstIdStmxcsr, // SSE + kX86InstIdStosB, // STOS - X86/X64 + kX86InstIdStosD, // STOS - X86/X64 + kX86InstIdStosQ, // STOS - X64 + kX86InstIdStosW, // STOS - X86/X64 + kX86InstIdSub, // X86/X64 + kX86InstIdSubpd, // SSE2 + kX86InstIdSubps, // SSE + kX86InstIdSubsd, // SSE2 + kX86InstIdSubss, // SSE + kX86InstIdTest, // X86/X64 + kX86InstIdTzcnt, // TZCNT + kX86InstIdUcomisd, // SSE2 + kX86InstIdUcomiss, // SSE + kX86InstIdUd2, // X86/X64 + kX86InstIdUnpckhpd, // SSE2 + kX86InstIdUnpckhps, // SSE + kX86InstIdUnpcklpd, // SSE2 + kX86InstIdUnpcklps, // SSE + kX86InstIdVaddpd, // AVX + kX86InstIdVaddps, // AVX + kX86InstIdVaddsd, // AVX + kX86InstIdVaddss, // AVX + kX86InstIdVaddsubpd, // AVX + kX86InstIdVaddsubps, // AVX + kX86InstIdVaesdec, // AVX+AESNI + kX86InstIdVaesdeclast, // AVX+AESNI + kX86InstIdVaesenc, // AVX+AESNI + kX86InstIdVaesenclast, // AVX+AESNI + kX86InstIdVaesimc, // AVX+AESNI + kX86InstIdVaeskeygenassist,// AVX+AESNI + kX86InstIdVandnpd, // AVX + kX86InstIdVandnps, // AVX + kX86InstIdVandpd, // AVX + kX86InstIdVandps, // AVX + kX86InstIdVblendpd, // AVX + kX86InstIdVblendps, // AVX + kX86InstIdVblendvpd, // AVX + kX86InstIdVblendvps, // AVX + kX86InstIdVbroadcastf128, // AVX + kX86InstIdVbroadcasti128, // AVX2 + kX86InstIdVbroadcastsd, // AVX/AVX2 + kX86InstIdVbroadcastss, // AVX/AVX2 + kX86InstIdVcmppd, // AVX + kX86InstIdVcmpps, // AVX + kX86InstIdVcmpsd, // AVX + kX86InstIdVcmpss, // AVX + kX86InstIdVcomisd, // AVX + kX86InstIdVcomiss, // AVX + kX86InstIdVcvtdq2pd, // AVX + kX86InstIdVcvtdq2ps, // AVX + kX86InstIdVcvtpd2dq, // AVX + kX86InstIdVcvtpd2ps, // AVX + kX86InstIdVcvtph2ps, // F16C + kX86InstIdVcvtps2dq, // AVX + kX86InstIdVcvtps2pd, // AVX + kX86InstIdVcvtps2ph, // F16C + kX86InstIdVcvtsd2si, // AVX + kX86InstIdVcvtsd2ss, // AVX + kX86InstIdVcvtsi2sd, // AVX + kX86InstIdVcvtsi2ss, // AVX + kX86InstIdVcvtss2sd, // AVX + kX86InstIdVcvtss2si, // AVX + kX86InstIdVcvttpd2dq, // AVX + kX86InstIdVcvttps2dq, // AVX + kX86InstIdVcvttsd2si, // AVX + kX86InstIdVcvttss2si, // AVX + kX86InstIdVdivpd, // AVX + kX86InstIdVdivps, // AVX + kX86InstIdVdivsd, // AVX + kX86InstIdVdivss, // AVX + kX86InstIdVdppd, // AVX + kX86InstIdVdpps, // AVX + kX86InstIdVextractf128, // AVX + kX86InstIdVextracti128, // AVX2 + kX86InstIdVextractps, // AVX + kX86InstIdVfmadd132pd, // FMA3 + kX86InstIdVfmadd132ps, // FMA3 + kX86InstIdVfmadd132sd, // FMA3 + kX86InstIdVfmadd132ss, // FMA3 + kX86InstIdVfmadd213pd, // FMA3 + kX86InstIdVfmadd213ps, // FMA3 + kX86InstIdVfmadd213sd, // FMA3 + kX86InstIdVfmadd213ss, // FMA3 + kX86InstIdVfmadd231pd, // FMA3 + kX86InstIdVfmadd231ps, // FMA3 + kX86InstIdVfmadd231sd, // FMA3 + kX86InstIdVfmadd231ss, // FMA3 + kX86InstIdVfmaddpd, // FMA4 + kX86InstIdVfmaddps, // FMA4 + kX86InstIdVfmaddsd, // FMA4 + kX86InstIdVfmaddss, // FMA4 + kX86InstIdVfmaddsub132pd, // FMA3 + kX86InstIdVfmaddsub132ps, // FMA3 + kX86InstIdVfmaddsub213pd, // FMA3 + kX86InstIdVfmaddsub213ps, // FMA3 + kX86InstIdVfmaddsub231pd, // FMA3 + kX86InstIdVfmaddsub231ps, // FMA3 + kX86InstIdVfmaddsubpd, // FMA4 + kX86InstIdVfmaddsubps, // FMA4 + kX86InstIdVfmsub132pd, // FMA3 + kX86InstIdVfmsub132ps, // FMA3 + kX86InstIdVfmsub132sd, // FMA3 + kX86InstIdVfmsub132ss, // FMA3 + kX86InstIdVfmsub213pd, // FMA3 + kX86InstIdVfmsub213ps, // FMA3 + kX86InstIdVfmsub213sd, // FMA3 + kX86InstIdVfmsub213ss, // FMA3 + kX86InstIdVfmsub231pd, // FMA3 + kX86InstIdVfmsub231ps, // FMA3 + kX86InstIdVfmsub231sd, // FMA3 + kX86InstIdVfmsub231ss, // FMA3 + kX86InstIdVfmsubadd132pd, // FMA3 + kX86InstIdVfmsubadd132ps, // FMA3 + kX86InstIdVfmsubadd213pd, // FMA3 + kX86InstIdVfmsubadd213ps, // FMA3 + kX86InstIdVfmsubadd231pd, // FMA3 + kX86InstIdVfmsubadd231ps, // FMA3 + kX86InstIdVfmsubaddpd, // FMA4 + kX86InstIdVfmsubaddps, // FMA4 + kX86InstIdVfmsubpd, // FMA4 + kX86InstIdVfmsubps, // FMA4 + kX86InstIdVfmsubsd, // FMA4 + kX86InstIdVfmsubss, // FMA4 + kX86InstIdVfnmadd132pd, // FMA3 + kX86InstIdVfnmadd132ps, // FMA3 + kX86InstIdVfnmadd132sd, // FMA3 + kX86InstIdVfnmadd132ss, // FMA3 + kX86InstIdVfnmadd213pd, // FMA3 + kX86InstIdVfnmadd213ps, // FMA3 + kX86InstIdVfnmadd213sd, // FMA3 + kX86InstIdVfnmadd213ss, // FMA3 + kX86InstIdVfnmadd231pd, // FMA3 + kX86InstIdVfnmadd231ps, // FMA3 + kX86InstIdVfnmadd231sd, // FMA3 + kX86InstIdVfnmadd231ss, // FMA3 + kX86InstIdVfnmaddpd, // FMA4 + kX86InstIdVfnmaddps, // FMA4 + kX86InstIdVfnmaddsd, // FMA4 + kX86InstIdVfnmaddss, // FMA4 + kX86InstIdVfnmsub132pd, // FMA3 + kX86InstIdVfnmsub132ps, // FMA3 + kX86InstIdVfnmsub132sd, // FMA3 + kX86InstIdVfnmsub132ss, // FMA3 + kX86InstIdVfnmsub213pd, // FMA3 + kX86InstIdVfnmsub213ps, // FMA3 + kX86InstIdVfnmsub213sd, // FMA3 + kX86InstIdVfnmsub213ss, // FMA3 + kX86InstIdVfnmsub231pd, // FMA3 + kX86InstIdVfnmsub231ps, // FMA3 + kX86InstIdVfnmsub231sd, // FMA3 + kX86InstIdVfnmsub231ss, // FMA3 + kX86InstIdVfnmsubpd, // FMA4 + kX86InstIdVfnmsubps, // FMA4 + kX86InstIdVfnmsubsd, // FMA4 + kX86InstIdVfnmsubss, // FMA4 + kX86InstIdVfrczpd, // XOP + kX86InstIdVfrczps, // XOP + kX86InstIdVfrczsd, // XOP + kX86InstIdVfrczss, // XOP + kX86InstIdVgatherdpd, // AVX2 + kX86InstIdVgatherdps, // AVX2 + kX86InstIdVgatherqpd, // AVX2 + kX86InstIdVgatherqps, // AVX2 + kX86InstIdVhaddpd, // AVX + kX86InstIdVhaddps, // AVX + kX86InstIdVhsubpd, // AVX + kX86InstIdVhsubps, // AVX + kX86InstIdVinsertf128, // AVX + kX86InstIdVinserti128, // AVX2 + kX86InstIdVinsertps, // AVX + kX86InstIdVlddqu, // AVX + kX86InstIdVldmxcsr, // AVX + kX86InstIdVmaskmovdqu, // AVX + kX86InstIdVmaskmovpd, // AVX + kX86InstIdVmaskmovps, // AVX + kX86InstIdVmaxpd, // AVX + kX86InstIdVmaxps, // AVX + kX86InstIdVmaxsd, // AVX + kX86InstIdVmaxss, // AVX + kX86InstIdVminpd, // AVX + kX86InstIdVminps, // AVX + kX86InstIdVminsd, // AVX + kX86InstIdVminss, // AVX + kX86InstIdVmovapd, // AVX + kX86InstIdVmovaps, // AVX + kX86InstIdVmovd, // AVX + kX86InstIdVmovddup, // AVX + kX86InstIdVmovdqa, // AVX + kX86InstIdVmovdqu, // AVX + kX86InstIdVmovhlps, // AVX + kX86InstIdVmovhpd, // AVX + kX86InstIdVmovhps, // AVX + kX86InstIdVmovlhps, // AVX + kX86InstIdVmovlpd, // AVX + kX86InstIdVmovlps, // AVX + kX86InstIdVmovmskpd, // AVX + kX86InstIdVmovmskps, // AVX + kX86InstIdVmovntdq, // AVX + kX86InstIdVmovntdqa, // AVX/AVX2 + kX86InstIdVmovntpd, // AVX + kX86InstIdVmovntps, // AVX + kX86InstIdVmovq, // AVX + kX86InstIdVmovsd, // AVX + kX86InstIdVmovshdup, // AVX + kX86InstIdVmovsldup, // AVX + kX86InstIdVmovss, // AVX + kX86InstIdVmovupd, // AVX + kX86InstIdVmovups, // AVX + kX86InstIdVmpsadbw, // AVX/AVX2 + kX86InstIdVmulpd, // AVX + kX86InstIdVmulps, // AVX + kX86InstIdVmulsd, // AVX + kX86InstIdVmulss, // AVX + kX86InstIdVorpd, // AVX + kX86InstIdVorps, // AVX + kX86InstIdVpabsb, // AVX2 + kX86InstIdVpabsd, // AVX2 + kX86InstIdVpabsw, // AVX2 + kX86InstIdVpackssdw, // AVX2 + kX86InstIdVpacksswb, // AVX2 + kX86InstIdVpackusdw, // AVX2 + kX86InstIdVpackuswb, // AVX2 + kX86InstIdVpaddb, // AVX2 + kX86InstIdVpaddd, // AVX2 + kX86InstIdVpaddq, // AVX2 + kX86InstIdVpaddsb, // AVX2 + kX86InstIdVpaddsw, // AVX2 + kX86InstIdVpaddusb, // AVX2 + kX86InstIdVpaddusw, // AVX2 + kX86InstIdVpaddw, // AVX2 + kX86InstIdVpalignr, // AVX2 + kX86InstIdVpand, // AVX2 + kX86InstIdVpandn, // AVX2 + kX86InstIdVpavgb, // AVX2 + kX86InstIdVpavgw, // AVX2 + kX86InstIdVpblendd, // AVX2 + kX86InstIdVpblendvb, // AVX2 + kX86InstIdVpblendw, // AVX2 + kX86InstIdVpbroadcastb, // AVX2 + kX86InstIdVpbroadcastd, // AVX2 + kX86InstIdVpbroadcastq, // AVX2 + kX86InstIdVpbroadcastw, // AVX2 + kX86InstIdVpclmulqdq, // AVX+PCLMULQDQ + kX86InstIdVpcmov, // XOP + kX86InstIdVpcmpeqb, // AVX2 + kX86InstIdVpcmpeqd, // AVX2 + kX86InstIdVpcmpeqq, // AVX2 + kX86InstIdVpcmpeqw, // AVX2 + kX86InstIdVpcmpestri, // AVX + kX86InstIdVpcmpestrm, // AVX + kX86InstIdVpcmpgtb, // AVX2 + kX86InstIdVpcmpgtd, // AVX2 + kX86InstIdVpcmpgtq, // AVX2 + kX86InstIdVpcmpgtw, // AVX2 + kX86InstIdVpcmpistri, // AVX + kX86InstIdVpcmpistrm, // AVX + kX86InstIdVpcomb, // XOP + kX86InstIdVpcomd, // XOP + kX86InstIdVpcomq, // XOP + kX86InstIdVpcomub, // XOP + kX86InstIdVpcomud, // XOP + kX86InstIdVpcomuq, // XOP + kX86InstIdVpcomuw, // XOP + kX86InstIdVpcomw, // XOP + kX86InstIdVperm2f128, // AVX + kX86InstIdVperm2i128, // AVX2 + kX86InstIdVpermd, // AVX2 + kX86InstIdVpermil2pd, // XOP + kX86InstIdVpermil2ps, // XOP + kX86InstIdVpermilpd, // AVX + kX86InstIdVpermilps, // AVX + kX86InstIdVpermpd, // AVX2 + kX86InstIdVpermps, // AVX2 + kX86InstIdVpermq, // AVX2 + kX86InstIdVpextrb, // AVX + kX86InstIdVpextrd, // AVX + kX86InstIdVpextrq, // AVX (x64 only) + kX86InstIdVpextrw, // AVX + kX86InstIdVpgatherdd, // AVX2 + kX86InstIdVpgatherdq, // AVX2 + kX86InstIdVpgatherqd, // AVX2 + kX86InstIdVpgatherqq, // AVX2 + kX86InstIdVphaddbd, // XOP + kX86InstIdVphaddbq, // XOP + kX86InstIdVphaddbw, // XOP + kX86InstIdVphaddd, // AVX2 + kX86InstIdVphadddq, // XOP + kX86InstIdVphaddsw, // AVX2 + kX86InstIdVphaddubd, // XOP + kX86InstIdVphaddubq, // XOP + kX86InstIdVphaddubw, // XOP + kX86InstIdVphaddudq, // XOP + kX86InstIdVphadduwd, // XOP + kX86InstIdVphadduwq, // XOP + kX86InstIdVphaddw, // AVX2 + kX86InstIdVphaddwd, // XOP + kX86InstIdVphaddwq, // XOP + kX86InstIdVphminposuw, // AVX + kX86InstIdVphsubbw, // XOP + kX86InstIdVphsubd, // AVX2 + kX86InstIdVphsubdq, // XOP + kX86InstIdVphsubsw, // AVX2 + kX86InstIdVphsubw, // AVX2 + kX86InstIdVphsubwd, // XOP + kX86InstIdVpinsrb, // AVX + kX86InstIdVpinsrd, // AVX + kX86InstIdVpinsrq, // AVX (x64 only) + kX86InstIdVpinsrw, // AVX + kX86InstIdVpmacsdd, // XOP + kX86InstIdVpmacsdqh, // XOP + kX86InstIdVpmacsdql, // XOP + kX86InstIdVpmacssdd, // XOP + kX86InstIdVpmacssdqh, // XOP + kX86InstIdVpmacssdql, // XOP + kX86InstIdVpmacsswd, // XOP + kX86InstIdVpmacssww, // XOP + kX86InstIdVpmacswd, // XOP + kX86InstIdVpmacsww, // XOP + kX86InstIdVpmadcsswd, // XOP + kX86InstIdVpmadcswd, // XOP + kX86InstIdVpmaddubsw, // AVX/AVX2 + kX86InstIdVpmaddwd, // AVX/AVX2 + kX86InstIdVpmaskmovd, // AVX2 + kX86InstIdVpmaskmovq, // AVX2 + kX86InstIdVpmaxsb, // AVX/AVX2 + kX86InstIdVpmaxsd, // AVX/AVX2 + kX86InstIdVpmaxsw, // AVX/AVX2 + kX86InstIdVpmaxub, // AVX/AVX2 + kX86InstIdVpmaxud, // AVX/AVX2 + kX86InstIdVpmaxuw, // AVX/AVX2 + kX86InstIdVpminsb, // AVX/AVX2 + kX86InstIdVpminsd, // AVX/AVX2 + kX86InstIdVpminsw, // AVX/AVX2 + kX86InstIdVpminub, // AVX/AVX2 + kX86InstIdVpminud, // AVX/AVX2 + kX86InstIdVpminuw, // AVX/AVX2 + kX86InstIdVpmovmskb, // AVX/AVX2 + kX86InstIdVpmovsxbd, // AVX/AVX2 + kX86InstIdVpmovsxbq, // AVX/AVX2 + kX86InstIdVpmovsxbw, // AVX/AVX2 + kX86InstIdVpmovsxdq, // AVX/AVX2 + kX86InstIdVpmovsxwd, // AVX/AVX2 + kX86InstIdVpmovsxwq, // AVX/AVX2 + kX86InstIdVpmovzxbd, // AVX/AVX2 + kX86InstIdVpmovzxbq, // AVX/AVX2 + kX86InstIdVpmovzxbw, // AVX/AVX2 + kX86InstIdVpmovzxdq, // AVX/AVX2 + kX86InstIdVpmovzxwd, // AVX/AVX2 + kX86InstIdVpmovzxwq, // AVX/AVX2 + kX86InstIdVpmuldq, // AVX/AVX2 + kX86InstIdVpmulhrsw, // AVX/AVX2 + kX86InstIdVpmulhuw, // AVX/AVX2 + kX86InstIdVpmulhw, // AVX/AVX2 + kX86InstIdVpmulld, // AVX/AVX2 + kX86InstIdVpmullw, // AVX/AVX2 + kX86InstIdVpmuludq, // AVX/AVX2 + kX86InstIdVpor, // AVX/AVX2 + kX86InstIdVpperm, // XOP + kX86InstIdVprotb, // XOP + kX86InstIdVprotd, // XOP + kX86InstIdVprotq, // XOP + kX86InstIdVprotw, // XOP + kX86InstIdVpsadbw, // AVX/AVX2 + kX86InstIdVpshab, // XOP + kX86InstIdVpshad, // XOP + kX86InstIdVpshaq, // XOP + kX86InstIdVpshaw, // XOP + kX86InstIdVpshlb, // XOP + kX86InstIdVpshld, // XOP + kX86InstIdVpshlq, // XOP + kX86InstIdVpshlw, // XOP + kX86InstIdVpshufb, // AVX/AVX2 + kX86InstIdVpshufd, // AVX/AVX2 + kX86InstIdVpshufhw, // AVX/AVX2 + kX86InstIdVpshuflw, // AVX/AVX2 + kX86InstIdVpsignb, // AVX/AVX2 + kX86InstIdVpsignd, // AVX/AVX2 + kX86InstIdVpsignw, // AVX/AVX2 + kX86InstIdVpslld, // AVX/AVX2 + kX86InstIdVpslldq, // AVX/AVX2 + kX86InstIdVpsllq, // AVX/AVX2 + kX86InstIdVpsllvd, // AVX2 + kX86InstIdVpsllvq, // AVX2 + kX86InstIdVpsllw, // AVX/AVX2 + kX86InstIdVpsrad, // AVX/AVX2 + kX86InstIdVpsravd, // AVX2 + kX86InstIdVpsraw, // AVX/AVX2 + kX86InstIdVpsrld, // AVX/AVX2 + kX86InstIdVpsrldq, // AVX/AVX2 + kX86InstIdVpsrlq, // AVX/AVX2 + kX86InstIdVpsrlvd, // AVX2 + kX86InstIdVpsrlvq, // AVX2 + kX86InstIdVpsrlw, // AVX/AVX2 + kX86InstIdVpsubb, // AVX/AVX2 + kX86InstIdVpsubd, // AVX/AVX2 + kX86InstIdVpsubq, // AVX/AVX2 + kX86InstIdVpsubsb, // AVX/AVX2 + kX86InstIdVpsubsw, // AVX/AVX2 + kX86InstIdVpsubusb, // AVX/AVX2 + kX86InstIdVpsubusw, // AVX/AVX2 + kX86InstIdVpsubw, // AVX/AVX2 + kX86InstIdVptest, // AVX + kX86InstIdVpunpckhbw, // AVX/AVX2 + kX86InstIdVpunpckhdq, // AVX/AVX2 + kX86InstIdVpunpckhqdq, // AVX/AVX2 + kX86InstIdVpunpckhwd, // AVX/AVX2 + kX86InstIdVpunpcklbw, // AVX/AVX2 + kX86InstIdVpunpckldq, // AVX/AVX2 + kX86InstIdVpunpcklqdq, // AVX/AVX2 + kX86InstIdVpunpcklwd, // AVX/AVX2 + kX86InstIdVpxor, // AVX/AVX2 + kX86InstIdVrcpps, // AVX + kX86InstIdVrcpss, // AVX + kX86InstIdVroundpd, // AVX + kX86InstIdVroundps, // AVX + kX86InstIdVroundsd, // AVX + kX86InstIdVroundss, // AVX + kX86InstIdVrsqrtps, // AVX + kX86InstIdVrsqrtss, // AVX + kX86InstIdVshufpd, // AVX + kX86InstIdVshufps, // AVX + kX86InstIdVsqrtpd, // AVX + kX86InstIdVsqrtps, // AVX + kX86InstIdVsqrtsd, // AVX + kX86InstIdVsqrtss, // AVX + kX86InstIdVstmxcsr, // AVX + kX86InstIdVsubpd, // AVX + kX86InstIdVsubps, // AVX + kX86InstIdVsubsd, // AVX + kX86InstIdVsubss, // AVX + kX86InstIdVtestpd, // AVX + kX86InstIdVtestps, // AVX + kX86InstIdVucomisd, // AVX + kX86InstIdVucomiss, // AVX + kX86InstIdVunpckhpd, // AVX + kX86InstIdVunpckhps, // AVX + kX86InstIdVunpcklpd, // AVX + kX86InstIdVunpcklps, // AVX + kX86InstIdVxorpd, // AVX + kX86InstIdVxorps, // AVX + kX86InstIdVzeroall, // AVX + kX86InstIdVzeroupper, // AVX + kX86InstIdWrfsbase, // FSGSBASE (x64) + kX86InstIdWrgsbase, // FSGSBASE (x64) + kX86InstIdXadd, // X86/X64 (i486+) + kX86InstIdXchg, // X86/X64 + kX86InstIdXgetbv, // XSAVE + kX86InstIdXor, // X86/X64 + kX86InstIdXorpd, // SSE2 + kX86InstIdXorps, // SSE + kX86InstIdXrstor, // XSAVE + kX86InstIdXrstor64, // XSAVE + kX86InstIdXsave, // XSAVE + kX86InstIdXsave64, // XSAVE + kX86InstIdXsaveopt, // XSAVE + kX86InstIdXsaveopt64, // XSAVE + kX86InstIdXsetbv, // XSAVE + + _kX86InstIdCount, + + _kX86InstIdCmovcc = kX86InstIdCmova, + _kX86InstIdJcc = kX86InstIdJa, + _kX86InstIdSetcc = kX86InstIdSeta, + + _kX86InstIdJbegin = kX86InstIdJa, + _kX86InstIdJend = kX86InstIdJmp +}; + +// ============================================================================ +// [asmjit::kX86InstOptions] +// ============================================================================ + +//! X86/X64 instruction emit options, mainly for internal purposes. +ASMJIT_ENUM(kX86InstOptions) { + //! Emit instruction with LOCK prefix. + //! + //! If this option is used and instruction doesn't support LOCK prefix an + //! invalid instruction error is generated. + kX86InstOptionLock = 0x00000010, + + //! Force REX prefix (X64). + //! + //! This option should be used carefully as there are combinations of + //! instructions and their operands that are not encodable. The REX prefix + //! can't be used together with AH, BH, CH, and DH registers. AsmJit reports + //! \ref kErrorIllegalInstruction in such case. + kX86InstOptionRex = 0x00000040, + + //! \internal + //! + //! Reserved by `X86Assembler`, do not use! + _kX86InstOptionNoRex = 0x00000080, + + //! Force 3-byte VEX prefix even if the instruction is encodable by 2-byte + //! VEX prefix (AVX). + //! + //! Ignored if the instruction is not AVX or `kX86InstOptionEVEX` is used. + kX86InstOptionVex3 = 0x00000100, + + //! Force 4-byte EVEX prefix even if the instruction is encodable by using + //! VEX prefix. Please note that all higher bits from `kX86InstOptionEvex` + //! are reserved for EVEX and forces EVEX encoding to be used implicitly. + kX86InstOptionEvex = 0x00010000, + //! Use zeroing instead of merging (AVX512+). + kX86InstOptionEvexZero = 0x00020000, + //! Broadcast one element to all other elements (AVX512+). + kX86InstOptionEvexOneN = 0x00040000, + //! Suppress all exceptions (AVX512+). + kX86InstOptionEvexSae = 0x00080000, + + //! Static rounding mode `round-to-nearest` (even) and `SAE` (AVX512+). + kX86InstOptionEvexRnSae = 0x00100000, + //! Static rounding mode `round-down` (toward -inf) and `SAE` (AVX512+). + kX86InstOptionEvexRdSae = 0x00200000, + //! Static rounding mode `round-up` (toward +inf) and `SAE` (AVX512+). + kX86InstOptionEvexRuSae = 0x00400000, + //! Static rounding mode `round-toward-zero` (truncate) and `SAE` (AVX512+). + kX86InstOptionEvexRzSae = 0x00800000 +}; + +// ============================================================================ +// [asmjit::kX86InstEncodingId] +// ============================================================================ + +//! \internal +//! +//! X86/X64 instruction groups. +//! +//! This group is specific to AsmJit and only used by `X86Assembler`. +ASMJIT_ENUM(kX86InstEncodingId) { + //! Never used. + kX86InstEncodingIdNone = 0, + + kX86InstEncodingIdX86Op, + kX86InstEncodingIdX86Op_66H, + kX86InstEncodingIdX86Rm, + kX86InstEncodingIdX86Rm_B, + kX86InstEncodingIdX86RmReg, + kX86InstEncodingIdX86RegRm, + kX86InstEncodingIdX86M, + //! Adc/Add/And/Cmp/Or/Sbb/Sub/Xor. + kX86InstEncodingIdX86Arith, + //! Bswap. + kX86InstEncodingIdX86BSwap, + //! Bt/Btc/Btr/Bts. + kX86InstEncodingIdX86BTest, + //! Call. + kX86InstEncodingIdX86Call, + //! Enter. + kX86InstEncodingIdX86Enter, + //! Imul. + kX86InstEncodingIdX86Imul, + //! Inc/Dec. + kX86InstEncodingIdX86IncDec, + //! Int. + kX86InstEncodingIdX86Int, + //! Jcc. + kX86InstEncodingIdX86Jcc, + //! Jcxz/Jecxz/Jrcxz. + kX86InstEncodingIdX86Jecxz, + //! Jmp. + kX86InstEncodingIdX86Jmp, + //! Lea. + kX86InstEncodingIdX86Lea, + //! Mov. + kX86InstEncodingIdX86Mov, + //! Movsx/Movzx. + kX86InstEncodingIdX86MovSxZx, + //! Movsxd. + kX86InstEncodingIdX86MovSxd, + //! Mov having absolute memory operand (x86/x64). + kX86InstEncodingIdX86MovPtr, + //! Push. + kX86InstEncodingIdX86Push, + //! Pop. + kX86InstEncodingIdX86Pop, + //! Rep/Repe/Repne LodsX/MovsX/StosX/CmpsX/ScasX. + kX86InstEncodingIdX86Rep, + //! Ret. + kX86InstEncodingIdX86Ret, + //! Rcl/Rcr/Rol/Ror/Sal/Sar/Shl/Shr. + kX86InstEncodingIdX86Rot, + //! Setcc. + kX86InstEncodingIdX86Set, + //! Shld/Rhrd. + kX86InstEncodingIdX86Shlrd, + //! Test. + kX86InstEncodingIdX86Test, + //! Xadd. + kX86InstEncodingIdX86Xadd, + //! Xchg. + kX86InstEncodingIdX86Xchg, + + //! Fincstp/Finit/FldX/Fnclex/Fninit/Fnop/Fpatan/Fprem/Fprem1/Fptan/Frndint/Fscale/Fsin/Fsincos/Fsqrt/Ftst/Fucompp/Fxam/Fxtract/Fyl2x/Fyl2xp1. + kX86InstEncodingIdFpuOp, + //! Fadd/Fdiv/Fdivr/Fmul/Fsub/Fsubr. + kX86InstEncodingIdFpuArith, + //! Fcom/Fcomp. + kX86InstEncodingIdFpuCom, + //! Fld/Fst/Fstp. + kX86InstEncodingIdFpuFldFst, + //! Fiadd/Ficom/Ficomp/Fidiv/Fidivr/Fild/Fimul/Fist/Fistp/Fisttp/Fisub/Fisubr. + kX86InstEncodingIdFpuM, + //! Fcmov/Fcomi/Fcomip/Ffree/Fucom/Fucomi/Fucomip/Fucomp/Fxch. + kX86InstEncodingIdFpuR, + //! Faddp/Fdivp/Fdivrp/Fmulp/Fsubp/Fsubrp. + kX86InstEncodingIdFpuRDef, + //! Fnstsw/Fstsw. + kX86InstEncodingIdFpuStsw, + + //! Mm/Xmm instruction. + kX86InstEncodingIdExtRm, + //! Mm/Xmm instruction (propagates 66H if the instruction uses Xmm register). + kX86InstEncodingIdExtRm_P, + //! Mm/Xmm instruction (propagates REX.W if GPQ is used). + kX86InstEncodingIdExtRm_Q, + //! Mm/Xmm instruction (propagates 66H and REX.W). + kX86InstEncodingIdExtRm_PQ, + //! Mm/Xmm instruction having Rm/Ri encodings. + kX86InstEncodingIdExtRmRi, + //! Mm/Xmm instruction having Rm/Ri encodings (propagates 66H if the instruction uses Xmm register). + kX86InstEncodingIdExtRmRi_P, + //! Mm/Xmm instruction having Rmi encoding. + kX86InstEncodingIdExtRmi, + //! Mm/Xmm instruction having Rmi encoding (propagates 66H if the instruction uses Xmm register). + kX86InstEncodingIdExtRmi_P, + //! Crc32. + kX86InstEncodingIdExtCrc, + //! Pextrb/Pextrw/Pextrd/Pextrq/Extractps. + kX86InstEncodingIdExtExtract, + //! Lfence/Mfence/Sfence. + kX86InstEncodingIdExtFence, + //! Mov Mm/Xmm. + //! + //! 0x66 prefix must be set manually in opcodes. + //! + //! - Primary opcode is used for instructions in (X)Mm <- (X)Mm/X86Mem format, + //! - Secondary opcode is used for instructions in (X)Mm/X86Mem <- (X)Mm format. + kX86InstEncodingIdExtMov, + //! Mov Mm/Xmm. + kX86InstEncodingIdExtMovNoRexW, + //! Movbe. + kX86InstEncodingIdExtMovBe, + //! Movd. + kX86InstEncodingIdExtMovD, + //! Movq. + kX86InstEncodingIdExtMovQ, + //! Prefetch. + kX86InstEncodingIdExtPrefetch, + + //! Extrq (SSE4a). + kX86InstEncodingIdExtExtrq, + //! Insrq (SSE4a). + kX86InstEncodingIdExtInsertq, + + //! 3dNow instruction. + kX86InstEncodingId3dNow, + + //! AVX instruction without operands. + kX86InstEncodingIdAvxOp, + //! AVX instruction encoded as 'M'. + kX86InstEncodingIdAvxM, + //! AVX instruction encoded as 'MR'. + kX86InstEncodingIdAvxMr, + //! AVX instruction encoded as 'MR' (Propagates AVX.L if Ymm used). + kX86InstEncodingIdAvxMr_P, + //! AVX instruction encoded as 'MRI'. + kX86InstEncodingIdAvxMri, + //! AVX instruction encoded as 'MRI' (Propagates AVX.L if Ymm used). + kX86InstEncodingIdAvxMri_P, + //! AVX instruction encoded as 'RM'. + kX86InstEncodingIdAvxRm, + //! AVX instruction encoded as 'RM' (Propagates AVX.L if Ymm used). + kX86InstEncodingIdAvxRm_P, + //! AVX instruction encoded as 'RMI'. + kX86InstEncodingIdAvxRmi, + //! AVX instruction encoded as 'RMI' (Propagates AVX.L if Ymm used). + kX86InstEncodingIdAvxRmi_P, + //! AVX instruction encoded as 'RVM'. + kX86InstEncodingIdAvxRvm, + //! AVX instruction encoded as 'RVM' (Propagates AVX.L if Ymm used). + kX86InstEncodingIdAvxRvm_P, + //! AVX instruction encoded as 'RVMR'. + kX86InstEncodingIdAvxRvmr, + //! AVX instruction encoded as 'RVMR' (Propagates AVX.L if Ymm used). + kX86InstEncodingIdAvxRvmr_P, + //! AVX instruction encoded as 'RVMI'. + kX86InstEncodingIdAvxRvmi, + //! AVX instruction encoded as 'RVMI' (Propagates AVX.L if Ymm used). + kX86InstEncodingIdAvxRvmi_P, + //! AVX instruction encoded as 'RMV'. + kX86InstEncodingIdAvxRmv, + //! AVX instruction encoded as 'RMVI'. + kX86InstEncodingIdAvxRmvi, + //! AVX instruction encoded as 'RM' or 'MR'. + kX86InstEncodingIdAvxRmMr, + //! AVX instruction encoded as 'RM' or 'MR' (Propagates AVX.L if Ymm used). + kX86InstEncodingIdAvxRmMr_P, + //! AVX instruction encoded as 'RVM' or 'RMI'. + kX86InstEncodingIdAvxRvmRmi, + //! AVX instruction encoded as 'RVM' or 'RMI' (Propagates AVX.L if Ymm used). + kX86InstEncodingIdAvxRvmRmi_P, + //! AVX instruction encoded as 'RVM' or 'MR'. + kX86InstEncodingIdAvxRvmMr, + //! AVX instruction encoded as 'RVM' or 'MVR'. + kX86InstEncodingIdAvxRvmMvr, + //! AVX instruction encoded as 'RVM' or 'MVR' (Propagates AVX.L if Ymm used). + kX86InstEncodingIdAvxRvmMvr_P, + //! AVX instruction encoded as 'RVM' or 'VMI'. + kX86InstEncodingIdAvxRvmVmi, + //! AVX instruction encoded as 'RVM' or 'VMI' (Propagates AVX.L if Ymm used). + kX86InstEncodingIdAvxRvmVmi_P, + //! AVX instruction encoded as 'VM'. + kX86InstEncodingIdAvxVm, + //! AVX instruction encoded as 'VMI'. + kX86InstEncodingIdAvxVmi, + //! AVX instruction encoded as 'VMI' (Propagates AVX.L if Ymm used). + kX86InstEncodingIdAvxVmi_P, + //! AVX instruction encoded as 'RVRM' or 'RVMR'. + kX86InstEncodingIdAvxRvrmRvmr, + //! AVX instruction encoded as 'RVRM' or 'RVMR' (Propagates AVX.L if Ymm used). + kX86InstEncodingIdAvxRvrmRvmr_P, + //! Vmovss/Vmovsd. + kX86InstEncodingIdAvxMovSsSd, + //! AVX2 gather family instructions (VSIB). + kX86InstEncodingIdAvxGather, + //! AVX2 gather family instructions (VSIB), differs only in mem operand. + kX86InstEncodingIdAvxGatherEx, + + //! FMA4 instruction in form [R, R, R/M, R/M]. + kX86InstEncodingIdFma4, + //! FMA4 instruction in form [R, R, R/M, R/M] (Propagates AVX.L if Ymm used). + kX86InstEncodingIdFma4_P, + + //! XOP instruction encoded as 'RM'. + kX86InstEncodingIdXopRm, + //! XOP instruction encoded as 'RM' (Propagates AVX.L if Ymm used). + kX86InstEncodingIdXopRm_P, + //! XOP instruction encoded as 'RVM' or 'RMV'. + kX86InstEncodingIdXopRvmRmv, + //! XOP instruction encoded as 'RVM' or 'RMI'. + kX86InstEncodingIdXopRvmRmi, + //! XOP instruction encoded as 'RVMR'. + kX86InstEncodingIdXopRvmr, + //! XOP instruction encoded as 'RVMR' (Propagates AVX.L if Ymm used). + kX86InstEncodingIdXopRvmr_P, + //! XOP instruction encoded as 'RVMI'. + kX86InstEncodingIdXopRvmi, + //! XOP instruction encoded as 'RVMI' (Propagates AVX.L if Ymm used). + kX86InstEncodingIdXopRvmi_P, + //! XOP instruction encoded as 'RVRM' or 'RVMR'. + kX86InstEncodingIdXopRvrmRvmr, + //! XOP instruction encoded as 'RVRM' or 'RVMR' (Propagates AVX.L if Ymm used). + kX86InstEncodingIdXopRvrmRvmr_P, + + //! Count of X86 instruction groups. + _kX86InstEncodingIdCount +}; + +// ============================================================================ +// [asmjit::kX86InstOpCode] +// ============================================================================ + +//! \internal +//! +//! X86/X64 Instruction opcode encoding used by asmjit 'X86InstInfo' table. +//! +//! This schema is AsmJit specific and has been designed to allow encoding of +//! all X86 instructions available. X86, MMX, and SSE+ instructions always use +//! `MMMMM` and `PP` fields, which are encoded to corresponding prefixes needed +//! by X86 or SIMD instructions. AVX+ instructions embed `MMMMM` and `PP` fields +//! in a VEX prefix. +//! +//! The instruction opcode definition uses 1 or 2 bytes as an opcode value. 1 +//! byte is needed by most of the instructions, 2 bytes are only used by legacy +//! X87-FPU instructions. This means that a second byte is free to by used by +//! AVX and AVX-512 instructions. +//! +//! The fields description: +//! +//! - `MMMMM` field is used to encode prefixes needed by the instruction or as +//! a part of VEX/EVEX prefix. +//! +//! - `PP` field is used to encode prefixes needed by the instruction or as a +//! part of VEX/EVEX prefix. +//! +//! - `L` field is used exclusively by AVX+ and AVX512+ instruction sets. It +//! describes vector size, which is 128-bit for Xmm register `L_128`, 256 +//! for Ymm register `L_256` and 512-bit for Zmm register `L_512`. The `L` +//! field is omitted in case that instruction supports multiple vector lengths, +//! however, if the instruction requires specific `L` value it's specified as +//! a part of the opcode. +//! +//! - `W` field is the most complicated. It was added by 64-bit architecture +//! to promote default operation width (instructions that perform 32-bit +//! operation by default require to override the width to 64-bit explicitly). +//! There is nothing wrong on this, however, some instructions introduced +//! implicit `W` override, for example a `cdqe` instruction is basically a +//! `cwde` instructiontion with overridden `W` (set to 1). There are some +//! others in the base X86 instruction set. More recent instruction sets +//! started using `W` field more often: +//! +//! - AVX instructions started using `W` field as an extended opcode for FMA, +//! GATHER, PERM, and other instructions. It also uses `W` field to override +//! the default operation width in instructions like `vmovq`. AVX `W` field +//! is +//! +//! - AVX-512 instructions started using `W` field as an extended opcode for +//! all new instructions. This wouldn't have been an issue if the `W` field +//! of AVX-512 have matched AVX, but this is not the case. +//! +//! - `O` field is an extended opcode field (3) bytes used by ModR/M BYTE. +ASMJIT_ENUM(kX86InstOpCode) { + // `MMMMM` field in AVX/XOP/AVX-512 instruction (5 bits). + // + // `OpCode` leading bytes in legacy encoding. + // + // AVX reserves 5 bits for `MMMMM` field, however AVX instructions only use + // 2 bits and XOP 4 bits. AVX-512 shrinks `MMMMM` field into `MM` so it's + // safe to assume that `MM` field won't grow in the future as EVEX doesn't + // use more than 2 bits. There is always a way how a fifth bit can be stored + // if needed. + kX86InstOpCode_MM_Shift = 16, + kX86InstOpCode_MM_Mask = 0x0FU << kX86InstOpCode_MM_Shift, + kX86InstOpCode_MM_00 = 0x00U << kX86InstOpCode_MM_Shift, + kX86InstOpCode_MM_0F = 0x01U << kX86InstOpCode_MM_Shift, + kX86InstOpCode_MM_0F38 = 0x02U << kX86InstOpCode_MM_Shift, + kX86InstOpCode_MM_0F3A = 0x03U << kX86InstOpCode_MM_Shift, + kX86InstOpCode_MM_00011 = 0x03U << kX86InstOpCode_MM_Shift, // XOP. + kX86InstOpCode_MM_01000 = 0x08U << kX86InstOpCode_MM_Shift, // XOP. + kX86InstOpCode_MM_01001 = 0x09U << kX86InstOpCode_MM_Shift, // XOP. + kX86InstOpCode_MM_0F01 = 0x0FU << kX86InstOpCode_MM_Shift, // AsmJit specific, not part of AVX. + + // `PP` field in AVX/XOP/AVX-512 instruction. + // + // `Mandatory Prefix` in legacy encoding. + // + // AVX reserves 2 bits for `PP` field, but AsmJit extends the storage by 1 + // more bit that is used to emit 9B prefix for some X87-FPU instructions. + kX86InstOpCode_PP_Shift = 20, + kX86InstOpCode_PP_Mask = 0x07U << kX86InstOpCode_PP_Shift, + kX86InstOpCode_PP_00 = 0x00U << kX86InstOpCode_PP_Shift, + kX86InstOpCode_PP_66 = 0x01U << kX86InstOpCode_PP_Shift, + kX86InstOpCode_PP_F3 = 0x02U << kX86InstOpCode_PP_Shift, + kX86InstOpCode_PP_F2 = 0x03U << kX86InstOpCode_PP_Shift, + kX86InstOpCode_PP_9B = 0x07U << kX86InstOpCode_PP_Shift, // AsmJit specific, not part of AVX. + + // `L` field in AVX/XOP/AVX-512 instruction. + // + // AVX/XOP can only use the first bit `L.128` or `L.256`. AVX-512 makes it + // possible to use also `L.512`. + // + // \note If the instruction set manual describes an instruction by using `LIG` + // it means that the `L` field is ignored. AsmJit emits `0` in such case. + kX86InstOpCode_L_Shift = 23, + kX86InstOpCode_L_Mask = 0x03U << kX86InstOpCode_L_Shift, + kX86InstOpCode_L_128 = 0x00U << kX86InstOpCode_L_Shift, + kX86InstOpCode_L_256 = 0x01U << kX86InstOpCode_L_Shift, + kX86InstOpCode_L_512 = 0x02U << kX86InstOpCode_L_Shift, + + // `O` field (ModR/M). + kX86InstOpCode_O_Shift = 25, + kX86InstOpCode_O_Mask = 0x07U << kX86InstOpCode_O_Shift, + + // `W` field used in EVEX instruction encoding. + kX86InstOpCode_EW_Shift = 30, + kX86InstOpCode_EW_Mask = 0x01U << kX86InstOpCode_EW_Shift, + kX86InstOpCode_EW = 0x01U << kX86InstOpCode_EW_Shift, + + // `W` field used in REX/VEX instruction encoding. + // + // \note If the instruction set manual describes an instruction by using `WIG` + // it means that the `W` field is ignored. AsmJit emits `0` in such case. + kX86InstOpCode_W_Shift = 31, + kX86InstOpCode_W_Mask = 0x01U << kX86InstOpCode_W_Shift, + kX86InstOpCode_W = 0x01U << kX86InstOpCode_W_Shift, +}; + +// ============================================================================ +// [asmjit::kX86InstFlags] +// ============================================================================ + +//! \internal +//! +//! X86/X64 instruction flags. +ASMJIT_ENUM(kX86InstFlags) { + //! No flags. + kX86InstFlagNone = 0x00000000, + + //! Instruction is a control-flow instruction. + //! + //! Control flow instructions are jmp, jcc, call and ret. + kX86InstFlagFlow = 0x00000001, + + //! Instruction is a compare/test like instruction. + kX86InstFlagTest = 0x00000002, + + //! Instruction is a move like instruction. + //! + //! Move instructions typically overwrite the first operand by the second + //! operand. The first operand can be the exact copy of the second operand + //! or it can be any kind of conversion or shuffling. + //! + //! Mov instructions are 'mov', 'movd', 'movq', movdq', 'lea', multimedia + //! instructions like 'cvtdq2pd', shuffle instructions like 'pshufb' and + //! SSE/SSE2 mathematic instructions like 'rcp?', 'round?' and 'rsqrt?'. + //! + //! There are some MOV instructions that do only a partial move (for example + //! 'cvtsi2ss'), register allocator has to know the variable size and use + //! the flag accordingly to it. + kX86InstFlagMove = 0x00000004, + + //! Instruction is an exchange like instruction. + //! + //! Exchange instruction typically overwrite first and second operand. So + //! far only the instructions 'xchg' and 'xadd' are considered. + kX86InstFlagXchg = 0x00000008, + + //! Instruction accesses Fp register(s). + kX86InstFlagFp = 0x00000010, + + //! Instruction can be prefixed by using the LOCK prefix. + kX86InstFlagLock = 0x00000020, + + //! Instruction requires special handling, used by \ref Compiler. + kX86InstFlagSpecial = 0x00000040, + + //! Instruction always performs memory access. + //! + //! This flag is always combined with `kX86InstFlagSpecial` and describes + //! that there is an implicit address which is accessed (usually EDI/RDI or + //! ESI/EDI). + kX86InstFlagSpecialMem = 0x00000080, + + //! Instruction memory operand can refer to 16-bit address (used by FPU). + kX86InstFlagMem2 = 0x00000100, + //! Instruction memory operand can refer to 32-bit address (used by FPU). + kX86InstFlagMem4 = 0x00000200, + //! Instruction memory operand can refer to 64-bit address (used by FPU). + kX86InstFlagMem8 = 0x00000400, + //! Instruction memory operand can refer to 80-bit address (used by FPU). + kX86InstFlagMem10 = 0x00000800, + + //! Zeroes the rest of the register if the source operand is memory. + //! + //! Special behavior related to some SIMD load instructions. + kX86InstFlagZ = 0x00001000, + + //! Instruction is supported by AVX. + kX86InstFlagAvx = 0x00010000, + //! Instruction is supported by XOP. + kX86InstFlagXop = 0x00020000, + + //! Instruction is supported by AVX-512 F (Zmm). + kX86InstFlagAvx512F = 0x00100000, + //! Instruction is supported by AVX-512 CD (Zmm). + kX86InstFlagAvx512CD = 0x00200000, + //! Instruction is supported by AVX-512 PF (Zmm). + kX86InstFlagAvx512PF = 0x00400000, + //! Instruction is supported by AVX-512 ER (Zmm). + kX86InstFlagAvx512ER = 0x00800000, + //! Instruction is supported by AVX-512 DQ (Zmm). + kX86InstFlagAvx512DQ = 0x01000000, + //! Instruction is supported by AVX-512 BW (Zmm). + kX86InstFlagAvx512BW = 0x02000000, + //! Instruction is supported by AVX-512 VL (Xmm/Ymm). + kX86InstFlagAvx512VL = 0x04000000, + + //! Instruction supports masking {k0..k7}. + kX86InstFlagAvx512KMask = 0x08000000, + //! Instruction supports zeroing of elements {k0z..k7z}. + kX86InstFlagAvx512KZero = 0x10000000, + //! Instruction supports broadcast {1toN}. + kX86InstFlagAvx512Broadcast = 0x20000000, + //! Instruction supports suppressing all exceptions {sae}. + kX86InstFlagAvx512Sae = 0x40000000, + //! Instruction supports static rounding control with SAE {rnd-sae}, + kX86InstFlagAvx512Rnd = 0x80000000 +}; + +// ============================================================================ +// [asmjit::kX86InstOp] +// ============================================================================ + +//! \internal +//! +//! X86/X64 instruction operand flags. +ASMJIT_ENUM(kX86InstOp) { + //! Instruction operand can be 8-bit Gpb register. + kX86InstOpGb = 0x0001, + //! Instruction operand can be 16-bit Gpw register. + kX86InstOpGw = 0x0002, + //! Instruction operand can be 32-bit Gpd register. + kX86InstOpGd = 0x0004, + //! Instruction operand can be 64-bit Gpq register. + kX86InstOpGq = 0x0008, + + //! Instruction operand can be Fp register. + kX86InstOpFp = 0x0010, + //! Instruction operand can be 64-bit Mm register. + kX86InstOpMm = 0x0020, + + //! Instruction operand can be 64-bit K register. + kX86InstOpK = 0x0040, + + //! Instruction operand can be 128-bit Xmm register. + kX86InstOpXmm = 0x0100, + //! Instruction operand can be 256-bit Ymm register. + kX86InstOpYmm = 0x0200, + //! Instruction operand can be 512-bit Zmm register. + kX86InstOpZmm = 0x0400, + + //! Instruction operand can be memory. + kX86InstOpMem = 0x1000, + //! Instruction operand can be immediate. + kX86InstOpImm = 0x2000, + //! Instruction operand can be label. + kX86InstOpLabel = 0x4000, + //! Instruction operand doesn't have to be used. + //! + //! \note If no operand is specified the meaning is clear (the operand at the + //! particular index doesn't exist), however, when one or more operand is + //! specified, it's not clear whether the operand can be omitted or not. When + //! `kX86InstOpNone` is used it means that the operand is not used in some + //! cases. + kX86InstOpNone = 0x8000 +}; + +// ============================================================================ +// [asmjit::kX86Cond] +// ============================================================================ + +//! X86/X64 Condition codes. +ASMJIT_ENUM(kX86Cond) { + kX86CondA = 0x07, // CF==0 & ZF==0 (unsigned) + kX86CondAE = 0x03, // CF==0 (unsigned) + kX86CondB = 0x02, // CF==1 (unsigned) + kX86CondBE = 0x06, // CF==1 | ZF==1 (unsigned) + kX86CondC = 0x02, // CF==1 + kX86CondE = 0x04, // ZF==1 (signed/unsigned) + kX86CondG = 0x0F, // ZF==0 & SF==OF (signed) + kX86CondGE = 0x0D, // SF==OF (signed) + kX86CondL = 0x0C, // SF!=OF (signed) + kX86CondLE = 0x0E, // ZF==1 | SF!=OF (signed) + kX86CondNA = 0x06, // CF==1 | ZF==1 (unsigned) + kX86CondNAE = 0x02, // CF==1 (unsigned) + kX86CondNB = 0x03, // CF==0 (unsigned) + kX86CondNBE = 0x07, // CF==0 & ZF==0 (unsigned) + kX86CondNC = 0x03, // CF==0 + kX86CondNE = 0x05, // ZF==0 (signed/unsigned) + kX86CondNG = 0x0E, // ZF==1 | SF!=OF (signed) + kX86CondNGE = 0x0C, // SF!=OF (signed) + kX86CondNL = 0x0D, // SF==OF (signed) + kX86CondNLE = 0x0F, // ZF==0 & SF==OF (signed) + kX86CondNO = 0x01, // OF==0 + kX86CondNP = 0x0B, // PF==0 + kX86CondNS = 0x09, // SF==0 + kX86CondNZ = 0x05, // ZF==0 + kX86CondO = 0x00, // OF==1 + kX86CondP = 0x0A, // PF==1 + kX86CondPE = 0x0A, // PF==1 + kX86CondPO = 0x0B, // PF==0 + kX86CondS = 0x08, // SF==1 + kX86CondZ = 0x04, // ZF==1 + + // Simplified condition codes. + kX86CondSign = kX86CondS , //!< Sign (S). + kX86CondNotSign = kX86CondNS, //!< Not Sign (NS). + + kX86CondOverflow = kX86CondO , //!< Signed Overflow (O) + kX86CondNotOverflow = kX86CondNO, //!< Not Signed Overflow (NO) + + kX86CondLess = kX86CondL , //!< Signed `a < b` (L or NGE). + kX86CondLessEqual = kX86CondLE, //!< Signed `a <= b` (LE or NG ). + kX86CondGreater = kX86CondG , //!< Signed `a > b` (G or NLE). + kX86CondGreaterEqual = kX86CondGE, //!< Signed `a >= b` (GE or NL ). + kX86CondBelow = kX86CondB , //!< Unsigned `a < b` (B or NAE). + kX86CondBelowEqual = kX86CondBE, //!< Unsigned `a <= b` (BE or NA ). + kX86CondAbove = kX86CondA , //!< Unsigned `a > b` (A or NBE). + kX86CondAboveEqual = kX86CondAE, //!< Unsigned `a >= b` (AE or NB ). + kX86CondEqual = kX86CondE , //!< Equal `a == b` (E or Z ). + kX86CondNotEqual = kX86CondNE, //!< Not Equal `a != b` (NE or NZ ). + + kX86CondParityEven = kX86CondP, + kX86CondParityOdd = kX86CondPO, + + // Aliases. + kX86CondZero = kX86CondZ, + kX86CondNotZero = kX86CondNZ, + kX86CondNegative = kX86CondS, + kX86CondPositive = kX86CondNS, + + // Fpu-only. + kX86CondFpuUnordered = 0x10, + kX86CondFpuNotUnordered = 0x11, + + //! No condition code. + kX86CondNone = 0x12 +}; + +// ============================================================================ +// [asmjit::kX86EFlags] +// ============================================================================ + +//! X86/X64 EFLAGs bits (AsmJit specific). +//! +//! Each instruction stored in AsmJit database contains flags that instruction +//! uses (reads) and flags that instruction modifies (writes). This is used by +//! instruction reordering, but can be used by third parties as it's part of +//! AsmJit API. +//! +//! \note Flags defined here don't correspond to real flags used by X86/X64 +//! architecture, defined in Intel's Manual Section `3.4.3 - EFLAGS Register`. +//! +//! \note Flags are designed to fit in an 8-bit integer. +ASMJIT_ENUM(kX86EFlags) { + // -------------------------------------------------------------------------- + // src-gendefs.js relies on the values of these masks, the tool has to be + // changed as you plan to modify `kX86EFlags`. + // -------------------------------------------------------------------------- + + //! Overflow flag (OF). + //! + //! Set if the integer result is too large a positive number or too small a + //! negative number (excluding the sign-bit) to fit in the destination + //! operand; cleared otherwise. This flag indicates an overflow condition for + //! signed-integer arithmetic. + kX86EFlagO = 0x01, + + //! Sign flag (SF). + //! + //! Set equal to the most-significant bit of the result, which is the sign + //! bit of a signed integer (0 == positive value, 1 == negative value). + kX86EFlagS = 0x02, + + //! Zero flag (ZF). + //! + //! Set if the result is zero; cleared otherwise. + kX86EFlagZ = 0x04, + + //! Adjust flag (AF). + //! + //! Set if an arithmetic operation generates a carry or a borrow out of bit + //! 3 of the result; cleared otherwise. This flag is used in binary-coded + //! decimal (BCD) arithmetic. + kX86EFlagA = 0x08, + + //! Parity flag (PF). + //! + //! Set if the least-significant byte of the result contains an even number + //! of 1 bits; cleared otherwise. + kX86EFlagP = 0x10, + + //! Carry flag (CF). + //! + //! Set if an arithmetic operation generates a carry or a borrow out of the + //! mostsignificant bit of the result; cleared otherwise. + kX86EFlagC = 0x20, + + //! Direction flag (DF). + //! + //! The direction flag controls string instructions `movs`, `cmps`, `scas, + //! `lods` and `stos`. + kX86EFlagD = 0x40, + + //! Any other flag that AsmJit doesn't use to keep track of. + kX86EFlagX = 0x80 +}; + +// ============================================================================ +// [asmjit::kX86FpSw] +// ============================================================================ + +//! X86/X64 FPU status word. +ASMJIT_ENUM(kX86FpSw) { + kX86FpSw_Invalid = 0x0001, + kX86FpSw_Denormalized = 0x0002, + kX86FpSw_DivByZero = 0x0004, + kX86FpSw_Overflow = 0x0008, + kX86FpSw_Underflow = 0x0010, + kX86FpSw_Precision = 0x0020, + kX86FpSw_StackFault = 0x0040, + kX86FpSw_Interrupt = 0x0080, + kX86FpSw_C0 = 0x0100, + kX86FpSw_C1 = 0x0200, + kX86FpSw_C2 = 0x0400, + kX86FpSw_Top = 0x3800, + kX86FpSw_C3 = 0x4000, + kX86FpSw_Busy = 0x8000 +}; + +// ============================================================================ +// [asmjit::kX86FpCw] +// ============================================================================ + +//! X86/X64 FPU control word. +ASMJIT_ENUM(kX86FpCw) { + kX86FpCw_EM_Mask = 0x003F, // Bits 0-5. + kX86FpCw_EM_Invalid = 0x0001, + kX86FpCw_EM_Denormal = 0x0002, + kX86FpCw_EM_DivByZero = 0x0004, + kX86FpCw_EM_Overflow = 0x0008, + kX86FpCw_EM_Underflow = 0x0010, + kX86FpCw_EM_Inexact = 0x0020, + + kX86FpCw_PC_Mask = 0x0300, // Bits 8-9. + kX86FpCw_PC_Float = 0x0000, + kX86FpCw_PC_Reserved = 0x0100, + kX86FpCw_PC_Double = 0x0200, + kX86FpCw_PC_Extended = 0x0300, + + kX86FpCw_RC_Mask = 0x0C00, // Bits 10-11. + kX86FpCw_RC_Nearest = 0x0000, + kX86FpCw_RC_Down = 0x0400, + kX86FpCw_RC_Up = 0x0800, + kX86FpCw_RC_Truncate = 0x0C00, + + kX86FpCw_IC_Mask = 0x1000, // Bit 12. + kX86FpCw_IC_Projective = 0x0000, + kX86FpCw_IC_Affine = 0x1000 +}; + +// ============================================================================ +// [asmjit::kX86Cmp] +// ============================================================================ + +//! X86/X64 Comparison predicate used by CMP[PD/PS/SD/SS] family instructions. +ASMJIT_ENUM(kX86Cmp) { + kX86CmpEQ = 0x00, //!< Equal (Quite). + kX86CmpLT = 0x01, //!< Less (Signaling). + kX86CmpLE = 0x02, //!< Less/Equal (Signaling). + kX86CmpUNORD = 0x03, //!< Unordered (Quite). + kX86CmpNEQ = 0x04, //!< Not Equal (Quite). + kX86CmpNLT = 0x05, //!< Not Less (Signaling). + kX86CmpNLE = 0x06, //!< Not Less/Equal (Signaling). + kX86CmpORD = 0x07 //!< Ordered (Quite). +}; + +// ============================================================================ +// [asmjit::kX86VCmp] +// ============================================================================ + +//! X86/X64 Comparison predicate used by VCMP[PD/PS/SD/SS] family instructions. +//! +//! The first 8 are compatible with \ref kX86Cmp. +ASMJIT_ENUM(kX86VCmp) { + kX86VCmpEQ_OQ = 0x00, //!< Equal (Quite, Ordered). + kX86VCmpLT_OS = 0x01, //!< Less (Signaling, Ordered). + kX86VCmpLE_OS = 0x02, //!< Less/Equal (Signaling, Ordered). + kX86VCmpUNORD_Q = 0x03, //!< Unordered (Quite). + kX86VCmpNEQ_UQ = 0x04, //!< Not Equal (Quite, Unordered). + kX86VCmpNLT_US = 0x05, //!< Not Less (Signaling, Unordered). + kX86VCmpNLE_US = 0x06, //!< Not Less/Equal (Signaling, Unordered). + kX86VCmpORD_Q = 0x07, //!< Ordered (Quite). + + kX86VCmpEQ_UQ = 0x08, //!< Equal (Quite, Unordered). + kX86VCmpNGE_US = 0x09, //!< Not Greater/Equal (Signaling, Unordered). + kX86VCmpNGT_US = 0x0A, //!< Not Greater (Signaling, Unordered). + kX86VCmpFALSE_OQ = 0x0B, //!< False (Quite, Ordered). + kX86VCmpNEQ_OQ = 0x0C, //!< Not Equal (Quite, Ordered). + kX86VCmpGE_OS = 0x0D, //!< Greater/Equal (Signaling, Ordered). + kX86VCmpGT_OS = 0x0E, //!< Greater (Signaling, Ordered). + kX86VCmpTRUE_UQ = 0x0F, //!< True (Quite, Unordered). + kX86VCmpEQ_OS = 0x10, //!< Equal (Signaling, Ordered). + kX86VCmpLT_OQ = 0x11, //!< Less (Quite, Ordered). + kX86VCmpLE_OQ = 0x12, //!< Less/Equal (Quite, Ordered). + kX86VCmpUNORD_S = 0x13, //!< Unordered (Signaling). + kX86VCmpNEQ_US = 0x14, //!< Not Equal (Signaling, Unordered). + kX86VCmpNLT_UQ = 0x15, //!< Not Less (Quite, Unordered). + kX86VCmpNLE_UQ = 0x16, //!< Not Less/Equal (Quite, Unordered). + kX86VCmpORD_S = 0x17, //!< Ordered (Signaling). + kX86VCmpEQ_US = 0x18, //!< Equal (Signaling, Unordered). + kX86VCmpNGE_UQ = 0x19, //!< Not Greater/Equal (Quite, Unordered). + kX86VCmpNGT_UQ = 0x1A, //!< Not Greater (Quite, Unordered). + kX86VCmpFALSE_OS = 0x1B, //!< False (Signaling, Ordered). + kX86VCmpNEQ_OS = 0x1C, //!< Not Equal (Signaling, Ordered). + kX86VCmpGE_OQ = 0x1D, //!< Greater/Equal (Quite, Ordered). + kX86VCmpGT_OQ = 0x1E, //!< Greater (Quite, Ordered). + kX86VCmpTRUE_US = 0x1F //!< True (Signaling, Unordered). +}; + +// ============================================================================ +// [asmjit::kX86Prefetch] +// ============================================================================ + +//! X86/X64 Prefetch hints. +ASMJIT_ENUM(kX86Prefetch) { + //! Prefetch using NT hint. + kX86PrefetchNTA = 0, + //! Prefetch to L0 cache. + kX86PrefetchT0 = 1, + //! Prefetch to L1 cache. + kX86PrefetchT1 = 2, + //! Prefetch to L2 cache. + kX86PrefetchT2 = 3 +}; + +// ============================================================================ +// [asmjit::X86InstExtendedInfo] +// ============================================================================ + +//! X86/X64 instruction extended information. +//! +//! Extended information has been introduced to minimize data needed for a +//! single instruction, because two or more instructions can share the common +//! data, for example operands definition or secondary opcode, which is only +//! used by few instructions. +struct X86InstExtendedInfo { + // -------------------------------------------------------------------------- + // [Accessors - Instruction Encoding] + // -------------------------------------------------------------------------- + + //! Get instruction encoding, see \ref kX86InstEncoding. + ASMJIT_INLINE uint32_t getEncodingId() const { + return _encodingId; + } + + // -------------------------------------------------------------------------- + // [Accessors - Instruction Flags] + // -------------------------------------------------------------------------- + + //! Get whether the instruction has a `flag`, see `kX86InstFlags`. + ASMJIT_INLINE bool hasInstFlag(uint32_t flag) const { + return (_instFlags & flag) != 0; + } + + //! Get all instruction flags, see `kX86InstFlags`. + ASMJIT_INLINE uint32_t getInstFlags() const { + return _instFlags; + } + + //! Get whether the instruction is a control-flow intruction. + //! + //! Control flow instruction is instruction that can perform a branch, + //! typically `jmp`, `jcc`, `call`, or `ret`. + ASMJIT_INLINE bool isFlow() const { + return (getInstFlags() & kX86InstFlagFlow) != 0; + } + + //! Get whether the instruction is a compare/test like intruction. + ASMJIT_INLINE bool isTest() const { + return (getInstFlags() & kX86InstFlagTest) != 0; + } + + //! Get whether the instruction is a typical move instruction. + //! + //! Move instructions overwrite the first operand or at least part of it, + //! This is a very useful hint that is used by variable liveness analysis + //! and `Compiler` in general to know which variable is completely + //! overwritten. + //! + //! All AVX/XOP instructions that have 3 or more operands are considered to + //! have move semantics move by default. + ASMJIT_INLINE bool isMove() const { + return (getInstFlags() & kX86InstFlagMove) != 0; + } + + //! Get whether the instruction is a typical Exchange instruction. + //! + //! Exchange instructios are 'xchg' and 'xadd'. + ASMJIT_INLINE bool isXchg() const { + return (getInstFlags() & kX86InstFlagXchg) != 0; + } + + //! Get whether the instruction accesses Fp register(s). + ASMJIT_INLINE bool isFp() const { + return (getInstFlags() & kX86InstFlagFp) != 0; + } + + //! Get whether the instruction can be prefixed by LOCK prefix. + ASMJIT_INLINE bool isLockable() const { + return (getInstFlags() & kX86InstFlagLock) != 0; + } + + //! Get whether the instruction is special type (this is used by `Compiler` + //! to manage additional variables or functionality). + ASMJIT_INLINE bool isSpecial() const { + return (getInstFlags() & kX86InstFlagSpecial) != 0; + } + + //! Get whether the instruction is special type and it performs memory access. + ASMJIT_INLINE bool isSpecialMem() const { + return (getInstFlags() & kX86InstFlagSpecialMem) != 0; + } + + //! Get whether the move instruction zeroes the rest of the register + //! if the source is memory operand. + //! + //! Basically flag needed only to support `movsd` and `movss` instructions. + ASMJIT_INLINE bool isZeroIfMem() const { + return (getInstFlags() & kX86InstFlagZ) != 0; + } + + // -------------------------------------------------------------------------- + // [Accessors - EFlags] + // -------------------------------------------------------------------------- + + //! Get EFLAGS that the instruction reads, see \ref kX86EFlags. + ASMJIT_INLINE uint32_t getEFlagsIn() const { + return _eflagsIn; + } + + //! Get EFLAGS that the instruction writes, see \ref kX86EFlags. + ASMJIT_INLINE uint32_t getEFlagsOut() const { + return _eflagsOut; + } + + // -------------------------------------------------------------------------- + // [Accessors - Write Index/Size] + // -------------------------------------------------------------------------- + + //! Get the destination index of WRITE operation. + ASMJIT_INLINE uint32_t getWriteIndex() const { + return _writeIndex; + } + + //! Get the number of bytes that will be written by a WRITE operation. + ASMJIT_INLINE uint32_t getWriteSize() const { + return _writeSize; + } + + // -------------------------------------------------------------------------- + // [Accessors - Operand-Flags] + // -------------------------------------------------------------------------- + + //! Get flags of operand at index `index`. + //! + //! See \ref X86InstInfo::getOperandFlags() for more details. + ASMJIT_INLINE uint16_t getOperandFlags(uint32_t index) const { + ASMJIT_ASSERT(index < ASMJIT_ARRAY_SIZE(_opFlags)); + return _opFlags[index]; + } + + // -------------------------------------------------------------------------- + // [Accessors - OpCode] + // -------------------------------------------------------------------------- + + //! Get the secondary instruction opcode, see \ref kX86InstOpCode. + //! + //! See \ref X86InstInfo::getSecondaryOpCode() for more details. + ASMJIT_INLINE uint32_t getSecondaryOpCode() const { + return _secondaryOpCode; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Instruction encoding ID. + uint8_t _encodingId; + + //! Destination index of WRITE operation, default 0. + uint8_t _writeIndex; + + //! Count of bytes affected by a write operation, needed by analysis for all + //! instructions that do not read the register overwritten. Only used with + //! `kX86InstFlagMove` flag. If `_writeSize` is zero it is automatically + //! deduced from the size of the destination register. + //! + //! In general most of SSE write-only instructions should use 16 bytes as + //! this is the size of the register (and of Ymm/Zmm registers). This means + //! that 16-bytes of the register are changed, the rest remains unchanged. + //! However, AVX instructions should use the size of Zmm register as every + //! AVX instruction zeroes the rest of the register (AVX/AVX2 instructions + //! zero the HI part of Zmm if available). + uint8_t _writeSize; + + //! EFlags read by the instruction. + uint8_t _eflagsIn; + //! EFlags written by the instruction. + uint8_t _eflagsOut; + + //! \internal + uint8_t _reserved; + + //! Operands' flags, up to 5 operands. + uint16_t _opFlags[5]; + + //! Instruction flags. + uint32_t _instFlags; + + //! Secondary opcode. + uint32_t _secondaryOpCode; +}; + +// ============================================================================ +// [asmjit::X86InstInfo] +// ============================================================================ + +//! X86/X64 instruction information. +struct X86InstInfo { + // -------------------------------------------------------------------------- + // [Accessors - Instruction Name] + // -------------------------------------------------------------------------- + +#if !defined(ASMJIT_DISABLE_NAMES) + //! Get instruction name string (null terminated). + ASMJIT_INLINE const char* getInstName() const { + return _x86InstName + static_cast(_nameIndex); + } + + //! Get instruction name index to `_x86InstName` array. + ASMJIT_INLINE uint32_t _getNameIndex() const { + return _nameIndex; + } +#endif // !ASMJIT_DISABLE_NAMES + + // -------------------------------------------------------------------------- + // [Accessors - Extended-Info] + // -------------------------------------------------------------------------- + + //! Get `X86InstExtendedInfo` for this instruction. + ASMJIT_INLINE const X86InstExtendedInfo& getExtendedInfo() const { + return _x86InstExtendedInfo[_extendedIndex]; + } + + //! Get index to the `_x86InstExtendedInfo` table. + ASMJIT_INLINE uint32_t _getExtendedIndex() const { + return _extendedIndex; + } + + // -------------------------------------------------------------------------- + // [Accessors - Instruction Encoding] + // -------------------------------------------------------------------------- + + //! Get instruction group, see \ref kX86InstEncodingId. + ASMJIT_INLINE uint32_t getEncodingId() const { + return getExtendedInfo().getEncodingId(); + } + + // -------------------------------------------------------------------------- + // [Accessors - Instruction Flags] + // -------------------------------------------------------------------------- + + //! Get instruction flags, see `kX86InstFlags`. + ASMJIT_INLINE uint32_t getInstFlags() const { + return getExtendedInfo().getInstFlags(); + } + + //! Get whether the instruction has flag `flag`, see `kX86InstFlags`. + ASMJIT_INLINE bool hasInstFlag(uint32_t flag) const { + return (getInstFlags() & flag) != 0; + } + + // -------------------------------------------------------------------------- + // [Accessors - EFlags] + // -------------------------------------------------------------------------- + + //! Get EFLAGS that the instruction reads, see \ref kX86EFlags. + ASMJIT_INLINE uint32_t getEFlagsIn() const { + return getExtendedInfo().getEFlagsIn(); + } + + //! Get EFLAGS that the instruction writes, see \ref kX86EFlags. + ASMJIT_INLINE uint32_t getEFlagsOut() const { + return getExtendedInfo().getEFlagsOut(); + } + + // -------------------------------------------------------------------------- + // [Accessors - Write Index/Size] + // -------------------------------------------------------------------------- + + //! Get the destination index of WRITE operation. + ASMJIT_INLINE uint32_t getWriteIndex() const { + return getExtendedInfo().getWriteIndex(); + } + + //! Get the number of bytes that will be written by a WRITE operation. + ASMJIT_INLINE uint32_t getWriteSize() const { + return getExtendedInfo().getWriteSize(); + } + + // -------------------------------------------------------------------------- + // [Accessors - Operand-Flags] + // -------------------------------------------------------------------------- + + //! Get flags of operand at index `index`. + ASMJIT_INLINE uint32_t getOperandFlags(uint32_t index) const { + return getExtendedInfo().getOperandFlags(index); + } + + // -------------------------------------------------------------------------- + // [Accessors - OpCode] + // -------------------------------------------------------------------------- + + //! Get the primary instruction opcode, see \ref kX86InstOpCode. + ASMJIT_INLINE uint32_t getPrimaryOpCode() const { + return _primaryOpCode; + } + + //! Get the secondary instruction opcode, see \ref kX86InstOpCode. + ASMJIT_INLINE uint32_t getSecondaryOpCode() const { + return getExtendedInfo().getSecondaryOpCode(); + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Instruction name index in `_x86InstName[]` array. + uint16_t _nameIndex; + //! Extended information name index in `_x86InstExtendedInfo[]` array. + uint16_t _extendedIndex; + + //! Primary opcode, secondary opcode is stored in `X86InstExtendedInfo` table. + uint32_t _primaryOpCode; +}; + +// ============================================================================ +// [asmjit::X86Util] +// ============================================================================ + +struct X86Util { + // -------------------------------------------------------------------------- + // [Instruction Info] + // -------------------------------------------------------------------------- + + //! Get instruction information based on `instId`. + //! + //! \note `instId` has to be valid instruction ID, it can't be greater than + //! or equal to `_kX86InstIdCount`. It asserts in debug mode. + static ASMJIT_INLINE const X86InstInfo& getInstInfo(uint32_t instId) { + ASMJIT_ASSERT(instId < _kX86InstIdCount); + return _x86InstInfo[instId]; + } + +#if !defined(ASMJIT_DISABLE_NAMES) + //! Get an instruction ID from a given instruction `name`. + //! + //! If there is an exact match the instruction id is returned, otherwise + //! `kInstIdNone` (zero) is returned. + //! + //! The given `name` doesn't have to be null-terminated if `len` is provided. + ASMJIT_API static uint32_t getInstIdByName( + const char* name, size_t len = kInvalidIndex); +#endif // !ASMJIT_DISABLE_NAMES + + // -------------------------------------------------------------------------- + // [Condition Codes] + // -------------------------------------------------------------------------- + + //! Corresponds to transposing the operands of a comparison. + static ASMJIT_INLINE uint32_t reverseCond(uint32_t cond) { + ASMJIT_ASSERT(cond < ASMJIT_ARRAY_SIZE(_x86ReverseCond)); + return _x86ReverseCond[cond]; + } + + //! Get the equivalent of negated condition code. + static ASMJIT_INLINE uint32_t negateCond(uint32_t cond) { + ASMJIT_ASSERT(cond < ASMJIT_ARRAY_SIZE(_x86ReverseCond)); + return static_cast(cond ^ static_cast(cond < kX86CondNone)); + } + + //! Translate condition code `cc` to `cmovcc` instruction code. + //! \sa \ref kX86InstId, \ref _kX86InstIdCmovcc. + static ASMJIT_INLINE uint32_t condToCmovcc(uint32_t cond) { + ASMJIT_ASSERT(static_cast(cond) < ASMJIT_ARRAY_SIZE(_x86CondToCmovcc)); + return _x86CondToCmovcc[cond]; + } + + //! Translate condition code `cc` to `jcc` instruction code. + //! \sa \ref kX86InstId, \ref _kX86InstIdJcc. + static ASMJIT_INLINE uint32_t condToJcc(uint32_t cond) { + ASMJIT_ASSERT(static_cast(cond) < ASMJIT_ARRAY_SIZE(_x86CondToJcc)); + return _x86CondToJcc[cond]; + } + + //! Translate condition code `cc` to `setcc` instruction code. + //! \sa \ref kX86InstId, \ref _kX86InstIdSetcc. + static ASMJIT_INLINE uint32_t condToSetcc(uint32_t cond) { + ASMJIT_ASSERT(static_cast(cond) < ASMJIT_ARRAY_SIZE(_x86CondToSetcc)); + return _x86CondToSetcc[cond]; + } + + // -------------------------------------------------------------------------- + // [MmShuffle] + // -------------------------------------------------------------------------- + + //! Pack a shuffle constant to be used with multimedia instrutions (2 values). + //! + //! \param x First component position, number at interval [0, 1] inclusive. + //! \param y Second component position, number at interval [0, 1] inclusive. + //! + //! Shuffle constants can be used to make immediate value for these intrinsics: + //! - `X86Assembler::shufpd()` and `X86Compiler::shufpd()` + static ASMJIT_INLINE int mmShuffle(uint32_t x, uint32_t y) { + return static_cast((x << 1) | y); + } + + //! Pack a shuffle constant to be used with multimedia instrutions (4 values). + //! + //! \param z First component position, number at interval [0, 3] inclusive. + //! \param x Second component position, number at interval [0, 3] inclusive. + //! \param y Third component position, number at interval [0, 3] inclusive. + //! \param w Fourth component position, number at interval [0, 3] inclusive. + //! + //! Shuffle constants can be used to make immediate value for these intrinsics: + //! - `X86Assembler::pshufw()` and `X86Compiler::pshufw()` + //! - `X86Assembler::pshufd()` and `X86Compiler::pshufd()` + //! - `X86Assembler::pshufhw()` and `X86Compiler::pshufhw()` + //! - `X86Assembler::pshuflw()` and `X86Compiler::pshuflw()` + //! - `X86Assembler::shufps()` and `X86Compiler::shufps()` + static ASMJIT_INLINE int mmShuffle(uint32_t z, uint32_t y, uint32_t x, uint32_t w) { + return static_cast((z << 6) | (y << 4) | (x << 2) | w); + } +}; + +//! \} + +} // asmjit namespace + +#undef _OP_ID + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // _ASMJIT_X86_X86INST_H diff --git a/third/Blackbone/src/3rd_party/AsmJit/x86/x86operand.cpp b/third/Blackbone/src/3rd_party/AsmJit/x86/x86operand.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e300ee940824c1226a7b93239d97ee3d0c33408 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/x86/x86operand.cpp @@ -0,0 +1,85 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Guard] +#include "../build.h" +#if defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64) + +// [Dependencies - AsmJit] +#include "../x86/x86operand.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { +namespace x86 { + +// ============================================================================ +// [asmjit::X86Mem - abs[]] +// ============================================================================ + +X86Mem ptr_abs(Ptr pAbs, int32_t disp, uint32_t size) { + X86Mem m(NoInit); + + m._init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeAbsolute, 0, kInvalidValue); + m._vmem.index = kInvalidValue; + m._vmem.displacement = static_cast((intptr_t)(pAbs + disp)); + + return m; +} + +X86Mem ptr_abs(Ptr pAbs, const X86Reg& index, uint32_t shift, int32_t disp, uint32_t size) { + X86Mem m(NoInit); + uint32_t flags = shift << kX86MemShiftIndex; + + if (index.isGp()) + flags |= X86Mem::_getGpdFlags(index); + else if (index.isXmm()) + flags |= kX86MemVSibXmm << kX86MemVSibIndex; + else if (index.isYmm()) + flags |= kX86MemVSibYmm << kX86MemVSibIndex; + + m._init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeAbsolute, flags, kInvalidValue); + m._vmem.index = index.getRegIndex(); + m._vmem.displacement = static_cast((intptr_t)(pAbs + disp)); + + return m; +} + +#if !defined(ASMJIT_DISABLE_COMPILER) +X86Mem ptr_abs(Ptr pAbs, const X86Var& index, uint32_t shift, int32_t disp, uint32_t size) { + X86Mem m(NoInit); + uint32_t flags = shift << kX86MemShiftIndex; + + const Var& index_ = reinterpret_cast(index); + uint32_t indexRegType = index_.getRegType(); + + if (indexRegType <= kX86RegTypeGpq) + flags |= X86Mem::_getGpdFlags(reinterpret_cast(index)); + else if (indexRegType == kX86RegTypeXmm) + flags |= kX86MemVSibXmm << kX86MemVSibIndex; + else if (indexRegType == kX86RegTypeYmm) + flags |= kX86MemVSibYmm << kX86MemVSibIndex; + + m._init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeAbsolute, flags, kInvalidValue); + m._vmem.index = index_.getId(); + m._vmem.displacement = static_cast((intptr_t)(pAbs + disp)); + + return m; +} +#endif // !ASMJIT_DISABLE_COMPILER + +} // x86 namespace +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64 diff --git a/third/Blackbone/src/3rd_party/AsmJit/x86/x86operand.h b/third/Blackbone/src/3rd_party/AsmJit/x86/x86operand.h new file mode 100644 index 0000000000000000000000000000000000000000..9d9cedc173a95e12cbdda16eb1babe95261e2c69 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/x86/x86operand.h @@ -0,0 +1,1974 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Guard] +#ifndef _ASMJIT_X86_X86OPERAND_H +#define _ASMJIT_X86_X86OPERAND_H + +// [Dependencies - AsmJit] +#include "../base/assembler.h" +#include "../base/compiler.h" +#include "../base/globals.h" +#include "../base/intutil.h" +#include "../base/operand.h" +#include "../base/vectypes.h" + +// [Api-Begin] +#include "../apibegin.h" + +//! \internal +//! +//! Internal macro to get an operand ID casting it to `Operand`. Basically +//! allows to get an id of operand that has been just 'typedef'ed. +#define ASMJIT_OP_ID(_Op_) reinterpret_cast(_Op_).getId() + +namespace asmjit { + +// ============================================================================ +// [Forward Declarations] +// ============================================================================ + +struct X86Reg; +struct X86RipReg; +struct X86SegReg; +struct X86GpReg; +struct X86FpReg; +struct X86MmReg; +struct X86KReg; +struct X86XmmReg; +struct X86YmmReg; +struct X86ZmmReg; + +#if !defined(ASMJIT_DISABLE_COMPILER) +struct X86Var; +struct X86GpVar; +struct X86MmVar; +struct X86KVar; +struct X86XmmVar; +struct X86YmmVar; +struct X86ZmmVar; +#endif // !ASMJIT_DISABLE_COMPILER + +//! \addtogroup asmjit_x86_general +//! \{ + +// ============================================================================ +// [asmjit::kX86RegClass] +// ============================================================================ + +//! X86/X64 variable class. +ASMJIT_ENUM(kX86RegClass) { + // -------------------------------------------------------------------------- + // [Regs & Vars] + // -------------------------------------------------------------------------- + + //! X86/X64 Gp register class (compatible with universal \ref kRegClassGp). + kX86RegClassGp = kRegClassGp, + //! X86/X64 Mm register class. + kX86RegClassMm = 1, + //! X86/X64 K register class. + kX86RegClassK = 2, + //! X86/X64 Xmm/Ymm/Zmm register class. + kX86RegClassXyz = 3, + + //! \internal + //! + //! Last register class that is managed by `X86Compiler`, used by asserts. + _kX86RegClassManagedCount = 4, + + // -------------------------------------------------------------------------- + // [Regs Only] + // -------------------------------------------------------------------------- + + //! X86/X64 Fp register class. + kX86RegClassFp = 4, + + //! Count of X86/X64 register classes. + kX86RegClassCount = 5 +}; + +// ============================================================================ +// [asmjit::kX86RegType] +// ============================================================================ + +//! X86/X64 register type. +ASMJIT_ENUM(kX86RegType) { + //! Gpb-lo register (AL, BL, CL, DL, ...). + kX86RegTypeGpbLo = 0x01, + //! Gpb-hi register (AH, BH, CH, DH only). + kX86RegTypeGpbHi = 0x02, + + //! \internal + //! + //! Gpb-hi register patched to native index (4-7). + _kX86RegTypePatchedGpbHi = kX86RegTypeGpbLo | kX86RegTypeGpbHi, + + //! Gpw register. + kX86RegTypeGpw = 0x10, + //! Gpd register. + kX86RegTypeGpd = 0x20, + //! Gpq register (X64). + kX86RegTypeGpq = 0x30, + + //! Fp register. + kX86RegTypeFp = 0x40, + //! Mm register (MMX+). + kX86RegTypeMm = 0x50, + + //! K register (AVX512+). + kX86RegTypeK = 0x60, + + //! Xmm register (SSE+). + kX86RegTypeXmm = 0x70, + //! Ymm register (AVX+). + kX86RegTypeYmm = 0x80, + //! Zmm register (AVX512+). + kX86RegTypeZmm = 0x90, + + //! Instruction pointer (RIP). + kX86RegTypeRip = 0xE0, + //! Segment register. + kX86RegTypeSeg = 0xF0 +}; + +// ============================================================================ +// [asmjit::kX86RegIndex] +// ============================================================================ + +//! X86/X64 register indexes. +//! +//! \note Register indexes have been reduced to only support general purpose +//! registers. There is no need to have enumerations with number suffix that +//! expands to the exactly same value as the suffix value itself. +ASMJIT_ENUM(kX86RegIndex) { + //! Index of Al/Ah/Ax/Eax/Rax registers. + kX86RegIndexAx = 0, + //! Index of Cl/Ch/Cx/Ecx/Rcx registers. + kX86RegIndexCx = 1, + //! Index of Dl/Dh/Dx/Edx/Rdx registers. + kX86RegIndexDx = 2, + //! Index of Bl/Bh/Bx/Ebx/Rbx registers. + kX86RegIndexBx = 3, + //! Index of Spl/Sp/Esp/Rsp registers. + kX86RegIndexSp = 4, + //! Index of Bpl/Bp/Ebp/Rbp registers. + kX86RegIndexBp = 5, + //! Index of Sil/Si/Esi/Rsi registers. + kX86RegIndexSi = 6, + //! Index of Dil/Di/Edi/Rdi registers. + kX86RegIndexDi = 7, + //! Index of R8b/R8w/R8d/R8 registers (64-bit only). + kX86RegIndexR8 = 8, + //! Index of R9B/R9w/R9d/R9 registers (64-bit only). + kX86RegIndexR9 = 9, + //! Index of R10B/R10w/R10D/R10 registers (64-bit only). + kX86RegIndexR10 = 10, + //! Index of R11B/R11w/R11d/R11 registers (64-bit only). + kX86RegIndexR11 = 11, + //! Index of R12B/R12w/R12d/R12 registers (64-bit only). + kX86RegIndexR12 = 12, + //! Index of R13B/R13w/R13d/R13 registers (64-bit only). + kX86RegIndexR13 = 13, + //! Index of R14B/R14w/R14d/R14 registers (64-bit only). + kX86RegIndexR14 = 14, + //! Index of R15B/R15w/R15d/R15 registers (64-bit only). + kX86RegIndexR15 = 15 +}; + +// ============================================================================ +// [asmjit::kX86Seg] +// ============================================================================ + +//! X86/X64 segment codes. +ASMJIT_ENUM(kX86Seg) { + //! No/Default segment. + kX86SegDefault = 0, + //! Es segment. + kX86SegEs = 1, + //! Cs segment. + kX86SegCs = 2, + //! Ss segment. + kX86SegSs = 3, + //! Ds segment. + kX86SegDs = 4, + //! Fs segment. + kX86SegFs = 5, + //! Gs segment. + kX86SegGs = 6, + + //! Count of X86 segment registers supported by AsmJit. + //! + //! \note X86 architecture has 6 segment registers - ES, CS, SS, DS, FS, GS. + //! X64 architecture lowers them down to just FS and GS. AsmJit supports 7 + //! segment registers - all addressable in both X86 and X64 modes and one + //! extra called `kX86SegDefault`, which is AsmJit specific and means that there + //! is no segment register specified so the segment prefix will not be emitted. + kX86SegCount = 7 +}; + +// ============================================================================ +// [asmjit::kX86MemVSib] +// ============================================================================ + +//! X86/X64 index register legacy and AVX2 (VSIB) support. +ASMJIT_ENUM(kX86MemVSib) { + //! Memory operand uses Gpd/Gpq index (or no index register). + kX86MemVSibGpz = 0, + //! Memory operand uses Xmm index (or no index register). + kX86MemVSibXmm = 1, + //! Memory operand uses Ymm index (or no index register). + kX86MemVSibYmm = 2, + //! Memory operand uses Zmm index (or no index register). + kX86MemVSibZmm = 3 +}; + +// ============================================================================ +// [asmjit::kX86MemFlags] +// ============================================================================ + +//! \internal +//! +//! X86/X64 specific memory flags. +ASMJIT_ENUM(kX86MemFlags) { + kX86MemSegBits = 0x7, + kX86MemSegIndex = 0, + kX86MemSegMask = kX86MemSegBits << kX86MemSegIndex, + + kX86MemGpdBits = 0x1, + kX86MemGpdIndex = 3, + kX86MemGpdMask = kX86MemGpdBits << kX86MemGpdIndex, + + kX86MemVSibBits = 0x3, + kX86MemVSibIndex = 4, + kX86MemVSibMask = kX86MemVSibBits << kX86MemVSibIndex, + + kX86MemShiftBits = 0x3, + kX86MemShiftIndex = 6, + kX86MemShiftMask = kX86MemShiftBits << kX86MemShiftIndex +}; + +// This is only defined by `x86operand_regs.cpp` when exporting registers. +#if defined(ASMJIT_EXPORTS_X86OPERAND_REGS) + +// Remap all classes to POD structs so they can be statically initialized +// without calling a constructor. Compiler will store these in .DATA section. +struct X86RipReg { Operand::VRegOp data; }; +struct X86SegReg { Operand::VRegOp data; }; +struct X86GpReg { Operand::VRegOp data; }; +struct X86FpReg { Operand::VRegOp data; }; +struct X86KReg { Operand::VRegOp data; }; +struct X86MmReg { Operand::VRegOp data; }; +struct X86XmmReg { Operand::VRegOp data; }; +struct X86YmmReg { Operand::VRegOp data; }; +struct X86ZmmReg { Operand::VRegOp data; }; + +#else + +// ============================================================================ +// [asmjit::X86RegCount] +// ============================================================================ + +//! \internal +//! +//! X86/X64 registers count (Gp, Mm, K, Xmm/Ymm/Zmm). +//! +//! Since the number of registers changed across CPU generations `X86RegCount` +//! class is used by `X86Assembler` and `X86Compiler` to provide a way to get +//! number of available registers dynamically. 32-bit mode offers always only +//! 8 registers of all classes, however, 64-bit mode offers 16 Gp registers and +//! 16 Xmm/Ymm/Zmm registers. AVX512 instruction set doubles the number of SIMD +//! registers (Xmm/Ymm/Zmm) to 32, this mode has to be explicitly enabled to +//! take effect as it changes some assumptions. +//! +//! `X86RegCount` is also used extensively by `X86Compiler`'s register allocator +//! and data structures. Fp registers were omitted as they are never mapped to +//! variables, thus, not needed to be managed. +//! +//! \note At the moment `X86RegCount` can fit into 32-bits, having 8-bits for +//! all register classes (except Fp). This can change in the future after a +//! new instruction set is announced. +struct X86RegCount { + // -------------------------------------------------------------------------- + // [Zero] + // -------------------------------------------------------------------------- + + //! Reset all counters to zero. + ASMJIT_INLINE void reset() { + _packed = 0; + } + + // -------------------------------------------------------------------------- + // [Get] + // -------------------------------------------------------------------------- + + //! Get register count by `classId`. + ASMJIT_INLINE uint32_t get(uint32_t classId) const { + ASMJIT_ASSERT(classId < _kX86RegClassManagedCount); + return _regs[classId]; + } + + //! Get Gp register count. + ASMJIT_INLINE uint32_t getGp() const { return _regs[kX86RegClassGp]; } + //! Get Mm register count. + ASMJIT_INLINE uint32_t getMm() const { return _regs[kX86RegClassMm]; } + //! Get K register count. + ASMJIT_INLINE uint32_t getK() const { return _regs[kX86RegClassK]; } + //! Get Xmm/Ymm/Zmm register count. + ASMJIT_INLINE uint32_t getXyz() const { return _regs[kX86RegClassXyz]; } + + // -------------------------------------------------------------------------- + // [Set] + // -------------------------------------------------------------------------- + + //! Set register count by `classId`. + ASMJIT_INLINE void set(uint32_t classId, uint32_t n) { + ASMJIT_ASSERT(classId < _kX86RegClassManagedCount); + ASMJIT_ASSERT(n <= 0xFF); + + _regs[classId] = static_cast(n); + } + + //! Set Gp register count. + ASMJIT_INLINE void setGp(uint32_t n) { set(kX86RegClassGp, n); } + //! Set Mm register count. + ASMJIT_INLINE void setMm(uint32_t n) { set(kX86RegClassMm, n); } + //! Set K register count. + ASMJIT_INLINE void setK(uint32_t n) { set(kX86RegClassK, n); } + //! Set Xmm/Ymm/Zmm register count. + ASMJIT_INLINE void setXyz(uint32_t n) { set(kX86RegClassXyz, n); } + + // -------------------------------------------------------------------------- + // [Add] + // -------------------------------------------------------------------------- + + //! Add register count by `classId`. + ASMJIT_INLINE void add(uint32_t classId, uint32_t n = 1) { + ASMJIT_ASSERT(classId < _kX86RegClassManagedCount); + ASMJIT_ASSERT(0xFF - static_cast(_regs[classId]) >= n); + + _regs[classId] += static_cast(n); + } + + //! Add Gp register count. + ASMJIT_INLINE void addGp(uint32_t n) { add(kX86RegClassGp, n); } + //! Add Mm register count. + ASMJIT_INLINE void addMm(uint32_t n) { add(kX86RegClassMm, n); } + //! Add K register count. + ASMJIT_INLINE void addK(uint32_t n) { add(kX86RegClassK, n); } + //! Add Xmm/Ymm/Zmm register count. + ASMJIT_INLINE void addXyz(uint32_t n) { add(kX86RegClassXyz, n); } + + // -------------------------------------------------------------------------- + // [Misc] + // -------------------------------------------------------------------------- + + //! Build a register indexes, based on register's `count`. + //! + //! Register index is used by \ref `X86Compiler` in per-instruction register + //! data. Indexes are sorted by register class in Gp, Mm, K, and Xmm/Ymm/Zmm + //! order. + ASMJIT_INLINE void indexFromRegCount(const X86RegCount& count) { + uint32_t x = count._regs[0]; + uint32_t y; + + _regs[0] = static_cast(0); + _regs[1] = static_cast(x); + + x = x + count._regs[1]; + y = x + count._regs[2]; + + ASMJIT_ASSERT(x <= 0xFF); + ASMJIT_ASSERT(y <= 0xFF); + + _regs[2] = static_cast(x); + _regs[3] = static_cast(y); + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + union { + struct { + //! Count of Gp registers. + uint8_t _gp; + //! Count of Mm registers. + uint8_t _mm; + //! Count of K registers. + uint8_t _k; + //! Count of Xmm/Ymm/Zmm registers. + uint8_t _xyz; + //! \internal + uint8_t _reserved[3]; + }; + + uint8_t _regs[4]; + uint32_t _packed; + }; +}; + +// ============================================================================ +// [asmjit::X86RegMask] +// ============================================================================ + +//! \internal +//! +//! X86/X64 registers mask (Gp, Mm, K, Xmm/Ymm/Zmm). +struct X86RegMask { + // -------------------------------------------------------------------------- + // [Reset] + // -------------------------------------------------------------------------- + + //! Reset all register masks to zero. + ASMJIT_INLINE void reset() { + _packed.reset(); + } + + // -------------------------------------------------------------------------- + // [IsEmpty / Has] + // -------------------------------------------------------------------------- + + //! Get whether all register masks are zero (empty). + ASMJIT_INLINE bool isEmpty() const { + return _packed.isZero(); + } + + ASMJIT_INLINE bool has(uint32_t classId, uint32_t mask = 0xFFFFFFFF) const { + ASMJIT_ASSERT(classId < _kX86RegClassManagedCount); + + switch (classId) { + case kX86RegClassGp : return (static_cast(_gp ) & mask) != 0; + case kX86RegClassMm : return (static_cast(_mm ) & mask) != 0; + case kX86RegClassK : return (static_cast(_k ) & mask) != 0; + case kX86RegClassXyz: return (static_cast(_xyz) & mask) != 0; + } + + return false; + } + + ASMJIT_INLINE bool hasGp(uint32_t mask = 0xFFFFFFFF) const { return has(kX86RegClassGp, mask); } + ASMJIT_INLINE bool hasMm(uint32_t mask = 0xFFFFFFFF) const { return has(kX86RegClassMm, mask); } + ASMJIT_INLINE bool hasK(uint32_t mask = 0xFFFFFFFF) const { return has(kX86RegClassK, mask); } + ASMJIT_INLINE bool hasXyz(uint32_t mask = 0xFFFFFFFF) const { return has(kX86RegClassXyz, mask); } + + // -------------------------------------------------------------------------- + // [Get] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE uint32_t get(uint32_t classId) const { + ASMJIT_ASSERT(classId < _kX86RegClassManagedCount); + + switch (classId) { + case kX86RegClassGp : return _gp; + case kX86RegClassMm : return _mm; + case kX86RegClassK : return _k; + case kX86RegClassXyz: return _xyz; + } + + return 0; + } + + ASMJIT_INLINE uint32_t getGp() const { return get(kX86RegClassGp); } + ASMJIT_INLINE uint32_t getMm() const { return get(kX86RegClassMm); } + ASMJIT_INLINE uint32_t getK() const { return get(kX86RegClassK); } + ASMJIT_INLINE uint32_t getXyz() const { return get(kX86RegClassXyz); } + + // -------------------------------------------------------------------------- + // [Zero] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE void zero(uint32_t classId) { + ASMJIT_ASSERT(classId < _kX86RegClassManagedCount); + + switch (classId) { + case kX86RegClassGp : _gp = 0; break; + case kX86RegClassMm : _mm = 0; break; + case kX86RegClassK : _k = 0; break; + case kX86RegClassXyz: _xyz = 0; break; + } + } + + ASMJIT_INLINE void zeroGp() { zero(kX86RegClassGp); } + ASMJIT_INLINE void zeroMm() { zero(kX86RegClassMm); } + ASMJIT_INLINE void zeroK() { zero(kX86RegClassK); } + ASMJIT_INLINE void zeroXyz() { zero(kX86RegClassXyz); } + + // -------------------------------------------------------------------------- + // [Set] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE void set(const X86RegMask& other) { + _packed = other._packed; + } + + ASMJIT_INLINE void set(uint32_t classId, uint32_t mask) { + ASMJIT_ASSERT(classId < _kX86RegClassManagedCount); + + switch (classId) { + case kX86RegClassGp : _gp = static_cast(mask); break; + case kX86RegClassMm : _mm = static_cast(mask); break; + case kX86RegClassK : _k = static_cast(mask); break; + case kX86RegClassXyz: _xyz = static_cast(mask); break; + } + } + + ASMJIT_INLINE void setGp(uint32_t mask) { return set(kX86RegClassGp, mask); } + ASMJIT_INLINE void setMm(uint32_t mask) { return set(kX86RegClassMm, mask); } + ASMJIT_INLINE void setK(uint32_t mask) { return set(kX86RegClassK, mask); } + ASMJIT_INLINE void setXyz(uint32_t mask) { return set(kX86RegClassXyz, mask); } + + // -------------------------------------------------------------------------- + // [And] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE void and_(const X86RegMask& other) { + _packed.and_(other._packed); + } + + ASMJIT_INLINE void and_(uint32_t classId, uint32_t mask) { + ASMJIT_ASSERT(classId < _kX86RegClassManagedCount); + + switch (classId) { + case kX86RegClassGp : _gp &= static_cast(mask); break; + case kX86RegClassMm : _mm &= static_cast(mask); break; + case kX86RegClassK : _k &= static_cast(mask); break; + case kX86RegClassXyz: _xyz &= static_cast(mask); break; + } + } + + ASMJIT_INLINE void andGp(uint32_t mask) { and_(kX86RegClassGp, mask); } + ASMJIT_INLINE void andMm(uint32_t mask) { and_(kX86RegClassMm, mask); } + ASMJIT_INLINE void andK(uint32_t mask) { and_(kX86RegClassK, mask); } + ASMJIT_INLINE void andXyz(uint32_t mask) { and_(kX86RegClassXyz, mask); } + + // -------------------------------------------------------------------------- + // [AndNot] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE void andNot(const X86RegMask& other) { + _packed.andNot(other._packed); + } + + ASMJIT_INLINE void andNot(uint32_t classId, uint32_t mask) { + ASMJIT_ASSERT(classId < _kX86RegClassManagedCount); + + switch (classId) { + case kX86RegClassGp : _gp &= ~static_cast(mask); break; + case kX86RegClassMm : _mm &= ~static_cast(mask); break; + case kX86RegClassK : _k &= ~static_cast(mask); break; + case kX86RegClassXyz: _xyz &= ~static_cast(mask); break; + } + } + + ASMJIT_INLINE void andNotGp(uint32_t mask) { andNot(kX86RegClassGp, mask); } + ASMJIT_INLINE void andNotMm(uint32_t mask) { andNot(kX86RegClassMm, mask); } + ASMJIT_INLINE void andNotK(uint32_t mask) { andNot(kX86RegClassK, mask); } + ASMJIT_INLINE void andNotXyz(uint32_t mask) { andNot(kX86RegClassXyz, mask); } + + // -------------------------------------------------------------------------- + // [Or] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE void or_(const X86RegMask& other) { + _packed.or_(other._packed); + } + + ASMJIT_INLINE void or_(uint32_t classId, uint32_t mask) { + ASMJIT_ASSERT(classId < _kX86RegClassManagedCount); + switch (classId) { + case kX86RegClassGp : _gp |= static_cast(mask); break; + case kX86RegClassMm : _mm |= static_cast(mask); break; + case kX86RegClassK : _k |= static_cast(mask); break; + case kX86RegClassXyz: _xyz |= static_cast(mask); break; + } + } + + ASMJIT_INLINE void orGp(uint32_t mask) { return or_(kX86RegClassGp, mask); } + ASMJIT_INLINE void orMm(uint32_t mask) { return or_(kX86RegClassMm, mask); } + ASMJIT_INLINE void orK(uint32_t mask) { return or_(kX86RegClassK, mask); } + ASMJIT_INLINE void orXyz(uint32_t mask) { return or_(kX86RegClassXyz, mask); } + + // -------------------------------------------------------------------------- + // [Xor] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE void xor_(const X86RegMask& other) { + _packed.xor_(other._packed); + } + + ASMJIT_INLINE void xor_(uint32_t classId, uint32_t mask) { + ASMJIT_ASSERT(classId < _kX86RegClassManagedCount); + + switch (classId) { + case kX86RegClassGp : _gp ^= static_cast(mask); break; + case kX86RegClassMm : _mm ^= static_cast(mask); break; + case kX86RegClassK : _k ^= static_cast(mask); break; + case kX86RegClassXyz: _xyz ^= static_cast(mask); break; + } + } + + ASMJIT_INLINE void xorGp(uint32_t mask) { xor_(kX86RegClassGp, mask); } + ASMJIT_INLINE void xorMm(uint32_t mask) { xor_(kX86RegClassMm, mask); } + ASMJIT_INLINE void xorK(uint32_t mask) { xor_(kX86RegClassK, mask); } + ASMJIT_INLINE void xorXyz(uint32_t mask) { xor_(kX86RegClassXyz, mask); } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + union { + struct { + //! Gp registers mask (16 bits). + uint16_t _gp; + //! Mm registers mask (8 bits). + uint8_t _mm; + //! K registers mask (8 bits). + uint8_t _k; + //! Xmm/Ymm/Zmm registers mask (32 bits). + uint32_t _xyz; + }; + + //! Packed masks. + UInt64 _packed; + }; +}; + +// ============================================================================ +// [asmjit::X86Reg] +// ============================================================================ + +//! X86/X86 register base class. +struct X86Reg : public Reg { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a dummy X86 register. + ASMJIT_INLINE X86Reg() : Reg() {} + //! Create a reference to `other` X86 register. + ASMJIT_INLINE X86Reg(const X86Reg& other) : Reg(other) {} + //! Create a reference to `other` X86 register and change the index to `index`. + ASMJIT_INLINE X86Reg(const X86Reg& other, uint32_t index) : Reg(other, index) {} + //! Create a custom X86 register. + ASMJIT_INLINE X86Reg(uint32_t type, uint32_t index, uint32_t size) : Reg(type, index, size) {} + //! Create non-initialized X86 register. + explicit ASMJIT_INLINE X86Reg(const _NoInit&) : Reg(NoInit) {} + + // -------------------------------------------------------------------------- + // [X86Reg Specific] + // -------------------------------------------------------------------------- + + ASMJIT_REG_OP(X86Reg) + + //! Get whether the register is Gp register. + ASMJIT_INLINE bool isGp() const { return _vreg.type <= kX86RegTypeGpq; } + //! Get whether the register is Gp byte (8-bit) register. + ASMJIT_INLINE bool isGpb() const { return _vreg.type <= kX86RegTypeGpbHi; } + //! Get whether the register is Gp lo-byte (8-bit) register. + ASMJIT_INLINE bool isGpbLo() const { return _vreg.type == kX86RegTypeGpbLo; } + //! Get whether the register is Gp hi-byte (8-bit) register. + ASMJIT_INLINE bool isGpbHi() const { return _vreg.type == kX86RegTypeGpbHi; } + //! Get whether the register is Gp word (16-bit) register. + ASMJIT_INLINE bool isGpw() const { return _vreg.type == kX86RegTypeGpw; } + //! Get whether the register is Gp dword (32-bit) register. + ASMJIT_INLINE bool isGpd() const { return _vreg.type == kX86RegTypeGpd; } + //! Get whether the register is Gp qword (64-bit) register. + ASMJIT_INLINE bool isGpq() const { return _vreg.type == kX86RegTypeGpq; } + + //! Get whether the register is Fp register. + ASMJIT_INLINE bool isFp() const { return _vreg.type == kX86RegTypeFp; } + //! Get whether the register is Mm (64-bit) register. + ASMJIT_INLINE bool isMm() const { return _vreg.type == kX86RegTypeMm; } + + //! Get whether the register is K (64-bit) register. + ASMJIT_INLINE bool isK() const { return _vreg.type == kX86RegTypeK; } + + //! Get whether the register is Xmm (128-bit) register. + ASMJIT_INLINE bool isXmm() const { return _vreg.type == kX86RegTypeXmm; } + //! Get whether the register is Ymm (256-bit) register. + ASMJIT_INLINE bool isYmm() const { return _vreg.type == kX86RegTypeYmm; } + //! Get whether the register is Zmm (512-bit) register. + ASMJIT_INLINE bool isZmm() const { return _vreg.type == kX86RegTypeZmm; } + + //! Get whether the register is RIP. + ASMJIT_INLINE bool isRip() const { return _vreg.type == kX86RegTypeRip; } + //! Get whether the register is Segment. + ASMJIT_INLINE bool isSeg() const { return _vreg.type == kX86RegTypeSeg; } + + // -------------------------------------------------------------------------- + // [Statics] + // -------------------------------------------------------------------------- + + //! Get whether the `op` operand is Gpb-Lo or Gpb-Hi register. + static ASMJIT_INLINE bool isGpbReg(const Operand& op) { + const uint32_t mask = IntUtil::pack32_2x8_1x16( + 0xFF, 0xFF, ~(_kX86RegTypePatchedGpbHi << 8) & 0xFF00); + + return (op._packed[0].u32[0] & mask) == IntUtil::pack32_2x8_1x16(kOperandTypeReg, 1, 0x0000); + } +}; + +// ============================================================================ +// [asmjit::X86RipReg] +// ============================================================================ + +//! X86/X64 RIP register. +struct X86RipReg : public X86Reg { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a RIP register. + ASMJIT_INLINE X86RipReg() : X86Reg(kX86RegTypeRip, 0, 0) {} + //! Create a reference to `other` RIP register. + ASMJIT_INLINE X86RipReg(const X86RipReg& other) : X86Reg(other) {} + //! Create non-initialized RIP register. + explicit ASMJIT_INLINE X86RipReg(const _NoInit&) : X86Reg(NoInit) {} + + // -------------------------------------------------------------------------- + // [X86RipReg Specific] + // -------------------------------------------------------------------------- + + ASMJIT_REG_OP(X86RipReg) +}; + +// ============================================================================ +// [asmjit::X86SegReg] +// ============================================================================ + +//! X86/X64 segment register. +struct X86SegReg : public X86Reg { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a dummy segment register. + ASMJIT_INLINE X86SegReg() : X86Reg() {} + //! Create a reference to `other` segment register. + ASMJIT_INLINE X86SegReg(const X86SegReg& other) : X86Reg(other) {} + //! Create a reference to `other` segment register and change the index to `index`. + ASMJIT_INLINE X86SegReg(const X86SegReg& other, uint32_t index) : X86Reg(other, index) {} + //! Create a custom segment register. + ASMJIT_INLINE X86SegReg(uint32_t type, uint32_t index, uint32_t size) : X86Reg(type, index, size) {} + //! Create non-initialized segment register. + explicit ASMJIT_INLINE X86SegReg(const _NoInit&) : X86Reg(NoInit) {} + + // -------------------------------------------------------------------------- + // [X86SegReg Specific] + // -------------------------------------------------------------------------- + + ASMJIT_REG_OP(X86SegReg) +}; + +// ============================================================================ +// [asmjit::X86GpReg] +// ============================================================================ + +//! X86/X64 Gpb/Gpw/Gpd/Gpq register. +struct X86GpReg : public X86Reg { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a dummy Gp register. + ASMJIT_INLINE X86GpReg() : X86Reg() {} + //! Create a reference to `other` Gp register. + ASMJIT_INLINE X86GpReg(const X86GpReg& other) : X86Reg(other) {} + //! Create a reference to `other` Gp register and change the index to `index`. + ASMJIT_INLINE X86GpReg(const X86GpReg& other, uint32_t index) : X86Reg(other, index) {} + //! Create a custom Gp register. + ASMJIT_INLINE X86GpReg(uint32_t type, uint32_t index, uint32_t size) : X86Reg(type, index, size) {} + //! Create non-initialized Gp register. + explicit ASMJIT_INLINE X86GpReg(const _NoInit&) : X86Reg(NoInit) {} + + // -------------------------------------------------------------------------- + // [X86GpReg Specific] + // -------------------------------------------------------------------------- + + ASMJIT_REG_OP(X86GpReg) +}; + +// ============================================================================ +// [asmjit::X86FpReg] +// ============================================================================ + +//! X86/X64 80-bit Fp register. +struct X86FpReg : public X86Reg { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a dummy Fp register. + ASMJIT_INLINE X86FpReg() : X86Reg() {} + //! Create a reference to `other` Fp register. + ASMJIT_INLINE X86FpReg(const X86FpReg& other) : X86Reg(other) {} + //! Create a reference to `other` Fp register and change the index to `index`. + ASMJIT_INLINE X86FpReg(const X86FpReg& other, uint32_t index) : X86Reg(other, index) {} + //! Create a custom Fp register. + ASMJIT_INLINE X86FpReg(uint32_t type, uint32_t index, uint32_t size) : X86Reg(type, index, size) {} + //! Create non-initialized Fp register. + explicit ASMJIT_INLINE X86FpReg(const _NoInit&) : X86Reg(NoInit) {} + + // -------------------------------------------------------------------------- + // [X86FpReg Specific] + // -------------------------------------------------------------------------- + + ASMJIT_REG_OP(X86FpReg) +}; + +// ============================================================================ +// [asmjit::X86MmReg] +// ============================================================================ + +//! X86/X64 64-bit Mm register (MMX+). +//! +//! Structure of MMX register and it's memory mapping: +//! +//! ~~~ +//! Memory Bytes +//! +--+--+--+--+--+--+--+--+ +//! |00|01|02|03|04|05|06|07| +//! +--+--+--+--+--+--+--+--+ +//! +//! MMX Register +//! +-----------------------+ +//! | QWord | +//! +-----------+-----------+ +//! | HI-DWord | LO-DWord | +//! +-----------+-----------+ +//! | W3 | W2 | W1 | W0 | +//! +--+--+--+--+--+--+--+--+ +//! |07|06|05|04|03|02|01|00| +//! +--+--+--+--+--+--+--+--+ +//! ~~~ +//! +//! Move instruction semantics: +//! +//! - `movd` - writes 4-bytes in `LO-DWord` and zeroes `HI-DWord`. +//! - `movq` - writes 8-bytes in `QWord`. +struct X86MmReg : public X86Reg { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a dummy Mm register. + ASMJIT_INLINE X86MmReg() : X86Reg() {} + //! Create a reference to `other` Mm register. + ASMJIT_INLINE X86MmReg(const X86MmReg& other) : X86Reg(other) {} + //! Create a reference to `other` Mm register and change the index to `index`. + ASMJIT_INLINE X86MmReg(const X86MmReg& other, uint32_t index) : X86Reg(other, index) {} + //! Create a custom Mm register. + ASMJIT_INLINE X86MmReg(uint32_t type, uint32_t index, uint32_t size) : X86Reg(type, index, size) {} + //! Create non-initialized Mm register. + explicit ASMJIT_INLINE X86MmReg(const _NoInit&) : X86Reg(NoInit) {} + + // -------------------------------------------------------------------------- + // [X86MmReg Specific] + // -------------------------------------------------------------------------- + + ASMJIT_REG_OP(X86MmReg) +}; + +// ============================================================================ +// [asmjit::X86KReg] +// ============================================================================ + +//! X86/X64 64-bit K register (AVX512+). +struct X86KReg : public X86Reg { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a dummy K register. + ASMJIT_INLINE X86KReg() : X86Reg() {} + //! Create a reference to `other` K register. + ASMJIT_INLINE X86KReg(const X86KReg& other) : X86Reg(other) {} + //! Create a reference to `other` K register and change the index to `index`. + ASMJIT_INLINE X86KReg(const X86KReg& other, uint32_t index) : X86Reg(other, index) {} + //! Create a custom K register. + ASMJIT_INLINE X86KReg(uint32_t type, uint32_t index, uint32_t size) : X86Reg(type, index, size) {} + //! Create non-initialized K register. + explicit ASMJIT_INLINE X86KReg(const _NoInit&) : X86Reg(NoInit) {} + + // -------------------------------------------------------------------------- + // [X86KReg Specific] + // -------------------------------------------------------------------------- + + ASMJIT_REG_OP(X86KReg) +}; + +// ============================================================================ +// [asmjit::X86XmmReg] +// ============================================================================ + +//! X86/X64 128-bit Xmm register (SSE+). +//! +//! Structure of XMM register and it's memory mapping: +//! +//! ~~~ +//! Memory Bytes +//! +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +//! |00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15| +//! +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +//! +//! XMM Register +//! +-----------------------------------------------+ +//! | OWord | +//! +-----------------------+-----------------------+ +//! | HI-QWord/PD | LO-QWord/SD | +//! +-----------+-----------+-----------+-----------+ +//! | D3/PS | D2/PS | D1/PS | D0/SS | +//! +-----------+-----------+-----------+-----------+ +//! | W7 | W6 | W5 | W4 | W3 | W2 | W1 | W0 | +//! +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +//! |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00| +//! +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +//! ~~~ +//! +//! Move instruction semantics: +//! +//! - `movd` - writes 4-bytes in `D0` and zeroes the rest. +//! - `movq` - writes 8-bytes in `Lo-QWord` and zeroes the rest. +//! - `movq2dq` - writes 8 bytes in `Lo-QWord` and zeroes the rest. +//! +//! - `movss` - writes 4-bytes in `D0` +//! (the rest is zeroed only if the source operand is a memory location). +//! - `movsd` - writes 8-bytes in `Lo-QWord` +//! (the rest is zeroed only if the source operand is a memory location). +//! +//! - `movaps`, +//! `movups`, +//! `movapd`, +//! `movupd`, +//! `movdqu`, +//! `movdqa`, +//! `lddqu` - writes 16-bytes in `OWord`. +//! +//! - `movlps`, +//! `movlpd`, +//! `movhlps` - writes 8-bytes in `Lo-QWord` and keeps the rest untouched. +//! +//! - `movhps`, +//! `movhpd`, +//! `movlhps` - writes 8-bytes in `Hi-QWord` and keeps the rest untouched. +//! +//! - `movddup`, +//! - `movsldup`, +//! - `movshdup` - writes 16 bytes in `OWord`. +struct X86XmmReg : public X86Reg { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a dummy Xmm register. + ASMJIT_INLINE X86XmmReg() : X86Reg() {} + //! Create a reference to `other` Xmm register. + ASMJIT_INLINE X86XmmReg(const X86XmmReg& other) : X86Reg(other) {} + //! Create a reference to `other` Xmm register and change the index to `index`. + ASMJIT_INLINE X86XmmReg(const X86XmmReg& other, uint32_t index) : X86Reg(other, index) {} + //! Create a custom Xmm register. + ASMJIT_INLINE X86XmmReg(uint32_t type, uint32_t index, uint32_t size) : X86Reg(type, index, size) {} + //! Create non-initialized Xmm register. + explicit ASMJIT_INLINE X86XmmReg(const _NoInit&) : X86Reg(NoInit) {} + + // -------------------------------------------------------------------------- + // [X86XmmReg Specific] + // -------------------------------------------------------------------------- + + ASMJIT_REG_OP(X86XmmReg) +}; + +// ============================================================================ +// [asmjit::X86YmmReg] +// ============================================================================ + +//! X86/X64 256-bit Ymm register (AVX+). +//! +//! Structure of YMM register and it's memory mapping: +//! +//! ~~~ +//! Memory Bytes +//! +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +//! |00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31| +//! +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +//! +//! YMM Register +//! +-----------------------------------------------+-----------------------------------------------+ +//! | HI-DQWord | LO-DQWord | +//! +-----------------------+-----------------------+-----------------------+-----------------------+ +//! | Q3/PD | Q2/PD | Q1/PD | Q0/SD | +//! +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ +//! | D7/PS | D6/PS | D5/PS | D4/PS | D3/PS | D2/PS | D1/PS | D0/SS | +//! +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ +//! | W15 | W14 | W13 | W12 | W11 | W10 | W9 | W8 | W7 | W6 | W5 | W4 | W3 | W2 | W1 | W0 | +//! +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +//! |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00| +//! +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +//! ~~~ +struct X86YmmReg : public X86Reg { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a dummy Ymm register. + ASMJIT_INLINE X86YmmReg() : X86Reg() {} + //! Create a reference to `other` Ymm register. + ASMJIT_INLINE X86YmmReg(const X86YmmReg& other) : X86Reg(other) {} + //! Create a reference to `other` Ymm register and change the index to `index`. + ASMJIT_INLINE X86YmmReg(const X86YmmReg& other, uint32_t index) : X86Reg(other, index) {} + //! Create a custom Ymm register. + ASMJIT_INLINE X86YmmReg(uint32_t type, uint32_t index, uint32_t size) : X86Reg(type, index, size) {} + //! Create non-initialized Ymm register. + explicit ASMJIT_INLINE X86YmmReg(const _NoInit&) : X86Reg(NoInit) {} + + // -------------------------------------------------------------------------- + // [X86YmmReg Specific] + // -------------------------------------------------------------------------- + + ASMJIT_REG_OP(X86YmmReg) +}; + +// ============================================================================ +// [asmjit::X86ZmmReg] +// ============================================================================ + +//! X86/X64 512-bit Zmm register (AVX512+). +struct X86ZmmReg : public X86Reg { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! Create a dummy Zmm register. + ASMJIT_INLINE X86ZmmReg() : X86Reg() {} + //! Create a reference to `other` Zmm register. + ASMJIT_INLINE X86ZmmReg(const X86ZmmReg& other) : X86Reg(other) {} + //! Create a reference to `other` Zmm register and change the index to `index`. + ASMJIT_INLINE X86ZmmReg(const X86ZmmReg& other, uint32_t index) : X86Reg(other, index) {} + //! Create a custom Zmm register. + ASMJIT_INLINE X86ZmmReg(uint32_t type, uint32_t index, uint32_t size) : X86Reg(type, index, size) {} + //! Create non-initialized Zmm register. + explicit ASMJIT_INLINE X86ZmmReg(const _NoInit&) : X86Reg(NoInit) {} + + // -------------------------------------------------------------------------- + // [X86ZmmReg Specific] + // -------------------------------------------------------------------------- + + ASMJIT_REG_OP(X86ZmmReg) +}; + +// ============================================================================ +// [asmjit::X86Mem] +// ============================================================================ + +//! X86 memory operand. +struct X86Mem : public BaseMem { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE X86Mem() : BaseMem(NoInit) { + reset(); + } + + ASMJIT_INLINE X86Mem(const Label& label, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) { + _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeLabel, 0, label._base.id); + _init_packed_d2_d3(kInvalidValue, disp); + } + + ASMJIT_INLINE X86Mem(const Label& label, const X86GpReg& index, uint32_t shift, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) { + ASMJIT_ASSERT(shift <= 3); + + _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeLabel, + (kX86MemVSibGpz << kX86MemVSibIndex) + + (shift << kX86MemShiftIndex), + label.getId()); + _vmem.index = index.getRegIndex(); + _vmem.displacement = disp; + } + + ASMJIT_INLINE X86Mem(const X86GpReg& base, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) { + _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex, + _getGpdFlags(base) + + (kX86MemVSibGpz << kX86MemVSibIndex), + base.getRegIndex()); + _init_packed_d2_d3(kInvalidValue, disp); + } + + ASMJIT_INLINE X86Mem(const X86GpReg& base, const X86GpReg& index, uint32_t shift, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) { + ASMJIT_ASSERT(shift <= 3); + + _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex, + _getGpdFlags(base) + (shift << kX86MemShiftIndex), + base.getRegIndex()); + _vmem.index = index.getRegIndex(); + _vmem.displacement = disp; + } + + ASMJIT_INLINE X86Mem(const X86GpReg& base, const X86XmmReg& index, uint32_t shift, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) { + ASMJIT_ASSERT(shift <= 3); + + _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex, + _getGpdFlags(base) + + (kX86MemVSibXmm << kX86MemVSibIndex) + + (shift << kX86MemShiftIndex), + base.getRegIndex()); + _vmem.index = index.getRegIndex(); + _vmem.displacement = disp; + } + + ASMJIT_INLINE X86Mem(const X86GpReg& base, const X86YmmReg& index, uint32_t shift, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) { + ASMJIT_ASSERT(shift <= 3); + + _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex, + _getGpdFlags(base) + + (kX86MemVSibYmm << kX86MemVSibIndex) + + (shift << kX86MemShiftIndex), + base.getRegIndex()); + _vmem.index = index.getRegIndex(); + _vmem.displacement = disp; + } + +#if !defined(ASMJIT_DISABLE_COMPILER) + ASMJIT_INLINE X86Mem(const Label& label, const X86GpVar& index, uint32_t shift, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) { + ASMJIT_ASSERT(shift <= 3); + + _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeLabel, + (kX86MemVSibGpz << kX86MemVSibIndex) + + (shift << kX86MemShiftIndex), + label.getId()); + _vmem.index = ASMJIT_OP_ID(index); + _vmem.displacement = disp; + } + + ASMJIT_INLINE X86Mem(const X86GpVar& base, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) { + _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex, + _getGpdFlags(reinterpret_cast(base)) + + (kX86MemVSibGpz << kX86MemVSibIndex), + ASMJIT_OP_ID(base)); + _init_packed_d2_d3(kInvalidValue, disp); + } + + ASMJIT_INLINE X86Mem(const X86GpVar& base, const X86GpVar& index, uint32_t shift, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) { + ASMJIT_ASSERT(shift <= 3); + + _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex, + _getGpdFlags(reinterpret_cast(base)) + + (shift << kX86MemShiftIndex), + ASMJIT_OP_ID(base)); + _vmem.index = ASMJIT_OP_ID(index); + _vmem.displacement = disp; + } + + ASMJIT_INLINE X86Mem(const X86GpVar& base, const X86XmmVar& index, uint32_t shift, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) { + ASMJIT_ASSERT(shift <= 3); + + _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex, + _getGpdFlags(reinterpret_cast(base)) + + (kX86MemVSibXmm << kX86MemVSibIndex) + + (shift << kX86MemShiftIndex), + ASMJIT_OP_ID(base)); + _vmem.index = ASMJIT_OP_ID(index); + _vmem.displacement = disp; + } + + ASMJIT_INLINE X86Mem(const X86GpVar& base, const X86YmmVar& index, uint32_t shift, int32_t disp, uint32_t size = 0) : BaseMem(NoInit) { + ASMJIT_ASSERT(shift <= 3); + + _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, kMemTypeBaseIndex, + _getGpdFlags(reinterpret_cast(base)) + + (kX86MemVSibYmm << kX86MemVSibIndex) + + (shift << kX86MemShiftIndex), + ASMJIT_OP_ID(base)); + _vmem.index = ASMJIT_OP_ID(index); + _vmem.displacement = disp; + } + + ASMJIT_INLINE X86Mem(const _Init&, uint32_t memType, const X86Var& base, int32_t disp, uint32_t size) : BaseMem(NoInit) { + _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, memType, 0, ASMJIT_OP_ID(base)); + _vmem.index = kInvalidValue; + _vmem.displacement = disp; + } + + ASMJIT_INLINE X86Mem(const _Init&, uint32_t memType, const X86Var& base, const X86GpVar& index, uint32_t shift, int32_t disp, uint32_t size) : BaseMem(NoInit) { + ASMJIT_ASSERT(shift <= 3); + + _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, memType, shift << kX86MemShiftIndex, ASMJIT_OP_ID(base)); + _vmem.index = ASMJIT_OP_ID(index); + _vmem.displacement = disp; + } +#endif // !ASMJIT_DISABLE_COMPILER + + ASMJIT_INLINE X86Mem(const X86Mem& other) : BaseMem(other) {} + explicit ASMJIT_INLINE X86Mem(const _NoInit&) : BaseMem(NoInit) {} + + // -------------------------------------------------------------------------- + // [X86Mem Specific] + // -------------------------------------------------------------------------- + + //! Clone X86Mem operand. + ASMJIT_INLINE X86Mem clone() const { + return X86Mem(*this); + } + + //! Reset X86Mem operand. + ASMJIT_INLINE void reset() { + _init_packed_op_sz_b0_b1_id(kOperandTypeMem, 0, kMemTypeBaseIndex, 0, kInvalidValue); + _init_packed_d2_d3(kInvalidValue, 0); + } + + //! \internal + ASMJIT_INLINE void _init(uint32_t memType, uint32_t base, int32_t disp, uint32_t size) { + _init_packed_op_sz_b0_b1_id(kOperandTypeMem, size, memType, 0, base); + _vmem.index = kInvalidValue; + _vmem.displacement = disp; + } + + // -------------------------------------------------------------------------- + // [Segment] + // -------------------------------------------------------------------------- + + //! Get whether the memory operand has segment override prefix. + ASMJIT_INLINE bool hasSegment() const { + return (_vmem.flags & kX86MemSegMask) != (kX86SegDefault << kX86MemSegIndex); + } + + //! Get memory operand segment, see `kX86Seg`. + ASMJIT_INLINE uint32_t getSegment() const { + return (static_cast(_vmem.flags) >> kX86MemSegIndex) & kX86MemSegBits; + } + + //! Set memory operand segment, see `kX86Seg`. + ASMJIT_INLINE X86Mem& setSegment(uint32_t segIndex) { + _vmem.flags = static_cast( + (static_cast(_vmem.flags) & kX86MemSegMask) + (segIndex << kX86MemSegIndex)); + return *this; + } + + //! Set memory operand segment, see `kX86Seg`. + ASMJIT_INLINE X86Mem& setSegment(const X86SegReg& seg) { + return setSegment(seg.getRegIndex()); + } + + // -------------------------------------------------------------------------- + // [Gpd] + // -------------------------------------------------------------------------- + + //! Get whether the memory operand has 32-bit GP base. + ASMJIT_INLINE bool hasGpdBase() const { + return (_packed[0].u32[0] & IntUtil::pack32_4x8(0x00, 0x00, 0x00, kX86MemGpdMask)) != 0; + } + + //! Set whether the memory operand has 32-bit GP base. + ASMJIT_INLINE X86Mem& setGpdBase() { + _packed[0].u32[0] |= IntUtil::pack32_4x8(0x00, 0x00, 0x00, kX86MemGpdMask); + return *this; + } + + //! Set whether the memory operand has 32-bit GP base to `b`. + ASMJIT_INLINE X86Mem& setGpdBase(uint32_t b) { + _packed[0].u32[0] &=~IntUtil::pack32_4x8(0x00, 0x00, 0x00, kX86MemGpdMask); + _packed[0].u32[0] |= IntUtil::pack32_4x8(0x00, 0x00, 0x00, b << kX86MemGpdIndex); + return *this; + } + + // -------------------------------------------------------------------------- + // [VSib] + // -------------------------------------------------------------------------- + + //! Get V-SIB type. + ASMJIT_INLINE uint32_t getVSib() const { + return (static_cast(_vmem.flags) >> kX86MemVSibIndex) & kX86MemVSibBits; + } + + //! Set V-SIB type. + ASMJIT_INLINE X86Mem& _setVSib(uint32_t vsib) { + _packed[0].u32[0] &=~IntUtil::pack32_4x8(0x00, 0x00, 0x00, kX86MemVSibMask); + _packed[0].u32[0] |= IntUtil::pack32_4x8(0x00, 0x00, 0x00, vsib << kX86MemVSibIndex); + return *this; + } + + // -------------------------------------------------------------------------- + // [Size] + // -------------------------------------------------------------------------- + + //! Set memory operand size. + ASMJIT_INLINE X86Mem& setSize(uint32_t size) { + _vmem.size = static_cast(size); + return *this; + } + + // -------------------------------------------------------------------------- + // [Base] + // -------------------------------------------------------------------------- + + //! Get whether the memory operand has base register. + ASMJIT_INLINE bool hasBase() const { + return _vmem.base != kInvalidValue; + } + + //! Get memory operand base register code, variable id, or `kInvalidValue`. + ASMJIT_INLINE uint32_t getBase() const { + return _vmem.base; + } + + //! Set memory operand base register code, variable id, or `kInvalidValue`. + ASMJIT_INLINE X86Mem& setBase(uint32_t base) { + _vmem.base = base; + return *this; + } + + // -------------------------------------------------------------------------- + // [Index] + // -------------------------------------------------------------------------- + + //! Get whether the memory operand has index. + ASMJIT_INLINE bool hasIndex() const { + return _vmem.index != kInvalidValue; + } + + //! Get memory operand index register code, variable id, or `kInvalidValue`. + ASMJIT_INLINE uint32_t getIndex() const { + return _vmem.index; + } + + //! Set memory operand index register code, variable id, or `kInvalidValue`. + ASMJIT_INLINE X86Mem& setIndex(uint32_t index) { + _vmem.index = index; + return *this; + } + + //! Set memory index. + ASMJIT_INLINE X86Mem& setIndex(const X86GpReg& index) { + _vmem.index = index.getRegIndex(); + return _setVSib(kX86MemVSibGpz); + } + + //! Set memory index. + ASMJIT_INLINE X86Mem& setIndex(const X86GpReg& index, uint32_t shift) { + _vmem.index = index.getRegIndex(); + return _setVSib(kX86MemVSibGpz).setShift(shift); + } + + //! Set memory index. + ASMJIT_INLINE X86Mem& setIndex(const X86XmmReg& index) { + _vmem.index = index.getRegIndex(); + return _setVSib(kX86MemVSibXmm); + } + + //! Set memory index. + ASMJIT_INLINE X86Mem& setIndex(const X86XmmReg& index, uint32_t shift) { + _vmem.index = index.getRegIndex(); + return _setVSib(kX86MemVSibXmm).setShift(shift); + } + + //! Set memory index. + ASMJIT_INLINE X86Mem& setIndex(const X86YmmReg& index) { + _vmem.index = index.getRegIndex(); + return _setVSib(kX86MemVSibYmm); + } + + //! Set memory index. + ASMJIT_INLINE X86Mem& setIndex(const X86YmmReg& index, uint32_t shift) { + _vmem.index = index.getRegIndex(); + return _setVSib(kX86MemVSibYmm).setShift(shift); + } + +#if !defined(ASMJIT_DISABLE_COMPILER) + //! Set memory index. + ASMJIT_INLINE X86Mem& setIndex(const X86GpVar& index) { + _vmem.index = ASMJIT_OP_ID(index); + return _setVSib(kX86MemVSibGpz); + } + + //! Set memory index. + ASMJIT_INLINE X86Mem& setIndex(const X86GpVar& index, uint32_t shift) { + _vmem.index = ASMJIT_OP_ID(index); + return _setVSib(kX86MemVSibGpz).setShift(shift); + } + + + //! Set memory index. + ASMJIT_INLINE X86Mem& setIndex(const X86XmmVar& index) { + _vmem.index = ASMJIT_OP_ID(index); + return _setVSib(kX86MemVSibXmm); + } + + //! Set memory index. + ASMJIT_INLINE X86Mem& setIndex(const X86XmmVar& index, uint32_t shift) { + _vmem.index = ASMJIT_OP_ID(index); + return _setVSib(kX86MemVSibXmm).setShift(shift); + } + + //! Set memory index. + ASMJIT_INLINE X86Mem& setIndex(const X86YmmVar& index) { + _vmem.index = ASMJIT_OP_ID(index); + return _setVSib(kX86MemVSibYmm); + } + + //! Set memory index. + ASMJIT_INLINE X86Mem& setIndex(const X86YmmVar& index, uint32_t shift) { + _vmem.index = ASMJIT_OP_ID(index); + return _setVSib(kX86MemVSibYmm).setShift(shift); + } +#endif // !ASMJIT_DISABLE_COMPILER + + //! Reset memory index. + ASMJIT_INLINE X86Mem& resetIndex() { + _vmem.index = kInvalidValue; + return _setVSib(kX86MemVSibGpz); + } + + // -------------------------------------------------------------------------- + // [Misc] + // -------------------------------------------------------------------------- + + //! Get whether the memory operand has base and index register. + ASMJIT_INLINE bool hasBaseOrIndex() const { + return _vmem.base != kInvalidValue || _vmem.index != kInvalidValue; + } + + //! Get whether the memory operand has base and index register. + ASMJIT_INLINE bool hasBaseAndIndex() const { + return _vmem.base != kInvalidValue && _vmem.index != kInvalidValue; + } + + // -------------------------------------------------------------------------- + // [Shift] + // -------------------------------------------------------------------------- + + //! Get whether the memory operand has shift used. + ASMJIT_INLINE bool hasShift() const { + return (_vmem.flags & kX86MemShiftMask) != 0; + } + + //! Get memory operand index scale (0, 1, 2 or 3). + ASMJIT_INLINE uint32_t getShift() const { + return _vmem.flags >> kX86MemShiftIndex; + } + + //! Set memory operand index scale (0, 1, 2 or 3). + ASMJIT_INLINE X86Mem& setShift(uint32_t shift) { + _packed[0].u32[0] &=~IntUtil::pack32_4x8(0x00, 0x00, 0x00, kX86MemShiftMask); + _packed[0].u32[0] |= IntUtil::pack32_4x8(0x00, 0x00, 0x00, shift << kX86MemShiftIndex); + return *this; + } + + // -------------------------------------------------------------------------- + // [Displacement] + // -------------------------------------------------------------------------- + + //! Get memory operand relative displacement. + ASMJIT_INLINE int32_t getDisplacement() const { + return _vmem.displacement; + } + + //! Set memory operand relative displacement. + ASMJIT_INLINE X86Mem& setDisplacement(int32_t disp) { + _vmem.displacement = disp; + return *this; + } + + //! Reset memory operand relative displacement. + ASMJIT_INLINE X86Mem& resetDisplacement(int32_t disp) { + _vmem.displacement = 0; + return *this; + } + + //! Adjust memory operand relative displacement by `disp`. + ASMJIT_INLINE X86Mem& adjust(int32_t disp) { + _vmem.displacement += disp; + return *this; + } + + //! Get new memory operand adjusted by `disp`. + ASMJIT_INLINE X86Mem adjusted(int32_t disp) const { + X86Mem result(*this); + result.adjust(disp); + return result; + } + + // -------------------------------------------------------------------------- + // [Operator Overload] + // -------------------------------------------------------------------------- + + ASMJIT_INLINE X86Mem& operator=(const X86Mem& other) { + _copy(other); + return *this; + } + + ASMJIT_INLINE bool operator==(const X86Mem& other) const { + return (_packed[0] == other._packed[0]) & (_packed[1] == other._packed[1]) ; + } + + ASMJIT_INLINE bool operator!=(const X86Mem& other) const { + return !(*this == other); + } + + // -------------------------------------------------------------------------- + // [Static] + // -------------------------------------------------------------------------- + + static ASMJIT_INLINE uint32_t _getGpdFlags(const Operand& base) { + return (base._vreg.size & 0x4) << (kX86MemGpdIndex - 2); + } +}; +#endif // ASMJIT_EXPORTS_X86OPERAND_REGS + +// ============================================================================ +// [asmjit::X86RegData] +// ============================================================================ + +struct X86RegData { + X86RipReg rip; + X86GpReg noGp; + + X86SegReg seg[7]; + + X86GpReg gpbLo[16]; + X86GpReg gpbHi[4]; + + X86GpReg gpw[16]; + X86GpReg gpd[16]; + X86GpReg gpq[16]; + + X86FpReg fp[8]; + X86MmReg mm[8]; + X86KReg k[8]; + + X86XmmReg xmm[32]; + X86YmmReg ymm[32]; + X86ZmmReg zmm[32]; +}; + +ASMJIT_VAR const X86RegData x86RegData; + +// ============================================================================ +// [asmjit::x86] +// ============================================================================ + +namespace x86 { + +// ============================================================================ +// [asmjit::x86 - Reg] +// ============================================================================ + +#define ASMJIT_DEF_REG(_Type_, _Name_, _Field_) \ + static const _Type_& _Name_ = x86RegData._Field_ + +ASMJIT_DEF_REG(X86RipReg, rip, rip); //!< RIP register. +ASMJIT_DEF_REG(X86GpReg , noGpReg, noGp); //!< No GP register (for `X86Mem` operand.). + +ASMJIT_DEF_REG(X86SegReg, es , seg[1]); //!< Cs segment register. +ASMJIT_DEF_REG(X86SegReg, cs , seg[2]); //!< Ss segment register. +ASMJIT_DEF_REG(X86SegReg, ss , seg[3]); //!< Ds segment register. +ASMJIT_DEF_REG(X86SegReg, ds , seg[4]); //!< Es segment register. +ASMJIT_DEF_REG(X86SegReg, fs , seg[5]); //!< Fs segment register. +ASMJIT_DEF_REG(X86SegReg, gs , seg[6]); //!< Gs segment register. + +ASMJIT_DEF_REG(X86GpReg , al , gpbLo[0]); //!< 8-bit Gpb-lo register. +ASMJIT_DEF_REG(X86GpReg , cl , gpbLo[1]); //!< 8-bit Gpb-lo register. +ASMJIT_DEF_REG(X86GpReg , dl , gpbLo[2]); //!< 8-bit Gpb-lo register. +ASMJIT_DEF_REG(X86GpReg , bl , gpbLo[3]); //!< 8-bit Gpb-lo register. +ASMJIT_DEF_REG(X86GpReg , spl , gpbLo[4]); //!< 8-bit Gpb-lo register (X64). +ASMJIT_DEF_REG(X86GpReg , bpl , gpbLo[5]); //!< 8-bit Gpb-lo register (X64). +ASMJIT_DEF_REG(X86GpReg , sil , gpbLo[6]); //!< 8-bit Gpb-lo register (X64). +ASMJIT_DEF_REG(X86GpReg , dil , gpbLo[7]); //!< 8-bit Gpb-lo register (X64). +ASMJIT_DEF_REG(X86GpReg , r8b , gpbLo[8]); //!< 8-bit Gpb-lo register (X64). +ASMJIT_DEF_REG(X86GpReg , r9b , gpbLo[9]); //!< 8-bit Gpb-lo register (X64). +ASMJIT_DEF_REG(X86GpReg , r10b , gpbLo[10]);//!< 8-bit Gpb-lo register (X64). +ASMJIT_DEF_REG(X86GpReg , r11b , gpbLo[11]);//!< 8-bit Gpb-lo register (X64). +ASMJIT_DEF_REG(X86GpReg , r12b , gpbLo[12]);//!< 8-bit Gpb-lo register (X64). +ASMJIT_DEF_REG(X86GpReg , r13b , gpbLo[13]);//!< 8-bit Gpb-lo register (X64). +ASMJIT_DEF_REG(X86GpReg , r14b , gpbLo[14]);//!< 8-bit Gpb-lo register (X64). +ASMJIT_DEF_REG(X86GpReg , r15b , gpbLo[15]);//!< 8-bit Gpb-lo register (X64). + +ASMJIT_DEF_REG(X86GpReg , ah , gpbHi[0]); //!< 8-bit Gpb-hi register. +ASMJIT_DEF_REG(X86GpReg , ch , gpbHi[1]); //!< 8-bit Gpb-hi register. +ASMJIT_DEF_REG(X86GpReg , dh , gpbHi[2]); //!< 8-bit Gpb-hi register. +ASMJIT_DEF_REG(X86GpReg , bh , gpbHi[3]); //!< 8-bit Gpb-hi register. + +ASMJIT_DEF_REG(X86GpReg , ax , gpw[0]); //!< 16-bit Gpw register. +ASMJIT_DEF_REG(X86GpReg , cx , gpw[1]); //!< 16-bit Gpw register. +ASMJIT_DEF_REG(X86GpReg , dx , gpw[2]); //!< 16-bit Gpw register. +ASMJIT_DEF_REG(X86GpReg , bx , gpw[3]); //!< 16-bit Gpw register. +ASMJIT_DEF_REG(X86GpReg , sp , gpw[4]); //!< 16-bit Gpw register. +ASMJIT_DEF_REG(X86GpReg , bp , gpw[5]); //!< 16-bit Gpw register. +ASMJIT_DEF_REG(X86GpReg , si , gpw[6]); //!< 16-bit Gpw register. +ASMJIT_DEF_REG(X86GpReg , di , gpw[7]); //!< 16-bit Gpw register. +ASMJIT_DEF_REG(X86GpReg , r8w , gpw[8]); //!< 16-bit Gpw register (X64). +ASMJIT_DEF_REG(X86GpReg , r9w , gpw[9]); //!< 16-bit Gpw register (X64). +ASMJIT_DEF_REG(X86GpReg , r10w , gpw[10]); //!< 16-bit Gpw register (X64). +ASMJIT_DEF_REG(X86GpReg , r11w , gpw[11]); //!< 16-bit Gpw register (X64). +ASMJIT_DEF_REG(X86GpReg , r12w , gpw[12]); //!< 16-bit Gpw register (X64). +ASMJIT_DEF_REG(X86GpReg , r13w , gpw[13]); //!< 16-bit Gpw register (X64). +ASMJIT_DEF_REG(X86GpReg , r14w , gpw[14]); //!< 16-bit Gpw register (X64). +ASMJIT_DEF_REG(X86GpReg , r15w , gpw[15]); //!< 16-bit Gpw register (X64). + +ASMJIT_DEF_REG(X86GpReg , eax , gpd[0]); //!< 32-bit Gpd register. +ASMJIT_DEF_REG(X86GpReg , ecx , gpd[1]); //!< 32-bit Gpd register. +ASMJIT_DEF_REG(X86GpReg , edx , gpd[2]); //!< 32-bit Gpd register. +ASMJIT_DEF_REG(X86GpReg , ebx , gpd[3]); //!< 32-bit Gpd register. +ASMJIT_DEF_REG(X86GpReg , esp , gpd[4]); //!< 32-bit Gpd register. +ASMJIT_DEF_REG(X86GpReg , ebp , gpd[5]); //!< 32-bit Gpd register. +ASMJIT_DEF_REG(X86GpReg , esi , gpd[6]); //!< 32-bit Gpd register. +ASMJIT_DEF_REG(X86GpReg , edi , gpd[7]); //!< 32-bit Gpd register. +ASMJIT_DEF_REG(X86GpReg , r8d , gpd[8]); //!< 32-bit Gpd register (X64). +ASMJIT_DEF_REG(X86GpReg , r9d , gpd[9]); //!< 32-bit Gpd register (X64). +ASMJIT_DEF_REG(X86GpReg , r10d , gpd[10]); //!< 32-bit Gpd register (X64). +ASMJIT_DEF_REG(X86GpReg , r11d , gpd[11]); //!< 32-bit Gpd register (X64). +ASMJIT_DEF_REG(X86GpReg , r12d , gpd[12]); //!< 32-bit Gpd register (X64). +ASMJIT_DEF_REG(X86GpReg , r13d , gpd[13]); //!< 32-bit Gpd register (X64). +ASMJIT_DEF_REG(X86GpReg , r14d , gpd[14]); //!< 32-bit Gpd register (X64). +ASMJIT_DEF_REG(X86GpReg , r15d , gpd[15]); //!< 32-bit Gpd register (X64). + +ASMJIT_DEF_REG(X86GpReg , rax , gpq[0]); //!< 64-bit Gpq register (X64). +ASMJIT_DEF_REG(X86GpReg , rcx , gpq[1]); //!< 64-bit Gpq register (X64) +ASMJIT_DEF_REG(X86GpReg , rdx , gpq[2]); //!< 64-bit Gpq register (X64) +ASMJIT_DEF_REG(X86GpReg , rbx , gpq[3]); //!< 64-bit Gpq register (X64) +ASMJIT_DEF_REG(X86GpReg , rsp , gpq[4]); //!< 64-bit Gpq register (X64) +ASMJIT_DEF_REG(X86GpReg , rbp , gpq[5]); //!< 64-bit Gpq register (X64) +ASMJIT_DEF_REG(X86GpReg , rsi , gpq[6]); //!< 64-bit Gpq register (X64) +ASMJIT_DEF_REG(X86GpReg , rdi , gpq[7]); //!< 64-bit Gpq register (X64) +ASMJIT_DEF_REG(X86GpReg , r8 , gpq[8]); //!< 64-bit Gpq register (X64) +ASMJIT_DEF_REG(X86GpReg , r9 , gpq[9]); //!< 64-bit Gpq register (X64) +ASMJIT_DEF_REG(X86GpReg , r10 , gpq[10]); //!< 64-bit Gpq register (X64) +ASMJIT_DEF_REG(X86GpReg , r11 , gpq[11]); //!< 64-bit Gpq register (X64) +ASMJIT_DEF_REG(X86GpReg , r12 , gpq[12]); //!< 64-bit Gpq register (X64) +ASMJIT_DEF_REG(X86GpReg , r13 , gpq[13]); //!< 64-bit Gpq register (X64) +ASMJIT_DEF_REG(X86GpReg , r14 , gpq[14]); //!< 64-bit Gpq register (X64) +ASMJIT_DEF_REG(X86GpReg , r15 , gpq[15]); //!< 64-bit Gpq register (X64) + +ASMJIT_DEF_REG(X86FpReg , fp0 , fp[0]); //!< 80-bit Fp register. +ASMJIT_DEF_REG(X86FpReg , fp1 , fp[1]); //!< 80-bit Fp register. +ASMJIT_DEF_REG(X86FpReg , fp2 , fp[2]); //!< 80-bit Fp register. +ASMJIT_DEF_REG(X86FpReg , fp3 , fp[3]); //!< 80-bit Fp register. +ASMJIT_DEF_REG(X86FpReg , fp4 , fp[4]); //!< 80-bit Fp register. +ASMJIT_DEF_REG(X86FpReg , fp5 , fp[5]); //!< 80-bit Fp register. +ASMJIT_DEF_REG(X86FpReg , fp6 , fp[6]); //!< 80-bit Fp register. +ASMJIT_DEF_REG(X86FpReg , fp7 , fp[7]); //!< 80-bit Fp register. + +ASMJIT_DEF_REG(X86MmReg , mm0 , mm[0]); //!< 64-bit Mm register. +ASMJIT_DEF_REG(X86MmReg , mm1 , mm[1]); //!< 64-bit Mm register. +ASMJIT_DEF_REG(X86MmReg , mm2 , mm[2]); //!< 64-bit Mm register. +ASMJIT_DEF_REG(X86MmReg , mm3 , mm[3]); //!< 64-bit Mm register. +ASMJIT_DEF_REG(X86MmReg , mm4 , mm[4]); //!< 64-bit Mm register. +ASMJIT_DEF_REG(X86MmReg , mm5 , mm[5]); //!< 64-bit Mm register. +ASMJIT_DEF_REG(X86MmReg , mm6 , mm[6]); //!< 64-bit Mm register. +ASMJIT_DEF_REG(X86MmReg , mm7 , mm[7]); //!< 64-bit Mm register. + +ASMJIT_DEF_REG(X86KReg , k0 , k[0]); //!< 64-bit K register. +ASMJIT_DEF_REG(X86KReg , k1 , k[1]); //!< 64-bit K register. +ASMJIT_DEF_REG(X86KReg , k2 , k[2]); //!< 64-bit K register. +ASMJIT_DEF_REG(X86KReg , k3 , k[3]); //!< 64-bit K register. +ASMJIT_DEF_REG(X86KReg , k4 , k[4]); //!< 64-bit K register. +ASMJIT_DEF_REG(X86KReg , k5 , k[5]); //!< 64-bit K register. +ASMJIT_DEF_REG(X86KReg , k6 , k[6]); //!< 64-bit K register. +ASMJIT_DEF_REG(X86KReg , k7 , k[7]); //!< 64-bit K register. + +ASMJIT_DEF_REG(X86XmmReg, xmm0 , xmm[0]); //!< 128-bit Xmm register. +ASMJIT_DEF_REG(X86XmmReg, xmm1 , xmm[1]); //!< 128-bit Xmm register. +ASMJIT_DEF_REG(X86XmmReg, xmm2 , xmm[2]); //!< 128-bit Xmm register. +ASMJIT_DEF_REG(X86XmmReg, xmm3 , xmm[3]); //!< 128-bit Xmm register. +ASMJIT_DEF_REG(X86XmmReg, xmm4 , xmm[4]); //!< 128-bit Xmm register. +ASMJIT_DEF_REG(X86XmmReg, xmm5 , xmm[5]); //!< 128-bit Xmm register. +ASMJIT_DEF_REG(X86XmmReg, xmm6 , xmm[6]); //!< 128-bit Xmm register. +ASMJIT_DEF_REG(X86XmmReg, xmm7 , xmm[7]); //!< 128-bit Xmm register. +ASMJIT_DEF_REG(X86XmmReg, xmm8 , xmm[8]); //!< 128-bit Xmm register (X64). +ASMJIT_DEF_REG(X86XmmReg, xmm9 , xmm[9]); //!< 128-bit Xmm register (X64). +ASMJIT_DEF_REG(X86XmmReg, xmm10, xmm[10]); //!< 128-bit Xmm register (X64). +ASMJIT_DEF_REG(X86XmmReg, xmm11, xmm[11]); //!< 128-bit Xmm register (X64). +ASMJIT_DEF_REG(X86XmmReg, xmm12, xmm[12]); //!< 128-bit Xmm register (X64). +ASMJIT_DEF_REG(X86XmmReg, xmm13, xmm[13]); //!< 128-bit Xmm register (X64). +ASMJIT_DEF_REG(X86XmmReg, xmm14, xmm[14]); //!< 128-bit Xmm register (X64). +ASMJIT_DEF_REG(X86XmmReg, xmm15, xmm[15]); //!< 128-bit Xmm register (X64). +ASMJIT_DEF_REG(X86XmmReg, xmm16, xmm[16]); //!< 128-bit Xmm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86XmmReg, xmm17, xmm[17]); //!< 128-bit Xmm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86XmmReg, xmm18, xmm[18]); //!< 128-bit Xmm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86XmmReg, xmm19, xmm[19]); //!< 128-bit Xmm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86XmmReg, xmm20, xmm[20]); //!< 128-bit Xmm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86XmmReg, xmm21, xmm[21]); //!< 128-bit Xmm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86XmmReg, xmm22, xmm[22]); //!< 128-bit Xmm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86XmmReg, xmm23, xmm[23]); //!< 128-bit Xmm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86XmmReg, xmm24, xmm[24]); //!< 128-bit Xmm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86XmmReg, xmm25, xmm[25]); //!< 128-bit Xmm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86XmmReg, xmm26, xmm[26]); //!< 128-bit Xmm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86XmmReg, xmm27, xmm[27]); //!< 128-bit Xmm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86XmmReg, xmm28, xmm[28]); //!< 128-bit Xmm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86XmmReg, xmm29, xmm[29]); //!< 128-bit Xmm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86XmmReg, xmm30, xmm[30]); //!< 128-bit Xmm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86XmmReg, xmm31, xmm[31]); //!< 128-bit Xmm register (X64 & AVX512VL+). + +ASMJIT_DEF_REG(X86YmmReg, ymm0 , ymm[0]); //!< 256-bit Ymm register. +ASMJIT_DEF_REG(X86YmmReg, ymm1 , ymm[1]); //!< 256-bit Ymm register. +ASMJIT_DEF_REG(X86YmmReg, ymm2 , ymm[2]); //!< 256-bit Ymm register. +ASMJIT_DEF_REG(X86YmmReg, ymm3 , ymm[3]); //!< 256-bit Ymm register. +ASMJIT_DEF_REG(X86YmmReg, ymm4 , ymm[4]); //!< 256-bit Ymm register. +ASMJIT_DEF_REG(X86YmmReg, ymm5 , ymm[5]); //!< 256-bit Ymm register. +ASMJIT_DEF_REG(X86YmmReg, ymm6 , ymm[6]); //!< 256-bit Ymm register. +ASMJIT_DEF_REG(X86YmmReg, ymm7 , ymm[7]); //!< 256-bit Ymm register. +ASMJIT_DEF_REG(X86YmmReg, ymm8 , ymm[8]); //!< 256-bit Ymm register (X64). +ASMJIT_DEF_REG(X86YmmReg, ymm9 , ymm[9]); //!< 256-bit Ymm register (X64). +ASMJIT_DEF_REG(X86YmmReg, ymm10, ymm[10]); //!< 256-bit Ymm register (X64). +ASMJIT_DEF_REG(X86YmmReg, ymm11, ymm[11]); //!< 256-bit Ymm register (X64). +ASMJIT_DEF_REG(X86YmmReg, ymm12, ymm[12]); //!< 256-bit Ymm register (X64). +ASMJIT_DEF_REG(X86YmmReg, ymm13, ymm[13]); //!< 256-bit Ymm register (X64). +ASMJIT_DEF_REG(X86YmmReg, ymm14, ymm[14]); //!< 256-bit Ymm register (X64). +ASMJIT_DEF_REG(X86YmmReg, ymm15, ymm[15]); //!< 256-bit Ymm register (X64). +ASMJIT_DEF_REG(X86YmmReg, ymm16, ymm[16]); //!< 256-bit Ymm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86YmmReg, ymm17, ymm[17]); //!< 256-bit Ymm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86YmmReg, ymm18, ymm[18]); //!< 256-bit Ymm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86YmmReg, ymm19, ymm[19]); //!< 256-bit Ymm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86YmmReg, ymm20, ymm[20]); //!< 256-bit Ymm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86YmmReg, ymm21, ymm[21]); //!< 256-bit Ymm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86YmmReg, ymm22, ymm[22]); //!< 256-bit Ymm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86YmmReg, ymm23, ymm[23]); //!< 256-bit Ymm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86YmmReg, ymm24, ymm[24]); //!< 256-bit Ymm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86YmmReg, ymm25, ymm[25]); //!< 256-bit Ymm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86YmmReg, ymm26, ymm[26]); //!< 256-bit Ymm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86YmmReg, ymm27, ymm[27]); //!< 256-bit Ymm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86YmmReg, ymm28, ymm[28]); //!< 256-bit Ymm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86YmmReg, ymm29, ymm[29]); //!< 256-bit Ymm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86YmmReg, ymm30, ymm[30]); //!< 256-bit Ymm register (X64 & AVX512VL+). +ASMJIT_DEF_REG(X86YmmReg, ymm31, ymm[31]); //!< 256-bit Ymm register (X64 & AVX512VL+). + +ASMJIT_DEF_REG(X86ZmmReg, zmm0 , zmm[0]); //!< 512-bit Zmm register. +ASMJIT_DEF_REG(X86ZmmReg, zmm1 , zmm[1]); //!< 512-bit Zmm register. +ASMJIT_DEF_REG(X86ZmmReg, zmm2 , zmm[2]); //!< 512-bit Zmm register. +ASMJIT_DEF_REG(X86ZmmReg, zmm3 , zmm[3]); //!< 512-bit Zmm register. +ASMJIT_DEF_REG(X86ZmmReg, zmm4 , zmm[4]); //!< 512-bit Zmm register. +ASMJIT_DEF_REG(X86ZmmReg, zmm5 , zmm[5]); //!< 512-bit Zmm register. +ASMJIT_DEF_REG(X86ZmmReg, zmm6 , zmm[6]); //!< 512-bit Zmm register. +ASMJIT_DEF_REG(X86ZmmReg, zmm7 , zmm[7]); //!< 512-bit Zmm register. +ASMJIT_DEF_REG(X86ZmmReg, zmm8 , zmm[8]); //!< 512-bit Zmm register (X64). +ASMJIT_DEF_REG(X86ZmmReg, zmm9 , zmm[9]); //!< 512-bit Zmm register (X64). +ASMJIT_DEF_REG(X86ZmmReg, zmm10, zmm[10]); //!< 512-bit Zmm register (X64). +ASMJIT_DEF_REG(X86ZmmReg, zmm11, zmm[11]); //!< 512-bit Zmm register (X64). +ASMJIT_DEF_REG(X86ZmmReg, zmm12, zmm[12]); //!< 512-bit Zmm register (X64). +ASMJIT_DEF_REG(X86ZmmReg, zmm13, zmm[13]); //!< 512-bit Zmm register (X64). +ASMJIT_DEF_REG(X86ZmmReg, zmm14, zmm[14]); //!< 512-bit Zmm register (X64). +ASMJIT_DEF_REG(X86ZmmReg, zmm15, zmm[15]); //!< 512-bit Zmm register (X64). +ASMJIT_DEF_REG(X86ZmmReg, zmm16, zmm[16]); //!< 512-bit Zmm register (X64 & AVX512+). +ASMJIT_DEF_REG(X86ZmmReg, zmm17, zmm[17]); //!< 512-bit Zmm register (X64 & AVX512+). +ASMJIT_DEF_REG(X86ZmmReg, zmm18, zmm[18]); //!< 512-bit Zmm register (X64 & AVX512+). +ASMJIT_DEF_REG(X86ZmmReg, zmm19, zmm[19]); //!< 512-bit Zmm register (X64 & AVX512+). +ASMJIT_DEF_REG(X86ZmmReg, zmm20, zmm[20]); //!< 512-bit Zmm register (X64 & AVX512+). +ASMJIT_DEF_REG(X86ZmmReg, zmm21, zmm[21]); //!< 512-bit Zmm register (X64 & AVX512+). +ASMJIT_DEF_REG(X86ZmmReg, zmm22, zmm[22]); //!< 512-bit Zmm register (X64 & AVX512+). +ASMJIT_DEF_REG(X86ZmmReg, zmm23, zmm[23]); //!< 512-bit Zmm register (X64 & AVX512+). +ASMJIT_DEF_REG(X86ZmmReg, zmm24, zmm[24]); //!< 512-bit Zmm register (X64 & AVX512+). +ASMJIT_DEF_REG(X86ZmmReg, zmm25, zmm[25]); //!< 512-bit Zmm register (X64 & AVX512+). +ASMJIT_DEF_REG(X86ZmmReg, zmm26, zmm[26]); //!< 512-bit Zmm register (X64 & AVX512+). +ASMJIT_DEF_REG(X86ZmmReg, zmm27, zmm[27]); //!< 512-bit Zmm register (X64 & AVX512+). +ASMJIT_DEF_REG(X86ZmmReg, zmm28, zmm[28]); //!< 512-bit Zmm register (X64 & AVX512+). +ASMJIT_DEF_REG(X86ZmmReg, zmm29, zmm[29]); //!< 512-bit Zmm register (X64 & AVX512+). +ASMJIT_DEF_REG(X86ZmmReg, zmm30, zmm[30]); //!< 512-bit Zmm register (X64 & AVX512+). +ASMJIT_DEF_REG(X86ZmmReg, zmm31, zmm[31]); //!< 512-bit Zmm register (X64 & AVX512+). +#undef ASMJIT_DEF_REG + +// This is only defined by `x86operand_regs.cpp` when exporting registers. +#if !defined(ASMJIT_EXPORTS_X86OPERAND_REGS) + +//! Create 8-bit Gpb-lo register operand. +static ASMJIT_INLINE X86GpReg gpb_lo(uint32_t index) { return X86GpReg(kX86RegTypeGpbLo, index, 1); } +//! Create 8-bit Gpb-hi register operand. +static ASMJIT_INLINE X86GpReg gpb_hi(uint32_t index) { return X86GpReg(kX86RegTypeGpbHi, index, 1); } +//! Create 16-bit Gpw register operand. +static ASMJIT_INLINE X86GpReg gpw(uint32_t index) { return X86GpReg(kX86RegTypeGpw, index, 2); } +//! Create 32-bit Gpd register operand. +static ASMJIT_INLINE X86GpReg gpd(uint32_t index) { return X86GpReg(kX86RegTypeGpd, index, 4); } +//! Create 64-bit Gpq register operand (X64). +static ASMJIT_INLINE X86GpReg gpq(uint32_t index) { return X86GpReg(kX86RegTypeGpq, index, 8); } +//! Create 80-bit Fp register operand. +static ASMJIT_INLINE X86FpReg fp(uint32_t index) { return X86FpReg(kX86RegTypeFp, index, 10); } +//! Create 64-bit Mm register operand. +static ASMJIT_INLINE X86MmReg mm(uint32_t index) { return X86MmReg(kX86RegTypeMm, index, 8); } +//! Create 64-bit K register operand. +static ASMJIT_INLINE X86KReg k(uint32_t index) { return X86KReg(kX86RegTypeK, index, 8); } +//! Create 128-bit Xmm register operand. +static ASMJIT_INLINE X86XmmReg xmm(uint32_t index) { return X86XmmReg(kX86RegTypeXmm, index, 16); } +//! Create 256-bit Ymm register operand. +static ASMJIT_INLINE X86YmmReg ymm(uint32_t index) { return X86YmmReg(kX86RegTypeYmm, index, 32); } +//! Create 512-bit Zmm register operand. +static ASMJIT_INLINE X86ZmmReg zmm(uint32_t index) { return X86ZmmReg(kX86RegTypeZmm, index, 64); } + +// ============================================================================ +// [asmjit::x86 - Ptr (Reg)] +// ============================================================================ + +//! Create `[base.reg + disp]` memory operand with no/custom size information. +static ASMJIT_INLINE X86Mem ptr(const X86GpReg& base, int32_t disp = 0, uint32_t size = 0) { + return X86Mem(base, disp, size); +} +//! Create `[base.reg + (index.reg << shift) + disp]` memory operand with no/custom size information. +static ASMJIT_INLINE X86Mem ptr(const X86GpReg& base, const X86GpReg& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0) { + return X86Mem(base, index, shift, disp, size); +} +//! Create `[base.reg + (xmm.reg << shift) + disp]` memory operand with no/custom size information. +static ASMJIT_INLINE X86Mem ptr(const X86GpReg& base, const X86XmmReg& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0) { + return X86Mem(base, index, shift, disp, size); +} +//! Create `[base.reg + (ymm.reg << shift) + disp]` memory operand with no/custom size information. +static ASMJIT_INLINE X86Mem ptr(const X86GpReg& base, const X86YmmReg& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0) { + return X86Mem(base, index, shift, disp, size); +} +//! Create `[label + disp]` memory operand with no/custom size information. +static ASMJIT_INLINE X86Mem ptr(const Label& label, int32_t disp = 0, uint32_t size = 0) { + return X86Mem(label, disp, size); +} +//! Create `[label + (index.reg << shift) + disp]` memory operand with no/custom size information. +static ASMJIT_INLINE X86Mem ptr(const Label& label, const X86GpReg& index, uint32_t shift, int32_t disp = 0, uint32_t size = 0) { \ + return X86Mem(label, index, shift, disp, size); \ +} + +//! Create `[pAbs + disp]` absolute memory operand with no/custom size information. +ASMJIT_API X86Mem ptr_abs(Ptr pAbs, int32_t disp = 0, uint32_t size = 0); +//! Create `[pAbs + (index.reg << shift) + disp]` absolute memory operand with no/custom size information. +ASMJIT_API X86Mem ptr_abs(Ptr pAbs, const X86Reg& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0); + +//! \internal +#define ASMJIT_EXPAND_PTR_REG(_Prefix_, _Size_) \ + /*! Create `[base.reg + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpReg& base, int32_t disp = 0) { \ + return X86Mem(base, disp, _Size_); \ + } \ + /*! Create `[base.reg + (index.reg << shift) + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpReg& base, const X86GpReg& index, uint32_t shift = 0, int32_t disp = 0) { \ + return ptr(base, index, shift, disp, _Size_); \ + } \ + /*! Create `[base.reg + (xmm.reg << shift) + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpReg& base, const X86XmmReg& index, uint32_t shift = 0, int32_t disp = 0) { \ + return ptr(base, index, shift, disp, _Size_); \ + } \ + /*! Create `[base.reg + (ymm.reg << shift) + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpReg& base, const X86YmmReg& index, uint32_t shift = 0, int32_t disp = 0) { \ + return ptr(base, index, shift, disp, _Size_); \ + } \ + /*! Create `[label + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const Label& label, int32_t disp = 0) { \ + return ptr(label, disp, _Size_); \ + } \ + /*! Create `[label + (index.reg << shift) + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const Label& label, const X86GpReg& index, uint32_t shift, int32_t disp = 0) { \ + return ptr(label, index, shift, disp, _Size_); \ + } \ + /*! Create `[pAbs + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, int32_t disp = 0) { \ + return ptr_abs(pAbs, disp, _Size_); \ + } \ + /*! Create `[pAbs + (index.reg << shift) + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86GpReg& index, uint32_t shift = 0, int32_t disp = 0) { \ + return ptr_abs(pAbs, index, shift, disp, _Size_); \ + } \ + /*! Create `[pAbs + (xmm.reg << shift) + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86XmmReg& index, uint32_t shift = 0, int32_t disp = 0) { \ + return ptr_abs(pAbs, index, shift, disp, _Size_); \ + } \ + /*! Create `[pAbs + (ymm.reg << shift) + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86YmmReg& index, uint32_t shift = 0, int32_t disp = 0) { \ + return ptr_abs(pAbs, index, shift, disp, _Size_); \ + } + +ASMJIT_EXPAND_PTR_REG(byte, 1) +ASMJIT_EXPAND_PTR_REG(word, 2) +ASMJIT_EXPAND_PTR_REG(dword, 4) +ASMJIT_EXPAND_PTR_REG(qword, 8) +ASMJIT_EXPAND_PTR_REG(tword, 10) +ASMJIT_EXPAND_PTR_REG(oword, 16) +ASMJIT_EXPAND_PTR_REG(yword, 32) +ASMJIT_EXPAND_PTR_REG(zword, 64) +#undef ASMJIT_EXPAND_PTR_REG + +// ============================================================================ +// [asmjit::x86 - Ptr (Var)] +// ============================================================================ + +#if !defined(ASMJIT_DISABLE_COMPILER) +//! Create `[base.var + disp]` memory operand with no/custom size information. +static ASMJIT_INLINE X86Mem ptr(const X86GpVar& base, int32_t disp = 0, uint32_t size = 0) { + return X86Mem(base, disp, size); +} +//! Create `[base.var + (index.var << shift) + disp]` memory operand with no/custom size information. +static ASMJIT_INLINE X86Mem ptr(const X86GpVar& base, const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0) { + return X86Mem(base, index, shift, disp, size); +} +//! Create `[base.var + (xmm.var << shift) + disp]` memory operand with no/custom size information. +static ASMJIT_INLINE X86Mem ptr(const X86GpVar& base, const X86XmmVar& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0) { + return X86Mem(base, index, shift, disp, size); +} +//! Create `[base.var + (ymm.var << shift) + disp]` memory operand with no/custom size information. +static ASMJIT_INLINE X86Mem ptr(const X86GpVar& base, const X86YmmVar& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0) { + return X86Mem(base, index, shift, disp, size); +} +//! Create `[label + (index.var << shift) + disp]` memory operand with no/custom size information. +static ASMJIT_INLINE X86Mem ptr(const Label& label, const X86GpVar& index, uint32_t shift, int32_t disp = 0, uint32_t size = 0) { \ + return X86Mem(label, index, shift, disp, size); \ +} + +//! Create `[pAbs + (index.var << shift) + disp]` absolute memory operand with no/custom size information. +ASMJIT_API X86Mem ptr_abs(Ptr pAbs, const X86Var& index, uint32_t shift = 0, int32_t disp = 0, uint32_t size = 0); + +//! \internal +#define ASMJIT_EXPAND_PTR_VAR(_Prefix_, _Size_) \ + /*! Create `[base.var + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpVar& base, int32_t disp = 0) { \ + return X86Mem(base, disp, _Size_); \ + } \ + /*! Create `[base.var + (index.var << shift) + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpVar& base, const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) { \ + return ptr(base, index, shift, disp, _Size_); \ + } \ + /*! Create `[base.var + (xmm.var << shift) + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpVar& base, const X86XmmVar& index, uint32_t shift = 0, int32_t disp = 0) { \ + return ptr(base, index, shift, disp, _Size_); \ + } \ + /*! Create `[base.var + (ymm.var << shift) + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const X86GpVar& base, const X86YmmVar& index, uint32_t shift = 0, int32_t disp = 0) { \ + return ptr(base, index, shift, disp, _Size_); \ + } \ + /*! Create `[label + (index.var << shift) + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr(const Label& label, const X86GpVar& index, uint32_t shift, int32_t disp = 0) { \ + return ptr(label, index, shift, disp, _Size_); \ + } \ + /*! Create `[pAbs + (index.var << shift) + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86GpVar& index, uint32_t shift = 0, int32_t disp = 0) { \ + return ptr_abs(pAbs, reinterpret_cast(index), shift, disp, _Size_); \ + } \ + /*! Create `[pAbs + (xmm.var << shift) + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86XmmVar& index, uint32_t shift = 0, int32_t disp = 0) { \ + return ptr_abs(pAbs, reinterpret_cast(index), shift, disp, _Size_); \ + } \ + /*! Create `[pAbs + (ymm.var << shift) + disp]` memory operand. */ \ + static ASMJIT_INLINE X86Mem _Prefix_##_ptr##_abs(Ptr pAbs, const X86YmmVar& index, uint32_t shift = 0, int32_t disp = 0) { \ + return ptr_abs(pAbs, reinterpret_cast(index), shift, disp, _Size_); \ + } + +ASMJIT_EXPAND_PTR_VAR(byte, 1) +ASMJIT_EXPAND_PTR_VAR(word, 2) +ASMJIT_EXPAND_PTR_VAR(dword, 4) +ASMJIT_EXPAND_PTR_VAR(qword, 8) +ASMJIT_EXPAND_PTR_VAR(tword, 10) +ASMJIT_EXPAND_PTR_VAR(oword, 16) +ASMJIT_EXPAND_PTR_VAR(yword, 32) +ASMJIT_EXPAND_PTR_VAR(zword, 64) +#undef ASMJIT_EXPAND_PTR_VAR +#endif // !ASMJIT_DISABLE_COMPILER + +#endif // !ASMJIT_EXPORTS_X86OPERAND_REGS + +} // x86 namespace + +//! \} + +} // asmjit namespace + +// [Cleanup] +#undef ASMJIT_OP_ID + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // _ASMJIT_X86_X86OPERAND_H diff --git a/third/Blackbone/src/3rd_party/AsmJit/x86/x86operand_regs.cpp b/third/Blackbone/src/3rd_party/AsmJit/x86/x86operand_regs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cc649e9c3cef9a7543210f004d3dd83a0ae3b8b7 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/x86/x86operand_regs.cpp @@ -0,0 +1,285 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS +#define ASMJIT_EXPORTS_X86OPERAND_REGS + +// [Guard] +#include "../build.h" +#if defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64) + +// [Dependencies - AsmJit] +#include "../x86/x86operand.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +#define REG(_Type_, _Index_, _Size_) {{ \ + kOperandTypeReg, _Size_, { ((_Type_) << 8) + _Index_ }, kInvalidValue, {{ kInvalidVar, 0 }} \ +}} + +const X86RegData x86RegData = { + // RIP. + REG(kX86RegTypeRip, 0, 0), + // NpGp. + REG(kInvalidReg, kInvalidReg, 0), + + // Segments. + { + REG(kX86RegTypeSeg, 0, 2), // Default. + REG(kX86RegTypeSeg, 1, 2), // ES. + REG(kX86RegTypeSeg, 2, 2), // CS. + REG(kX86RegTypeSeg, 3, 2), // SS. + REG(kX86RegTypeSeg, 4, 2), // DS. + REG(kX86RegTypeSeg, 5, 2), // FS. + REG(kX86RegTypeSeg, 6, 2) // GS. + }, + + // GpbLo. + { + REG(kX86RegTypeGpbLo, 0, 1), + REG(kX86RegTypeGpbLo, 1, 1), + REG(kX86RegTypeGpbLo, 2, 1), + REG(kX86RegTypeGpbLo, 3, 1), + REG(kX86RegTypeGpbLo, 4, 1), + REG(kX86RegTypeGpbLo, 5, 1), + REG(kX86RegTypeGpbLo, 6, 1), + REG(kX86RegTypeGpbLo, 7, 1), + REG(kX86RegTypeGpbLo, 8, 1), + REG(kX86RegTypeGpbLo, 9, 1), + REG(kX86RegTypeGpbLo, 10, 1), + REG(kX86RegTypeGpbLo, 11, 1), + REG(kX86RegTypeGpbLo, 12, 1), + REG(kX86RegTypeGpbLo, 13, 1), + REG(kX86RegTypeGpbLo, 14, 1), + REG(kX86RegTypeGpbLo, 15, 1) + }, + + // GpbHi. + { + REG(kX86RegTypeGpbHi, 0, 1), + REG(kX86RegTypeGpbHi, 1, 1), + REG(kX86RegTypeGpbHi, 2, 1), + REG(kX86RegTypeGpbHi, 3, 1) + }, + + // Gpw. + { + REG(kX86RegTypeGpw, 0, 2), + REG(kX86RegTypeGpw, 1, 2), + REG(kX86RegTypeGpw, 2, 2), + REG(kX86RegTypeGpw, 3, 2), + REG(kX86RegTypeGpw, 4, 2), + REG(kX86RegTypeGpw, 5, 2), + REG(kX86RegTypeGpw, 6, 2), + REG(kX86RegTypeGpw, 7, 2), + REG(kX86RegTypeGpw, 8, 2), + REG(kX86RegTypeGpw, 9, 2), + REG(kX86RegTypeGpw, 10, 2), + REG(kX86RegTypeGpw, 11, 2), + REG(kX86RegTypeGpw, 12, 2), + REG(kX86RegTypeGpw, 13, 2), + REG(kX86RegTypeGpw, 14, 2), + REG(kX86RegTypeGpw, 15, 2) + }, + + // Gpd. + { + REG(kX86RegTypeGpd, 0, 4), + REG(kX86RegTypeGpd, 1, 4), + REG(kX86RegTypeGpd, 2, 4), + REG(kX86RegTypeGpd, 3, 4), + REG(kX86RegTypeGpd, 4, 4), + REG(kX86RegTypeGpd, 5, 4), + REG(kX86RegTypeGpd, 6, 4), + REG(kX86RegTypeGpd, 7, 4), + REG(kX86RegTypeGpd, 8, 4), + REG(kX86RegTypeGpd, 9, 4), + REG(kX86RegTypeGpd, 10, 4), + REG(kX86RegTypeGpd, 11, 4), + REG(kX86RegTypeGpd, 12, 4), + REG(kX86RegTypeGpd, 13, 4), + REG(kX86RegTypeGpd, 14, 4), + REG(kX86RegTypeGpd, 15, 4) + }, + + // Gpq. + { + REG(kX86RegTypeGpq, 0, 8), + REG(kX86RegTypeGpq, 1, 8), + REG(kX86RegTypeGpq, 2, 8), + REG(kX86RegTypeGpq, 3, 8), + REG(kX86RegTypeGpq, 4, 8), + REG(kX86RegTypeGpq, 5, 8), + REG(kX86RegTypeGpq, 6, 8), + REG(kX86RegTypeGpq, 7, 8), + REG(kX86RegTypeGpq, 8, 8), + REG(kX86RegTypeGpq, 9, 8), + REG(kX86RegTypeGpq, 10, 8), + REG(kX86RegTypeGpq, 11, 8), + REG(kX86RegTypeGpq, 12, 8), + REG(kX86RegTypeGpq, 13, 8), + REG(kX86RegTypeGpq, 14, 8), + REG(kX86RegTypeGpq, 15, 8) + }, + + // Fp. + { + REG(kX86RegTypeFp, 0, 10), + REG(kX86RegTypeFp, 1, 10), + REG(kX86RegTypeFp, 2, 10), + REG(kX86RegTypeFp, 3, 10), + REG(kX86RegTypeFp, 4, 10), + REG(kX86RegTypeFp, 5, 10), + REG(kX86RegTypeFp, 6, 10), + REG(kX86RegTypeFp, 7, 10) + }, + + // Mm. + { + REG(kX86RegTypeMm, 0, 8), + REG(kX86RegTypeMm, 1, 8), + REG(kX86RegTypeMm, 2, 8), + REG(kX86RegTypeMm, 3, 8), + REG(kX86RegTypeMm, 4, 8), + REG(kX86RegTypeMm, 5, 8), + REG(kX86RegTypeMm, 6, 8), + REG(kX86RegTypeMm, 7, 8) + }, + + // K. + { + REG(kX86RegTypeK, 0, 8), + REG(kX86RegTypeK, 1, 8), + REG(kX86RegTypeK, 2, 8), + REG(kX86RegTypeK, 3, 8), + REG(kX86RegTypeK, 4, 8), + REG(kX86RegTypeK, 5, 8), + REG(kX86RegTypeK, 6, 8), + REG(kX86RegTypeK, 7, 8) + }, + + // Xmm. + { + REG(kX86RegTypeXmm, 0, 16), + REG(kX86RegTypeXmm, 1, 16), + REG(kX86RegTypeXmm, 2, 16), + REG(kX86RegTypeXmm, 3, 16), + REG(kX86RegTypeXmm, 4, 16), + REG(kX86RegTypeXmm, 5, 16), + REG(kX86RegTypeXmm, 6, 16), + REG(kX86RegTypeXmm, 7, 16), + REG(kX86RegTypeXmm, 8, 16), + REG(kX86RegTypeXmm, 9, 16), + REG(kX86RegTypeXmm, 10, 16), + REG(kX86RegTypeXmm, 11, 16), + REG(kX86RegTypeXmm, 12, 16), + REG(kX86RegTypeXmm, 13, 16), + REG(kX86RegTypeXmm, 14, 16), + REG(kX86RegTypeXmm, 15, 16), + REG(kX86RegTypeXmm, 16, 16), + REG(kX86RegTypeXmm, 17, 16), + REG(kX86RegTypeXmm, 18, 16), + REG(kX86RegTypeXmm, 19, 16), + REG(kX86RegTypeXmm, 20, 16), + REG(kX86RegTypeXmm, 21, 16), + REG(kX86RegTypeXmm, 22, 16), + REG(kX86RegTypeXmm, 23, 16), + REG(kX86RegTypeXmm, 24, 16), + REG(kX86RegTypeXmm, 25, 16), + REG(kX86RegTypeXmm, 26, 16), + REG(kX86RegTypeXmm, 27, 16), + REG(kX86RegTypeXmm, 28, 16), + REG(kX86RegTypeXmm, 29, 16), + REG(kX86RegTypeXmm, 30, 16), + REG(kX86RegTypeXmm, 31, 16) + }, + + // Ymm. + { + REG(kX86RegTypeYmm, 0, 32), + REG(kX86RegTypeYmm, 1, 32), + REG(kX86RegTypeYmm, 2, 32), + REG(kX86RegTypeYmm, 3, 32), + REG(kX86RegTypeYmm, 4, 32), + REG(kX86RegTypeYmm, 5, 32), + REG(kX86RegTypeYmm, 6, 32), + REG(kX86RegTypeYmm, 7, 32), + REG(kX86RegTypeYmm, 8, 32), + REG(kX86RegTypeYmm, 9, 32), + REG(kX86RegTypeYmm, 10, 32), + REG(kX86RegTypeYmm, 11, 32), + REG(kX86RegTypeYmm, 12, 32), + REG(kX86RegTypeYmm, 13, 32), + REG(kX86RegTypeYmm, 14, 32), + REG(kX86RegTypeYmm, 15, 32), + REG(kX86RegTypeYmm, 16, 32), + REG(kX86RegTypeYmm, 17, 32), + REG(kX86RegTypeYmm, 18, 32), + REG(kX86RegTypeYmm, 19, 32), + REG(kX86RegTypeYmm, 20, 32), + REG(kX86RegTypeYmm, 21, 32), + REG(kX86RegTypeYmm, 22, 32), + REG(kX86RegTypeYmm, 23, 32), + REG(kX86RegTypeYmm, 24, 32), + REG(kX86RegTypeYmm, 25, 32), + REG(kX86RegTypeYmm, 26, 32), + REG(kX86RegTypeYmm, 27, 32), + REG(kX86RegTypeYmm, 28, 32), + REG(kX86RegTypeYmm, 29, 32), + REG(kX86RegTypeYmm, 30, 32), + REG(kX86RegTypeYmm, 31, 32) + }, + + // Zmm. + { + REG(kX86RegTypeZmm, 0, 64), + REG(kX86RegTypeZmm, 1, 64), + REG(kX86RegTypeZmm, 2, 64), + REG(kX86RegTypeZmm, 3, 64), + REG(kX86RegTypeZmm, 4, 64), + REG(kX86RegTypeZmm, 5, 64), + REG(kX86RegTypeZmm, 6, 64), + REG(kX86RegTypeZmm, 7, 64), + REG(kX86RegTypeZmm, 8, 64), + REG(kX86RegTypeZmm, 9, 64), + REG(kX86RegTypeZmm, 10, 64), + REG(kX86RegTypeZmm, 11, 64), + REG(kX86RegTypeZmm, 12, 64), + REG(kX86RegTypeZmm, 13, 64), + REG(kX86RegTypeZmm, 14, 64), + REG(kX86RegTypeZmm, 15, 64), + REG(kX86RegTypeZmm, 16, 64), + REG(kX86RegTypeZmm, 17, 64), + REG(kX86RegTypeZmm, 18, 64), + REG(kX86RegTypeZmm, 19, 64), + REG(kX86RegTypeZmm, 20, 64), + REG(kX86RegTypeZmm, 21, 64), + REG(kX86RegTypeZmm, 22, 64), + REG(kX86RegTypeZmm, 23, 64), + REG(kX86RegTypeZmm, 24, 64), + REG(kX86RegTypeZmm, 25, 64), + REG(kX86RegTypeZmm, 26, 64), + REG(kX86RegTypeZmm, 27, 64), + REG(kX86RegTypeZmm, 28, 64), + REG(kX86RegTypeZmm, 29, 64), + REG(kX86RegTypeZmm, 30, 64), + REG(kX86RegTypeZmm, 31, 64) + } +}; + +#undef REG + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64 diff --git a/third/Blackbone/src/3rd_party/AsmJit/x86/x86scheduler.cpp b/third/Blackbone/src/3rd_party/AsmJit/x86/x86scheduler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10a2332ac591d913ac609791db190f712a2ac309 --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/x86/x86scheduler.cpp @@ -0,0 +1,94 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Export] +#define ASMJIT_EXPORTS + +// [Guard] +#include "../build.h" +#if !defined(ASMJIT_DISABLE_COMPILER) && (defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64)) + +// [Dependencies - AsmJit] +#include "../base/containers.h" +#include "../x86/x86scheduler_p.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [Internals] +// ============================================================================ + +//! \internal +struct X86ScheduleData { + //! Registers read by the instruction. + X86RegMask regsIn; + //! Registers written by the instruction. + X86RegMask regsOut; + + //! Flags read by the instruction. + uint8_t flagsIn; + //! Flags written by the instruction. + uint8_t flagsOut; + + //! How many `uops` or `cycles` the instruction takes. + uint8_t ops; + //! Instruction latency. + uint8_t latency; + + //! Which ports the instruction can run at. + uint16_t ports; + //! \internal + uint16_t reserved; + + //! All instructions that this instruction depends on. + PodList::Link* dependsOn; + //! All instructions that use the result of this instruction. + PodList::Link* usedBy; +}; + +// ============================================================================ +// [asmjit::X86Scheduler - Construction / Destruction] +// ============================================================================ + +X86Scheduler::X86Scheduler(X86Compiler* compiler, const X86CpuInfo* cpuInfo) : + _compiler(compiler), + _cpuInfo(cpuInfo) {} +X86Scheduler::~X86Scheduler() {} + +// ============================================================================ +// [asmjit::X86Scheduler - Run] +// ============================================================================ + +Error X86Scheduler::run(Node* start, Node* stop) { + /* + ASMJIT_TLOG("[Schedule] === Begin ==="); + + Zone zone(8096 - kZoneOverhead); + Node* node_ = start; + + while (node_ != stop) { + Node* next = node_->getNext(); + ASMJIT_ASSERT(node_->getType() == kNodeTypeInst); + + printf(" %s\n", X86Util::getInstInfo(static_cast(node_)->getInstId()).getInstName()); + node_ = next; + } + + ASMJIT_TLOG("[Schedule] === End ==="); + */ + return kErrorOk; +} + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // !ASMJIT_DISABLE_COMPILER && (ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64) diff --git a/third/Blackbone/src/3rd_party/AsmJit/x86/x86scheduler_p.h b/third/Blackbone/src/3rd_party/AsmJit/x86/x86scheduler_p.h new file mode 100644 index 0000000000000000000000000000000000000000..1afeb90d3e4eb7505a5edf17113b77bb9f83171d --- /dev/null +++ b/third/Blackbone/src/3rd_party/AsmJit/x86/x86scheduler_p.h @@ -0,0 +1,63 @@ +// [AsmJit] +// Complete x86/x64 JIT and Remote Assembler for C++. +// +// [License] +// Zlib - See LICENSE.md file in the package. + +// [Guard] +#ifndef _ASMJIT_X86_X86SCHEDULER_P_H +#define _ASMJIT_X86_X86SCHEDULER_P_H + +#include "../build.h" +#if !defined(ASMJIT_DISABLE_COMPILER) + +// [Dependencies - AsmJit] +#include "../x86/x86compiler.h" +#include "../x86/x86context_p.h" +#include "../x86/x86cpuinfo.h" +#include "../x86/x86inst.h" + +// [Api-Begin] +#include "../apibegin.h" + +namespace asmjit { + +// ============================================================================ +// [asmjit::X86Scheduler] +// ============================================================================ + +//! \internal +//! +//! X86 scheduler. +struct X86Scheduler { + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + X86Scheduler(X86Compiler* compiler, const X86CpuInfo* cpuInfo); + ~X86Scheduler(); + + // -------------------------------------------------------------------------- + // [Run] + // -------------------------------------------------------------------------- + + Error run(Node* start, Node* stop); + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! Attached compiler. + X86Compiler* _compiler; + //! CPU information used for scheduling. + const X86CpuInfo* _cpuInfo; +}; + +} // asmjit namespace + +// [Api-End] +#include "../apiend.h" + +// [Guard] +#endif // !ASMJIT_DISABLE_COMPILER +#endif // _ASMJIT_X86_X86SCHEDULER_P_H diff --git a/third/Blackbone/src/3rd_party/BeaEngine/Warning_for_C_coders.txt b/third/Blackbone/src/3rd_party/BeaEngine/Warning_for_C_coders.txt new file mode 100644 index 0000000000000000000000000000000000000000..796a2c38e09ae949c87fcc8922158115050de069 --- /dev/null +++ b/third/Blackbone/src/3rd_party/BeaEngine/Warning_for_C_coders.txt @@ -0,0 +1,7 @@ +The library included in this package has been compiled using the stdcall convention( to respect habits from previous versions). But, header file is now configured to use by default the DLL version in cdecl convention. + +If you want to use the static library BeaEngine.lib, just add this at the very beginning of your source code : + +#define BEA_ENGINE_STATIC +#define BEA_USE_STDCALL +#include "BeaEngine.h" diff --git a/third/Blackbone/src/3rd_party/BeaEngine/headers/BeaEngine.h b/third/Blackbone/src/3rd_party/BeaEngine/headers/BeaEngine.h new file mode 100644 index 0000000000000000000000000000000000000000..007f931b452cf030b2d9dcde15a6f54d91f23377 --- /dev/null +++ b/third/Blackbone/src/3rd_party/BeaEngine/headers/BeaEngine.h @@ -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 diff --git a/third/Blackbone/src/3rd_party/BeaEngine/headers/Includes/basic_types.h b/third/Blackbone/src/3rd_party/BeaEngine/headers/Includes/basic_types.h new file mode 100644 index 0000000000000000000000000000000000000000..4c50f117aa43cfb04305fdfb934399463e70786d --- /dev/null +++ b/third/Blackbone/src/3rd_party/BeaEngine/headers/Includes/basic_types.h @@ -0,0 +1,250 @@ +/** + * @file basic_types.h + * @author + * @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 . */ + +#ifndef __BEA_BASIC_TYPES_HPP__ +#define __BEA_BASIC_TYPES_HPP__ + +#include + +#if defined(__GNUC__) || defined (__INTEL_COMPILER) || defined(__LCC__) +#include +#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 diff --git a/third/Blackbone/src/3rd_party/BeaEngine/headers/Includes/export.h b/third/Blackbone/src/3rd_party/BeaEngine/headers/Includes/export.h new file mode 100644 index 0000000000000000000000000000000000000000..6e550dbb851eb5b7e136b507b79a88afee727e49 --- /dev/null +++ b/third/Blackbone/src/3rd_party/BeaEngine/headers/Includes/export.h @@ -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 . */ + +#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 diff --git a/third/Blackbone/src/3rd_party/CorError.h b/third/Blackbone/src/3rd_party/CorError.h new file mode 100644 index 0000000000000000000000000000000000000000..e92b0a8e797ee3b3849b776bbda1ee1de9a588de --- /dev/null +++ b/third/Blackbone/src/3rd_party/CorError.h @@ -0,0 +1,2152 @@ +// ==++== +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// ==--== +/********************************************************************* + ** ** + ** CorError.h - lists the HResults used by the .NET Framework's ** + ** Common Language Runtime. ** + ** Created: September 3, 1999. ** + ** ** + *********************************************************************/ + + +#ifndef __COMMON_LANGUAGE_RUNTIME_HRESULTS__ +#define __COMMON_LANGUAGE_RUNTIME_HRESULTS__ + +/********************************************************************* + +These HRESULTs are used for mapping managed exceptions to COM error codes +and vice versa through COM Interop. For background on COM error codes see +http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/error_9td2.asp. + +FACILITY_URT is defined as 0x13 (0x8013xxxx). The facility range is reserved +for the .NET Framework SDK teams. + +Within that range, the following subranges have been allocated for different +feature areas: + +0x10yy for Execution Engine +0x11yy for Metadata, TypeLib Export, and CLDB +0x12yy for MetaData Validator +0x13yy for Debugger and Profiler errors +0x14yy for Security +0x15yy for BCL +0x1600 - 0x161F for Reflection +0x1620 - 0x163F for System.IO +0x1640 - 0x165F for Security +0x1660 - 0x16FF for BCL +0x17yy for shim +0x18yy for IL Verifier +0x19yy for .NET Framework +0x1Ayy for .NET Framework +0x1Byy for MetaData Validator +0x1Cyy for more debugger errors +0x1Dyy for PE Format Validation +0x1Eyy for CLR Optimization Service errors +0x1Fyy for NGEN errors +0x30yy for VSA errors + +Base class library HRESULTs are copied from this file into many different +files named __HResults.cs under the BCL directory. Frameworks HRESULTs are +defined in src/main/HResults.cs. If you make any modifications to +the range allocations described above, please make sure the corerror.h file +gets updated. + +*********************************************************************/ + +#include + +#ifndef FACILITY_URT +#define FACILITY_URT 0x13 +#endif + +#ifndef EMAKEHR +#define SMAKEHR(val) MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_URT, val) +#define EMAKEHR(val) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_URT, val) +#endif + + +// ****************** +// FACILITY_UTF +// ****************** + + +// ****************** +// Metadata errors +// ****************** + +//**** ICeeFileGen errors. +#define CEE_E_ENTRYPOINT EMAKEHR(0x1000) // The entry point info is invalid. +#define CEE_E_CVTRES_NOT_FOUND EMAKEHR(0x1001) // cannot find cvtres.exe + +//**** EE errors +#define MSEE_E_LOADLIBFAILED EMAKEHR(0x1010) // Failed to delay load library %s (Win32 error: %d). +#define MSEE_E_GETPROCFAILED EMAKEHR(0x1011) // Failed to get entry point %s (Win32 error: %d). +#define MSEE_E_MULTCOPIESLOADED EMAKEHR(0x1012) // Multiple copies of MSCOREE.dll have been loaded by the same process. +// the following two are COR to match the name used in the library +#define COR_E_APPDOMAINUNLOADED EMAKEHR(0x1014) // access unloaded appdomain +#define COR_E_CANNOTUNLOADAPPDOMAIN EMAKEHR(0x1015) // Error while unloading an appdomain +#define MSEE_E_ASSEMBLYLOADINPROGRESS EMAKEHR(0x1016) // Assembly is being currently being loaded +#define MSEE_E_CANNOTCREATEAPPDOMAIN EMAKEHR(0x1017) // Attempt to create appdomain failed +#define COR_E_FIXUPSINEXE EMAKEHR(0x1019) // Attempt to load an unverifiable exe with fixups (IAT with more than 2 sections or a TLS section) +#define COR_E_NO_LOADLIBRARY_ALLOWED EMAKEHR(0x101A) // Attempt to LoadLibrary a managed image in an improper way (only assemblies with EAT's area allowed.) +#define COR_E_NEWER_RUNTIME EMAKEHR(0x101B) // The assembly is built by a runtime newer than the currently loaded runtime, and cannot be loaded. +#define COR_E_CANNOT_SET_POLICY EMAKEHR(0x101C) // Unable to set app domain security policy after non-GAC domain neutral assemblies are loaded +#define COR_E_CANNOT_SPECIFY_EVIDENCE EMAKEHR(0x101D) // Unable to use assembly evidence after non-GAC domain neutral assemblies are loaded + +// The CLR hosting support reserves 0x1020-0x102F. +#define HOST_E_DEADLOCK EMAKEHR(0x1020) // Host detects deadlock on a blocking operation +#define HOST_E_INTERRUPTED EMAKEHR(0x1021) // Host interrupts a wait, similar to APC +#define HOST_E_INVALIDOPERATION EMAKEHR(0x1022) // The operation is invalid +#define HOST_E_CLRNOTAVAILABLE EMAKEHR(0x1023) // CLR has been disabled due to unrecoverable error +#define HOST_E_TIMEOUT EMAKEHR(0x1024) // A wait times out +#define HOST_E_NOT_OWNER EMAKEHR(0x1025) // +#define HOST_E_ABANDONED EMAKEHR(0x1026) // An event is abandoned +#define HOST_E_EXITPROCESS_THREADABORT EMAKEHR(0x1027) // ExitProcess due to ThreadAbort escalation +#define HOST_E_EXITPROCESS_ADUNLOAD EMAKEHR(0x1028) // ExitProcess due to AD Unload escalation +#define HOST_E_EXITPROCESS_TIMEOUT EMAKEHR(0x1029) // ExitProcess due to Timeout escalation +#define HOST_E_EXITPROCESS_OUTOFMEMORY EMAKEHR(0x102a) // ExitProcess due to OutOfMemory escalation +#define HOST_E_EXITPROCESS_STACKOVERFLOW EMAKEHR(0x102b) // ExitProcess due to StackOverflow escalation + +//**** Assembly Cache errors +#define COR_E_MODULE_HASH_CHECK_FAILED EMAKEHR(0x1039) // The check of the module's hash failed. +#define FUSION_E_REF_DEF_MISMATCH EMAKEHR(0x1040) // The located assembly's manifest definition does not match the assembly reference. +#define FUSION_E_INVALID_PRIVATE_ASM_LOCATION EMAKEHR(0x1041) // The private assembly was located outside the appbase directory. +#define FUSION_E_ASM_MODULE_MISSING EMAKEHR(0x1042) // A module specified in the manifest was not found. +#define FUSION_E_UNEXPECTED_MODULE_FOUND EMAKEHR(0x1043) // Modules which are not in the manifest were streamed in. +#define FUSION_E_PRIVATE_ASM_DISALLOWED EMAKEHR(0x1044) // A strongly-named assembly is required. +#define FUSION_E_SIGNATURE_CHECK_FAILED EMAKEHR(0x1045) // The check of the signature failed. +#define FUSION_E_DATABASE_ERROR EMAKEHR(0x1046) // An unexpected error was encountered in the Assembly Cache database. +#define FUSION_E_INVALID_NAME EMAKEHR(0x1047) // The given assembly name or codebase was invalid. +#define FUSION_E_CODE_DOWNLOAD_DISABLED EMAKEHR(0x1048) // HTTP download of assemblies has been disabled for this appdomain. +#define FUSION_E_UNINSTALL_DISALLOWED EMAKEHR(0x1049) // Uninstall of given assembly is not allowed. +#define FUSION_E_HOST_GAC_ASM_MISMATCH EMAKEHR(0x1050) // Assembly in host store has a different signature than assembly in GAC +#define FUSION_E_LOADFROM_BLOCKED EMAKEHR(0x1051) // Hosted environment doesn't permit loading by location +#define FUSION_E_CACHEFILE_FAILED EMAKEHR(0x1052) // Failed to add file to AppDomain cache + + +//============================================================================= +// THE VALIDATOR IS CURRENTLY USING ERROR CODES STARTING WITH 0x1050 ONWARDS. +// LOOK AT ERROR CODES STARTING FROM VLDTR_E_AS_NAMENULL. JUST A NOTE IN CASE +// THE EE EVER COMES TO THE POINT OF NEEDING THOSE!!! +//============================================================================= + +//**** Generic errors. +#define CLDB_E_FILE_BADREAD EMAKEHR(0x1100) // Error occured during a read. +#define CLDB_E_FILE_BADWRITE EMAKEHR(0x1101) // Error occured during a write. +#define CLDB_E_FILE_READONLY EMAKEHR(0x1103) // File is read only. +#define CLDB_E_NAME_ERROR EMAKEHR(0x1105) // An ill-formed name was given. +#define CLDB_S_TRUNCATION SMAKEHR(0x1106) // STATUS: Data value was truncated. +#define CLDB_E_TRUNCATION EMAKEHR(0x1106) // ERROR: Data value was truncated. +#define CLDB_E_FILE_OLDVER EMAKEHR(0x1107) // Old version error. +#define CLDB_E_RELOCATED EMAKEHR(0x1108) // A shared mem open failed to open at the originally + // assigned memory address. +#define CLDB_S_NULL SMAKEHR(0x1109) // NULL data value. +#define CLDB_E_SMDUPLICATE EMAKEHR(0x110A) // Create of shared memory failed. A memory mapping of the same name already exists. +#define CLDB_E_NO_DATA EMAKEHR(0x110B) // There isn't .CLB data in the memory or stream. +#define CLDB_E_READONLY EMAKEHR(0x110C) // Database is read only. +#define CLDB_E_INCOMPATIBLE EMAKEHR(0x110D) // The importing scope is not comptabile with the emitting scope + +//**** Schema errors. +#define CLDB_E_FILE_CORRUPT EMAKEHR(0x110E) // File is corrupt. +#define CLDB_E_SCHEMA_VERNOTFOUND EMAKEHR(0x110F) // Version %d of schema '%s' not found. +#define CLDB_E_BADUPDATEMODE EMAKEHR(0x1110) // cannot open a incrementally build scope for full update + +//**** Index errors. +#define CLDB_E_INDEX_NONULLKEYS EMAKEHR(0x1121) // Null value not allowed in unique index or primary key. +#define CLDB_E_INDEX_DUPLICATE EMAKEHR(0x1122) // Unique index %s has been violated. +#define CLDB_E_INDEX_BADTYPE EMAKEHR(0x1123) // The columns data type is not allowed in an index. +#define CLDB_E_INDEX_NOTFOUND EMAKEHR(0x1124) // Index %s not found. +#define CLDB_S_INDEX_TABLESCANREQUIRED SMAKEHR(0x1125) // Table scan required to run query. + +//**** Record errors. +#define CLDB_E_RECORD_NOTFOUND EMAKEHR(0x1130) // Record wasn't found on lookup. +#define CLDB_E_RECORD_OVERFLOW EMAKEHR(0x1131) // Too many records were returned for criteria. +#define CLDB_E_RECORD_DUPLICATE EMAKEHR(0x1132) // Record is a duplicate. +#define CLDB_E_RECORD_PKREQUIRED EMAKEHR(0x1133) // Primary key value is required. +#define CLDB_E_RECORD_DELETED EMAKEHR(0x1134) // Record is valid but deleted. +#define CLDB_E_RECORD_OUTOFORDER EMAKEHR(0x1135) // Record is emitted out of order. + +//**** Column errors. +#define CLDB_E_COLUMN_OVERFLOW EMAKEHR(0x1140) // Data too large. +#define CLDB_E_COLUMN_READONLY EMAKEHR(0x1141) // Column cannot be changed. +#define CLDB_E_COLUMN_SPECIALCOL EMAKEHR(0x1142) // Too many RID or primary key columns, 1 is max. +#define CLDB_E_COLUMN_PKNONULLS EMAKEHR(0x1143) // Primary key column %s may not allow the null value. + +//**** Table errors. +#define CLDB_E_TABLE_CANTDROP EMAKEHR(0x1150) // Can't auto-drop table while open. + +//**** Object errors. +#define CLDB_E_OBJECT_NOTFOUND EMAKEHR(0x1151) // Object was not found in the database. +#define CLDB_E_OBJECT_COLNOTFOUND EMAKEHR(0x1152) // The column was not found. + +//**** Vector errors. +#define CLDB_E_VECTOR_BADINDEX EMAKEHR(0x1153) // The index given was invalid. + +//**** Heap errors; +#define CLDB_E_TOO_BIG EMAKEHR(0x1154) // A blob or string was too big. + +//**** IMeta* errors. +#define META_E_INVALID_TOKEN_TYPE EMAKEHR(0x115f) // A token of the wrong type passed to a metadata function. + +#define TLBX_E_INVALID_TYPEINFO EMAKEHR(0x1160) // Typelib import: invalid type, not converted. +#define TLBX_E_INVALID_TYPEINFO_UNNAMED EMAKEHR(0x1161) // Typelib import: invalid type, not converted -- name unknown. +#define TLBX_E_CTX_NESTED EMAKEHR(0x1162) // Typelib export: Format string for nested contexts. +#define TLBX_E_ERROR_MESSAGE EMAKEHR(0x1163) // Typelib export: Error message wrapper. +#define TLBX_E_CANT_SAVE EMAKEHR(0x1164) // Typelib export: cant "SaveAllChanges()" +#define TLBX_W_LIBNOTREGISTERED EMAKEHR(0x1165) // Typelib export: type library is not registered. +#define TLBX_E_CANTLOADLIBRARY EMAKEHR(0x1166) // Typelib export: type library cannot be loaded. +#define TLBX_E_BAD_VT_TYPE EMAKEHR(0x1167) // Typelib import: invalid VT_*, not converted. +#define TLBX_E_NO_MSCOREE_TLB EMAKEHR(0x1168) // Typelib export: can't load mscoree.tlb +#define TLBX_E_BAD_MSCOREE_TLB EMAKEHR(0x1169) // Typelib export: can't get a required typeinfo from mscoree.tlb. +#define TLBX_E_TLB_EXCEPTION EMAKEHR(0x116a) // Typelib import: fault reading a typelib. +#define TLBX_E_MULTIPLE_LCIDS EMAKEHR(0x116b) // Typelib import: Multiple LCID's parameters on a method. +#define TLBX_I_TYPEINFO_IMPORTED SMAKEHR(0x116c) // Typelib import: progress report. +#define TLBX_E_AMBIGUOUS_RETURN EMAKEHR(0x116d) // Typelib import: duplicate or ambiguous return types. +#define TLBX_E_DUPLICATE_TYPE_NAME EMAKEHR(0x116e) // Typelib import: duplicate name (due to user-defined name). +#define TLBX_I_USEIUNKNOWN SMAKEHR(0x116f) // Typelib export: substituted IUnknown for type. + +#define TLBX_I_UNCONVERTABLE_ARGS SMAKEHR(0x1170) // Typelib import: signature can't be converted (eg, struct**) +#define TLBX_I_UNCONVERTABLE_FIELD SMAKEHR(0x1171) // Typelib import: signature can't be converted (eg, struct**) +#define TLBX_I_NONSEQUENTIALSTRUCT EMAKEHR(0x1172) // Typelib export: Can't convert non-sequential structs. +#define TLBX_W_WARNING_MESSAGE SMAKEHR(0x1173) // Typelib export: Warning message wrapper. +#define TLBX_I_RESOLVEREFFAILED EMAKEHR(0x1174) // Typelib import: The resolve ref call failed. +#define TLBX_E_ASANY EMAKEHR(0x1175) // Typelib export: Encounterd "AsAny" -- ignored. +#define TLBX_E_INVALIDLCIDPARAM EMAKEHR(0x1176) // Typelib export: Encounterd an LCID attribute set to an invalid param. +#define TLBX_E_LCIDONDISPONLYITF EMAKEHR(0x1177) // Typelib export: Encounterd an LCID attribute on a disp only interface. +#define TLBX_E_NONPUBLIC_FIELD EMAKEHR(0x1178) // Typelib export: Non-public field in public struct. +#define TLBX_I_TYPE_EXPORTED SMAKEHR(0x1179) // Typelib export: type exported +#define TLBX_I_DUPLICATE_DISPID SMAKEHR(0x117A) // Typelib export: duplicate dispid -- auto corrected. +#define TLBX_E_BAD_NAMES EMAKEHR(0x117B) // Typelib export: bad names list. +#define TLBX_I_REF_TYPE_AS_STRUCT SMAKEHR(0x117C) // Typelib export: referenct tyep had layout, exported as struct. +#define TLBX_E_GENERICINST_SIGNATURE EMAKEHR(0x117D) // TypeLib export: generic type instance in signature. +#define TLBX_E_GENERICPAR_SIGNATURE EMAKEHR(0x117E) // TypeLib export: generic type parameter in signature. +#define TLBX_I_GENERIC_TYPE SMAKEHR(0x117F) // TypeLib export: generic type definition + +#define META_E_DUPLICATE EMAKEHR(0x1180) // Attempt to define an object that already exists. +#define META_E_GUID_REQUIRED EMAKEHR(0x1181) // A guid was not provided where one was required. +#define META_E_TYPEDEF_MISMATCH EMAKEHR(0x1182) // Merge: an import typedef matched ns.name, but not version and guid. +#define META_E_MERGE_COLLISION EMAKEHR(0x1183) // Merge: conflict between import and emit +#define TLBX_W_NON_INTEGRAL_CA_TYPE SMAKEHR(0x1184) // TypeLib import: Ignoring IDL custom attribute -- does not have an integral value. +#define TLBX_W_IENUM_CA_ON_IUNK SMAKEHR(0x1185) // TypeLib import: Ignoring IDL custom attribute -- using IEnum CA on an IUnknown derived interface. +#define TLBX_E_NO_SAFEHANDLE_ARRAYS EMAKEHR(0x1186) // TypeLib export: detected array of SafeHandles +#define META_E_METHD_NOT_FOUND EMAKEHR(0x1187) // Merge: Class already in emit scope, but member not found +#define META_E_FIELD_NOT_FOUND EMAKEHR(0x1188) // Merge: Class already in emit scope, but member not found +#define META_S_PARAM_MISMATCH SMAKEHR(0x1189) // Merge: Parameter information mismatched. +#define META_E_PARAM_MISMATCH EMAKEHR(0x1189) // Merge: Parameter information mismatched. +#define META_E_BADMETADATA EMAKEHR(0x118A) // Merge: Inconsistency in meta data import scope +#define META_E_INTFCEIMPL_NOT_FOUND EMAKEHR(0x118B) // Merge: Class already in emit scope, but interfaceimpl not found +#define TLBX_E_NO_CRITICALHANDLE_ARRAYS EMAKEHR(0x118C) // TypeLib export: detected array of CriticalHandles +#define META_E_CLASS_LAYOUT_INCONSISTENT EMAKEHR(0x118D) // Merge: Class is duplicated but class layout information is not consistent +#define META_E_FIELD_MARSHAL_NOT_FOUND EMAKEHR(0x118E) // Merge: Field is duplicated but we cannot find the matching FieldMarshal information +#define META_E_METHODSEM_NOT_FOUND EMAKEHR(0x118F) // Merge: + +#define META_E_EVENT_NOT_FOUND EMAKEHR(0x1190) // Merge: Method is duplicated but we cannot find the matching event info. +#define META_E_PROP_NOT_FOUND EMAKEHR(0x1191) // Merge: Method is duplicated but we cannot find the maching property info. +#define META_E_BAD_SIGNATURE EMAKEHR(0x1192) // Bad binary signature +#define META_E_BAD_INPUT_PARAMETER EMAKEHR(0x1193) // Bad input parameters +#define META_E_METHDIMPL_INCONSISTENT EMAKEHR(0x1194) // Merge: duplicated methods have inconsistent ImplFlags +#define META_E_MD_INCONSISTENCY EMAKEHR(0x1195) // Merge: Inconsistency in meta data +#define META_E_CANNOTRESOLVETYPEREF EMAKEHR(0x1196) // Cannot resolve typeref +#define META_S_DUPLICATE SMAKEHR(0x1197) // Attempt to define an object that already exists in valid scenerios. +#define META_E_STRINGSPACE_FULL EMAKEHR(0x1198) // No logical space left to create more user strings. +#define META_E_UNEXPECTED_REMAP EMAKEHR(0x1199) // A TokenRemap occurred which we weren't prepared to handle. +#define META_E_HAS_UNMARKALL EMAKEHR(0x119A) // Unmark all has been called already +#define META_E_MUST_CALL_UNMARKALL EMAKEHR(0x119B) // Must call UnmarkAll first before marking. +#define META_E_GENERICPARAM_INCONSISTENT EMAKEHR(0x119C) // Merge: duplicated types/methods have inconsistent GenericParams +#define META_E_EVENT_COUNTS EMAKEHR(0x119D) // Merge: different event counts in import and emit scopes. +#define META_E_PROPERTY_COUNTS EMAKEHR(0x119E) // Merge: different property counts in import and emit scopes. +#define META_E_TYPEDEF_MISSING EMAKEHR(0x119F) // Merge: An input scope has a TypeRef which should but doesn't have a matching TypeDef. + +#define TLBX_E_CANT_LOAD_MODULE EMAKEHR(0x11A0) // TypeLib export: can't open the module to export. +#define TLBX_E_CANT_LOAD_CLASS EMAKEHR(0x11A1) // TypeLib export: can't load a class. +#define TLBX_E_NULL_MODULE EMAKEHR(0x11A2) // TypeLib export: the hMod of a loaded class is 0; can't export it. +#define TLBX_E_NO_CLSID_KEY EMAKEHR(0x11A3) // TypeLib export: no CLSID or Interface subkey to HKCR. +#define TLBX_E_CIRCULAR_EXPORT EMAKEHR(0x11A4) // TypeLib export: attempt to export a CLB imported from a TLB. +#define TLBX_E_CIRCULAR_EXPORT2 EMAKEHR(0x1B52) // TypeLib export: attempt to export a CLB imported from a TLB. +#define TLBX_E_CIRCULAR_IMPORT EMAKEHR(0x11A5) // TypeLib import: attempt to import a TLB exported from a CLB. +#define TLBX_E_BAD_NATIVETYPE EMAKEHR(0x11A6) // TypeLib export: bad Native type in method signature. +#define TLBX_E_BAD_VTABLE EMAKEHR(0x11A7) // TypeLib import: non-increasing vtable (duplicate slots). +#define TLBX_E_CRM_NON_STATIC EMAKEHR(0x11A8) // TypeLib export: the COM register method is non static. +#define TLBX_E_CRM_INVALID_SIG EMAKEHR(0x11A9) // TypeLib export: the specified COM register method does not have the correct signature. +#define TLBX_E_CLASS_LOAD_EXCEPTION EMAKEHR(0x11AA) // TypeLib export: can't load, have the class load exception. +#define TLBX_E_UNKNOWN_SIGNATURE EMAKEHR(0x11AB) // TypeLib export: unknown element in signature. +#define TLBX_E_REFERENCED_TYPELIB EMAKEHR(0x11AC) // TypeLib import: reference to an external typelib. +#define TLBX_S_REFERENCED_TYPELIB SMAKEHR(0x11AC) // TypeLib import: reference to an external typelib. +#define TLBX_E_INVALID_NAMESPACE EMAKEHR(0x11AD) // TypeLib import: an imported typelib has an invalid namespace name. +#define TLBX_E_LAYOUT_ERROR EMAKEHR(0x11AE) // Typelib export: an error on Layout() +#define TLBX_E_NOTIUNKNOWN EMAKEHR(0x11AF) // Typelib import: Interface not derived from IUnknown. + +#define TLBX_E_NONVISIBLEVALUECLASS EMAKEHR(0x11B0) // Typelib export: Non COM visible value type in method signature. +#define TLBX_E_LPTSTR_NOT_ALLOWED EMAKEHR(0x11B1) // Typelib export: Types which contain the native type NATIVE_TYPE_LPTSTR are not allowed to be exported to COM. +#define TLBX_E_AUTO_CS_NOT_ALLOWED EMAKEHR(0x11B2) // Typelib export: Types with a char set of auto are not allowed to be exported to COM. +#define TLBX_S_NOSTDINTERFACE SMAKEHR(0x11B3) // Typelib export: Found an interface marked as IID_IDispatch or IID_IUnknown. +#define TLBX_S_DUPLICATE_DISPID SMAKEHR(0x11B4) // Typelib export: duplicate dispid found; ignored. +#define TLBX_E_ENUM_VALUE_INVALID EMAKEHR(0x11B5) // Typelib export: The enum value is not legal for a typelib. +#define TLBX_E_DUPLICATE_IID EMAKEHR(0x11B6) // Typelib export: Duplicate IID +#define TLBX_E_NO_NESTED_ARRAYS EMAKEHR(0x11B7) // Tyeplib export: detected nested arrays. +#define TLBX_E_PARAM_ERROR_NAMED EMAKEHR(0x11B8) // Typelib import: param type couldn't be converted. +#define TLBX_E_PARAM_ERROR_UNNAMED EMAKEHR(0x11B9) // Typelib import: param type couldn't be converted -- param name unknown. +#define TLBX_E_AGNOST_SIGNATURE EMAKEHR(0x11BA) // TypeLib export: size agnostic element in signature. +#define TLBX_E_CONVERT_FAIL EMAKEHR(0x11BB) // TypeLib export: exporter failed. +#define TLBX_W_DUAL_NOT_DISPATCH EMAKEHR(0x11BC) // Typelib import: [dual] interface not derived from IDispatch. +#define TLBX_E_BAD_SIGNATURE EMAKEHR(0x11BD) // Typelib export: unconvertable signature (use specific error for reporting!) +#define TLBX_E_ARRAY_NEEDS_NT_FIXED EMAKEHR(0x11BE) // Typelib export: non-fixed/non-safearray array in struct +#define TLBX_E_CLASS_NEEDS_NT_INTF EMAKEHR(0x11BF) // Typelib export: non-interface class in struct + +#define META_E_CA_INVALID_TARGET EMAKEHR(0x11C0) // Known custom attribute on invalid target. +#define META_E_CA_INVALID_VALUE EMAKEHR(0x11C1) // Known custom attribute had invalid value. +#define META_E_CA_INVALID_BLOB EMAKEHR(0x11C2) // Known custom attribute blob is bad format. +#define META_E_CA_REPEATED_ARG EMAKEHR(0x11C3) // Known custom attribute blob has repeated named argument. +#define META_E_CA_UNKNOWN_ARGUMENT EMAKEHR(0x11C4) // Known custom attrubte named arg not recognized. +#define META_E_CA_VARIANT_NYI EMAKEHR(0x11C5) // Known attribute named argument doesn't support variant. +#define META_E_CA_ARRAY_NYI EMAKEHR(0x11C6) // Known attribute named argument doesn't support array. +#define META_E_CA_UNEXPECTED_TYPE EMAKEHR(0x11C7) // Known attribute parser found unexpected type. +#define META_E_CA_INVALID_ARGTYPE EMAKEHR(0x11C8) // Known attribute parser only handles fields -- no properties. +#define META_E_CA_INVALID_ARG_FOR_TYPE EMAKEHR(0x11C9) // Known attribute parser found an argument that is invalid for the object it is applied to. +#define META_E_CA_INVALID_UUID EMAKEHR(0x11CA) // The format of the UUID was invalid. +#define META_E_CA_INVALID_MARSHALAS_FIELDS EMAKEHR(0x11CB) // The MarshalAs attribute has fields set that are not valid for the specified unmanaged type. +#define META_E_CA_NT_FIELDONLY EMAKEHR(0x11CC) // The specified unmanaged type is only valid on fields. +#define META_E_CA_NEGATIVE_PARAMINDEX EMAKEHR(0x11CD) // The parameter index cannot be negative. +#define META_E_CA_NEGATIVE_MULTIPLIER EMAKEHR(0x11CE) // The multiplier cannot be negative. +#define META_E_CA_NEGATIVE_CONSTSIZE EMAKEHR(0x11CF) // The constant size cannot be negative. + +#define META_E_CA_FIXEDSTR_SIZE_REQUIRED EMAKEHR(0x11D0) // A fixed string requires a size. +#define META_E_CA_CUSTMARSH_TYPE_REQUIRED EMAKEHR(0x11D1) // A custom marshaler requires the custom marshaler type. +#define META_E_CA_FILENAME_REQUIRED EMAKEHR(0x11D2) // A DllImport attribute requires a filename. +#define TLBX_W_NO_PROPS_IN_EVENTS EMAKEHR(0x11D3) // TypeLib import: Detected properties in a source dispinterface. +#define META_E_NOT_IN_ENC_MODE EMAKEHR(0x11D4) // SaveDelta was called without being in EnC mode +#define TLBX_W_ENUM_VALUE_TOOBIG SMAKEHR(0x11D5) // Typelib export: The enum value is not legal for a typelib. +#define META_E_METHOD_COUNTS EMAKEHR(0x11D6) // Merge: different method counts in import and emit scopes. +#define META_E_FIELD_COUNTS EMAKEHR(0x11D7) // Merge: different field counts in import and emit scopes. +#define META_E_PARAM_COUNTS EMAKEHR(0x11D8) // Merge: different param counts in import and emit scopes. +#define TLBX_W_EXPORTING_AUTO_LAYOUT SMAKEHR(0x11D9) // TypeLib export: Exporting an auto-layout type. +#define TLBX_E_TYPED_REF EMAKEHR(0x11DA) // TypeLib export: Exporting a TypedReference. +#define TLBX_W_DEFAULT_INTF_NOT_VISIBLE SMAKEHR(0x11DB) // TypeLib export: ComDefaultInterface is not COMVisible. +#define TLBX_W_BAD_SAFEARRAYFIELD_NO_ELEMENTVT SMAKEHR(0x11DE) // TypeLib export: System.Array SAFEARRAY field without a SafeArraySubType. +#define TLBX_W_LAYOUTCLASS_AS_INTERFACE SMAKEHR(0x11DF) // TypeLib export: Class with layout parameter of field marked with UnmanagedType.Interface +#define TLBX_I_GENERIC_BASE_TYPE SMAKEHR(0x11E0) // TypeLib export: type deriving from a generic type. +#define TLBX_E_BITNESS_MISMATCH EMAKEHR(0x11E1) // TypeLib export: bitness of assembly doesn't match bitness of output type library +#define TLBX_E_EVENT_WITH_NEWENUM EMAKEHR(0x11E2) // TypeLib import: source interface with NewEnum member. +#define TLBX_E_PROPGET_WITHOUT_RETURN EMAKEHR(0x11E3) // TypeLib import: propget without return type +#define META_E_MISMATCHED_VISIBLITY EMAKEHR(0x11E4) // Merge - Match found for type/method/etc but differs in visiblity +#define META_E_CA_BAD_FRIENDS_ARGS EMAKEHR(0x11E5) // InternalsVisibileTo can't have a version, culture, or processor architecture +#define META_E_CA_FRIENDS_SN_REQUIRED EMAKEHR(0x11E6) // Strong-name signed assemblies can only grant friend access to strong name-signed assemblies + + +// Return values from validator functions. +#define VLDTR_S_WRN SMAKEHR(0x1200) // Warnings found in the validator. +#define VLDTR_S_ERR SMAKEHR(0x1201) // Errors found in the validator. +#define VLDTR_S_WRNERR SMAKEHR(0x1202) // Warnings and errors found in the validator. + +// Validator structural errors. +#define VLDTR_E_RID_OUTOFRANGE EMAKEHR(0x1203) // Rid is out of range. +#define VLDTR_E_CDTKN_OUTOFRANGE EMAKEHR(0x1204) // Coded token type is out of range. +#define VLDTR_E_CDRID_OUTOFRANGE EMAKEHR(0x1205) // Coded rid is out of range. +#define VLDTR_E_STRING_INVALID EMAKEHR(0x1206) // String offset is invalid. +#define VLDTR_E_GUID_INVALID EMAKEHR(0x1207) // GUID offset is invalid. +#define VLDTR_E_BLOB_INVALID EMAKEHR(0x1208) // Blob offset if invalid. + +// Validator semantic errors. +#define VLDTR_E_MOD_MULTI EMAKEHR(0x1209) // Multiple module records found. +#define VLDTR_E_MOD_NULLMVID EMAKEHR(0x120A) // Module has null MVID. +#define VLDTR_E_TR_NAMENULL EMAKEHR(0x120B) // TypeRef name is NULL. +#define VLDTR_E_TR_DUP EMAKEHR(0x120C) // TypeRef has a dup. +#define VLDTR_E_TD_NAMENULL EMAKEHR(0x120D) // TypeDef name is NULL. +#define VLDTR_E_TD_DUPNAME EMAKEHR(0x120E) // TypeDef has a dup based on name+namespace. +#define VLDTR_E_TD_DUPGUID EMAKEHR(0x120F) // TypeDef has a dup based on GUID. +#define VLDTR_E_TD_NOTIFACEOBJEXTNULL EMAKEHR(0x1210) // TypeDef that's not an Interface and not System.Object extends nil parent. +#define VLDTR_E_TD_OBJEXTENDSNONNULL EMAKEHR(0x1211) // System.Object extends a non-nil parent. +#define VLDTR_E_TD_EXTENDSSEALED EMAKEHR(0x1212) // TypeDef extends sealed class. +#define VLDTR_E_TD_DLTNORTSPCL EMAKEHR(0x1213) // TypeDef is Deleted but not marked with RTSpecialName. +#define VLDTR_E_TD_RTSPCLNOTDLT EMAKEHR(0x1214) // TypeDef is marked RTSpecialName, but is not a Deleted record. +#define VLDTR_E_MI_DECLPRIV EMAKEHR(0x1215) // MethodImpl's Decl is private +#define VLDTR_E_AS_BADNAME EMAKEHR(0x1216) // Assembly [Ref] name has path and/or extension. +#define VLDTR_E_FILE_SYSNAME EMAKEHR(0x1217) // File has a system name (con, com, aux, etc.). +#define VLDTR_E_MI_BODYSTATIC EMAKEHR(0x1218) // MethodImpl's body is static. +#define VLDTR_E_TD_IFACENOTABS EMAKEHR(0x1219) // TypeDef is marked Interface but not Abstract. +#define VLDTR_E_TD_IFACEPARNOTNIL EMAKEHR(0x121A) // TypeDef is marked Interface but parent is not Nil. +#define VLDTR_E_TD_IFACEGUIDNULL EMAKEHR(0x121B) // TypeDef is marked Interface but GUID is NULL. +#define VLDTR_E_MI_DECLFINAL EMAKEHR(0x121C) // TMethodImpl's Decl is final. +#define VLDTR_E_TD_VTNOTSEAL EMAKEHR(0x121D) // TypeDef is marked ValueType but not marked Sealed. +#define VLDTR_E_PD_BADFLAGS EMAKEHR(0x121E) // Param has extra bits in flags. +#define VLDTR_E_IFACE_DUP EMAKEHR(0x121F) // InterfaceImpl has a dup. +#define VLDTR_E_MR_NAMENULL EMAKEHR(0x1220) // MemberRef name is NULL. +#define VLDTR_E_MR_VTBLNAME EMAKEHR(0x1221) // MemberRef has an invalid name, _VtblGap*. +#define VLDTR_E_MR_DELNAME EMAKEHR(0x1222) // MemberRef has an invalid name, _Deleted*. +#define VLDTR_E_MR_PARNIL EMAKEHR(0x1223) // MemberRef parent Nil in a PE file. +#define VLDTR_E_MR_BADCALLINGCONV EMAKEHR(0x1224) // MemberRef has invalid calling convention. +#define VLDTR_E_MR_NOTVARARG EMAKEHR(0x1225) // MemberRef has Method parent but calling convention is not VARARG. +#define VLDTR_E_MR_NAMEDIFF EMAKEHR(0x1226) // MemberRef name different from parent MethodDef. +#define VLDTR_E_MR_SIGDIFF EMAKEHR(0x1227) // MemberRef signature different from parent MethodDef. +#define VLDTR_E_MR_DUP EMAKEHR(0x1228) // MemberRef has a dup. +#define VLDTR_E_CL_TDAUTO EMAKEHR(0x1229) // ClassLayout parent TypeDef is marked AutoLayout. +#define VLDTR_E_CL_BADPCKSZ EMAKEHR(0x122A) // ClassLayout has bad PackingSize. +#define VLDTR_E_CL_DUP EMAKEHR(0x122B) // ClassLayout has dup. +#define VLDTR_E_FL_BADOFFSET EMAKEHR(0x122C) // FieldLayout2 has bad offset. +#define VLDTR_E_FL_TDNIL EMAKEHR(0x122D) // FieldLayout2 has field with nil parent. +#define VLDTR_E_FL_NOCL EMAKEHR(0x122E) // FieldLayout2 has no ClassLayout record. +#define VLDTR_E_FL_TDNOTEXPLCT EMAKEHR(0x122F) // FieldLayout2 parent TypeDef is not marked with ExplicitLayout. +#define VLDTR_E_FL_FLDSTATIC EMAKEHR(0x1230) // FieldLayout2 has field marked Static. +#define VLDTR_E_FL_DUP EMAKEHR(0x1231) // FieldLayout2 has a dup. +#define VLDTR_E_MODREF_NAMENULL EMAKEHR(0x1232) // ModuleRef name is NULL. +#define VLDTR_E_MODREF_DUP EMAKEHR(0x1233) // ModuleRef has a dup. +#define VLDTR_E_TR_BADSCOPE EMAKEHR(0x1234) // TypeRef has a bad resolution scope. +#define VLDTR_E_TD_NESTEDNOENCL EMAKEHR(0x1235) // TypeDef marked nested has no encloser. +#define VLDTR_E_TD_EXTTRRES EMAKEHR(0x1236) // TypeDef extends a TypeRef which resolves to a TypeDef in the same module. +#define VLDTR_E_SIGNULL EMAKEHR(0x1237) // Signature specified is zero-sized. +#define VLDTR_E_SIGNODATA EMAKEHR(0x1238) // Signature does not have enough data at specified byte. +#define VLDTR_E_MD_BADCALLINGCONV EMAKEHR(0x1239) // Method signature has invalid calling convention. +#define VLDTR_E_MD_THISSTATIC EMAKEHR(0x123A) // Method is marked static but has HASTHIS/EXPLICITTHIS set on the calling convention. +#define VLDTR_E_MD_NOTTHISNOTSTATIC EMAKEHR(0x123B) // Method is not marked static but is not HASTHIS/EXPLICITTHIS. +#define VLDTR_E_MD_NOARGCNT EMAKEHR(0x123C) // Method signature is missing the argument count. +#define VLDTR_E_SIG_MISSELTYPE EMAKEHR(0x123D) // Signature missing element type. +#define VLDTR_E_SIG_MISSTKN EMAKEHR(0x123E) // Signature missing token. +#define VLDTR_E_SIG_TKNBAD EMAKEHR(0x123F) // Signature has bad token. +#define VLDTR_E_SIG_MISSFPTR EMAKEHR(0x1240) // Signature is missing function pointer. +#define VLDTR_E_SIG_MISSFPTRARGCNT EMAKEHR(0x1241) // Signature has function pointer missing argument count. +#define VLDTR_E_SIG_MISSRANK EMAKEHR(0x1242) // Signature is missing rank specification. +#define VLDTR_E_SIG_MISSNSIZE EMAKEHR(0x1243) // Signature is missing count of sized dimensions. +#define VLDTR_E_SIG_MISSSIZE EMAKEHR(0x1244) // Signature is missing size of dimension. +#define VLDTR_E_SIG_MISSNLBND EMAKEHR(0x1245) // Signature is missing count of lower bounds. +#define VLDTR_E_SIG_MISSLBND EMAKEHR(0x1246) // Signature is missing a lower bound. +#define VLDTR_E_SIG_BADELTYPE EMAKEHR(0x1247) // Signature has bad element type. +#define VLDTR_E_SIG_MISSVASIZE EMAKEHR(0x1248) // Signature has value array missing size. +#define VLDTR_E_FD_BADCALLINGCONV EMAKEHR(0x1249) // Field signature has invalid calling convention. +#define VLDTR_E_MD_NAMENULL EMAKEHR(0x124A) // Method name is NULL. +#define VLDTR_E_MD_PARNIL EMAKEHR(0x124B) // Method has parent NIL. +#define VLDTR_E_MD_DUP EMAKEHR(0x124C) // Method has dup. +#define VLDTR_E_FD_NAMENULL EMAKEHR(0x124D) // Field name is NULL. +#define VLDTR_E_FD_PARNIL EMAKEHR(0x124E) // Field parent is Nil. +#define VLDTR_E_FD_DUP EMAKEHR(0x124F) // Field has dup. +#define VLDTR_E_AS_MULTI EMAKEHR(0x1250) // Multiple Assembly records found. +#define VLDTR_E_AS_NAMENULL EMAKEHR(0x1251) // Assembly name is NULL. +#define VLDTR_E_SIG_TOKTYPEMISMATCH EMAKEHR(0x1252) // E_T_VALUETYPE or E_T_CLASS. +#define VLDTR_E_CL_TDINTF EMAKEHR(0x1253) // Class layout on an Interface. +#define VLDTR_E_ASOS_OSPLTFRMIDINVAL EMAKEHR(0x1254) // AssemblyOS platform ID invalid. +#define VLDTR_E_AR_NAMENULL EMAKEHR(0x1255) // AssemblyRef name is NULL. +#define VLDTR_E_TD_ENCLNOTNESTED EMAKEHR(0x1256) // TypeDef not nested has encloser. +#define VLDTR_E_AROS_OSPLTFRMIDINVAL EMAKEHR(0x1257) // AssemblyRefOS has invalid platform ID. +#define VLDTR_E_FILE_NAMENULL EMAKEHR(0x1258) // File name is NULL. +#define VLDTR_E_CT_NAMENULL EMAKEHR(0x1259) // ExportedType name is NULL. +#define VLDTR_E_TD_EXTENDSCHILD EMAKEHR(0x125A) // TypeDef extends its own child. +#define VLDTR_E_MAR_NAMENULL EMAKEHR(0x125B) // ManifestResource name is NULL. +#define VLDTR_E_FILE_DUP EMAKEHR(0x125C) // File has dup. +#define VLDTR_E_FILE_NAMEFULLQLFD EMAKEHR(0x125D) // File name is fully qualified. +#define VLDTR_E_CT_DUP EMAKEHR(0x125E) // ExportedType has dup. +#define VLDTR_E_MAR_DUP EMAKEHR(0x125F) // ManifestResource has dup. +#define VLDTR_E_MAR_NOTPUBPRIV EMAKEHR(0x1260) // ManifestResource is neither Public not Private. +#define VLDTR_E_TD_ENUMNOVALUE EMAKEHR(0x1261) // Enum has no "value__" field. +#define VLDTR_E_TD_ENUMVALSTATIC EMAKEHR(0x1262) // Enum's "value__" field is static. +#define VLDTR_E_TD_ENUMVALNOTSN EMAKEHR(0x1263) // Enum's "value__" field is not SpecialName. +#define VLDTR_E_TD_ENUMFLDNOTST EMAKEHR(0x1264) // Enum's field is not static. +#define VLDTR_E_TD_ENUMFLDNOTLIT EMAKEHR(0x1265) // Enum's field is not literal. +#define VLDTR_E_TD_ENUMNOLITFLDS EMAKEHR(0x1266) // Enum has no literal fields. +#define VLDTR_E_TD_ENUMFLDSIGMISMATCH EMAKEHR(0x1267) // Enum's field sig does not match value__ sig. +#define VLDTR_E_TD_ENUMVALNOT1ST EMAKEHR(0x1268) // Enum's "value__" field is not first. +#define VLDTR_E_FD_NOTVALUERTSN EMAKEHR(0x1269) // Field is RTSpecialName but name is not "value__". +#define VLDTR_E_FD_VALUEPARNOTENUM EMAKEHR(0x126A) // Field "value__" in not Enum class. +#define VLDTR_E_FD_INSTINIFACE EMAKEHR(0x126B) // Instance field in interface. +#define VLDTR_E_FD_NOTPUBINIFACE EMAKEHR(0x126C) // Non-public field in interface. +#define VLDTR_E_FMD_GLOBALNOTPUBPRIVSC EMAKEHR(0x126D) // Global field/method neither Public nor PrivateScope. +#define VLDTR_E_FMD_GLOBALNOTSTATIC EMAKEHR(0x126E) // Global field/method not static. +#define VLDTR_E_FD_GLOBALNORVA EMAKEHR(0x126F) // Global field has no RVA. +#define VLDTR_E_MD_CTORZERORVA EMAKEHR(0x1270) // .ctor,.cctor has zero RVA. +#define VLDTR_E_FD_MARKEDNOMARSHAL EMAKEHR(0x1271) // Field is marked marshaled but has no marshaling rec. +#define VLDTR_E_FD_MARSHALNOTMARKED EMAKEHR(0x1272) // Field has marshaling rec but is not marked marshaled. +#define VLDTR_E_FD_MARKEDNODEFLT EMAKEHR(0x1273) // Field is marked HasDefault but has no const value. +#define VLDTR_E_FD_DEFLTNOTMARKED EMAKEHR(0x1274) // Field has const value rec but is not marked HasDefault. +#define VLDTR_E_FMD_MARKEDNOSECUR EMAKEHR(0x1275) // Field/method is marked HasSecurity but has no security rec. +#define VLDTR_E_FMD_SECURNOTMARKED EMAKEHR(0x1276) // Field/method has security rec but is not marked HasSecurity. +#define VLDTR_E_FMD_PINVOKENOTSTATIC EMAKEHR(0x1277) // Field/method is PInvoke but is not marked Static. +#define VLDTR_E_FMD_MARKEDNOPINVOKE EMAKEHR(0x1278) // Field/method is marked PInvoke but has no ImplMap. +#define VLDTR_E_FMD_PINVOKENOTMARKED EMAKEHR(0x1279) // Field/method has ImplMap but is not marked PInvoke. +#define VLDTR_E_FMD_BADIMPLMAP EMAKEHR(0x127A) // Field/method has invalid ImplMap +#define VLDTR_E_IMAP_BADMODREF EMAKEHR(0x127B) // ImplMap has invalid ModuleRef +#define VLDTR_E_IMAP_BADMEMBER EMAKEHR(0x127C) // ImplMap has invalid MemberForwarded +#define VLDTR_E_IMAP_BADIMPORTNAME EMAKEHR(0x127D) // ImplMap has invalid ImportName +#define VLDTR_E_IMAP_BADCALLCONV EMAKEHR(0x127E) // ImplMap has invalid call conv +#define VLDTR_E_FMD_BADACCESSFLAG EMAKEHR(0x127F) // Field/method has invalid access flag +#define VLDTR_E_FD_INITONLYANDLITERAL EMAKEHR(0x1280) // Field is InitOnly and Literal +#define VLDTR_E_FD_LITERALNOTSTATIC EMAKEHR(0x1281) // Field is Literal but not Static +#define VLDTR_E_FMD_RTSNNOTSN EMAKEHR(0x1282) // Field/method is RTSpec.Name but not Spec.Name +#define VLDTR_E_MD_ABSTPARNOTABST EMAKEHR(0x1283) // Method is abstract, parent is not +#define VLDTR_E_MD_NOTSTATABSTININTF EMAKEHR(0x1284) // Method not static or abstract in interface +#define VLDTR_E_MD_NOTPUBININTF EMAKEHR(0x1285) // Method not public in interface +#define VLDTR_E_MD_CTORININTF EMAKEHR(0x1286) // ctor in interface +#define VLDTR_E_MD_GLOBALCTORCCTOR EMAKEHR(0x1287) // global ctor or cctor +#define VLDTR_E_MD_CTORSTATIC EMAKEHR(0x1288) // static ctor +#define VLDTR_E_MD_CTORNOTSNRTSN EMAKEHR(0x1289) // ctor,cctor not marked SpecialName,RTSpecialName +#define VLDTR_E_MD_CTORVIRT EMAKEHR(0x128A) // virtual ctor,cctor +#define VLDTR_E_MD_CTORABST EMAKEHR(0x128B) // abstract ctor,cctor +#define VLDTR_E_MD_CCTORNOTSTATIC EMAKEHR(0x128C) // instance cctor +#define VLDTR_E_MD_ZERORVA EMAKEHR(0x128D) // RVA=0, method not abstract or pinvoke or runtime, or reverse +#define VLDTR_E_MD_FINNOTVIRT EMAKEHR(0x128E) // Method is final and not virtual +#define VLDTR_E_MD_STATANDFINORVIRT EMAKEHR(0x128F) // Method is static and final or virtual +#define VLDTR_E_MD_ABSTANDFINAL EMAKEHR(0x1290) // Method is abstract and final +#define VLDTR_E_MD_ABSTANDIMPL EMAKEHR(0x1291) // Method is abstract and implemented +#define VLDTR_E_MD_ABSTANDPINVOKE EMAKEHR(0x1292) // Method is abstract and pinvoke +#define VLDTR_E_MD_ABSTNOTVIRT EMAKEHR(0x1293) // Method is abstract and not virtual +#define VLDTR_E_MD_NOTABSTNOTIMPL EMAKEHR(0x1294) // Method is not abstract and not implemented +#define VLDTR_E_MD_NOTABSTBADFLAGSRVA EMAKEHR(0x1295) // Method is not abstract and not (RVA!=0 or pinvoke or runtime) +#define VLDTR_E_MD_PRIVSCOPENORVA EMAKEHR(0x1296) // Method is PrivateScope and has RVA==0 +#define VLDTR_E_MD_GLOBALABSTORVIRT EMAKEHR(0x1297) // Global method is abstract or virtual +#define VLDTR_E_SIG_LONGFORM EMAKEHR(0x1298) // Signature uses long form +#define VLDTR_E_MD_MULTIPLESEMANTICS EMAKEHR(0x1299) // Method has multiple semantics (warning) +#define VLDTR_E_MD_INVALIDSEMANTICS EMAKEHR(0x129A) // Method has invalid semantics (not event or prop) +#define VLDTR_E_MD_SEMANTICSNOTEXIST EMAKEHR(0x129B) // Method has semantics assoc that does not exist +#define VLDTR_E_MI_DECLNOTVIRT EMAKEHR(0x129C) // MethodImpl's Decl is not virtual +#define VLDTR_E_FMD_GLOBALITEM EMAKEHR(0x129D) // Global field/method (warning,CLS) +#define VLDTR_E_MD_MULTSEMANTICFLAGS EMAKEHR(0x129E) // Method has multiple semantic flags set +#define VLDTR_E_MD_NOSEMANTICFLAGS EMAKEHR(0x129F) // Method has no semantic flags set +#define VLDTR_E_FD_FLDINIFACE EMAKEHR(0x12A0) // Field in Interface (warning, CLS) +#define VLDTR_E_AS_HASHALGID EMAKEHR(0x12A1) // Unrecognized Hash Alg ID (warning) +#define VLDTR_E_AS_PROCID EMAKEHR(0x12A2) // Unrecognized Processor ID in Assembly(warning) +#define VLDTR_E_AR_PROCID EMAKEHR(0x12A3) // Unrecognized Processor ID in AssemblyRef(warning) +#define VLDTR_E_CN_PARENTRANGE EMAKEHR(0x12A4) // Constant: parent token out of range +#define VLDTR_E_AS_BADFLAGS EMAKEHR(0x12A5) // Invalid flags in Assembly +#define VLDTR_E_TR_HASTYPEDEF EMAKEHR(0x12A6) // There is TypeDef with same name as TypeRef (warning) +#define VLDTR_E_IFACE_BADIMPL EMAKEHR(0x12A7) // In InterfaceImpl, the implementing token is not TypeDef +#define VLDTR_E_IFACE_BADIFACE EMAKEHR(0x12A8) // In InterfaceImpl, the implemented token is not TypeDef or TypeRef +#define VLDTR_E_TD_SECURNOTMARKED EMAKEHR(0x12A9) // TypeDef has security rec but not marked HasSecurity +#define VLDTR_E_TD_MARKEDNOSECUR EMAKEHR(0x12AA) // TypeDef marked HasSecurity but has no security rec +#define VLDTR_E_MD_CCTORHASARGS EMAKEHR(0x12AB) // .cctor has arguments +#define VLDTR_E_CT_BADIMPL EMAKEHR(0x12AC) // ExportedType has invalid Implementation +#define VLDTR_E_MI_ALIENBODY EMAKEHR(0x12AD) // MethodImpl has body from other class +#define VLDTR_E_MD_CCTORCALLCONV EMAKEHR(0x12AE) // .cctor has invalid calling convention +#define VLDTR_E_MI_BADCLASS EMAKEHR(0x12AF) // MethodImpl has invalid Class token +#define VLDTR_E_MI_CLASSISINTF EMAKEHR(0x12B0) // MethodImpl declared in Interface +#define VLDTR_E_MI_BADDECL EMAKEHR(0x12B1) // MethodImpl has invalid MethodDeclaration token +#define VLDTR_E_MI_BADBODY EMAKEHR(0x12B2) // MethodImpl has invalid MethodBody token +#define VLDTR_E_MI_DUP EMAKEHR(0x12B3) // MethodImpl has duplicate +#define VLDTR_E_FD_BADPARENT EMAKEHR(0x12B4) // Bad field parent +#define VLDTR_E_MD_PARAMOUTOFSEQ EMAKEHR(0x12B5) // Param out of sequence (warning) +#define VLDTR_E_MD_PARASEQTOOBIG EMAKEHR(0x12B6) // Param's sequence num exceeds num of args +#define VLDTR_E_MD_PARMMARKEDNOMARSHAL EMAKEHR(0x12B7) // Param marked HasMarshal, has no marshaling info +#define VLDTR_E_MD_PARMMARSHALNOTMARKED EMAKEHR(0x12B8) // Param has marshaling info, not marked HasMarshal +#define VLDTR_E_MD_PARMMARKEDNODEFLT EMAKEHR(0x12BA) // Param marked HasDefault, has no const value +#define VLDTR_E_MD_PARMDEFLTNOTMARKED EMAKEHR(0x12BB) // Param has const value, not marked HasDefault +#define VLDTR_E_PR_BADSCOPE EMAKEHR(0x12BC) // Prop has invalid scope +#define VLDTR_E_PR_NONAME EMAKEHR(0x12BD) // Prop has no name +#define VLDTR_E_PR_NOSIG EMAKEHR(0x12BE) // Prop has no signature +#define VLDTR_E_PR_DUP EMAKEHR(0x12BF) // Prop has a duplicate +#define VLDTR_E_PR_BADCALLINGCONV EMAKEHR(0x12C0) // Prop has bad calling convention +#define VLDTR_E_PR_MARKEDNODEFLT EMAKEHR(0x12C1) // Prop marked HasDefault, has no const value +#define VLDTR_E_PR_DEFLTNOTMARKED EMAKEHR(0x12C2) // Prop has const value, not marked HasDefault +#define VLDTR_E_PR_BADSEMANTICS EMAKEHR(0x12C3) // Prop has method not (Setter,Getter, or Other) +#define VLDTR_E_PR_BADMETHOD EMAKEHR(0x12C4) // Prop has method with invalid token +#define VLDTR_E_PR_ALIENMETHOD EMAKEHR(0x12C5) // Prop has method from another class +#define VLDTR_E_CN_BLOBNOTNULL EMAKEHR(0x12C6) // Const has non-null blob when it should not +#define VLDTR_E_CN_BLOBNULL EMAKEHR(0x12C7) // Const has null value blob +#define VLDTR_E_EV_BADSCOPE EMAKEHR(0x12C8) // Event has invalid scope +#define VLDTR_E_EV_NONAME EMAKEHR(0x12CA) // Event has no name +#define VLDTR_E_EV_DUP EMAKEHR(0x12CB) // Event has a duplicate +#define VLDTR_E_EV_BADEVTYPE EMAKEHR(0x12CC) // Event has invalid EventType +#define VLDTR_E_EV_EVTYPENOTCLASS EMAKEHR(0x12CD) // Event's EventType is not a class +#define VLDTR_E_EV_BADSEMANTICS EMAKEHR(0x12CE) // Event has method not (AddOn,RemoveOn,Fire,Other) +#define VLDTR_E_EV_BADMETHOD EMAKEHR(0x12CF) // Event has method with invalid token +#define VLDTR_E_EV_ALIENMETHOD EMAKEHR(0x12D0) // Event has method from another class +#define VLDTR_E_EV_NOADDON EMAKEHR(0x12D1) // Event has no AddOn method +#define VLDTR_E_EV_NOREMOVEON EMAKEHR(0x12D2) // Event has no RemoveOn method +#define VLDTR_E_CT_DUPTDNAME EMAKEHR(0x12D3) // ExportedType has same name as TypeDef +#define VLDTR_E_MAR_BADOFFSET EMAKEHR(0x12D4) // MRes refers to non-PE file with offset !=0 +#define VLDTR_E_DS_BADOWNER EMAKEHR(0x12D5) // Decl.security has invalid owner token +#define VLDTR_E_DS_BADFLAGS EMAKEHR(0x12D6) // Decl.security has invalid action flags +#define VLDTR_E_DS_NOBLOB EMAKEHR(0x12D7) // Decl.security has no permission blob +#define VLDTR_E_MAR_BADIMPL EMAKEHR(0x12D8) // Manifest resource has invalid Implementation +#define VLDTR_E_MR_VARARGCALLINGCONV EMAKEHR(0x12DA) // MemberRef has VARARG calling conv. (CLS warning) +#define VLDTR_E_MD_CTORNOTVOID EMAKEHR(0x12DB) // .ctor,.cctor returning not void +#define VLDTR_E_EV_FIRENOTVOID EMAKEHR(0x12DC) // Fire method returning not void +#define VLDTR_E_AS_BADLOCALE EMAKEHR(0x12DD) // Invalid locale +#define VLDTR_E_CN_PARENTTYPE EMAKEHR(0x12DE) // Constant has parent of invalid type +#define VLDTR_E_SIG_SENTINMETHODDEF EMAKEHR(0x12DF) // E_T_SENTINEL in MethodDef signature +#define VLDTR_E_SIG_SENTMUSTVARARG EMAKEHR(0x12E0) // E_T_SENTINEL <=> VARARG +#define VLDTR_E_SIG_MULTSENTINELS EMAKEHR(0x12E1) // Multiple E_T_SENTINELs +#define VLDTR_E_SIG_LASTSENTINEL EMAKEHR(0x12E2) // E_T_SENTINEL not followed by type +#define VLDTR_E_SIG_MISSARG EMAKEHR(0x12E3) // Signature missing argument +#define VLDTR_E_SIG_BYREFINFIELD EMAKEHR(0x12E4) // Field of ByRef type +#define VLDTR_E_MD_SYNCMETHODINVTYPE EMAKEHR(0x12E5) // Synchronized method in value class +#define VLDTR_E_TD_NAMETOOLONG EMAKEHR(0x12E6) // TypeDef name too long +#define VLDTR_E_AS_PROCDUP EMAKEHR(0x12E7) // Duplicate Assembly Processor +#define VLDTR_E_ASOS_DUP EMAKEHR(0x12E8) // Duplicate Assembly OS (ID+ver.major+ver.minor) +#define VLDTR_E_MAR_BADFLAGS EMAKEHR(0x12E9) // Manifest Resource has bad flags +#define VLDTR_E_CT_NOTYPEDEFID EMAKEHR(0x12EA) // ExportedType has nil TypeDefId +#define VLDTR_E_FILE_BADFLAGS EMAKEHR(0x12EB) // File has bad flags +#define VLDTR_E_FILE_NULLHASH EMAKEHR(0x12EC) // File has no hash blob +#define VLDTR_E_MOD_NONAME EMAKEHR(0x12ED) // Module has no name +#define VLDTR_E_MOD_NAMEFULLQLFD EMAKEHR(0x12EE) // Module has fully-qualified name +#define VLDTR_E_TD_RTSPCLNOTSPCL EMAKEHR(0x12EF) // TypeDef is tdRTSpecialName but not tdSpecialName +#define VLDTR_E_TD_EXTENDSIFACE EMAKEHR(0x12F0) // TypeDef extends interface +#define VLDTR_E_MD_CTORPINVOKE EMAKEHR(0x12F1) // .ctor,.cctor is PInvokeImpl +#define VLDTR_E_TD_SYSENUMNOTCLASS EMAKEHR(0x12F2) // System.Enum is not a class +#define VLDTR_E_TD_SYSENUMNOTEXTVTYPE EMAKEHR(0x12F3) // System.Enum extends not System.ValueType +#define VLDTR_E_MI_SIGMISMATCH EMAKEHR(0x12F4) // MethodImpl's Decl and Body signatures mismatch +#define VLDTR_E_TD_ENUMHASMETHODS EMAKEHR(0x12F5) // TypeDef extends System.Enum but has methods +#define VLDTR_E_TD_ENUMIMPLIFACE EMAKEHR(0x12F6) // TypeDef extends System.Enum but impls interface(s) +#define VLDTR_E_TD_ENUMHASPROP EMAKEHR(0x12F7) // TypeDef extends System.Enum but has prop(s) +#define VLDTR_E_TD_ENUMHASEVENT EMAKEHR(0x12F8) // TypeDef extends System.Enum but has event(s) +#define VLDTR_E_TD_BADMETHODLST EMAKEHR(0x12F9) // TypeDef has MethodList > Nmethods+1 +#define VLDTR_E_TD_BADFIELDLST EMAKEHR(0x12FA) // TypeDef has FieldList > Nfields+1 +#define VLDTR_E_CN_BADTYPE EMAKEHR(0x12FB) // Constant has wrong type +#define VLDTR_E_TD_ENUMNOINSTFLD EMAKEHR(0x12FC) // Enum has no instance fields +#define VLDTR_E_TD_ENUMMULINSTFLD EMAKEHR(0x12FD) // Enum has multiple instance fields + + +#define VLDTR_E_INTERRUPTED EMAKEHR(0x12FE) // Validator has been interrupted by the VEHandler. +#define VLDTR_E_NOTINIT EMAKEHR(0x12FF) // Validator failed to initialize correctly. + +#define VLDTR_E_IFACE_NOTIFACE EMAKEHR(0x1B00) // Interface in InterfaceImpl is not marked tdInterface +#define VLDTR_E_FD_RVAHASNORVA EMAKEHR(0x1B01) // Field marked fdHasFieldRVA but has no RVA rec +#define VLDTR_E_FD_RVAHASZERORVA EMAKEHR(0x1B02) // Field marked fdHasFieldRVA has RVA =0 +#define VLDTR_E_MD_RVAANDIMPLMAP EMAKEHR(0x1B03) // Method has both RVA !=0 and ImplMap +#define VLDTR_E_TD_EXTRAFLAGS EMAKEHR(0x1B04) // TypeDef has extraneous bits in flags +#define VLDTR_E_TD_EXTENDSITSELF EMAKEHR(0x1B05) // TypeDef extends itself +#define VLDTR_E_TD_SYSVTNOTEXTOBJ EMAKEHR(0x1B06) // System.ValueType does not extend System.Object +#define VLDTR_E_TD_EXTTYPESPEC EMAKEHR(0x1B07) // Class extends TypeSpec (warning) +#define VLDTR_E_TD_VTNOSIZE EMAKEHR(0x1B09) // Value Class has zero size +#define VLDTR_E_TD_IFACESEALED EMAKEHR(0x1B0A) // Interface is sealed +#define VLDTR_E_NC_BADNESTED EMAKEHR(0x1B0B) // Bad "nested" token in NestedClass +#define VLDTR_E_NC_BADENCLOSER EMAKEHR(0x1B0C) // Bad "enclosing" token in NestedClass +#define VLDTR_E_NC_DUP EMAKEHR(0x1B0D) // Duplicate NestedClass record +#define VLDTR_E_NC_DUPENCLOSER EMAKEHR(0x1B0E) // Duplicate NestedClass with different encloser +#define VLDTR_E_FRVA_ZERORVA EMAKEHR(0x1B0F) // RVA=0 in FieldRVA record +#define VLDTR_E_FRVA_BADFIELD EMAKEHR(0x1B10) // Invalid field token in FieldRVA record +#define VLDTR_E_FRVA_DUPRVA EMAKEHR(0x1B11) // Duplicate RVA in FieldRVA record +#define VLDTR_E_FRVA_DUPFIELD EMAKEHR(0x1B12) // Duplicate field in FieldRVA record +#define VLDTR_E_EP_BADTOKEN EMAKEHR(0x1B13) // Bad token as entry point in CLR header +#define VLDTR_E_EP_INSTANCE EMAKEHR(0x1B14) // Entry point in CLR header is a token of instance method +#define VLDTR_E_TD_ENUMFLDBADTYPE EMAKEHR(0x1B15) // Enum has non-integral underlying type +#define VLDTR_E_MD_BADRVA EMAKEHR(0x1B16) // Method has bogus RVA +#define VLDTR_E_FD_LITERALNODEFAULT EMAKEHR(0x1B17) // Literal field has no const value +#define VLDTR_E_IFACE_METHNOTIMPL EMAKEHR(0x1B18) // Class implementing an interface doesn't impl.one of methods +#define VLDTR_E_CA_BADPARENT EMAKEHR(0x1B19) // CA has invalid owner +#define VLDTR_E_CA_BADTYPE EMAKEHR(0x1B1A) // CA has invalid type +#define VLDTR_E_CA_NOTCTOR EMAKEHR(0x1B1B) // CA type is not .ctor +#define VLDTR_E_CA_BADSIG EMAKEHR(0x1B1C) // CA type has bad signature +#define VLDTR_E_CA_NOSIG EMAKEHR(0x1B1D) // CA type has no signature +#define VLDTR_E_CA_BADPROLOG EMAKEHR(0x1B1E) // CA blob has bad prolog (not 0x01 0x00) +#define VLDTR_E_MD_BADLOCALSIGTOK EMAKEHR(0x1B1F) // Method has invalid LocalSig token +#define VLDTR_E_MD_BADHEADER EMAKEHR(0x1B20) // Method has invalid header +#define VLDTR_E_EP_TOOMANYARGS EMAKEHR(0x1B21) // Entry point has more than one arg +#define VLDTR_E_EP_BADRET EMAKEHR(0x1B22) // Entry point has bad return type +#define VLDTR_E_EP_BADARG EMAKEHR(0x1B23) // Entry point has bad argument +#define VLDTR_E_SIG_BADVOID EMAKEHR(0x1B24) // Illegal "void" in signature +#define VLDTR_E_IFACE_METHMULTIMPL EMAKEHR(0x1B25) // Multiple implementation of method +//@GENERICS +#define VLDTR_E_GP_NAMENULL EMAKEHR(0x1B26) // GenericParam name is NULL +#define VLDTR_E_GP_OWNERNIL EMAKEHR(0x1B27) // GenericParam has nil owner. +#define VLDTR_E_GP_DUPNAME EMAKEHR(0x1B28) // GenericParam has duplicate by owner and name. +#define VLDTR_E_GP_DUPNUMBER EMAKEHR(0x1B29) // GenericParam has duplicate by owner and number. +#define VLDTR_E_GP_NONSEQ_BY_OWNER EMAKEHR(0x1B2A) // GenericParam is non sequential by owner +#define VLDTR_E_GP_NONSEQ_BY_NUMBER EMAKEHR(0x1B2B) // GenericParam is non sequential by number +#define VLDTR_E_GP_UNEXPECTED_OWNER_FOR_VARIANT_VAR EMAKEHR(0x1B2C) // GenericParam has variance but its owner is not an interface or delegate +#define VLDTR_E_GP_ILLEGAL_VARIANT_MVAR EMAKEHR(0x1B2D) // GenericParam is a method type parameter and must be non-variant +#define VLDTR_E_GP_ILLEGAL_VARIANCE_FLAGS EMAKEHR(0x1B2E) // GenericParam has illegal value for variance flags +#define VLDTR_E_GP_REFANDVALUETYPE EMAKEHR(0x1B2F) // GenericParam has incompatible special constraints reference type and valuetype +#define VLDTR_E_GPC_OWNERNIL EMAKEHR(0x1B30) // GenericParamConstraint has nil owner +#define VLDTR_E_GPC_DUP EMAKEHR(0x1B31) // GenericParamConstraint has duplicate by owner and constraint +#define VLDTR_E_GPC_NONCONTIGUOUS EMAKEHR(0x1B32) // GenericParamConstraint is non-contiguous with preceeding constraints for same owner +#define VLDTR_E_MS_METHODNIL EMAKEHR(0x1B33) // MethodSpec has nil method +#define VLDTR_E_MS_DUP EMAKEHR(0x1B34) // MethodSpec has duplicate based own method and instantiation +#define VLDTR_E_MS_BADCALLINGCONV EMAKEHR(0x1B35) // MethodSpec signature has invalid calling convention +#define VLDTR_E_MS_MISSARITY EMAKEHR(0x1B36) // MethodSpec signature is missing arity specification +#define VLDTR_E_MS_MISSARG EMAKEHR(0x1B37) // MethodSpec signature is missing type argument +#define VLDTR_E_MS_ARITYMISMATCH EMAKEHR(0x1B38) // MethodSpec arity of generic method and instantiation do not match +#define VLDTR_E_MS_METHODNOTGENERIC EMAKEHR(0x1B39) // MethodSpec method is not generic +#define VLDTR_E_SIG_MISSARITY EMAKEHR(0x1B3A) // Signature missing arity of instantiated generic type +#define VLDTR_E_SIG_ARITYMISMATCH EMAKEHR(0x1B3B) // Signature has generic type of arity instantiated at different arity +#define VLDTR_E_MD_GENERIC_CCTOR EMAKEHR(0x1B3C) // Method cannot be both generic and a class constructor +#define VLDTR_E_MD_GENERIC_CTOR EMAKEHR(0x1B3D) // Method cannot be both generic and an instance constructor +#define VLDTR_E_MD_GENERIC_IMPORT EMAKEHR(0x1B3E) // Method cannot be both generic and defined on an imported type +#define VLDTR_E_MD_GENERIC_BADCALLCONV EMAKEHR(0x1B3F) // Method cannot be both generic and have non-default calling convention +#define VLDTR_E_EP_GENERIC_METHOD EMAKEHR(0x1B40) // Entry point in CLR header is the token for a generic method +#define VLDTR_E_MD_MISSARITY EMAKEHR(0x1B41) // Method signature is generic but is missing its arity +#define VLDTR_E_MD_ARITYZERO EMAKEHR(0x1B42) // Method signature is generic but its arity is zero +#define VLDTR_E_SIG_ARITYZERO EMAKEHR(0x1B43) // Signature has generic type instantiated at arity 0 +#define VLDTR_E_MS_ARITYZERO EMAKEHR(0x1B44) // MethodSpec signature has arity 0 +#define VLDTR_E_MD_GPMISMATCH EMAKEHR(0x1B45) // MethodDef signature has arity n but owns m GenericParams +#define VLDTR_E_EP_GENERIC_TYPE EMAKEHR(0x1B46) // Entry point in CLR header is the token for a method in a generic type +#define VLDTR_E_MI_DECLNOTGENERIC EMAKEHR(0x1B47) // MethodImpl overrides non-generic method with generic method +#define VLDTR_E_MI_IMPLNOTGENERIC EMAKEHR(0x1B48) // MethodImpl overrides non-generic method with generic method +#define VLDTR_E_MI_ARITYMISMATCH EMAKEHR(0x1B49) // MethodImpl overrides generic method of arity n with generic method of arity m +#define VLDTR_E_TD_EXTBADTYPESPEC EMAKEHR(0x1B4A) // TypeDef extends a TypeSpec that is not an instantiated type +#define VLDTR_E_SIG_BYREFINST EMAKEHR(0x1B4B) // Signature has type instantiated at byref at offset i +#define VLDTR_E_MS_BYREFINST EMAKEHR(0x1B4C) // Signature has type instantiated at byref at offset i +#define VLDTR_E_TS_EMPTY EMAKEHR(0x1B4D) // TypeSpec has empty signature +#define VLDTR_E_TS_HASSENTINALS EMAKEHR(0x1B4E) // TypeSpec has signature containing one or more sentinals +#define VLDTR_E_TD_GENERICHASEXPLAYOUT EMAKEHR(0x1B4F) // TypeDef is generic but has explicit layout +#define VLDTR_E_SIG_BADTOKTYPE EMAKEHR(0x1B50) // Signature has token following ELEMENT_TYPE_CLASS (_VALUETYPE) that is not a TypeDef or TypeRef +#define VLDTR_E_IFACE_METHNOTIMPLTHISMOD EMAKEHR(0x1B51) // Warn:Class doesn't implement interface method in this module + +//**** Common Language Runtime Debugging Services errors +#define CORDBG_E_UNRECOVERABLE_ERROR EMAKEHR(0x1300) // Unrecoverable API error. +#define CORDBG_E_PROCESS_TERMINATED EMAKEHR(0x1301) // Process was terminated. +#define CORDBG_E_PROCESS_NOT_SYNCHRONIZED EMAKEHR(0x1302) // Process not synchronized. +#define CORDBG_E_CLASS_NOT_LOADED EMAKEHR(0x1303) // A class is not loaded. +#define CORDBG_E_IL_VAR_NOT_AVAILABLE EMAKEHR(0x1304) // An IL variable is not available at the + // current native IP. +#define CORDBG_E_BAD_REFERENCE_VALUE EMAKEHR(0x1305) // A reference value was found to be bad + // during dereferencing. +#define CORDBG_E_FIELD_NOT_AVAILABLE EMAKEHR(0x1306) // A field in a class is not available, + // because the runtime optimized it away. +#define CORDBG_E_NON_NATIVE_FRAME EMAKEHR(0x1307) // "Native frame only" operation on + // non-native frame +#define CORDBG_E_NONCONTINUABLE_EXCEPTION EMAKEHR(0x1308) // Continue on non-continuable exception +#define CORDBG_E_CODE_NOT_AVAILABLE EMAKEHR(0x1309) // The code is currently unavailable +#define CORDBG_E_FUNCTION_NOT_IL EMAKEHR(0x130A) // Attempt to get a ICorDebugFunction for + // a function that is not IL. +#define CORDBG_S_BAD_START_SEQUENCE_POINT SMAKEHR(0x130B) // Attempt to SetIP not at a sequence point +#define CORDBG_S_BAD_END_SEQUENCE_POINT SMAKEHR(0x130C) // Attempt to SetIP when not going to a + // sequence point. If both this and + // CORDBG_E_BAD_START_SEQUENCE_POINT are + // true, only CORDBG_E_BAD_START_SEQUENCE_POINT + // will be reported. +#define CORDBG_S_INSUFFICIENT_INFO_FOR_SET_IP SMAKEHR(0x130D) // SetIP is possible, but the debugger doesn't + // have enough info to fix variable locations, + // GC refs, or anything else. Use at your own + // risk. +#define CORDBG_E_CANT_SET_IP_INTO_FINALLY EMAKEHR(0x130E) // SetIP isn't possible, because SetIP would + // move EIP from outside of an exception + // handling finally clause to a point inside + // of one. +#define CORDBG_E_CANT_SET_IP_OUT_OF_FINALLY EMAKEHR(0x130F) // SetIP isn't possible because it would move + // EIP from within an exception handling finally + // clause to a point outside of one. +#define CORDBG_E_CANT_SET_IP_INTO_CATCH EMAKEHR(0x1310) // SetIP isn't possible, because SetIP would + // move EIP from outside of an exception + // handling catch clause to a point inside of + // one. +#define CORDBG_E_SET_IP_NOT_ALLOWED_ON_NONLEAF_FRAME EMAKEHR(0x1311) // Setip cannot be done on any frame except + // the leaf frame. +#define CORDBG_E_SET_IP_IMPOSSIBLE EMAKEHR(0x1312) // SetIP isn't allowed. For example, there is + // insufficient memory to perform SetIP. +#define CORDBG_E_FUNC_EVAL_BAD_START_POINT EMAKEHR(0x1313) // Func eval can't work if we're, for example, + // not stopped at a GC safe point. +#define CORDBG_E_INVALID_OBJECT EMAKEHR(0x1314) // This object value is no longer valid. +#define CORDBG_E_FUNC_EVAL_NOT_COMPLETE EMAKEHR(0x1315) // If you call CordbEval::GetResult before the + // func eval has finished, you'll get this + // result. +#define CORDBG_S_FUNC_EVAL_HAS_NO_RESULT SMAKEHR(0x1316) // Some Func evals will lack a return value, + // such as those whose return type is void. +#define CORDBG_S_VALUE_POINTS_TO_VOID SMAKEHR(0x1317) // The Debugging API doesn't support + // dereferencing pointers of type void. +#define CORDBG_E_INPROC_NOT_IMPL EMAKEHR(0x1318) // The inproc version of the debugging API + // doesn't implement this function, +#define CORDBG_S_FUNC_EVAL_ABORTED SMAKEHR(0x1319) // The func eval completed, but was aborted. +#define CORDBG_E_STATIC_VAR_NOT_AVAILABLE EMAKEHR(0x131A) // A static variable isn't available because + // it hasn't been initialized yet. +#define CORDBG_E_OBJECT_IS_NOT_COPYABLE_VALUE_CLASS EMAKEHR(0x131B) // Can't copy a VC with object refs in it. +#define CORDBG_E_CANT_SETIP_INTO_OR_OUT_OF_FILTER EMAKEHR(0x131C) // SetIP can't leave or enter a filter +#define CORDBG_E_CANT_CHANGE_JIT_SETTING_FOR_ZAP_MODULE EMAKEHR(0x131D) // You can't change JIT settings for ZAP + // modules. +#define CORDBG_E_CANT_SET_IP_OUT_OF_FINALLY_ON_WIN64 EMAKEHR(0x131E) // SetIP isn't possible because it would move + // EIP from within a finally clause to a point + // outside of one on WIN64 platforms. +#define CORDBG_E_CANT_SET_IP_OUT_OF_CATCH_ON_WIN64 EMAKEHR(0x131F) // SetIP isn't possible because it would move + // EIP from within a catch clause to a point + // outside of one on WIN64 platforms. + +#define CORDBG_E_REMOTE_CONNECTION_CONN_RESET EMAKEHR(0x1320) // The remote device closed the connection. +#define CORDBG_E_REMOTE_CONNECTION_KEEP_ALIVE EMAKEHR(0x1321) // The connection was closed due to akeep alive failure. +#define CORDBG_E_REMOTE_CONNECTION_FATAL_ERROR EMAKEHR(0x1322) // Generic error that the device connection has been broken with no chance for recovery. + +#define CORDBG_E_CANT_SET_TO_JMC EMAKEHR(0x1323) // Can't use JMC on this code (likely wrong jit settings). + +#define CORDBG_E_BAD_THREAD_STATE EMAKEHR(0x132d) // The state of the thread is invalid. +#define CORDBG_E_DEBUGGER_ALREADY_ATTACHED EMAKEHR(0x132e) // This process has already been attached to +#define CORDBG_E_SUPERFLOUS_CONTINUE EMAKEHR(0x132f) // Returned from a call to Continue that was + // Not matched with a stopping event. +#define CORDBG_E_SET_VALUE_NOT_ALLOWED_ON_NONLEAF_FRAME EMAKEHR(0x1330) // Can't perfrom SetValue on non-leaf frames. +#define CORDBG_E_ENC_EH_MAX_NESTING_LEVEL_CANT_INCREASE EMAKEHR(0x1331) // When doing EnC, some JITters don't let you + // increase the maximum level to which + // exception handling can be nested. +#define CORDBG_E_ENC_MODULE_NOT_ENC_ENABLED EMAKEHR(0x1332) // Tried to do EnC on a module that wasn't + // started in EnC mode. +#define CORDBG_E_SET_IP_NOT_ALLOWED_ON_EXCEPTION EMAKEHR(0x1333) // Setip cannot be done on any exception +#define CORDBG_E_VARIABLE_IS_ACTUALLY_LITERAL EMAKEHR(0x1334) // The 'variable' doesn't exist because it is a + // literal optimized away by the compiler - ask + // Metadata for it's default value, instead. +#define CORDBG_E_PROCESS_DETACHED EMAKEHR(0x1335) // Process has been detached from +#define CORDBG_E_ENC_METHOD_SIG_CHANGED EMAKEHR(0x1336) // Not allowed to change the signature of an + // existing method - compiler should make new method + // instead. +#define CORDBG_E_ENC_METHOD_NO_LOCAL_SIG EMAKEHR(0x1337) // Can't get the local signature for the method + // we're trying to EnC. +#define CORDBG_E_ENC_CANT_ADD_FIELD_TO_VALUE_OR_LAYOUT_CLASS EMAKEHR(0x1338) // Adding a field to a value or layout class is prohibitted, + // since we can't guarantee the new field is contiguous to + // VC's on the stack, embedded in other objects, etc. +#define CORDBG_E_ENC_CANT_CHANGE_FIELD EMAKEHR(0x1339) // Once you've got a field, you're not allowed to change + // it, since that would change the size of the type it belongs to. +#define CORDBG_E_ENC_CANT_ADD_NON_PRIVATE_MEMBER EMAKEHR(0x133A) // Only support addition of private members. +#define CORDBG_E_FIELD_NOT_STATIC EMAKEHR(0x133B) // Returned if someone tries to call GetStaticFieldValue + // on a non-static field +#define CORDBG_E_FIELD_NOT_INSTANCE EMAKEHR(0x133C) // Returned if someone tries to call GetStaticFieldValue + // on a non-instance field +#define CORDBG_E_ENC_ZAPPED_WITHOUT_ENC EMAKEHR(0x133D) // If a zap file was created without the EnC flag set, then + // we can't do EnC on it, no matter what. +#define CORDBG_E_ENC_BAD_METHOD_INFO EMAKEHR(0x133E) // Lacking information about method. +#define CORDBG_E_ENC_JIT_CANT_UPDATE EMAKEHR(0x133F) // The JIT is unable to update the method. +#define CORDBG_E_ENC_MISSING_CLASS EMAKEHR(0x1340) // An internal structure about the class is missing +#define CORDBG_E_ENC_INTERNAL_ERROR EMAKEHR(0x1341) // Generic message for "Something user doesn't control went wrong" message. +#define CORDBG_E_ENC_HANGING_FIELD EMAKEHR(0x1342) // The field was added via enc after the class was loaded, and so instead of + // the field being contiguous with the other fields, it's 'hanging' off the + // instance, so the right side will have to go & get (instance-specific + // info based on the particular object. +#define CORDBG_E_MODULE_NOT_LOADED EMAKEHR(0x1343) // If the module isn't loaded, including if it's been unloaded. + +#define CORDBG_E_ENC_CANT_CHANGE_SUPERCLASS EMAKEHR(0x1344) // Not allowed to change which class something inherits from +#define CORDBG_E_UNABLE_TO_SET_BREAKPOINT EMAKEHR(0x1345) // Can't set a breakpoint here. +#define CORDBG_E_DEBUGGING_NOT_POSSIBLE EMAKEHR(0x1346) // Debugging isn't possible due to an incompatability within the CLR implementation. +#define CORDBG_E_KERNEL_DEBUGGER_ENABLED EMAKEHR(0x1347) // Debugging isn't possible because a kernel debugger is enabled on the system. +#define CORDBG_E_KERNEL_DEBUGGER_PRESENT EMAKEHR(0x1348) // Debugging isn't possible because a kernel debugger is present on the system. +#define CORDBG_E_HELPER_THREAD_DEAD EMAKEHR(0x1349) // The debugger's internal helper thread is dead. +#define CORDBG_E_INTERFACE_INHERITANCE_CANT_CHANGE EMAKEHR(0x134A) // Not allowed to change interface inheritance. +#define CORDBG_E_INCOMPATIBLE_PROTOCOL EMAKEHR(0x134B) // The debugger's protocol is incompatible with the debuggee. +#define CORDBG_E_TOO_MANY_PROCESSES EMAKEHR(0x134C) // The debugger can only handle a finite number of debuggees. +#define CORDBG_E_INTEROP_NOT_SUPPORTED EMAKEHR(0x134D) // Interop is not allowed on a win9x platform +#define CORDBG_E_NO_REMAP_BREAKPIONT EMAKEHR(0x134E) // Cannot call RemapFunction until have received RemapBreakpoint +#define CORDBG_E_OBJECT_NEUTERED EMAKEHR(0x134F) // Object has been neutered (it's in a zombie state). +// NOTE! YOU CANNOT PUT MORE ERRORS HERE! They run into the range for profiling errors. All new +// new error need to be added below (search for cordbg_e_ in your editor). + +//**** Common Language Runtime Profiling Services errors +#define CORPROF_E_FUNCTION_NOT_COMPILED EMAKEHR(0x1350) // Function not yet compiled. +#define CORPROF_E_DATAINCOMPLETE EMAKEHR(0x1351) // The ID is not fully loaded/defined yet. +#define CORPROF_E_NOT_REJITABLE_METHODS EMAKEHR(0x1352) // The Module is not configured for updateable methods. +#define CORPROF_E_CANNOT_UPDATE_METHOD EMAKEHR(0x1353) // The Method could not be updated for re-jit. +#define CORPROF_E_FUNCTION_NOT_IL EMAKEHR(0x1354) // The Method has no associated IL +#define CORPROF_E_NOT_MANAGED_THREAD EMAKEHR(0x1355) // The thread has never run managed code before +#define CORPROF_E_CALL_ONLY_FROM_INIT EMAKEHR(0x1356) // The function may only be called during profiler init +#define CORPROF_E_INPROC_NOT_ENABLED EMAKEHR(0x1357) // Inprocess debugging must be enabled during init + // Also returned when BeginInprocDebugging not called + // before using the inprocess debugging services +#define CORPROF_E_JITMAPS_NOT_ENABLED EMAKEHR(0x1358) // Can't get a JIT map becuase they are not enabled +#define CORPROF_E_INPROC_ALREADY_BEGUN EMAKEHR(0x1359) // If a profiler tries to call BeginInprocDebugging more than + // once, it will get this error. +#define CORPROF_E_INPROC_NOT_AVAILABLE EMAKEHR(0x135A) // States that inprocess debugging not allowed at this point + // (for example during GC callbacks or RuntimeSuspention callbacks +#define CORPROF_E_NOT_YET_AVAILABLE EMAKEHR(0x135B) // This is a general error used to indicated that the information + // requested is not yet available +#define CORPROF_E_TYPE_IS_PARAMETERIZED EMAKEHR(0x135C) // The given type is a generic and cannot be used with this method. +#define CORPROF_E_FUNCTION_IS_PARAMETERIZED EMAKEHR(0x135D) // The given function is a generic and cannot be used with this method. +#define CORPROF_E_STACKSNAPSHOT_INVALID_TGT_THREAD EMAKEHR(0x135E) // A profiler tried to walk the stack of an invalid thread +#define CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX EMAKEHR(0x135F) // A profiler can not walk a thread that is currently executing unmanaged code +#define CORPROF_E_STACKSNAPSHOT_UNSAFE EMAKEHR(0x1360) // A stackwalk at this point may cause dead locks or data corruption +#define CORPROF_E_STACKSNAPSHOT_ABORTED EMAKEHR(0x1361) // Stackwalking callback requested the walk to abort +#define CORPROF_E_LITERALS_HAVE_NO_ADDRESS EMAKEHR(0x1362) // Returned when asked for the address of a static that is a literal. +#define CORPROF_E_UNSUPPORTED_CALL_SEQUENCE EMAKEHR(0x1363) // A call was made at an unsupported time (e.g., API illegally called asynchronously) +#define CORPROF_E_ASYNCHRONOUS_UNSAFE EMAKEHR(0x1364) // A legal asynchronous call was made at an unsafe time (e.g., CLR locks are held) +#define CORPROF_E_CLASSID_IS_ARRAY EMAKEHR(0x1365) // The specified ClassID cannot be inspected by this function because it is an array +#define CORPROF_E_CLASSID_IS_COMPOSITE EMAKEHR(0x1366) // The specified ClassID is a non-array composite type (e.g., ref) and cannot be inspected + + +//**** Security errors +#define SECURITY_E_XML_TO_ASN_ENCODING EMAKEHR(0x1400) // Failed to convert XML to ASN +#define SECURITY_E_INCOMPATIBLE_SHARE EMAKEHR(0x1401) // Loading this assembly would produce a different grant set from other instances +#define SECURITY_E_UNVERIFIABLE EMAKEHR(0x1402) // Unverifable code failed policy check +#define SECURITY_E_INCOMPATIBLE_EVIDENCE EMAKEHR(0x1403) // Assembly already loaded without additional security evidence. + +//**** Reserved. +#define CLDB_E_INTERNALERROR EMAKEHR(0x1fff) + +// ****************** +// Debugger & Profiler errors +// ****************** + + +// ****************** +// Security errors +// ****************** + +#define CORSEC_E_DECODE_SET EMAKEHR(0x1410) // Failure decoding permission set +#define CORSEC_E_ENCODE_SET EMAKEHR(0x1411) // Failure encoding permission set +#define CORSEC_E_UNSUPPORTED_FORMAT EMAKEHR(0x1412) // Unrecognized encoding format +#define SN_CRYPTOAPI_CALL_FAILED EMAKEHR(0x1413) // StrongName APIs not supported on system +#define CORSEC_E_CRYPTOAPI_CALL_FAILED EMAKEHR(0x1413) // StrongName APIs not supported on system +#define SN_NO_SUITABLE_CSP EMAKEHR(0x1414) // StrongName APIs couldn't locate a matching CSP +#define CORSEC_E_NO_SUITABLE_CSP EMAKEHR(0x1414) // StrongName APIs couldn't locate a matching CSP +#define CORSEC_E_INVALID_ATTR EMAKEHR(0x1415) // Invalid security custom attribute +#define CORSEC_E_POLICY_EXCEPTION EMAKEHR(0x1416) // PolicyException thrown +#define CORSEC_E_MIN_GRANT_FAIL EMAKEHR(0x1417) // Failed to grant minimum permission requests +#define CORSEC_E_NO_EXEC_PERM EMAKEHR(0x1418) // Failed to grant permission to execute +#define CORSEC_E_XMLSYNTAX EMAKEHR(0x1419) // XML Syntax error +#define CORSEC_E_INVALID_STRONGNAME EMAKEHR(0x141a) // Strong name validation failed +#define CORSEC_E_MISSING_STRONGNAME EMAKEHR(0x141b) // Assembly is not strong named +#define CORSEC_E_CONTAINER_NOT_FOUND EMAKEHR(0x141c) // Strong name key container not found +#define CORSEC_E_INVALID_IMAGE_FORMAT EMAKEHR(0x141d) // Invalid assembly file format +#define CORSEC_E_INVALID_PUBLICKEY EMAKEHR(0x141e) // Invalid assembly public key +#define CORSEC_E_SIGNATURE_MISMATCH EMAKEHR(0x1420) // Signature size mismatch + +//**** crypto errors 1430 -- 1439 +#define CORSEC_E_CRYPTO EMAKEHR(0x1430) // generic CryptographicException +#define CORSEC_E_CRYPTO_UNEX_OPER EMAKEHR(0x1431) // generic CryptographicUnexpectedOperationException + +//**** security custom attribute errors 143a -- 144f +#define CORSECATTR_E_BAD_ATTRIBUTE EMAKEHR(0x143a) // Generic problem with a custom attribute +#define CORSECATTR_E_MISSING_CONSTRUCTOR EMAKEHR(0x143b) // Missing a required constructor +#define CORSECATTR_E_FAILED_TO_CREATE_PERM EMAKEHR(0x143c) // Unable to create a permission for this attribute +#define CORSECATTR_E_BAD_ACTION_ASM EMAKEHR(0x143d) // SecurityAction type invalid on assembly +#define CORSECATTR_E_BAD_ACTION_OTHER EMAKEHR(0x143e) // SecurityAction type invalid on types and methods +#define CORSECATTR_E_BAD_PARENT EMAKEHR(0x143f) // Security custom attribute attached to invalid parent +#define CORSECATTR_E_TRUNCATED EMAKEHR(0x1440) // Bad custom attribute serialized blob +#define CORSECATTR_E_BAD_VERSION EMAKEHR(0x1441) // Bad custom attribute serialized blob version +#define CORSECATTR_E_BAD_ACTION EMAKEHR(0x1442) // Invalid security action code +#define CORSECATTR_E_NO_SELF_REF EMAKEHR(0x1443) // CA ref to CA def'd in same assembly +#define CORSECATTR_E_BAD_NONCAS EMAKEHR(0x1444) // Use of non-CAS perm with invalid action +#define CORSECATTR_E_ASSEMBLY_LOAD_FAILED EMAKEHR(0x1445) // Failed to load assembly containing CA (or req'd CA type) +#define CORSECATTR_E_ASSEMBLY_LOAD_FAILED_EX EMAKEHR(0x1446) // Failed to load assembly containing CA (or req'd CA type) +#define CORSECATTR_E_TYPE_LOAD_FAILED EMAKEHR(0x1447) // Failed to load CA type (or reqd CA type) +#define CORSECATTR_E_TYPE_LOAD_FAILED_EX EMAKEHR(0x1448) // Failed to load CA type (or reqd CA type) +#define CORSECATTR_E_ABSTRACT EMAKEHR(0x1449) // CA type is abstract +#define CORSECATTR_E_UNSUPPORTED_TYPE EMAKEHR(0x144a) // Unsupported type for field/property setter +#define CORSECATTR_E_UNSUPPORTED_ENUM_TYPE EMAKEHR(0x144b) // Unsupported base type for enum field/property +#define CORSECATTR_E_NO_FIELD EMAKEHR(0x144c) // Couldn't find a CA field +#define CORSECATTR_E_NO_PROPERTY EMAKEHR(0x144d) // Couldn't find a CA property +#define CORSECATTR_E_EXCEPTION EMAKEHR(0x144e) // Unexpected exception +#define CORSECATTR_E_EXCEPTION_HR EMAKEHR(0x144f) // Unexpected exception + + +//**** Isolated Storage Errors 1450 - 14FF +#define ISS_E_ISOSTORE EMAKEHR(0x1450L) + +#define ISS_E_OPEN_STORE_FILE EMAKEHR(0x1460L) +#define ISS_E_OPEN_FILE_MAPPING EMAKEHR(0x1461L) +#define ISS_E_MAP_VIEW_OF_FILE EMAKEHR(0x1462L) +#define ISS_E_GET_FILE_SIZE EMAKEHR(0x1463L) +#define ISS_E_CREATE_MUTEX EMAKEHR(0x1464L) +#define ISS_E_LOCK_FAILED EMAKEHR(0x1465L) +#define ISS_E_FILE_WRITE EMAKEHR(0x1466L) +#define ISS_E_SET_FILE_POINTER EMAKEHR(0x1467L) +#define ISS_E_CREATE_DIR EMAKEHR(0x1468L) +#define ISS_E_STORE_NOT_OPEN EMAKEHR(0x1469L) + +#define ISS_E_CORRUPTED_STORE_FILE EMAKEHR(0x1480L) +#define ISS_E_STORE_VERSION EMAKEHR(0x1481L) +#define ISS_E_FILE_NOT_MAPPED EMAKEHR(0x1482L) +#define ISS_E_BLOCK_SIZE_TOO_SMALL EMAKEHR(0x1483L) +#define ISS_E_ALLOC_TOO_LARGE EMAKEHR(0x1484L) +#define ISS_E_USAGE_WILL_EXCEED_QUOTA EMAKEHR(0x1485L) +#define ISS_E_TABLE_ROW_NOT_FOUND EMAKEHR(0x1486L) + +#define ISS_E_DEPRECATE EMAKEHR(0x14A0L) +#define ISS_E_CALLER EMAKEHR(0x14A1L) +#define ISS_E_PATH_LENGTH EMAKEHR(0x14A2L) +#define ISS_E_MACHINE EMAKEHR(0x14A3L) +#define ISS_E_MACHINE_DACL EMAKEHR(0x14A4L) + +#define ISS_E_ISOSTORE_START EMAKEHR(0x1450L) +#define ISS_E_ISOSTORE_END EMAKEHR(0x14FFL) + +// ****************** +// Classlib errors +// ****************** + + +// +// MessageId: COR_E_APPLICATION +// +// MessageText: +// +// The base class for all "less serious" exceptions. +// +#define COR_E_APPLICATION EMAKEHR(0x1600L) + + +// +// MessageId: COR_E_ARGUMENT +// +// MessageText: +// +// An argument does not meet the contract of the method. +// +#define COR_E_ARGUMENT E_INVALIDARG // 0x80070057 + + +// +// MessageId: COR_E_ARGUMENTOUTOFRANGE +// +// MessageText: +// +// An argument was out of its legal range. +// +#define COR_E_ARGUMENTOUTOFRANGE EMAKEHR(0x1502L) + + +// +// MessageId: COR_E_ARITHMETIC +// +// MessageText: +// +// Overflow or underflow in mathematical operations. +// +#define COR_E_ARITHMETIC HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW) // 0x80070216 + + +// +// MessageId: COR_E_ARRAYTYPEMISMATCH +// +// MessageText: +// +// Attempted to store an object of the wrong type in an array +// +#define COR_E_ARRAYTYPEMISMATCH EMAKEHR(0x1503L) + + +// +// MessageId: COR_E_CONTEXTMARSHAL +// +// MessageText: +// +// +// +#define COR_E_CONTEXTMARSHAL EMAKEHR(0x1504L) + + +// +// MessageId: COR_E_TIMEOUT +// +// MessageText: +// +// +// +#define COR_E_TIMEOUT EMAKEHR(0x1505L) + + +// +// MessageId: COR_E_KEYNOTFOUND +// +// MessageText: +// +// +// +#define COR_E_KEYNOTFOUND EMAKEHR(0x1577L) + + + +// +// MessageId: COR_E_DEVICESNOTSUPPORTED +// +// MessageText: +// +// +// +#define COR_E_DEVICESNOTSUPPORTED EMAKEHR(0x1540L) + +// +// MessageId: COR_E_DIVIDEBYZERO +// +// MessageText: +// +// Attempted to divide a number by zero. +// +#define COR_E_DIVIDEBYZERO _HRESULT_TYPEDEF_(0x80020012L) // DISP_E_DIVBYZERO + + +// +// MessageId: COR_E_EXCEPTION +// +// MessageText: +// +// Base class for all exceptions in the runtime +// +#define COR_E_EXCEPTION EMAKEHR(0x1500L) + + +// +// MessageId: COR_E_EXECUTIONENGINE +// +// MessageText: +// +// An internal error happened in the Common Language Runtime's Execution Engine +// +#define COR_E_EXECUTIONENGINE EMAKEHR(0x1506L) + + +// +// MessageId: COR_E_FIELDACCESS +// +// MessageText: +// +// Access to this field is denied. +// +#define COR_E_FIELDACCESS EMAKEHR(0x1507L) + + +// +// MessageId: COR_E_FORMAT +// +// MessageText: +// +// The format of one arguments does not meet the contract of the method. +// +#define COR_E_FORMAT EMAKEHR(0x1537L) + + +// +// MessageId: COR_E_BADIMAGEFORMAT +// +// MessageText: +// +// The format of DLL or executable being loaded is invalid. +// +#define COR_E_BADIMAGEFORMAT _HRESULT_TYPEDEF_(0x8007000BL) + + +// +// MessageId: COR_E_ASSEMBLYEXPECTED +// +// MessageText: +// +// The module was expected to contain an assembly manifest. +// +#define COR_E_ASSEMBLYEXPECTED EMAKEHR(0x1018L) + +// +// MessageId: COR_E_TYPEUNLOADED +// +// MessageText: +// +// The type had been unloaded. +// +#define COR_E_TYPEUNLOADED EMAKEHR(0x1013L) + +// +// MessageId: COR_E_INDEXOUTOFRANGE +// +// MessageText: +// +// Attempted to access an element within an array by using an index that is +// not within the bound of that array. +// +#define COR_E_INDEXOUTOFRANGE EMAKEHR(0x1508L) + + +// +// MessageId: COR_E_INSUFFICIENTMEMORY +// +// MessageText: +// +// Not enough memory was available for an operation. +// This may not be potentially fatal (vs. an OutOfMemoryException). +// +#define COR_E_INSUFFICIENTMEMORY EMAKEHR(0x153DL) + + +// +// MessageId: COR_E_RUNTIMEWRAPPED +// +// MessageText: +// +// An object that does not derive from System.Exception has been wrapped in a RuntimeWrappedException. +// +#define COR_E_RUNTIMEWRAPPED EMAKEHR(0x153EL) + + +// +// MessageId: COR_E_INVALIDCAST +// +// MessageText: +// +// Indicates a bad cast condition +// +#define COR_E_INVALIDCAST E_NOINTERFACE // 0x80004002 + + +// +// MessageId: COR_E_INVALIDOPERATION +// +// MessageText: +// +// An operation is not legal in the current state. +// +#define COR_E_INVALIDOPERATION EMAKEHR(0x1509L) + + +// +// MessageId: COR_E_INVALIDPROGRAM +// +// MessageText: +// +// A program contained invalid IL or bad metadata. Usually this is a compiler bug. +// +#define COR_E_INVALIDPROGRAM EMAKEHR(0x153AL) + + +// +// MessageId: COR_E_MEMBERACCESS +// +// MessageText: +// +// Access to this member is denied. +// +#define COR_E_MEMBERACCESS EMAKEHR(0x151AL) + + +// +// MessageId: COR_E_METHODACCESS +// +// MessageText: +// +// Access to this method is denied. +// +#define COR_E_METHODACCESS EMAKEHR(0x1510L) + + +// +// MessageId: COR_E_MISSINGFIELD +// +// MessageText: +// +// An attempt was made to dynamically access a field that does not exist. +// +#define COR_E_MISSINGFIELD EMAKEHR(0x1511L) + + +// +// MessageId: COR_E_MISSINGMANIFESTRESOURCE +// +// MessageText: +// +// An expected resource in the assembly manifest was missing. +// +#define COR_E_MISSINGMANIFESTRESOURCE EMAKEHR(0x1532L) + + +// +// MessageId: COR_E_MISSINGMEMBER +// +// MessageText: +// +// An attempt was made to dynamically invoke or access a field or method +// that does not exist. +// +#define COR_E_MISSINGMEMBER EMAKEHR(0x1512L) + + +// +// MessageId: COR_E_MISSINGMETHOD +// +// MessageText: +// +// An attempt was made to dynamically invoke a method that does not exist +// +#define COR_E_MISSINGMETHOD EMAKEHR(0x1513L) + + +// +// MessageId: COR_E_MISSINGSATELLITEASSEMBLY +// +// MessageText: +// +// An expected satellite assembly containing the ultimate fallback resources +// for a given culture was not found or couldn't be loaded. Setup problem? +// +#define COR_E_MISSINGSATELLITEASSEMBLY EMAKEHR(0x1536L) + + +// +// MessageId: COR_E_MULTICASTNOTSUPPORTED +// +// MessageText: +// +// Attempted to combine delegates that are not multicast +// +#define COR_E_MULTICASTNOTSUPPORTED EMAKEHR(0x1514L) + + +// +// MessageId: COR_E_NOTFINITENUMBER +// +// MessageText: +// +// Thrown if value (a floating point number) is either the not a number value (NaN) or +- infinity value +// VB needs this stuff +#define COR_E_NOTFINITENUMBER EMAKEHR(0x1528L) + + +// +// MessageId: COR_E_DUPLICATEWAITOBJECT +// +// MessageText: +// +// An object appears more than once in the wait objects array. +// +#define COR_E_DUPLICATEWAITOBJECT EMAKEHR(0x1529L) + + +// +// MessageId: COR_E_PLATFORMNOTSUPPORTED +// +// MessageText: +// +// The method is not supported on this platform +// +#define COR_E_PLATFORMNOTSUPPORTED EMAKEHR(0x1539L) + +// +// MessageId: COR_E_NOTSUPPORTED +// +// MessageText: +// +// The operation is not supported +// +#define COR_E_NOTSUPPORTED EMAKEHR(0x1515L) + +// +// MessageId: COR_E_NULLREFERENCE +// +// MessageText: +// +// Dereferencing a null reference. In general class libraries should not throw this +// +#define COR_E_NULLREFERENCE E_POINTER // 0x80004003 + + +// +// MessageId: COR_E_OUTOFMEMORY +// +// MessageText: +// +// The EE thows this exception when no more memory is avaible to continue execution +// +#define COR_E_OUTOFMEMORY E_OUTOFMEMORY // 0x8007000E + + +// +// MessageId: COR_E_OVERFLOW +// +// MessageText: +// +// An arithmetic, casting, or conversion operation overflowed or underflowed. +// +#define COR_E_OVERFLOW EMAKEHR(0x1516L) + + +// +// MessageId: COR_E_RANK +// +// MessageText: +// +// An array has the wrong number of dimensions for a particular operation. +// +#define COR_E_RANK EMAKEHR(0x1517L) + + +// +// MessageId: COR_E_REMOTING +// +// MessageText: +// +// An error relating to remoting occurred. +// +#define COR_E_REMOTING EMAKEHR(0x150BL) +#define COR_E_SERVER EMAKEHR(0x150EL) + +// +// MessageId: COR_E_SERVICEDCOMPONENT +// +// MessageText: +// +// An error relating to ServicedComponent occurred. +// +#define COR_E_SERVICEDCOMPONENT EMAKEHR(0x150FL) + + +// +// MessageId: COR_E_SECURITY +// +// MessageText: +// +// An error relating to security occured. +// +#define COR_E_SECURITY EMAKEHR(0x150AL) + + +// +// MessageID: COR_E_SERIALIZATION +// +// MessageText: +// +// An error relating to serialization has occurred. +// +#define COR_E_SERIALIZATION EMAKEHR(0x150CL) + + +// +// MessageId: COR_E_STACKOVERFLOW +// +// MessageText: +// +// Is raised by the EE when the execution stack overflows as it is attempting to ex +// +#define COR_E_STACKOVERFLOW HRESULT_FROM_WIN32(ERROR_STACK_OVERFLOW) // 0x800703E9 + + +// +// MessageId: COR_E_SYNCHRONIZATIONLOCK +// +// MessageText: +// +// Wait(), Notify() or NotifyAll() was called from an unsynchronized ** block of c +// +#define COR_E_SYNCHRONIZATIONLOCK EMAKEHR(0x1518L) + + +// +// MessageId: COR_E_SYSTEM +// +// MessageText: +// +// The base class for the runtime's "less serious" exceptions +// +#define COR_E_SYSTEM EMAKEHR(0x1501L) + + +// +// MessageId: COR_E_THREADABORTED +// +// MessageText: +// +// Thrown into a thread to cause it to abort. Not catchable. +// +#define COR_E_THREADABORTED EMAKEHR(0x1530L) + + +// +// MessageId: COR_E_OPERATIONCANCELED +// +// MessageText: +// +// The operation was cancelled. +// +#define COR_E_OPERATIONCANCELED EMAKEHR(0x153BL) + + +// +// MessageId: COR_E_THREADINTERRUPTED +// +// MessageText: +// +// Indicates that the thread was interrupted from a waiting state +// +#define COR_E_THREADINTERRUPTED EMAKEHR(0x1519L) + + +// +// MessageId: COR_E_THREADSTATE +// +// MessageText: +// +// Indicate that the Thread class is in an invalid state for the method call +// +#define COR_E_THREADSTATE EMAKEHR(0x1520L) + + +// +// MessageId: COR_E_THREADSTOP +// +// MessageText: +// +// Thrown into a thread to cause it to stop. This exception is typically not caught +// +#define COR_E_THREADSTOP EMAKEHR(0x1521L) + + +// +// MessageId: COR_E_THREADSTART +// +// MessageText: +// +// Indicate that a user thread fails to start. +// +#define COR_E_THREADSTART EMAKEHR(0x1525L) + + +// +// MessageId: COR_E_TYPEINITIALIZATION +// +// MessageText: +// +// An exception was thrown by a type's initializer (.cctor). +// +#define COR_E_TYPEINITIALIZATION EMAKEHR(0x1534L) + + +// +// MessageId: COR_E_TYPELOAD +// +// MessageText: +// +// Could not find or load a specific type (class, enum, etc). +// +#define COR_E_TYPELOAD EMAKEHR(0x1522L) + + +// +// MessageId: COR_E_ENTRYPOINTNOTFOUND +// +// MessageText: +// +// Could not find the specified DllImport entry point +// +#define COR_E_ENTRYPOINTNOTFOUND EMAKEHR(0x1523L) + + +// +// MessageId: COR_E_DLLNOTFOUND +// +// MessageText: +// +// Could not find the specified DllImport DLL. +// +#define COR_E_DLLNOTFOUND EMAKEHR(0x1524L) + + +// +// MessageId: COR_E_UNAUTHORIZEDACCESS +// +// MessageText: +// +// Access is denied. +// +#define COR_E_UNAUTHORIZEDACCESS E_ACCESSDENIED // 0x80070005 + + +// +// MessageId: COR_E_VERIFICATION +// +// MessageText: +// +// A verification failure occurred +// +#define COR_E_VERIFICATION EMAKEHR(0x150DL) + + +// +// MessageId: COR_E_INVALIDCOMOBJECT +// +// MessageText: +// +// An invalid __ComObject has been used. +// +#define COR_E_INVALIDCOMOBJECT EMAKEHR(0x1527L) + + +// +// MessageId: COR_E_SEMAPHOREFULL +// +// MessageText: +// +// Adding the given count to the semaphore would cause it to exceed its maximum count. +// +#define COR_E_SEMAPHOREFULL EMAKEHR(0x152BL) + + +// +// MessageId: COR_E_WAITHANDLECANNOTBEOPENED +// +// MessageText: +// +// No Semaphore of the given name exists. +// +#define COR_E_WAITHANDLECANNOTBEOPENED EMAKEHR(0x152CL) + +// +// MessageId: COR_E_ABANDONEDMUTEX +// +// MessageText: +// +// The wait completed due to an abandoned mutex. +// +#define COR_E_ABANDONEDMUTEX EMAKEHR(0x152DL) + +// +// MessageId: COR_E_MARSHALDIRECTIVE +// +// MessageText: +// +// The marshaling directives are invalid. +// +#define COR_E_MARSHALDIRECTIVE EMAKEHR(0x1535L) + + +// +// MessageId: COR_E_INVALIDOLEVARIANTTYPE +// +// MessageText: +// +// The type of an OLE variant that was passed into the runtime is invalid. +// +#define COR_E_INVALIDOLEVARIANTTYPE EMAKEHR(0x1531L) + + +// +// MessageId: COR_E_SAFEARRAYTYPEMISMATCH +// +// MessageText: +// +// A mismatch has occured between the runtime type of the array and the +// sub type recorded in the metadata. +// +#define COR_E_SAFEARRAYTYPEMISMATCH EMAKEHR(0x1533L) + + +// +// MessageId: COR_E_SAFEARRAYRANKMISMATCH +// +// MessageText: +// +// A mismatch has occured between the runtime rank of the array and the +// rank recorded in the metadata. +// +#define COR_E_SAFEARRAYRANKMISMATCH EMAKEHR(0x1538L) + +// +// MessageId: COR_E_DATAMISALIGNED +// +// MessageText: +// +// A datatype misalignment was detected in a load or store instruction. +// +#define COR_E_DATAMISALIGNED EMAKEHR(0x1541L) + + +// +// MessageId: COR_E_TARGETPARAMCOUNT +// +// MessageText: +// +// There was a mismatch between number of arguments provided and the number expected +// +#define COR_E_TARGETPARAMCOUNT _HRESULT_TYPEDEF_(0x8002000EL) // DISP_E_BADPARAMCOUNT + + +// +// MessageId: COR_E_AMBIGUOUSMATCH +// +// MessageText: +// +// While late binding to a method via reflection, could not resolve between +// multiple overloads of a method. +// +#define COR_E_AMBIGUOUSMATCH _HRESULT_TYPEDEF_(0x8000211DL) + + +// +// MessageId: COR_E_INVALIDFILTERCRITERIA +// +// MessageText: +// +// The given filter criteria does not match the filter contract. +// +#define COR_E_INVALIDFILTERCRITERIA EMAKEHR(0x1601L) + + +// +// MessageId: COR_E_REFLECTIONTYPELOAD +// +// MessageText: +// +// Could not find or load a specific class that was requested through Reflection +// +#define COR_E_REFLECTIONTYPELOAD EMAKEHR(0x1602L) + + +// +// MessageId: COR_E_TARGET +// +// MessageText: +// +// - If you attempt to invoke a non-static method with a null Object - If you atte +// +#define COR_E_TARGET EMAKEHR(0x1603L) + + +// +// MessageId: COR_E_TARGETINVOCATION +// +// MessageText: +// +// If the method called throws an exception +// +#define COR_E_TARGETINVOCATION EMAKEHR(0x1604L) + + +// +// MessageId: COR_E_CUSTOMATTRIBUTEFORMAT +// +// MessageText: +// +// If the binary format of a custom attribute is invalid. +// +#define COR_E_CUSTOMATTRIBUTEFORMAT EMAKEHR(0x1605L) + + +// +// MessageId: COR_E_ENDOFSTREAM +// +// MessageText: +// +// Thrown when the End of file is reached +// +#define COR_E_ENDOFSTREAM HRESULT_FROM_WIN32(ERROR_HANDLE_EOF) + + +// +// MessageId: COR_E_FILELOAD +// +// MessageText: +// +// +// +#define COR_E_FILELOAD EMAKEHR(0x1621L) + + +// +// MessageId: COR_E_FILENOTFOUND +// +// MessageText: +// +// +// +#define COR_E_FILENOTFOUND HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) + +// +// MessageId: ERROR_BAD_PATHNAME +// +// MessageText: +// +// The specified path is invalid. +// +#define COR_E_BAD_PATHNAME HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME) + +// +// MessageId: COR_E_IO +// +// MessageText: +// +// Some sort of I/O error. +// +#define COR_E_IO EMAKEHR(0x1620L) + + +// +// MessageId: COR_E_DIRECTORYNOTFOUND +// +// MessageText: +// +// The specified path couldn't be found. +// +#define COR_E_DIRECTORYNOTFOUND HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) + + +// +// MessageId: COR_E_PATHTOOLONG +// +// MessageText: +// +// The specified path was too long. +// +#define COR_E_PATHTOOLONG HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE) + + +// +// MessageId: COR_E_OBJECTDISPOSED +// +// MessageText: +// +// The object has already been disposed. +// +#define COR_E_OBJECTDISPOSED EMAKEHR(0x1622L) + + +// +// MessageId: COR_E_FAILFAST +// +// MessageText: +// +// Runtime operation halted by call to System.Environment.FailFast(). +// +#define COR_E_FAILFAST EMAKEHR(0x1623L) + + +// +// MessageId: COR_E_HOSTPROTECTION +// +// MessageText: +// +// Attempted to perform an operation that was forbidden by the host. +// +#define COR_E_HOSTPROTECTION EMAKEHR(0x1640L) + + +// +// MessageId: COR_E_ILLEGAL_REENTRANCY +// +// MessageText: +// +// Attempted to call into managed code when executing inside a low level extensibility point. +// +#define COR_E_ILLEGAL_REENTRANCY EMAKEHR(0x1641L) + + +//**** Shim errors 1700 - 1750 +// +#define CLR_E_SHIM_RUNTIMELOAD EMAKEHR(0x1700) // Failed to load the runtime +#define CLR_E_SHIM_RUNTIMEEXPORT EMAKEHR(0x1701) // Failed to find a required export in the runtime +#define CLR_E_SHIM_INSTALLROOT EMAKEHR(0x1702) // Install root is not defined +#define CLR_E_SHIM_INSTALLCOMP EMAKEHR(0x1703) // Expected component of the runtime is not available + +//**** Verifier Errors 1800 - 18FF +// See src/dlls/mscorrc/mscorrc.rc for a description of each error + +#define VER_E_HRESULT EMAKEHR(0x1801) +#define VER_E_OFFSET EMAKEHR(0x1802) +#define VER_E_OPCODE EMAKEHR(0x1803) +#define VER_E_OPERAND EMAKEHR(0x1804) +#define VER_E_TOKEN EMAKEHR(0x1805) +#define VER_E_EXCEPT EMAKEHR(0x1806) +#define VER_E_STACK_SLOT EMAKEHR(0x1807) +#define VER_E_LOC EMAKEHR(0x1808) +#define VER_E_ARG EMAKEHR(0x1809) +#define VER_E_FOUND EMAKEHR(0x180A) +#define VER_E_EXPECTED EMAKEHR(0x180B) +#define VER_E_LOC_BYNAME EMAKEHR(0x180C) + +#define VER_E_UNKNOWN_OPCODE EMAKEHR(0x1810) +#define VER_E_SIG_CALLCONV EMAKEHR(0x1811) +#define VER_E_SIG_ELEMTYPE EMAKEHR(0x1812) + +#define VER_E_RET_SIG EMAKEHR(0x1814) +#define VER_E_FIELD_SIG EMAKEHR(0x1815) + +#define VER_E_INTERNAL EMAKEHR(0x1818) +#define VER_E_STACK_TOO_LARGE EMAKEHR(0x1819) +#define VER_E_ARRAY_NAME_LONG EMAKEHR(0x181A) + +#define VER_E_FALLTHRU EMAKEHR(0x1820) +#define VER_E_TRY_GTEQ_END EMAKEHR(0x1821) +#define VER_E_TRYEND_GT_CS EMAKEHR(0x1822) +#define VER_E_HND_GTEQ_END EMAKEHR(0x1823) +#define VER_E_HNDEND_GT_CS EMAKEHR(0x1824) +#define VER_E_FLT_GTEQ_CS EMAKEHR(0x1825) +#define VER_E_TRY_START EMAKEHR(0x1826) +#define VER_E_HND_START EMAKEHR(0x1827) +#define VER_E_FLT_START EMAKEHR(0x1828) +#define VER_E_TRY_OVERLAP EMAKEHR(0x1829) +#define VER_E_TRY_EQ_HND_FIL EMAKEHR(0x182A) +#define VER_E_TRY_SHARE_FIN_FAL EMAKEHR(0x182B) +#define VER_E_HND_OVERLAP EMAKEHR(0x182C) +#define VER_E_HND_EQ EMAKEHR(0x182D) +#define VER_E_FIL_OVERLAP EMAKEHR(0x182E) +#define VER_E_FIL_EQ EMAKEHR(0x182F) +#define VER_E_FIL_CONT_TRY EMAKEHR(0x1830) +#define VER_E_FIL_CONT_HND EMAKEHR(0x1831) +#define VER_E_FIL_CONT_FIL EMAKEHR(0x1832) +#define VER_E_FIL_GTEQ_CS EMAKEHR(0x1833) +#define VER_E_FIL_START EMAKEHR(0x1834) +#define VER_E_FALLTHRU_EXCEP EMAKEHR(0x1835) +#define VER_E_FALLTHRU_INTO_HND EMAKEHR(0x1836) +#define VER_E_FALLTHRU_INTO_FIL EMAKEHR(0x1837) +#define VER_E_LEAVE EMAKEHR(0x1838) +#define VER_E_RETHROW EMAKEHR(0x1839) +#define VER_E_ENDFINALLY EMAKEHR(0x183A) +#define VER_E_ENDFILTER EMAKEHR(0x183B) +#define VER_E_ENDFILTER_MISSING EMAKEHR(0x183C) +#define VER_E_BR_INTO_TRY EMAKEHR(0x183D) +#define VER_E_BR_INTO_HND EMAKEHR(0x183E) +#define VER_E_BR_INTO_FIL EMAKEHR(0x183F) +#define VER_E_BR_OUTOF_TRY EMAKEHR(0x1840) +#define VER_E_BR_OUTOF_HND EMAKEHR(0x1841) +#define VER_E_BR_OUTOF_FIL EMAKEHR(0x1842) +#define VER_E_BR_OUTOF_FIN EMAKEHR(0x1843) +#define VER_E_RET_FROM_TRY EMAKEHR(0x1844) +#define VER_E_RET_FROM_HND EMAKEHR(0x1845) +#define VER_E_RET_FROM_FIL EMAKEHR(0x1846) +#define VER_E_BAD_JMP_TARGET EMAKEHR(0x1847) +#define VER_E_PATH_LOC EMAKEHR(0x1848) +#define VER_E_PATH_THIS EMAKEHR(0x1849) +#define VER_E_PATH_STACK EMAKEHR(0x184A) +#define VER_E_PATH_STACK_DEPTH EMAKEHR(0x184B) +#define VER_E_THIS EMAKEHR(0x184C) +#define VER_E_THIS_UNINIT_EXCEP EMAKEHR(0x184D) +#define VER_E_THIS_UNINIT_STORE EMAKEHR(0x184E) +#define VER_E_THIS_UNINIT_RET EMAKEHR(0x184F) +#define VER_E_THIS_UNINIT_V_RET EMAKEHR(0x1850) +#define VER_E_THIS_UNINIT_BR EMAKEHR(0x1851) +#define VER_E_LDFTN_CTOR EMAKEHR(0x1852) +#define VER_E_STACK_NOT_EQ EMAKEHR(0x1853) +#define VER_E_STACK_UNEXPECTED EMAKEHR(0x1854) +#define VER_E_STACK_EXCEPTION EMAKEHR(0x1855) +#define VER_E_STACK_OVERFLOW EMAKEHR(0x1856) +#define VER_E_STACK_UNDERFLOW EMAKEHR(0x1857) +#define VER_E_STACK_EMPTY EMAKEHR(0x1858) +#define VER_E_STACK_UNINIT EMAKEHR(0x1859) +#define VER_E_STACK_I_I4_I8 EMAKEHR(0x185A) +#define VER_E_STACK_R_R4_R8 EMAKEHR(0x185B) +#define VER_E_STACK_NO_R_I8 EMAKEHR(0x185C) +#define VER_E_STACK_NUMERIC EMAKEHR(0x185D) +#define VER_E_STACK_OBJREF EMAKEHR(0x185E) +#define VER_E_STACK_P_OBJREF EMAKEHR(0x185F) +#define VER_E_STACK_BYREF EMAKEHR(0x1860) +#define VER_E_STACK_METHOD EMAKEHR(0x1861) +#define VER_E_STACK_ARRAY_SD EMAKEHR(0x1862) +#define VER_E_STACK_VALCLASS EMAKEHR(0x1863) +#define VER_E_STACK_P_VALCLASS EMAKEHR(0x1864) +#define VER_E_STACK_NO_VALCLASS EMAKEHR(0x1865) +#define VER_E_LOC_DEAD EMAKEHR(0x1866) +#define VER_E_LOC_NUM EMAKEHR(0x1867) +#define VER_E_ARG_NUM EMAKEHR(0x1868) +#define VER_E_TOKEN_RESOLVE EMAKEHR(0x1869) +#define VER_E_TOKEN_TYPE EMAKEHR(0x186A) +#define VER_E_TOKEN_TYPE_MEMBER EMAKEHR(0x186B) +#define VER_E_TOKEN_TYPE_FIELD EMAKEHR(0x186C) +#define VER_E_TOKEN_TYPE_SIG EMAKEHR(0x186D) +#define VER_E_UNVERIFIABLE EMAKEHR(0x186E) +#define VER_E_LDSTR_OPERAND EMAKEHR(0x186F) +#define VER_E_RET_PTR_TO_STACK EMAKEHR(0x1870) +#define VER_E_RET_VOID EMAKEHR(0x1871) +#define VER_E_RET_MISSING EMAKEHR(0x1872) +#define VER_E_RET_EMPTY EMAKEHR(0x1873) +#define VER_E_RET_UNINIT EMAKEHR(0x1874) +#define VER_E_ARRAY_ACCESS EMAKEHR(0x1875) +#define VER_E_ARRAY_V_STORE EMAKEHR(0x1876) +#define VER_E_ARRAY_SD EMAKEHR(0x1877) +#define VER_E_ARRAY_SD_PTR EMAKEHR(0x1878) +#define VER_E_ARRAY_FIELD EMAKEHR(0x1879) +#define VER_E_ARGLIST EMAKEHR(0x187A) +#define VER_E_VALCLASS EMAKEHR(0x187B) +#define VER_E_METHOD_ACCESS EMAKEHR(0x187C) +#define VER_E_FIELD_ACCESS EMAKEHR(0x187D) +#define VER_E_DEAD EMAKEHR(0x187E) +#define VER_E_FIELD_STATIC EMAKEHR(0x187F) +#define VER_E_FIELD_NO_STATIC EMAKEHR(0x1880) +#define VER_E_ADDR EMAKEHR(0x1881) +#define VER_E_ADDR_BYREF EMAKEHR(0x1882) +#define VER_E_ADDR_LITERAL EMAKEHR(0x1883) +#define VER_E_INITONLY EMAKEHR(0x1884) +#define VER_E_THROW EMAKEHR(0x1885) +#define VER_E_CALLVIRT_VALCLASS EMAKEHR(0x1886) +#define VER_E_CALL_SIG EMAKEHR(0x1887) +#define VER_E_CALL_STATIC EMAKEHR(0x1888) +#define VER_E_CTOR EMAKEHR(0x1889) +#define VER_E_CTOR_VIRT EMAKEHR(0x188A) +#define VER_E_CTOR_OR_SUPER EMAKEHR(0x188B) +#define VER_E_CTOR_MUL_INIT EMAKEHR(0x188C) +#define VER_E_SIG EMAKEHR(0x188D) +#define VER_E_SIG_ARRAY EMAKEHR(0x188E) +#define VER_E_SIG_ARRAY_PTR EMAKEHR(0x188F) +#define VER_E_SIG_ARRAY_BYREF EMAKEHR(0x1890) +#define VER_E_SIG_ELEM_PTR EMAKEHR(0x1891) +#define VER_E_SIG_VARARG EMAKEHR(0x1892) +#define VER_E_SIG_VOID EMAKEHR(0x1893) +#define VER_E_SIG_BYREF_BYREF EMAKEHR(0x1894) +#define VER_E_CODE_SIZE_ZERO EMAKEHR(0x1896) +#define VER_E_BAD_VARARG EMAKEHR(0x1897) +#define VER_E_TAIL_CALL EMAKEHR(0x1898) +#define VER_E_TAIL_BYREF EMAKEHR(0x1899) +#define VER_E_TAIL_RET EMAKEHR(0x189A) +#define VER_E_TAIL_RET_VOID EMAKEHR(0x189B) +#define VER_E_TAIL_RET_TYPE EMAKEHR(0x189C) +#define VER_E_TAIL_STACK_EMPTY EMAKEHR(0x189D) +#define VER_E_METHOD_END EMAKEHR(0x189E) +#define VER_E_BAD_BRANCH EMAKEHR(0x189F) +#define VER_E_FIN_OVERLAP EMAKEHR(0x18A0) +#define VER_E_LEXICAL_NESTING EMAKEHR(0x18A1) +#define VER_E_VOLATILE EMAKEHR(0x18A2) +#define VER_E_UNALIGNED EMAKEHR(0x18A3) +#define VER_E_INNERMOST_FIRST EMAKEHR(0x18A4) +#define VER_E_CALLI_VIRTUAL EMAKEHR(0x18A5) +#define VER_E_CALL_ABSTRACT EMAKEHR(0x18A6) +#define VER_E_STACK_UNEXP_ARRAY EMAKEHR(0x18A7) +#define VER_E_NOT_IN_GC_HEAP EMAKEHR(0x18A8) +#define VER_E_TRY_N_EMPTY_STACK EMAKEHR(0x18A9) +#define VER_E_DLGT_CTOR EMAKEHR(0x18AA) +#define VER_E_DLGT_BB EMAKEHR(0x18AB) +#define VER_E_DLGT_PATTERN EMAKEHR(0x18AC) +#define VER_E_DLGT_LDFTN EMAKEHR(0x18AD) +#define VER_E_FTN_ABSTRACT EMAKEHR(0x18AE) +#define VER_E_SIG_C_VC EMAKEHR(0x18AF) +#define VER_E_SIG_VC_C EMAKEHR(0x18B0) +#define VER_E_BOX_PTR_TO_STACK EMAKEHR(0x18B1) +#define VER_E_SIG_BYREF_TB_AH EMAKEHR(0x18B2) +#define VER_E_SIG_ARRAY_TB_AH EMAKEHR(0x18B3) +#define VER_E_ENDFILTER_STACK EMAKEHR(0x18B4) +#define VER_E_DLGT_SIG_I EMAKEHR(0x18B5) +#define VER_E_DLGT_SIG_O EMAKEHR(0x18B6) +#define VER_E_RA_PTR_TO_STACK EMAKEHR(0x18B7) +#define VER_E_CATCH_VALUE_TYPE EMAKEHR(0x18B8) +#define VER_E_CATCH_BYREF EMAKEHR(0x18B9) +#define VER_E_FIL_PRECEED_HND EMAKEHR(0x18BA) +#define VER_E_LDVIRTFTN_STATIC EMAKEHR(0x18BB) +#define VER_E_CALLVIRT_STATIC EMAKEHR(0x18BC) +#define VER_E_INITLOCALS EMAKEHR(0x18BD) +#define VER_E_BR_TO_EXCEPTION EMAKEHR(0x18BE) +#define VER_E_CALL_CTOR EMAKEHR(0x18BF) + +//@GENERICSVER: new generics related error messages +#define VER_E_VALCLASS_OBJREF_VAR EMAKEHR(0x18C0) +#define VER_E_STACK_P_VALCLASS_OBJREF_VAR EMAKEHR(0x18C1) +#define VER_E_SIG_VAR_PARAM EMAKEHR(0x18C2) +#define VER_E_SIG_MVAR_PARAM EMAKEHR(0x18C3) +#define VER_E_SIG_VAR_ARG EMAKEHR(0x18C4) +#define VER_E_SIG_MVAR_ARG EMAKEHR(0x18C5) +#define VER_E_SIG_GENERICINST EMAKEHR(0x18C6) +#define VER_E_SIG_METHOD_INST EMAKEHR(0x18C7) +#define VER_E_SIG_METHOD_PARENT_INST EMAKEHR(0x18C8) +#define VER_E_SIG_FIELD_PARENT_INST EMAKEHR(0x18C9) +#define VER_E_CALLCONV_NOT_GENERICINST EMAKEHR(0x18CA) +#define VER_E_TOKEN_BAD_METHOD_SPEC EMAKEHR(0x18CB) +#define VER_E_BAD_READONLY_PREFIX EMAKEHR(0x18CC) +#define VER_E_BAD_CONSTRAINED_PREFIX EMAKEHR(0x18CD) +//these two are actually raised by the EE - should they appear elsewhere? +#define VER_E_CIRCULAR_VAR_CONSTRAINTS EMAKEHR(0x18CE) +#define VER_E_CIRCULAR_MVAR_CONSTRAINTS EMAKEHR(0x18CF) +//these are used by the new peverify +#define VER_E_UNSATISFIED_METHOD_INST EMAKEHR(0x18D0) +#define VER_E_UNSATISFIED_METHOD_PARENT_INST EMAKEHR(0x18D1) +#define VER_E_UNSATISFIED_FIELD_PARENT_INST EMAKEHR(0x18D2) +#define VER_E_UNSATISFIED_BOX_OPERAND EMAKEHR(0x18D3) +#define VER_E_CONSTRAINED_CALL_WITH_NON_BYREF_THIS EMAKEHR(0x18D4) +#define VER_E_CONSTRAINED_OF_NON_VARIABLE_TYPE EMAKEHR(0x18D5) +#define VER_E_READONLY_UNEXPECTED_CALLEE EMAKEHR(0x18D6) +#define VER_E_READONLY_ILLEGAL_WRITE EMAKEHR(0x18D7) +#define VER_E_READONLY_IN_MKREFANY EMAKEHR(0x18D8) +#define VER_E_UNALIGNED_ALIGNMENT EMAKEHR(0x18D9) +#define VER_E_TAILCALL_INSIDE_EH EMAKEHR(0x18DA) +#define VER_E_BACKWARD_BRANCH EMAKEHR(0x18DB) +#define VER_E_CALL_TO_VTYPE_BASE EMAKEHR(0x18DC) +#define VER_E_NEWOBJ_OF_ABSTRACT_CLASS EMAKEHR(0x18DD) +#define VER_E_UNMANAGED_POINTER EMAKEHR(0x18DE) +#define VER_E_LDFTN_NON_FINAL_VIRTUAL EMAKEHR(0x18DF) +#define VER_E_FIELD_OVERLAP EMAKEHR(0x18E0) +#define VER_E_THIS_MISMATCH EMAKEHR(0x18E1) +#define VER_E_STACK_I_I4 EMAKEHR(0x18E2) + +#define VER_E_BAD_PE EMAKEHR(0x18F0) +#define VER_E_BAD_MD EMAKEHR(0x18F1) +#define VER_E_BAD_APPDOMAIN EMAKEHR(0x18F2) +#define VER_E_TYPELOAD EMAKEHR(0x18F3) +#define VER_E_PE_LOAD EMAKEHR(0x18F4) +#define VER_E_WRITE_RVA_STATIC EMAKEHR(0x18F5) + + +// +// ATTENTION: Range 0x1900 - 0x1AFF is reserved for Framework errors +// Range 0x1B00 - 0x1BFF is reserved for MD Validator errors (see above VLDTR_E_...) +// + +// System.Xml +#define COR_E_Xml EMAKEHR(0x1940) +#define COR_E_XmlSchema EMAKEHR(0x1941) +#define COR_E_XmlXslt EMAKEHR(0x1942) +#define COR_E_XmlXPath EMAKEHR(0x1943) +#define COR_E_XmlQuery EMAKEHR(0x1944) + +// System.Data DataSet +#define COR_E_Data EMAKEHR(0x1920) +#define COR_E_DataDeletedRowInaccessible EMAKEHR(0x1921) +#define COR_E_DataDuplicateName EMAKEHR(0x1922) +#define COR_E_DataInRowChangingEvent EMAKEHR(0x1923) +#define COR_E_DataInvalidConstraint EMAKEHR(0x1924) +#define COR_E_DataMissingPrimaryKey EMAKEHR(0x1925) +#define COR_E_DataNoNullAllowed EMAKEHR(0x1926) +#define COR_E_DataReadOnly EMAKEHR(0x1927) +#define COR_E_DataRowNotInTable EMAKEHR(0x1928) +#define COR_E_DataVersionNotFound EMAKEHR(0x1929) +#define COR_E_DataConstraint EMAKEHR(0x192A) +#define COR_E_StrongTyping EMAKEHR(0x192B) + +// System.Data Managed Providers +#define COR_E_SqlType EMAKEHR(0x1930) +#define COR_E_SqlNullValue EMAKEHR(0x1931) +#define COR_E_SqlTruncate EMAKEHR(0x1932) +#define COR_E_AdapterMapping EMAKEHR(0x1933) +#define COR_E_DataAdapter EMAKEHR(0x1934) +#define COR_E_DBConcurrency EMAKEHR(0x1935) +#define COR_E_OperationAborted EMAKEHR(0x1936) +#define COR_E_InvalidUdt EMAKEHR(0x1937) + +#define COR_E_SqlException EMAKEHR(0x1904) // System.Data.SqlClient.SqlClientException +#define COR_E_OdbcException EMAKEHR(0x1937) // System.Data.Odbc.OdbcException +#define COR_E_OracleException EMAKEHR(0x1938) // System.Data.OracleClient.OracleException + + +//**** More debugger error 1C00 - 1CFF +// +#define CORDBG_E_THREAD_NOT_SCHEDULED EMAKEHR(0x1C00) // Thread is not scheduled. Thus we may not have OSThreadId, handle, or context +#define CORDBG_E_HANDLE_HAS_BEEN_DISPOSED EMAKEHR(0x1C01) // Handle has been disposed. +#define CORDBG_E_NONINTERCEPTABLE_EXCEPTION EMAKEHR(0x1C02) // Cant intercept this exception. +#define CORDBG_E_CANT_UNWIND_ABOVE_CALLBACK EMAKEHR(0x1C03) // When intercepting an exception, cannot intercept above the current frame. +#define CORDBG_E_INTERCEPT_FRAME_ALREADY_SET EMAKEHR(0x1C04) // The intercept frame for this exception has already been set. +#define CORDBG_E_NO_NATIVE_PATCH_AT_ADDR EMAKEHR(0x1C05) // there's no native patch at the given address. +#define CORDBG_E_MUST_BE_INTEROP_DEBUGGING EMAKEHR(0x1C06) // This API is only allowed when interop debugging. +#define CORDBG_E_NATIVE_PATCH_ALREADY_AT_ADDR EMAKEHR(0x1C07) // There's already a native patch at the address +#define CORDBG_E_TIMEOUT EMAKEHR(0x1C08) // a wait timed out .. likely an indication of deadlock. +#define CORDBG_E_CANT_CALL_ON_THIS_THREAD EMAKEHR(0x1C09) // Can't use the API on this thread. +#define CORDBG_E_ENC_INFOLESS_METHOD EMAKEHR(0x1C0A) // Method was not JITed in EnC mode +#define CORDBG_E_ENC_NESTED_HANLDERS EMAKEHR(0x1C0B) // Frame cant be updated due to change in max nesting of handlers +#define CORDBG_E_ENC_IN_FUNCLET EMAKEHR(0x1C0C) // Method is in a callable handler/filter. Cant grow stack +#define CORDBG_E_ENC_LOCALLOC EMAKEHR(0x1C0D) // Frame cant be updated due to localloc +#define CORDBG_E_ENC_EDIT_NOT_SUPPORTED EMAKEHR(0x1C0E) // Attempt to perform unsupported edit +#define CORDBG_E_FEABORT_DELAYED_UNTIL_THREAD_RESUMED EMAKEHR(0x1C0F) // Attempt to func eval abort on a suspended thread. +#define CORDBG_E_NOTREADY EMAKEHR(0x1C10) // The LS is not in a good spot to perform the requested operation. +#define CORDBG_E_CANNOT_RESOLVE_ASSEMBLY EMAKEHR(0x1c11) // We failed to resolve assembly given an AssemblyRef token. Assembly may be not loaded yet or not a valid token. +#define CORDBG_E_MUST_BE_IN_LOAD_MODULE EMAKEHR(0x1C12) // Must be in context of LoadModule callback to perform requested operation +#define CORDBG_E_CANNOT_BE_ON_ATTACH EMAKEHR(0x1C13) // Requested operation cannot be performed during an attach operation +#define CORDBG_S_NOT_ALL_BITS_SET SMAKEHR(0x1C13) // Not all bits specified were successfully applied +#define CORDBG_E_NGEN_NOT_SUPPORTED EMAKEHR(0x1C14) // NGEN must be supported to perform the requested operation +#define CORDBG_E_ILLEGAL_SHUTDOWN_ORDER EMAKEHR(0x1C15) // Trying to shutdown out of order. +#define CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS EMAKEHR(0x1C16) // For Whidbey, we don't support debugging fiber mode managed process +#define CORDBG_E_MUST_BE_IN_CREATE_PROCESS EMAKEHR(0x1C17) // Must be in context of CreateProcess callback to perform requested operation +#define CORDBG_E_DETACH_FAILED_OUTSTANDING_EVALS EMAKEHR(0x1C18) // All outstanding func-evals have not completed, detaching is not allowed at this time. +#define CORDBG_E_DETACH_FAILED_OUTSTANDING_STEPPERS EMAKEHR(0x1C19) // All outstanding steppers have not been closed, detaching is not allowed at this time. +#define CORDBG_E_CANT_INTEROP_STEP_OUT EMAKEHR(0x1C20) // Can't have an ICorDebugStepper do a native step-out. +#define CORDBG_E_DETACH_FAILED_OUTSTANDING_BREAKPOINTS EMAKEHR(0x1C21) // All outstanding breakpoints have not been closed, detaching is not allowed at this time. +#define CORDBG_E_ILLEGAL_IN_STACK_OVERFLOW EMAKEHR(0x1c22) // the operation is illegal because of a stackoverflow. +#define CORDBG_E_ILLEGAL_AT_GC_UNSAFE_POINT EMAKEHR(0x1c23) // The operation failed because it's a GC unsafe point. +#define CORDBG_E_ILLEGAL_IN_PROLOG EMAKEHR(0x1c24) // The operation failed because the thread is in the prolog +#define CORDBG_E_ILLEGAL_IN_NATIVE_CODE EMAKEHR(0x1c25) // The operation failed because the thread is in native code +#define CORDBG_E_ILLEGAL_IN_OPTIMIZED_CODE EMAKEHR(0x1c26) // The operation failed because the thread is in optimized code. +#define CORDBG_E_MINIDUMP_UNSUPPORTED EMAKEHR(0x1c27) // +#define CORDBG_E_APPDOMAIN_MISMATCH EMAKEHR(0x1c28) // A supplied object or type belongs to the wrong AppDomain +#define CORDBG_E_CONTEXT_UNVAILABLE EMAKEHR(0x1c29) // The thread's context is not available. +#define CORDBG_E_UNCOMPATIBLE_PLATFORMS EMAKEHR(0x1c30) // The operation failed because debuggee and debugger are on incompatible platform +#define CORDBG_E_DEBUGGING_DISABLED EMAKEHR(0x1c31) // The operation failed because the debugging has been disabled +#define CORDBG_E_DETACH_FAILED_ON_ENC EMAKEHR(0x1c32) // Detach is illegal after a module has been EnCed. +#define CORDBG_E_CURRENT_EXCEPTION_IS_OUTSIDE_CURRENT_EXECUTION_SCOPE EMAKEHR(0x1c33) // Interception of the current exception is not legal +#define CORDBG_E_HELPER_MAY_DEADLOCK EMAKEHR(0x1c34) // Helper thread can not safely run code. The opereration may work at a later time. + + + +//**** PE Format validation errors 1D00 - 1DFF +// +#define PEFMT_E_NO_CONTENTS EMAKEHR(0x1D00) // File is empty +#define PEFMT_E_NO_NTHEADERS EMAKEHR(0x1D01) // File has no NT headers +#define PEFMT_E_64BIT EMAKEHR(0x1D02) // File is PE32+ +#define PEFMT_E_NO_CORHEADER EMAKEHR(0x1D03) // File has no COR header +#define PEFMT_E_NOT_ILONLY EMAKEHR(0x1D04) // Flag IL_ONLY not set +#define PEFMT_E_IMPORT_DLLS EMAKEHR(0x1D05) // Bad import DLLs +#define PEFMT_E_EXE_NOENTRYPOINT EMAKEHR(0x1D06) // EXE file has no mgd entry point +#define PEFMT_E_BASE_RELOCS EMAKEHR(0x1D07) // Bad base relocations +#define PEFMT_E_ENTRYPOINT EMAKEHR(0x1D08) // Bad managed entry point +#define PEFMT_E_ZERO_SIZEOFCODE EMAKEHR(0x1D09) // OptHeader.SizeOfCode==0 +#define PEFMT_E_BAD_CORHEADER EMAKEHR(0x1D0A) // File has invalid COR header + +//**** CLR Optimization service 1E00 - 1EFF +// +#define CLR_OPTSVC_E_CONTROLLER_INTERRUPT EMAKEHR(0x1E00) // Service controller interrupted work + + +//**** CLR Optimization service 1F00 - 1FFF +// +#define NGEN_FAILED_GET_DEPENDENCIES EMAKEHR(0x1F00) // Service manager failed to get ICorSvcDependencies interface +#define NGEN_FAILED_NATIVE_IMAGE_DELETE EMAKEHR(0x1F01) // Failed to delete native image + + + + + +#endif // __COMMON_LANGUAGE_RUNTIME_HRESULTS__ diff --git a/third/Blackbone/src/3rd_party/DIA/cvconst.h b/third/Blackbone/src/3rd_party/DIA/cvconst.h new file mode 100644 index 0000000000000000000000000000000000000000..5ad1f7eded94261555a288fea42d232fb2764499 --- /dev/null +++ b/third/Blackbone/src/3rd_party/DIA/cvconst.h @@ -0,0 +1,4093 @@ +// cvconst.h - codeview constant definitions +//----------------------------------------------------------------- +// +// Copyright Microsoft Corporation. All Rights Reserved. +// +//--------------------------------------------------------------- +#ifndef _CVCONST_H_ +#define _CVCONST_H_ + + + +// Enumeration for function call type + + +typedef enum CV_call_e +{ + CV_CALL_NEAR_C = 0x00, // near right to left push, caller pops stack + CV_CALL_FAR_C = 0x01, // far right to left push, caller pops stack + CV_CALL_NEAR_PASCAL = 0x02, // near left to right push, callee pops stack + CV_CALL_FAR_PASCAL = 0x03, // far left to right push, callee pops stack + CV_CALL_NEAR_FAST = 0x04, // near left to right push with regs, callee pops stack + CV_CALL_FAR_FAST = 0x05, // far left to right push with regs, callee pops stack + CV_CALL_SKIPPED = 0x06, // skipped (unused) call index + CV_CALL_NEAR_STD = 0x07, // near standard call + CV_CALL_FAR_STD = 0x08, // far standard call + CV_CALL_NEAR_SYS = 0x09, // near sys call + CV_CALL_FAR_SYS = 0x0a, // far sys call + CV_CALL_THISCALL = 0x0b, // this call (this passed in register) + CV_CALL_MIPSCALL = 0x0c, // Mips call + CV_CALL_GENERIC = 0x0d, // Generic call sequence + CV_CALL_ALPHACALL = 0x0e, // Alpha call + CV_CALL_PPCCALL = 0x0f, // PPC call + CV_CALL_SHCALL = 0x10, // Hitachi SuperH call + CV_CALL_ARMCALL = 0x11, // ARM call + CV_CALL_AM33CALL = 0x12, // AM33 call + CV_CALL_TRICALL = 0x13, // TriCore Call + CV_CALL_SH5CALL = 0x14, // Hitachi SuperH-5 call + CV_CALL_M32RCALL = 0x15, // M32R Call + CV_CALL_CLRCALL = 0x16, // clr call + CV_CALL_INLINE = 0x17, // Marker for routines always inlined and thus lacking a convention + CV_CALL_NEAR_VECTOR = 0x18, // near left to right push with regs, callee pops stack + CV_CALL_SWIFT = 0x19, // Swift calling convention + CV_CALL_RESERVED = 0x20 // first unused call enumeration + + // Do NOT add any more machine specific conventions. This is to be used for + // calling conventions in the source only (e.g. __cdecl, __stdcall). +} CV_call_e; + + +// Values for the access protection of class attributes + + +typedef enum CV_access_e +{ + CV_private = 1, + CV_protected = 2, + CV_public = 3 +} CV_access_e; + + +typedef enum THUNK_ORDINAL +{ + THUNK_ORDINAL_NOTYPE, // standard thunk + THUNK_ORDINAL_ADJUSTOR, // "this" adjustor thunk + THUNK_ORDINAL_VCALL, // virtual call thunk + THUNK_ORDINAL_PCODE, // pcode thunk + THUNK_ORDINAL_LOAD, // thunk which loads the address to jump to + // via unknown means... + + // trampoline thunk ordinals - only for use in Trampoline thunk symbols + + THUNK_ORDINAL_TRAMP_INCREMENTAL, + THUNK_ORDINAL_TRAMP_BRANCHISLAND, + THUNK_ORDINAL_TRAMP_STRICTICF, +} THUNK_ORDINAL; + + +enum CV_SourceChksum_t +{ + CHKSUM_TYPE_NONE = 0, // indicates no checksum is available + CHKSUM_TYPE_MD5, + CHKSUM_TYPE_SHA1, + CHKSUM_TYPE_SHA_256, +}; + +// +// DIA enums +// + +enum SymTagEnum +{ + SymTagNull, + SymTagExe, + SymTagCompiland, + SymTagCompilandDetails, + SymTagCompilandEnv, + SymTagFunction, + SymTagBlock, + SymTagData, + SymTagAnnotation, + SymTagLabel, + SymTagPublicSymbol, + SymTagUDT, + SymTagEnum, + SymTagFunctionType, + SymTagPointerType, + SymTagArrayType, + SymTagBaseType, + SymTagTypedef, + SymTagBaseClass, + SymTagFriend, + SymTagFunctionArgType, + SymTagFuncDebugStart, + SymTagFuncDebugEnd, + SymTagUsingNamespace, + SymTagVTableShape, + SymTagVTable, + SymTagCustom, + SymTagThunk, + SymTagCustomType, + SymTagManagedType, + SymTagDimension, + SymTagCallSite, + SymTagInlineSite, + SymTagBaseInterface, + SymTagVectorType, + SymTagMatrixType, + SymTagHLSLType, + SymTagCaller, + SymTagCallee, + SymTagExport, + SymTagHeapAllocationSite, + SymTagCoffGroup, + SymTagInlinee, + SymTagMax +}; + +enum LocationType +{ + LocIsNull, + LocIsStatic, + LocIsTLS, + LocIsRegRel, + LocIsThisRel, + LocIsEnregistered, + LocIsBitField, + LocIsSlot, + LocIsIlRel, + LocInMetaData, + LocIsConstant, + LocIsRegRelAliasIndir, + LocTypeMax +}; + +enum DataKind +{ + DataIsUnknown, + DataIsLocal, + DataIsStaticLocal, + DataIsParam, + DataIsObjectPtr, + DataIsFileStatic, + DataIsGlobal, + DataIsMember, + DataIsStaticMember, + DataIsConstant +}; + +enum UdtKind +{ + UdtStruct, + UdtClass, + UdtUnion, + UdtInterface +}; + +enum BasicType +{ + btNoType = 0, + btVoid = 1, + btChar = 2, + btWChar = 3, + btInt = 6, + btUInt = 7, + btFloat = 8, + btBCD = 9, + btBool = 10, + btLong = 13, + btULong = 14, + btCurrency = 25, + btDate = 26, + btVariant = 27, + btComplex = 28, + btBit = 29, + btBSTR = 30, + btHresult = 31, + btChar16 = 32, // char16_t + btChar32 = 33, // char32_t +}; + + +// enumeration for type modifier values + +typedef enum CV_modifier_e +{ + // 0x0000 - 0x01ff - Reserved. + + CV_MOD_INVALID = 0x0000, + + // Standard modifiers. + + CV_MOD_CONST = 0x0001, + CV_MOD_VOLATILE = 0x0002, + CV_MOD_UNALIGNED = 0x0003, + + // 0x0200 - 0x03ff - HLSL modifiers. + + CV_MOD_HLSL_UNIFORM = 0x0200, + CV_MOD_HLSL_LINE = 0x0201, + CV_MOD_HLSL_TRIANGLE = 0x0202, + CV_MOD_HLSL_LINEADJ = 0x0203, + CV_MOD_HLSL_TRIANGLEADJ = 0x0204, + CV_MOD_HLSL_LINEAR = 0x0205, + CV_MOD_HLSL_CENTROID = 0x0206, + CV_MOD_HLSL_CONSTINTERP = 0x0207, + CV_MOD_HLSL_NOPERSPECTIVE = 0x0208, + CV_MOD_HLSL_SAMPLE = 0x0209, + CV_MOD_HLSL_CENTER = 0x020a, + CV_MOD_HLSL_SNORM = 0x020b, + CV_MOD_HLSL_UNORM = 0x020c, + CV_MOD_HLSL_PRECISE = 0x020d, + CV_MOD_HLSL_UAV_GLOBALLY_COHERENT = 0x020e, + + // 0x0400 - 0xffff - Unused. + +} CV_modifier_e; + + +// built-in type kinds + + +typedef enum CV_builtin_e +{ + // 0x0000 - 0x01ff - Reserved. + CV_BI_INVALID = 0x0000, + + // 0x0200 - 0x03ff - HLSL types. + + CV_BI_HLSL_INTERFACE_POINTER = 0x0200, + CV_BI_HLSL_TEXTURE1D = 0x0201, + CV_BI_HLSL_TEXTURE1D_ARRAY = 0x0202, + CV_BI_HLSL_TEXTURE2D = 0x0203, + CV_BI_HLSL_TEXTURE2D_ARRAY = 0x0204, + CV_BI_HLSL_TEXTURE3D = 0x0205, + CV_BI_HLSL_TEXTURECUBE = 0x0206, + CV_BI_HLSL_TEXTURECUBE_ARRAY = 0x0207, + CV_BI_HLSL_TEXTURE2DMS = 0x0208, + CV_BI_HLSL_TEXTURE2DMS_ARRAY = 0x0209, + CV_BI_HLSL_SAMPLER = 0x020a, + CV_BI_HLSL_SAMPLERCOMPARISON = 0x020b, + CV_BI_HLSL_BUFFER = 0x020c, + CV_BI_HLSL_POINTSTREAM = 0x020d, + CV_BI_HLSL_LINESTREAM = 0x020e, + CV_BI_HLSL_TRIANGLESTREAM = 0x020f, + CV_BI_HLSL_INPUTPATCH = 0x0210, + CV_BI_HLSL_OUTPUTPATCH = 0x0211, + CV_BI_HLSL_RWTEXTURE1D = 0x0212, + CV_BI_HLSL_RWTEXTURE1D_ARRAY = 0x0213, + CV_BI_HLSL_RWTEXTURE2D = 0x0214, + CV_BI_HLSL_RWTEXTURE2D_ARRAY = 0x0215, + CV_BI_HLSL_RWTEXTURE3D = 0x0216, + CV_BI_HLSL_RWBUFFER = 0x0217, + CV_BI_HLSL_BYTEADDRESS_BUFFER = 0x0218, + CV_BI_HLSL_RWBYTEADDRESS_BUFFER = 0x0219, + CV_BI_HLSL_STRUCTURED_BUFFER = 0x021a, + CV_BI_HLSL_RWSTRUCTURED_BUFFER = 0x021b, + CV_BI_HLSL_APPEND_STRUCTURED_BUFFER = 0x021c, + CV_BI_HLSL_CONSUME_STRUCTURED_BUFFER= 0x021d, + CV_BI_HLSL_MIN8FLOAT = 0x021e, + CV_BI_HLSL_MIN10FLOAT = 0x021f, + CV_BI_HLSL_MIN16FLOAT = 0x0220, + CV_BI_HLSL_MIN12INT = 0x0221, + CV_BI_HLSL_MIN16INT = 0x0222, + CV_BI_HLSL_MIN16UINT = 0x0223, + CV_BI_HLSL_CONSTANT_BUFFER = 0x0224, + + // 0x0400 - 0xffff - Unused. + +} CV_builtin_e; + + +// enum describing the compile flag source language + + +typedef enum CV_CFL_LANG +{ + CV_CFL_C = 0x00, + CV_CFL_CXX = 0x01, + CV_CFL_FORTRAN = 0x02, + CV_CFL_MASM = 0x03, + CV_CFL_PASCAL = 0x04, + CV_CFL_BASIC = 0x05, + CV_CFL_COBOL = 0x06, + CV_CFL_LINK = 0x07, + CV_CFL_CVTRES = 0x08, + CV_CFL_CVTPGD = 0x09, + CV_CFL_CSHARP = 0x0A, // C# + CV_CFL_VB = 0x0B, // Visual Basic + CV_CFL_ILASM = 0x0C, // IL (as in CLR) ASM + CV_CFL_JAVA = 0x0D, + CV_CFL_JSCRIPT = 0x0E, + CV_CFL_MSIL = 0x0F, // Unknown MSIL (LTCG of .NETMODULE) + CV_CFL_HLSL = 0x10, // High Level Shader Language + CV_CFL_OBJC = 0x11, // Objective-C + CV_CFL_OBJCXX = 0x12, // Objective-C++ + CV_CFL_SWIFT = 0x13, // Swift +} CV_CFL_LANG; + + +// enum describing target processor + + +typedef enum CV_CPU_TYPE_e +{ + CV_CFL_8080 = 0x00, + CV_CFL_8086 = 0x01, + CV_CFL_80286 = 0x02, + CV_CFL_80386 = 0x03, + CV_CFL_80486 = 0x04, + CV_CFL_PENTIUM = 0x05, + CV_CFL_PENTIUMII = 0x06, + CV_CFL_PENTIUMPRO = CV_CFL_PENTIUMII, + CV_CFL_PENTIUMIII = 0x07, + CV_CFL_MIPS = 0x10, + CV_CFL_MIPSR4000 = CV_CFL_MIPS, // don't break current code + CV_CFL_MIPS16 = 0x11, + CV_CFL_MIPS32 = 0x12, + CV_CFL_MIPS64 = 0x13, + CV_CFL_MIPSI = 0x14, + CV_CFL_MIPSII = 0x15, + CV_CFL_MIPSIII = 0x16, + CV_CFL_MIPSIV = 0x17, + CV_CFL_MIPSV = 0x18, + CV_CFL_M68000 = 0x20, + CV_CFL_M68010 = 0x21, + CV_CFL_M68020 = 0x22, + CV_CFL_M68030 = 0x23, + CV_CFL_M68040 = 0x24, + CV_CFL_ALPHA = 0x30, + CV_CFL_ALPHA_21064 = 0x30, + CV_CFL_ALPHA_21164 = 0x31, + CV_CFL_ALPHA_21164A = 0x32, + CV_CFL_ALPHA_21264 = 0x33, + CV_CFL_ALPHA_21364 = 0x34, + CV_CFL_PPC601 = 0x40, + CV_CFL_PPC603 = 0x41, + CV_CFL_PPC604 = 0x42, + CV_CFL_PPC620 = 0x43, + CV_CFL_PPCFP = 0x44, + CV_CFL_PPCBE = 0x45, + CV_CFL_SH3 = 0x50, + CV_CFL_SH3E = 0x51, + CV_CFL_SH3DSP = 0x52, + CV_CFL_SH4 = 0x53, + CV_CFL_SHMEDIA = 0x54, + CV_CFL_ARM3 = 0x60, + CV_CFL_ARM4 = 0x61, + CV_CFL_ARM4T = 0x62, + CV_CFL_ARM5 = 0x63, + CV_CFL_ARM5T = 0x64, + CV_CFL_ARM6 = 0x65, + CV_CFL_ARM_XMAC = 0x66, + CV_CFL_ARM_WMMX = 0x67, + CV_CFL_ARM7 = 0x68, + CV_CFL_OMNI = 0x70, + CV_CFL_IA64 = 0x80, + CV_CFL_IA64_1 = 0x80, + CV_CFL_IA64_2 = 0x81, + CV_CFL_CEE = 0x90, + CV_CFL_AM33 = 0xA0, + CV_CFL_M32R = 0xB0, + CV_CFL_TRICORE = 0xC0, + CV_CFL_X64 = 0xD0, + CV_CFL_AMD64 = CV_CFL_X64, + CV_CFL_EBC = 0xE0, + CV_CFL_THUMB = 0xF0, + CV_CFL_ARMNT = 0xF4, + CV_CFL_ARM64 = 0xF6, + CV_CFL_HYBRID_X86_ARM64 = 0xF7, + CV_CFL_D3D11_SHADER = 0x100, +} CV_CPU_TYPE_e; + +typedef enum CV_HREG_e +{ + // Register subset shared by all processor types, + // must not overlap with any of the ranges below, hence the high values + + CV_ALLREG_ERR = 30000, + CV_ALLREG_TEB = 30001, + CV_ALLREG_TIMER = 30002, + CV_ALLREG_EFAD1 = 30003, + CV_ALLREG_EFAD2 = 30004, + CV_ALLREG_EFAD3 = 30005, + CV_ALLREG_VFRAME= 30006, + CV_ALLREG_HANDLE= 30007, + CV_ALLREG_PARAMS= 30008, + CV_ALLREG_LOCALS= 30009, + CV_ALLREG_TID = 30010, + CV_ALLREG_ENV = 30011, + CV_ALLREG_CMDLN = 30012, + + + // Register set for the Intel 80x86 and ix86 processor series + // (plus PCODE registers) + + CV_REG_NONE = 0, + CV_REG_AL = 1, + CV_REG_CL = 2, + CV_REG_DL = 3, + CV_REG_BL = 4, + CV_REG_AH = 5, + CV_REG_CH = 6, + CV_REG_DH = 7, + CV_REG_BH = 8, + CV_REG_AX = 9, + CV_REG_CX = 10, + CV_REG_DX = 11, + CV_REG_BX = 12, + CV_REG_SP = 13, + CV_REG_BP = 14, + CV_REG_SI = 15, + CV_REG_DI = 16, + CV_REG_EAX = 17, + CV_REG_ECX = 18, + CV_REG_EDX = 19, + CV_REG_EBX = 20, + CV_REG_ESP = 21, + CV_REG_EBP = 22, + CV_REG_ESI = 23, + CV_REG_EDI = 24, + CV_REG_ES = 25, + CV_REG_CS = 26, + CV_REG_SS = 27, + CV_REG_DS = 28, + CV_REG_FS = 29, + CV_REG_GS = 30, + CV_REG_IP = 31, + CV_REG_FLAGS = 32, + CV_REG_EIP = 33, + CV_REG_EFLAGS = 34, + CV_REG_TEMP = 40, // PCODE Temp + CV_REG_TEMPH = 41, // PCODE TempH + CV_REG_QUOTE = 42, // PCODE Quote + CV_REG_PCDR3 = 43, // PCODE reserved + CV_REG_PCDR4 = 44, // PCODE reserved + CV_REG_PCDR5 = 45, // PCODE reserved + CV_REG_PCDR6 = 46, // PCODE reserved + CV_REG_PCDR7 = 47, // PCODE reserved + CV_REG_CR0 = 80, // CR0 -- control registers + CV_REG_CR1 = 81, + CV_REG_CR2 = 82, + CV_REG_CR3 = 83, + CV_REG_CR4 = 84, // Pentium + CV_REG_DR0 = 90, // Debug register + CV_REG_DR1 = 91, + CV_REG_DR2 = 92, + CV_REG_DR3 = 93, + CV_REG_DR4 = 94, + CV_REG_DR5 = 95, + CV_REG_DR6 = 96, + CV_REG_DR7 = 97, + CV_REG_GDTR = 110, + CV_REG_GDTL = 111, + CV_REG_IDTR = 112, + CV_REG_IDTL = 113, + CV_REG_LDTR = 114, + CV_REG_TR = 115, + + CV_REG_PSEUDO1 = 116, + CV_REG_PSEUDO2 = 117, + CV_REG_PSEUDO3 = 118, + CV_REG_PSEUDO4 = 119, + CV_REG_PSEUDO5 = 120, + CV_REG_PSEUDO6 = 121, + CV_REG_PSEUDO7 = 122, + CV_REG_PSEUDO8 = 123, + CV_REG_PSEUDO9 = 124, + + CV_REG_ST0 = 128, + CV_REG_ST1 = 129, + CV_REG_ST2 = 130, + CV_REG_ST3 = 131, + CV_REG_ST4 = 132, + CV_REG_ST5 = 133, + CV_REG_ST6 = 134, + CV_REG_ST7 = 135, + CV_REG_CTRL = 136, + CV_REG_STAT = 137, + CV_REG_TAG = 138, + CV_REG_FPIP = 139, + CV_REG_FPCS = 140, + CV_REG_FPDO = 141, + CV_REG_FPDS = 142, + CV_REG_ISEM = 143, + CV_REG_FPEIP = 144, + CV_REG_FPEDO = 145, + + CV_REG_MM0 = 146, + CV_REG_MM1 = 147, + CV_REG_MM2 = 148, + CV_REG_MM3 = 149, + CV_REG_MM4 = 150, + CV_REG_MM5 = 151, + CV_REG_MM6 = 152, + CV_REG_MM7 = 153, + + CV_REG_XMM0 = 154, // KATMAI registers + CV_REG_XMM1 = 155, + CV_REG_XMM2 = 156, + CV_REG_XMM3 = 157, + CV_REG_XMM4 = 158, + CV_REG_XMM5 = 159, + CV_REG_XMM6 = 160, + CV_REG_XMM7 = 161, + + CV_REG_XMM00 = 162, // KATMAI sub-registers + CV_REG_XMM01 = 163, + CV_REG_XMM02 = 164, + CV_REG_XMM03 = 165, + CV_REG_XMM10 = 166, + CV_REG_XMM11 = 167, + CV_REG_XMM12 = 168, + CV_REG_XMM13 = 169, + CV_REG_XMM20 = 170, + CV_REG_XMM21 = 171, + CV_REG_XMM22 = 172, + CV_REG_XMM23 = 173, + CV_REG_XMM30 = 174, + CV_REG_XMM31 = 175, + CV_REG_XMM32 = 176, + CV_REG_XMM33 = 177, + CV_REG_XMM40 = 178, + CV_REG_XMM41 = 179, + CV_REG_XMM42 = 180, + CV_REG_XMM43 = 181, + CV_REG_XMM50 = 182, + CV_REG_XMM51 = 183, + CV_REG_XMM52 = 184, + CV_REG_XMM53 = 185, + CV_REG_XMM60 = 186, + CV_REG_XMM61 = 187, + CV_REG_XMM62 = 188, + CV_REG_XMM63 = 189, + CV_REG_XMM70 = 190, + CV_REG_XMM71 = 191, + CV_REG_XMM72 = 192, + CV_REG_XMM73 = 193, + + CV_REG_XMM0L = 194, + CV_REG_XMM1L = 195, + CV_REG_XMM2L = 196, + CV_REG_XMM3L = 197, + CV_REG_XMM4L = 198, + CV_REG_XMM5L = 199, + CV_REG_XMM6L = 200, + CV_REG_XMM7L = 201, + + CV_REG_XMM0H = 202, + CV_REG_XMM1H = 203, + CV_REG_XMM2H = 204, + CV_REG_XMM3H = 205, + CV_REG_XMM4H = 206, + CV_REG_XMM5H = 207, + CV_REG_XMM6H = 208, + CV_REG_XMM7H = 209, + + CV_REG_MXCSR = 211, // XMM status register + + CV_REG_EDXEAX = 212, // EDX:EAX pair + + CV_REG_EMM0L = 220, // XMM sub-registers (WNI integer) + CV_REG_EMM1L = 221, + CV_REG_EMM2L = 222, + CV_REG_EMM3L = 223, + CV_REG_EMM4L = 224, + CV_REG_EMM5L = 225, + CV_REG_EMM6L = 226, + CV_REG_EMM7L = 227, + + CV_REG_EMM0H = 228, + CV_REG_EMM1H = 229, + CV_REG_EMM2H = 230, + CV_REG_EMM3H = 231, + CV_REG_EMM4H = 232, + CV_REG_EMM5H = 233, + CV_REG_EMM6H = 234, + CV_REG_EMM7H = 235, + + // do not change the order of these regs, first one must be even too + CV_REG_MM00 = 236, + CV_REG_MM01 = 237, + CV_REG_MM10 = 238, + CV_REG_MM11 = 239, + CV_REG_MM20 = 240, + CV_REG_MM21 = 241, + CV_REG_MM30 = 242, + CV_REG_MM31 = 243, + CV_REG_MM40 = 244, + CV_REG_MM41 = 245, + CV_REG_MM50 = 246, + CV_REG_MM51 = 247, + CV_REG_MM60 = 248, + CV_REG_MM61 = 249, + CV_REG_MM70 = 250, + CV_REG_MM71 = 251, + + CV_REG_YMM0 = 252, // AVX registers + CV_REG_YMM1 = 253, + CV_REG_YMM2 = 254, + CV_REG_YMM3 = 255, + CV_REG_YMM4 = 256, + CV_REG_YMM5 = 257, + CV_REG_YMM6 = 258, + CV_REG_YMM7 = 259, + + CV_REG_YMM0H = 260, + CV_REG_YMM1H = 261, + CV_REG_YMM2H = 262, + CV_REG_YMM3H = 263, + CV_REG_YMM4H = 264, + CV_REG_YMM5H = 265, + CV_REG_YMM6H = 266, + CV_REG_YMM7H = 267, + + CV_REG_YMM0I0 = 268, // AVX integer registers + CV_REG_YMM0I1 = 269, + CV_REG_YMM0I2 = 270, + CV_REG_YMM0I3 = 271, + CV_REG_YMM1I0 = 272, + CV_REG_YMM1I1 = 273, + CV_REG_YMM1I2 = 274, + CV_REG_YMM1I3 = 275, + CV_REG_YMM2I0 = 276, + CV_REG_YMM2I1 = 277, + CV_REG_YMM2I2 = 278, + CV_REG_YMM2I3 = 279, + CV_REG_YMM3I0 = 280, + CV_REG_YMM3I1 = 281, + CV_REG_YMM3I2 = 282, + CV_REG_YMM3I3 = 283, + CV_REG_YMM4I0 = 284, + CV_REG_YMM4I1 = 285, + CV_REG_YMM4I2 = 286, + CV_REG_YMM4I3 = 287, + CV_REG_YMM5I0 = 288, + CV_REG_YMM5I1 = 289, + CV_REG_YMM5I2 = 290, + CV_REG_YMM5I3 = 291, + CV_REG_YMM6I0 = 292, + CV_REG_YMM6I1 = 293, + CV_REG_YMM6I2 = 294, + CV_REG_YMM6I3 = 295, + CV_REG_YMM7I0 = 296, + CV_REG_YMM7I1 = 297, + CV_REG_YMM7I2 = 298, + CV_REG_YMM7I3 = 299, + + CV_REG_YMM0F0 = 300, // AVX floating-point single precise registers + CV_REG_YMM0F1 = 301, + CV_REG_YMM0F2 = 302, + CV_REG_YMM0F3 = 303, + CV_REG_YMM0F4 = 304, + CV_REG_YMM0F5 = 305, + CV_REG_YMM0F6 = 306, + CV_REG_YMM0F7 = 307, + CV_REG_YMM1F0 = 308, + CV_REG_YMM1F1 = 309, + CV_REG_YMM1F2 = 310, + CV_REG_YMM1F3 = 311, + CV_REG_YMM1F4 = 312, + CV_REG_YMM1F5 = 313, + CV_REG_YMM1F6 = 314, + CV_REG_YMM1F7 = 315, + CV_REG_YMM2F0 = 316, + CV_REG_YMM2F1 = 317, + CV_REG_YMM2F2 = 318, + CV_REG_YMM2F3 = 319, + CV_REG_YMM2F4 = 320, + CV_REG_YMM2F5 = 321, + CV_REG_YMM2F6 = 322, + CV_REG_YMM2F7 = 323, + CV_REG_YMM3F0 = 324, + CV_REG_YMM3F1 = 325, + CV_REG_YMM3F2 = 326, + CV_REG_YMM3F3 = 327, + CV_REG_YMM3F4 = 328, + CV_REG_YMM3F5 = 329, + CV_REG_YMM3F6 = 330, + CV_REG_YMM3F7 = 331, + CV_REG_YMM4F0 = 332, + CV_REG_YMM4F1 = 333, + CV_REG_YMM4F2 = 334, + CV_REG_YMM4F3 = 335, + CV_REG_YMM4F4 = 336, + CV_REG_YMM4F5 = 337, + CV_REG_YMM4F6 = 338, + CV_REG_YMM4F7 = 339, + CV_REG_YMM5F0 = 340, + CV_REG_YMM5F1 = 341, + CV_REG_YMM5F2 = 342, + CV_REG_YMM5F3 = 343, + CV_REG_YMM5F4 = 344, + CV_REG_YMM5F5 = 345, + CV_REG_YMM5F6 = 346, + CV_REG_YMM5F7 = 347, + CV_REG_YMM6F0 = 348, + CV_REG_YMM6F1 = 349, + CV_REG_YMM6F2 = 350, + CV_REG_YMM6F3 = 351, + CV_REG_YMM6F4 = 352, + CV_REG_YMM6F5 = 353, + CV_REG_YMM6F6 = 354, + CV_REG_YMM6F7 = 355, + CV_REG_YMM7F0 = 356, + CV_REG_YMM7F1 = 357, + CV_REG_YMM7F2 = 358, + CV_REG_YMM7F3 = 359, + CV_REG_YMM7F4 = 360, + CV_REG_YMM7F5 = 361, + CV_REG_YMM7F6 = 362, + CV_REG_YMM7F7 = 363, + + CV_REG_YMM0D0 = 364, // AVX floating-point double precise registers + CV_REG_YMM0D1 = 365, + CV_REG_YMM0D2 = 366, + CV_REG_YMM0D3 = 367, + CV_REG_YMM1D0 = 368, + CV_REG_YMM1D1 = 369, + CV_REG_YMM1D2 = 370, + CV_REG_YMM1D3 = 371, + CV_REG_YMM2D0 = 372, + CV_REG_YMM2D1 = 373, + CV_REG_YMM2D2 = 374, + CV_REG_YMM2D3 = 375, + CV_REG_YMM3D0 = 376, + CV_REG_YMM3D1 = 377, + CV_REG_YMM3D2 = 378, + CV_REG_YMM3D3 = 379, + CV_REG_YMM4D0 = 380, + CV_REG_YMM4D1 = 381, + CV_REG_YMM4D2 = 382, + CV_REG_YMM4D3 = 383, + CV_REG_YMM5D0 = 384, + CV_REG_YMM5D1 = 385, + CV_REG_YMM5D2 = 386, + CV_REG_YMM5D3 = 387, + CV_REG_YMM6D0 = 388, + CV_REG_YMM6D1 = 389, + CV_REG_YMM6D2 = 390, + CV_REG_YMM6D3 = 391, + CV_REG_YMM7D0 = 392, + CV_REG_YMM7D1 = 393, + CV_REG_YMM7D2 = 394, + CV_REG_YMM7D3 = 395, + + CV_REG_BND0 = 396, // x86 MPX bounds registers + CV_REG_BND1 = 397, + CV_REG_BND2 = 398, + CV_REG_BND3 = 399, + CV_REG_BNDCFGU = 400, + CV_REG_BNDSTATUS = 401, + + CV_REG_ZMM0 = 402, // AVX-512 registers + CV_REG_ZMM1 = 403, + CV_REG_ZMM2 = 404, + CV_REG_ZMM3 = 405, + CV_REG_ZMM4 = 406, + CV_REG_ZMM5 = 407, + CV_REG_ZMM6 = 408, + CV_REG_ZMM7 = 409, + + CV_REG_ZMM0H = 410, + CV_REG_ZMM1H = 411, + CV_REG_ZMM2H = 412, + CV_REG_ZMM3H = 413, + CV_REG_ZMM4H = 414, + CV_REG_ZMM5H = 415, + CV_REG_ZMM6H = 416, + CV_REG_ZMM7H = 417, + + CV_REG_K0 = 418, + CV_REG_K1 = 419, + CV_REG_K2 = 420, + CV_REG_K3 = 421, + CV_REG_K4 = 422, + CV_REG_K5 = 423, + CV_REG_K6 = 424, + CV_REG_K7 = 425, + + // registers for the 68K processors + + CV_R68_D0 = 0, + CV_R68_D1 = 1, + CV_R68_D2 = 2, + CV_R68_D3 = 3, + CV_R68_D4 = 4, + CV_R68_D5 = 5, + CV_R68_D6 = 6, + CV_R68_D7 = 7, + CV_R68_A0 = 8, + CV_R68_A1 = 9, + CV_R68_A2 = 10, + CV_R68_A3 = 11, + CV_R68_A4 = 12, + CV_R68_A5 = 13, + CV_R68_A6 = 14, + CV_R68_A7 = 15, + CV_R68_CCR = 16, + CV_R68_SR = 17, + CV_R68_USP = 18, + CV_R68_MSP = 19, + CV_R68_SFC = 20, + CV_R68_DFC = 21, + CV_R68_CACR = 22, + CV_R68_VBR = 23, + CV_R68_CAAR = 24, + CV_R68_ISP = 25, + CV_R68_PC = 26, + //reserved 27 + CV_R68_FPCR = 28, + CV_R68_FPSR = 29, + CV_R68_FPIAR = 30, + //reserved 31 + CV_R68_FP0 = 32, + CV_R68_FP1 = 33, + CV_R68_FP2 = 34, + CV_R68_FP3 = 35, + CV_R68_FP4 = 36, + CV_R68_FP5 = 37, + CV_R68_FP6 = 38, + CV_R68_FP7 = 39, + //reserved 40 + CV_R68_MMUSR030 = 41, + CV_R68_MMUSR = 42, + CV_R68_URP = 43, + CV_R68_DTT0 = 44, + CV_R68_DTT1 = 45, + CV_R68_ITT0 = 46, + CV_R68_ITT1 = 47, + //reserved 50 + CV_R68_PSR = 51, + CV_R68_PCSR = 52, + CV_R68_VAL = 53, + CV_R68_CRP = 54, + CV_R68_SRP = 55, + CV_R68_DRP = 56, + CV_R68_TC = 57, + CV_R68_AC = 58, + CV_R68_SCC = 59, + CV_R68_CAL = 60, + CV_R68_TT0 = 61, + CV_R68_TT1 = 62, + //reserved 63 + CV_R68_BAD0 = 64, + CV_R68_BAD1 = 65, + CV_R68_BAD2 = 66, + CV_R68_BAD3 = 67, + CV_R68_BAD4 = 68, + CV_R68_BAD5 = 69, + CV_R68_BAD6 = 70, + CV_R68_BAD7 = 71, + CV_R68_BAC0 = 72, + CV_R68_BAC1 = 73, + CV_R68_BAC2 = 74, + CV_R68_BAC3 = 75, + CV_R68_BAC4 = 76, + CV_R68_BAC5 = 77, + CV_R68_BAC6 = 78, + CV_R68_BAC7 = 79, + + // Register set for the MIPS 4000 + + CV_M4_NOREG = CV_REG_NONE, + + CV_M4_IntZERO = 10, /* CPU REGISTER */ + CV_M4_IntAT = 11, + CV_M4_IntV0 = 12, + CV_M4_IntV1 = 13, + CV_M4_IntA0 = 14, + CV_M4_IntA1 = 15, + CV_M4_IntA2 = 16, + CV_M4_IntA3 = 17, + CV_M4_IntT0 = 18, + CV_M4_IntT1 = 19, + CV_M4_IntT2 = 20, + CV_M4_IntT3 = 21, + CV_M4_IntT4 = 22, + CV_M4_IntT5 = 23, + CV_M4_IntT6 = 24, + CV_M4_IntT7 = 25, + CV_M4_IntS0 = 26, + CV_M4_IntS1 = 27, + CV_M4_IntS2 = 28, + CV_M4_IntS3 = 29, + CV_M4_IntS4 = 30, + CV_M4_IntS5 = 31, + CV_M4_IntS6 = 32, + CV_M4_IntS7 = 33, + CV_M4_IntT8 = 34, + CV_M4_IntT9 = 35, + CV_M4_IntKT0 = 36, + CV_M4_IntKT1 = 37, + CV_M4_IntGP = 38, + CV_M4_IntSP = 39, + CV_M4_IntS8 = 40, + CV_M4_IntRA = 41, + CV_M4_IntLO = 42, + CV_M4_IntHI = 43, + + CV_M4_Fir = 50, + CV_M4_Psr = 51, + + CV_M4_FltF0 = 60, /* Floating point registers */ + CV_M4_FltF1 = 61, + CV_M4_FltF2 = 62, + CV_M4_FltF3 = 63, + CV_M4_FltF4 = 64, + CV_M4_FltF5 = 65, + CV_M4_FltF6 = 66, + CV_M4_FltF7 = 67, + CV_M4_FltF8 = 68, + CV_M4_FltF9 = 69, + CV_M4_FltF10 = 70, + CV_M4_FltF11 = 71, + CV_M4_FltF12 = 72, + CV_M4_FltF13 = 73, + CV_M4_FltF14 = 74, + CV_M4_FltF15 = 75, + CV_M4_FltF16 = 76, + CV_M4_FltF17 = 77, + CV_M4_FltF18 = 78, + CV_M4_FltF19 = 79, + CV_M4_FltF20 = 80, + CV_M4_FltF21 = 81, + CV_M4_FltF22 = 82, + CV_M4_FltF23 = 83, + CV_M4_FltF24 = 84, + CV_M4_FltF25 = 85, + CV_M4_FltF26 = 86, + CV_M4_FltF27 = 87, + CV_M4_FltF28 = 88, + CV_M4_FltF29 = 89, + CV_M4_FltF30 = 90, + CV_M4_FltF31 = 91, + CV_M4_FltFsr = 92, + + + // Register set for the ALPHA AXP + + CV_ALPHA_NOREG = CV_REG_NONE, + + CV_ALPHA_FltF0 = 10, // Floating point registers + CV_ALPHA_FltF1 = 11, + CV_ALPHA_FltF2 = 12, + CV_ALPHA_FltF3 = 13, + CV_ALPHA_FltF4 = 14, + CV_ALPHA_FltF5 = 15, + CV_ALPHA_FltF6 = 16, + CV_ALPHA_FltF7 = 17, + CV_ALPHA_FltF8 = 18, + CV_ALPHA_FltF9 = 19, + CV_ALPHA_FltF10 = 20, + CV_ALPHA_FltF11 = 21, + CV_ALPHA_FltF12 = 22, + CV_ALPHA_FltF13 = 23, + CV_ALPHA_FltF14 = 24, + CV_ALPHA_FltF15 = 25, + CV_ALPHA_FltF16 = 26, + CV_ALPHA_FltF17 = 27, + CV_ALPHA_FltF18 = 28, + CV_ALPHA_FltF19 = 29, + CV_ALPHA_FltF20 = 30, + CV_ALPHA_FltF21 = 31, + CV_ALPHA_FltF22 = 32, + CV_ALPHA_FltF23 = 33, + CV_ALPHA_FltF24 = 34, + CV_ALPHA_FltF25 = 35, + CV_ALPHA_FltF26 = 36, + CV_ALPHA_FltF27 = 37, + CV_ALPHA_FltF28 = 38, + CV_ALPHA_FltF29 = 39, + CV_ALPHA_FltF30 = 40, + CV_ALPHA_FltF31 = 41, + + CV_ALPHA_IntV0 = 42, // Integer registers + CV_ALPHA_IntT0 = 43, + CV_ALPHA_IntT1 = 44, + CV_ALPHA_IntT2 = 45, + CV_ALPHA_IntT3 = 46, + CV_ALPHA_IntT4 = 47, + CV_ALPHA_IntT5 = 48, + CV_ALPHA_IntT6 = 49, + CV_ALPHA_IntT7 = 50, + CV_ALPHA_IntS0 = 51, + CV_ALPHA_IntS1 = 52, + CV_ALPHA_IntS2 = 53, + CV_ALPHA_IntS3 = 54, + CV_ALPHA_IntS4 = 55, + CV_ALPHA_IntS5 = 56, + CV_ALPHA_IntFP = 57, + CV_ALPHA_IntA0 = 58, + CV_ALPHA_IntA1 = 59, + CV_ALPHA_IntA2 = 60, + CV_ALPHA_IntA3 = 61, + CV_ALPHA_IntA4 = 62, + CV_ALPHA_IntA5 = 63, + CV_ALPHA_IntT8 = 64, + CV_ALPHA_IntT9 = 65, + CV_ALPHA_IntT10 = 66, + CV_ALPHA_IntT11 = 67, + CV_ALPHA_IntRA = 68, + CV_ALPHA_IntT12 = 69, + CV_ALPHA_IntAT = 70, + CV_ALPHA_IntGP = 71, + CV_ALPHA_IntSP = 72, + CV_ALPHA_IntZERO = 73, + + + CV_ALPHA_Fpcr = 74, // Control registers + CV_ALPHA_Fir = 75, + CV_ALPHA_Psr = 76, + CV_ALPHA_FltFsr = 77, + CV_ALPHA_SoftFpcr = 78, + + // Register Set for Motorola/IBM PowerPC + + /* + ** PowerPC General Registers ( User Level ) + */ + CV_PPC_GPR0 = 1, + CV_PPC_GPR1 = 2, + CV_PPC_GPR2 = 3, + CV_PPC_GPR3 = 4, + CV_PPC_GPR4 = 5, + CV_PPC_GPR5 = 6, + CV_PPC_GPR6 = 7, + CV_PPC_GPR7 = 8, + CV_PPC_GPR8 = 9, + CV_PPC_GPR9 = 10, + CV_PPC_GPR10 = 11, + CV_PPC_GPR11 = 12, + CV_PPC_GPR12 = 13, + CV_PPC_GPR13 = 14, + CV_PPC_GPR14 = 15, + CV_PPC_GPR15 = 16, + CV_PPC_GPR16 = 17, + CV_PPC_GPR17 = 18, + CV_PPC_GPR18 = 19, + CV_PPC_GPR19 = 20, + CV_PPC_GPR20 = 21, + CV_PPC_GPR21 = 22, + CV_PPC_GPR22 = 23, + CV_PPC_GPR23 = 24, + CV_PPC_GPR24 = 25, + CV_PPC_GPR25 = 26, + CV_PPC_GPR26 = 27, + CV_PPC_GPR27 = 28, + CV_PPC_GPR28 = 29, + CV_PPC_GPR29 = 30, + CV_PPC_GPR30 = 31, + CV_PPC_GPR31 = 32, + + /* + ** PowerPC Condition Register ( User Level ) + */ + CV_PPC_CR = 33, + CV_PPC_CR0 = 34, + CV_PPC_CR1 = 35, + CV_PPC_CR2 = 36, + CV_PPC_CR3 = 37, + CV_PPC_CR4 = 38, + CV_PPC_CR5 = 39, + CV_PPC_CR6 = 40, + CV_PPC_CR7 = 41, + + /* + ** PowerPC Floating Point Registers ( User Level ) + */ + CV_PPC_FPR0 = 42, + CV_PPC_FPR1 = 43, + CV_PPC_FPR2 = 44, + CV_PPC_FPR3 = 45, + CV_PPC_FPR4 = 46, + CV_PPC_FPR5 = 47, + CV_PPC_FPR6 = 48, + CV_PPC_FPR7 = 49, + CV_PPC_FPR8 = 50, + CV_PPC_FPR9 = 51, + CV_PPC_FPR10 = 52, + CV_PPC_FPR11 = 53, + CV_PPC_FPR12 = 54, + CV_PPC_FPR13 = 55, + CV_PPC_FPR14 = 56, + CV_PPC_FPR15 = 57, + CV_PPC_FPR16 = 58, + CV_PPC_FPR17 = 59, + CV_PPC_FPR18 = 60, + CV_PPC_FPR19 = 61, + CV_PPC_FPR20 = 62, + CV_PPC_FPR21 = 63, + CV_PPC_FPR22 = 64, + CV_PPC_FPR23 = 65, + CV_PPC_FPR24 = 66, + CV_PPC_FPR25 = 67, + CV_PPC_FPR26 = 68, + CV_PPC_FPR27 = 69, + CV_PPC_FPR28 = 70, + CV_PPC_FPR29 = 71, + CV_PPC_FPR30 = 72, + CV_PPC_FPR31 = 73, + + /* + ** PowerPC Floating Point Status and Control Register ( User Level ) + */ + CV_PPC_FPSCR = 74, + + /* + ** PowerPC Machine State Register ( Supervisor Level ) + */ + CV_PPC_MSR = 75, + + /* + ** PowerPC Segment Registers ( Supervisor Level ) + */ + CV_PPC_SR0 = 76, + CV_PPC_SR1 = 77, + CV_PPC_SR2 = 78, + CV_PPC_SR3 = 79, + CV_PPC_SR4 = 80, + CV_PPC_SR5 = 81, + CV_PPC_SR6 = 82, + CV_PPC_SR7 = 83, + CV_PPC_SR8 = 84, + CV_PPC_SR9 = 85, + CV_PPC_SR10 = 86, + CV_PPC_SR11 = 87, + CV_PPC_SR12 = 88, + CV_PPC_SR13 = 89, + CV_PPC_SR14 = 90, + CV_PPC_SR15 = 91, + + /* + ** For all of the special purpose registers add 100 to the SPR# that the + ** Motorola/IBM documentation gives with the exception of any imaginary + ** registers. + */ + + /* + ** PowerPC Special Purpose Registers ( User Level ) + */ + CV_PPC_PC = 99, // PC (imaginary register) + + CV_PPC_MQ = 100, // MPC601 + CV_PPC_XER = 101, + CV_PPC_RTCU = 104, // MPC601 + CV_PPC_RTCL = 105, // MPC601 + CV_PPC_LR = 108, + CV_PPC_CTR = 109, + + CV_PPC_COMPARE = 110, // part of XER (internal to the debugger only) + CV_PPC_COUNT = 111, // part of XER (internal to the debugger only) + + /* + ** PowerPC Special Purpose Registers ( Supervisor Level ) + */ + CV_PPC_DSISR = 118, + CV_PPC_DAR = 119, + CV_PPC_DEC = 122, + CV_PPC_SDR1 = 125, + CV_PPC_SRR0 = 126, + CV_PPC_SRR1 = 127, + CV_PPC_SPRG0 = 372, + CV_PPC_SPRG1 = 373, + CV_PPC_SPRG2 = 374, + CV_PPC_SPRG3 = 375, + CV_PPC_ASR = 280, // 64-bit implementations only + CV_PPC_EAR = 382, + CV_PPC_PVR = 287, + CV_PPC_BAT0U = 628, + CV_PPC_BAT0L = 629, + CV_PPC_BAT1U = 630, + CV_PPC_BAT1L = 631, + CV_PPC_BAT2U = 632, + CV_PPC_BAT2L = 633, + CV_PPC_BAT3U = 634, + CV_PPC_BAT3L = 635, + CV_PPC_DBAT0U = 636, + CV_PPC_DBAT0L = 637, + CV_PPC_DBAT1U = 638, + CV_PPC_DBAT1L = 639, + CV_PPC_DBAT2U = 640, + CV_PPC_DBAT2L = 641, + CV_PPC_DBAT3U = 642, + CV_PPC_DBAT3L = 643, + + /* + ** PowerPC Special Purpose Registers Implementation Dependent ( Supervisor Level ) + */ + + /* + ** Doesn't appear that IBM/Motorola has finished defining these. + */ + + CV_PPC_PMR0 = 1044, // MPC620, + CV_PPC_PMR1 = 1045, // MPC620, + CV_PPC_PMR2 = 1046, // MPC620, + CV_PPC_PMR3 = 1047, // MPC620, + CV_PPC_PMR4 = 1048, // MPC620, + CV_PPC_PMR5 = 1049, // MPC620, + CV_PPC_PMR6 = 1050, // MPC620, + CV_PPC_PMR7 = 1051, // MPC620, + CV_PPC_PMR8 = 1052, // MPC620, + CV_PPC_PMR9 = 1053, // MPC620, + CV_PPC_PMR10 = 1054, // MPC620, + CV_PPC_PMR11 = 1055, // MPC620, + CV_PPC_PMR12 = 1056, // MPC620, + CV_PPC_PMR13 = 1057, // MPC620, + CV_PPC_PMR14 = 1058, // MPC620, + CV_PPC_PMR15 = 1059, // MPC620, + + CV_PPC_DMISS = 1076, // MPC603 + CV_PPC_DCMP = 1077, // MPC603 + CV_PPC_HASH1 = 1078, // MPC603 + CV_PPC_HASH2 = 1079, // MPC603 + CV_PPC_IMISS = 1080, // MPC603 + CV_PPC_ICMP = 1081, // MPC603 + CV_PPC_RPA = 1082, // MPC603 + + CV_PPC_HID0 = 1108, // MPC601, MPC603, MPC620 + CV_PPC_HID1 = 1109, // MPC601 + CV_PPC_HID2 = 1110, // MPC601, MPC603, MPC620 ( IABR ) + CV_PPC_HID3 = 1111, // Not Defined + CV_PPC_HID4 = 1112, // Not Defined + CV_PPC_HID5 = 1113, // MPC601, MPC604, MPC620 ( DABR ) + CV_PPC_HID6 = 1114, // Not Defined + CV_PPC_HID7 = 1115, // Not Defined + CV_PPC_HID8 = 1116, // MPC620 ( BUSCSR ) + CV_PPC_HID9 = 1117, // MPC620 ( L2CSR ) + CV_PPC_HID10 = 1118, // Not Defined + CV_PPC_HID11 = 1119, // Not Defined + CV_PPC_HID12 = 1120, // Not Defined + CV_PPC_HID13 = 1121, // MPC604 ( HCR ) + CV_PPC_HID14 = 1122, // Not Defined + CV_PPC_HID15 = 1123, // MPC601, MPC604, MPC620 ( PIR ) + + // + // JAVA VM registers + // + + CV_JAVA_PC = 1, + + // + // Register set for the Hitachi SH3 + // + + CV_SH3_NOREG = CV_REG_NONE, + + CV_SH3_IntR0 = 10, // CPU REGISTER + CV_SH3_IntR1 = 11, + CV_SH3_IntR2 = 12, + CV_SH3_IntR3 = 13, + CV_SH3_IntR4 = 14, + CV_SH3_IntR5 = 15, + CV_SH3_IntR6 = 16, + CV_SH3_IntR7 = 17, + CV_SH3_IntR8 = 18, + CV_SH3_IntR9 = 19, + CV_SH3_IntR10 = 20, + CV_SH3_IntR11 = 21, + CV_SH3_IntR12 = 22, + CV_SH3_IntR13 = 23, + CV_SH3_IntFp = 24, + CV_SH3_IntSp = 25, + CV_SH3_Gbr = 38, + CV_SH3_Pr = 39, + CV_SH3_Mach = 40, + CV_SH3_Macl = 41, + + CV_SH3_Pc = 50, + CV_SH3_Sr = 51, + + CV_SH3_BarA = 60, + CV_SH3_BasrA = 61, + CV_SH3_BamrA = 62, + CV_SH3_BbrA = 63, + CV_SH3_BarB = 64, + CV_SH3_BasrB = 65, + CV_SH3_BamrB = 66, + CV_SH3_BbrB = 67, + CV_SH3_BdrB = 68, + CV_SH3_BdmrB = 69, + CV_SH3_Brcr = 70, + + // + // Additional registers for Hitachi SH processors + // + + CV_SH_Fpscr = 75, // floating point status/control register + CV_SH_Fpul = 76, // floating point communication register + + CV_SH_FpR0 = 80, // Floating point registers + CV_SH_FpR1 = 81, + CV_SH_FpR2 = 82, + CV_SH_FpR3 = 83, + CV_SH_FpR4 = 84, + CV_SH_FpR5 = 85, + CV_SH_FpR6 = 86, + CV_SH_FpR7 = 87, + CV_SH_FpR8 = 88, + CV_SH_FpR9 = 89, + CV_SH_FpR10 = 90, + CV_SH_FpR11 = 91, + CV_SH_FpR12 = 92, + CV_SH_FpR13 = 93, + CV_SH_FpR14 = 94, + CV_SH_FpR15 = 95, + + CV_SH_XFpR0 = 96, + CV_SH_XFpR1 = 97, + CV_SH_XFpR2 = 98, + CV_SH_XFpR3 = 99, + CV_SH_XFpR4 = 100, + CV_SH_XFpR5 = 101, + CV_SH_XFpR6 = 102, + CV_SH_XFpR7 = 103, + CV_SH_XFpR8 = 104, + CV_SH_XFpR9 = 105, + CV_SH_XFpR10 = 106, + CV_SH_XFpR11 = 107, + CV_SH_XFpR12 = 108, + CV_SH_XFpR13 = 109, + CV_SH_XFpR14 = 110, + CV_SH_XFpR15 = 111, + + // + // Register set for the ARM processor. + // + + CV_ARM_NOREG = CV_REG_NONE, + + CV_ARM_R0 = 10, + CV_ARM_R1 = 11, + CV_ARM_R2 = 12, + CV_ARM_R3 = 13, + CV_ARM_R4 = 14, + CV_ARM_R5 = 15, + CV_ARM_R6 = 16, + CV_ARM_R7 = 17, + CV_ARM_R8 = 18, + CV_ARM_R9 = 19, + CV_ARM_R10 = 20, + CV_ARM_R11 = 21, // Frame pointer, if allocated + CV_ARM_R12 = 22, + CV_ARM_SP = 23, // Stack pointer + CV_ARM_LR = 24, // Link Register + CV_ARM_PC = 25, // Program counter + CV_ARM_CPSR = 26, // Current program status register + + CV_ARM_ACC0 = 27, // DSP co-processor 0 40 bit accumulator + + // + // Registers for ARM VFP10 support + // + + CV_ARM_FPSCR = 40, + CV_ARM_FPEXC = 41, + + CV_ARM_FS0 = 50, + CV_ARM_FS1 = 51, + CV_ARM_FS2 = 52, + CV_ARM_FS3 = 53, + CV_ARM_FS4 = 54, + CV_ARM_FS5 = 55, + CV_ARM_FS6 = 56, + CV_ARM_FS7 = 57, + CV_ARM_FS8 = 58, + CV_ARM_FS9 = 59, + CV_ARM_FS10 = 60, + CV_ARM_FS11 = 61, + CV_ARM_FS12 = 62, + CV_ARM_FS13 = 63, + CV_ARM_FS14 = 64, + CV_ARM_FS15 = 65, + CV_ARM_FS16 = 66, + CV_ARM_FS17 = 67, + CV_ARM_FS18 = 68, + CV_ARM_FS19 = 69, + CV_ARM_FS20 = 70, + CV_ARM_FS21 = 71, + CV_ARM_FS22 = 72, + CV_ARM_FS23 = 73, + CV_ARM_FS24 = 74, + CV_ARM_FS25 = 75, + CV_ARM_FS26 = 76, + CV_ARM_FS27 = 77, + CV_ARM_FS28 = 78, + CV_ARM_FS29 = 79, + CV_ARM_FS30 = 80, + CV_ARM_FS31 = 81, + + // + // ARM VFP Floating Point Extra control registers + // + + CV_ARM_FPEXTRA0 = 90, + CV_ARM_FPEXTRA1 = 91, + CV_ARM_FPEXTRA2 = 92, + CV_ARM_FPEXTRA3 = 93, + CV_ARM_FPEXTRA4 = 94, + CV_ARM_FPEXTRA5 = 95, + CV_ARM_FPEXTRA6 = 96, + CV_ARM_FPEXTRA7 = 97, + + // XSCALE Concan co-processor registers + CV_ARM_WR0 = 128, + CV_ARM_WR1 = 129, + CV_ARM_WR2 = 130, + CV_ARM_WR3 = 131, + CV_ARM_WR4 = 132, + CV_ARM_WR5 = 133, + CV_ARM_WR6 = 134, + CV_ARM_WR7 = 135, + CV_ARM_WR8 = 136, + CV_ARM_WR9 = 137, + CV_ARM_WR10 = 138, + CV_ARM_WR11 = 139, + CV_ARM_WR12 = 140, + CV_ARM_WR13 = 141, + CV_ARM_WR14 = 142, + CV_ARM_WR15 = 143, + + // XSCALE Concan co-processor control registers + CV_ARM_WCID = 144, + CV_ARM_WCON = 145, + CV_ARM_WCSSF = 146, + CV_ARM_WCASF = 147, + CV_ARM_WC4 = 148, + CV_ARM_WC5 = 149, + CV_ARM_WC6 = 150, + CV_ARM_WC7 = 151, + CV_ARM_WCGR0 = 152, + CV_ARM_WCGR1 = 153, + CV_ARM_WCGR2 = 154, + CV_ARM_WCGR3 = 155, + CV_ARM_WC12 = 156, + CV_ARM_WC13 = 157, + CV_ARM_WC14 = 158, + CV_ARM_WC15 = 159, + + // + // ARM VFPv3/Neon extended floating Point + // + + CV_ARM_FS32 = 200, + CV_ARM_FS33 = 201, + CV_ARM_FS34 = 202, + CV_ARM_FS35 = 203, + CV_ARM_FS36 = 204, + CV_ARM_FS37 = 205, + CV_ARM_FS38 = 206, + CV_ARM_FS39 = 207, + CV_ARM_FS40 = 208, + CV_ARM_FS41 = 209, + CV_ARM_FS42 = 210, + CV_ARM_FS43 = 211, + CV_ARM_FS44 = 212, + CV_ARM_FS45 = 213, + CV_ARM_FS46 = 214, + CV_ARM_FS47 = 215, + CV_ARM_FS48 = 216, + CV_ARM_FS49 = 217, + CV_ARM_FS50 = 218, + CV_ARM_FS51 = 219, + CV_ARM_FS52 = 220, + CV_ARM_FS53 = 221, + CV_ARM_FS54 = 222, + CV_ARM_FS55 = 223, + CV_ARM_FS56 = 224, + CV_ARM_FS57 = 225, + CV_ARM_FS58 = 226, + CV_ARM_FS59 = 227, + CV_ARM_FS60 = 228, + CV_ARM_FS61 = 229, + CV_ARM_FS62 = 230, + CV_ARM_FS63 = 231, + + // ARM double-precision floating point + + CV_ARM_ND0 = 300, + CV_ARM_ND1 = 301, + CV_ARM_ND2 = 302, + CV_ARM_ND3 = 303, + CV_ARM_ND4 = 304, + CV_ARM_ND5 = 305, + CV_ARM_ND6 = 306, + CV_ARM_ND7 = 307, + CV_ARM_ND8 = 308, + CV_ARM_ND9 = 309, + CV_ARM_ND10 = 310, + CV_ARM_ND11 = 311, + CV_ARM_ND12 = 312, + CV_ARM_ND13 = 313, + CV_ARM_ND14 = 314, + CV_ARM_ND15 = 315, + CV_ARM_ND16 = 316, + CV_ARM_ND17 = 317, + CV_ARM_ND18 = 318, + CV_ARM_ND19 = 319, + CV_ARM_ND20 = 320, + CV_ARM_ND21 = 321, + CV_ARM_ND22 = 322, + CV_ARM_ND23 = 323, + CV_ARM_ND24 = 324, + CV_ARM_ND25 = 325, + CV_ARM_ND26 = 326, + CV_ARM_ND27 = 327, + CV_ARM_ND28 = 328, + CV_ARM_ND29 = 329, + CV_ARM_ND30 = 330, + CV_ARM_ND31 = 331, + + // ARM extended precision floating point + + CV_ARM_NQ0 = 400, + CV_ARM_NQ1 = 401, + CV_ARM_NQ2 = 402, + CV_ARM_NQ3 = 403, + CV_ARM_NQ4 = 404, + CV_ARM_NQ5 = 405, + CV_ARM_NQ6 = 406, + CV_ARM_NQ7 = 407, + CV_ARM_NQ8 = 408, + CV_ARM_NQ9 = 409, + CV_ARM_NQ10 = 410, + CV_ARM_NQ11 = 411, + CV_ARM_NQ12 = 412, + CV_ARM_NQ13 = 413, + CV_ARM_NQ14 = 414, + CV_ARM_NQ15 = 415, + + // + // Register set for ARM64 + // + + CV_ARM64_NOREG = CV_REG_NONE, + + // General purpose 32-bit integer registers + + CV_ARM64_W0 = 10, + CV_ARM64_W1 = 11, + CV_ARM64_W2 = 12, + CV_ARM64_W3 = 13, + CV_ARM64_W4 = 14, + CV_ARM64_W5 = 15, + CV_ARM64_W6 = 16, + CV_ARM64_W7 = 17, + CV_ARM64_W8 = 18, + CV_ARM64_W9 = 19, + CV_ARM64_W10 = 20, + CV_ARM64_W11 = 21, + CV_ARM64_W12 = 22, + CV_ARM64_W13 = 23, + CV_ARM64_W14 = 24, + CV_ARM64_W15 = 25, + CV_ARM64_W16 = 26, + CV_ARM64_W17 = 27, + CV_ARM64_W18 = 28, + CV_ARM64_W19 = 29, + CV_ARM64_W20 = 30, + CV_ARM64_W21 = 31, + CV_ARM64_W22 = 32, + CV_ARM64_W23 = 33, + CV_ARM64_W24 = 34, + CV_ARM64_W25 = 35, + CV_ARM64_W26 = 36, + CV_ARM64_W27 = 37, + CV_ARM64_W28 = 38, + CV_ARM64_W29 = 39, + CV_ARM64_W30 = 40, + CV_ARM64_WZR = 41, + + // General purpose 64-bit integer registers + + CV_ARM64_X0 = 50, + CV_ARM64_X1 = 51, + CV_ARM64_X2 = 52, + CV_ARM64_X3 = 53, + CV_ARM64_X4 = 54, + CV_ARM64_X5 = 55, + CV_ARM64_X6 = 56, + CV_ARM64_X7 = 57, + CV_ARM64_X8 = 58, + CV_ARM64_X9 = 59, + CV_ARM64_X10 = 60, + CV_ARM64_X11 = 61, + CV_ARM64_X12 = 62, + CV_ARM64_X13 = 63, + CV_ARM64_X14 = 64, + CV_ARM64_X15 = 65, + CV_ARM64_IP0 = 66, + CV_ARM64_IP1 = 67, + CV_ARM64_X18 = 68, + CV_ARM64_X19 = 69, + CV_ARM64_X20 = 70, + CV_ARM64_X21 = 71, + CV_ARM64_X22 = 72, + CV_ARM64_X23 = 73, + CV_ARM64_X24 = 74, + CV_ARM64_X25 = 75, + CV_ARM64_X26 = 76, + CV_ARM64_X27 = 77, + CV_ARM64_X28 = 78, + CV_ARM64_FP = 79, + CV_ARM64_LR = 80, + CV_ARM64_SP = 81, + CV_ARM64_ZR = 82, + CV_ARM64_PC = 83, + + // status registers + + CV_ARM64_NZCV = 90, + CV_ARM64_CPSR = 91, + + // 32-bit floating point registers + + CV_ARM64_S0 = 100, + CV_ARM64_S1 = 101, + CV_ARM64_S2 = 102, + CV_ARM64_S3 = 103, + CV_ARM64_S4 = 104, + CV_ARM64_S5 = 105, + CV_ARM64_S6 = 106, + CV_ARM64_S7 = 107, + CV_ARM64_S8 = 108, + CV_ARM64_S9 = 109, + CV_ARM64_S10 = 110, + CV_ARM64_S11 = 111, + CV_ARM64_S12 = 112, + CV_ARM64_S13 = 113, + CV_ARM64_S14 = 114, + CV_ARM64_S15 = 115, + CV_ARM64_S16 = 116, + CV_ARM64_S17 = 117, + CV_ARM64_S18 = 118, + CV_ARM64_S19 = 119, + CV_ARM64_S20 = 120, + CV_ARM64_S21 = 121, + CV_ARM64_S22 = 122, + CV_ARM64_S23 = 123, + CV_ARM64_S24 = 124, + CV_ARM64_S25 = 125, + CV_ARM64_S26 = 126, + CV_ARM64_S27 = 127, + CV_ARM64_S28 = 128, + CV_ARM64_S29 = 129, + CV_ARM64_S30 = 130, + CV_ARM64_S31 = 131, + + // 64-bit floating point registers + + CV_ARM64_D0 = 140, + CV_ARM64_D1 = 141, + CV_ARM64_D2 = 142, + CV_ARM64_D3 = 143, + CV_ARM64_D4 = 144, + CV_ARM64_D5 = 145, + CV_ARM64_D6 = 146, + CV_ARM64_D7 = 147, + CV_ARM64_D8 = 148, + CV_ARM64_D9 = 149, + CV_ARM64_D10 = 150, + CV_ARM64_D11 = 151, + CV_ARM64_D12 = 152, + CV_ARM64_D13 = 153, + CV_ARM64_D14 = 154, + CV_ARM64_D15 = 155, + CV_ARM64_D16 = 156, + CV_ARM64_D17 = 157, + CV_ARM64_D18 = 158, + CV_ARM64_D19 = 159, + CV_ARM64_D20 = 160, + CV_ARM64_D21 = 161, + CV_ARM64_D22 = 162, + CV_ARM64_D23 = 163, + CV_ARM64_D24 = 164, + CV_ARM64_D25 = 165, + CV_ARM64_D26 = 166, + CV_ARM64_D27 = 167, + CV_ARM64_D28 = 168, + CV_ARM64_D29 = 169, + CV_ARM64_D30 = 170, + CV_ARM64_D31 = 171, + + // 128-bit SIMD registers + + CV_ARM64_Q0 = 180, + CV_ARM64_Q1 = 181, + CV_ARM64_Q2 = 182, + CV_ARM64_Q3 = 183, + CV_ARM64_Q4 = 184, + CV_ARM64_Q5 = 185, + CV_ARM64_Q6 = 186, + CV_ARM64_Q7 = 187, + CV_ARM64_Q8 = 188, + CV_ARM64_Q9 = 189, + CV_ARM64_Q10 = 190, + CV_ARM64_Q11 = 191, + CV_ARM64_Q12 = 192, + CV_ARM64_Q13 = 193, + CV_ARM64_Q14 = 194, + CV_ARM64_Q15 = 195, + CV_ARM64_Q16 = 196, + CV_ARM64_Q17 = 197, + CV_ARM64_Q18 = 198, + CV_ARM64_Q19 = 199, + CV_ARM64_Q20 = 200, + CV_ARM64_Q21 = 201, + CV_ARM64_Q22 = 202, + CV_ARM64_Q23 = 203, + CV_ARM64_Q24 = 204, + CV_ARM64_Q25 = 205, + CV_ARM64_Q26 = 206, + CV_ARM64_Q27 = 207, + CV_ARM64_Q28 = 208, + CV_ARM64_Q29 = 209, + CV_ARM64_Q30 = 210, + CV_ARM64_Q31 = 211, + + // Floating point status register + + CV_ARM64_FPSR = 220, + CV_ARM64_FPCR = 221, + + // 8-bit floating point registers + + CV_ARM64_B0 = 230, + CV_ARM64_B1 = 231, + CV_ARM64_B2 = 232, + CV_ARM64_B3 = 233, + CV_ARM64_B4 = 234, + CV_ARM64_B5 = 235, + CV_ARM64_B6 = 236, + CV_ARM64_B7 = 237, + CV_ARM64_B8 = 238, + CV_ARM64_B9 = 239, + CV_ARM64_B10 = 240, + CV_ARM64_B11 = 241, + CV_ARM64_B12 = 242, + CV_ARM64_B13 = 243, + CV_ARM64_B14 = 244, + CV_ARM64_B15 = 245, + CV_ARM64_B16 = 246, + CV_ARM64_B17 = 247, + CV_ARM64_B18 = 248, + CV_ARM64_B19 = 249, + CV_ARM64_B20 = 250, + CV_ARM64_B21 = 251, + CV_ARM64_B22 = 252, + CV_ARM64_B23 = 253, + CV_ARM64_B24 = 254, + CV_ARM64_B25 = 255, + CV_ARM64_B26 = 256, + CV_ARM64_B27 = 257, + CV_ARM64_B28 = 258, + CV_ARM64_B29 = 259, + CV_ARM64_B30 = 260, + CV_ARM64_B31 = 261, + + // 16-bit floating point registers + + CV_ARM64_H0 = 270, + CV_ARM64_H1 = 271, + CV_ARM64_H2 = 272, + CV_ARM64_H3 = 273, + CV_ARM64_H4 = 274, + CV_ARM64_H5 = 275, + CV_ARM64_H6 = 276, + CV_ARM64_H7 = 277, + CV_ARM64_H8 = 278, + CV_ARM64_H9 = 279, + CV_ARM64_H10 = 280, + CV_ARM64_H11 = 281, + CV_ARM64_H12 = 282, + CV_ARM64_H13 = 283, + CV_ARM64_H14 = 284, + CV_ARM64_H15 = 285, + CV_ARM64_H16 = 286, + CV_ARM64_H17 = 287, + CV_ARM64_H18 = 288, + CV_ARM64_H19 = 289, + CV_ARM64_H20 = 290, + CV_ARM64_H21 = 291, + CV_ARM64_H22 = 292, + CV_ARM64_H23 = 293, + CV_ARM64_H24 = 294, + CV_ARM64_H25 = 295, + CV_ARM64_H26 = 296, + CV_ARM64_H27 = 297, + CV_ARM64_H28 = 298, + CV_ARM64_H29 = 299, + CV_ARM64_H30 = 300, + CV_ARM64_H31 = 301, + + // 128-bit vector registers + + CV_ARM64_V0 = 310, + CV_ARM64_V1 = 311, + CV_ARM64_V2 = 312, + CV_ARM64_V3 = 313, + CV_ARM64_V4 = 314, + CV_ARM64_V5 = 315, + CV_ARM64_V6 = 316, + CV_ARM64_V7 = 317, + CV_ARM64_V8 = 318, + CV_ARM64_V9 = 319, + CV_ARM64_V10 = 320, + CV_ARM64_V11 = 321, + CV_ARM64_V12 = 322, + CV_ARM64_V13 = 323, + CV_ARM64_V14 = 324, + CV_ARM64_V15 = 325, + CV_ARM64_V16 = 326, + CV_ARM64_V17 = 327, + CV_ARM64_V18 = 328, + CV_ARM64_V19 = 329, + CV_ARM64_V20 = 330, + CV_ARM64_V21 = 331, + CV_ARM64_V22 = 332, + CV_ARM64_V23 = 333, + CV_ARM64_V24 = 334, + CV_ARM64_V25 = 335, + CV_ARM64_V26 = 336, + CV_ARM64_V27 = 337, + CV_ARM64_V28 = 338, + CV_ARM64_V29 = 339, + CV_ARM64_V30 = 340, + CV_ARM64_V31 = 341, + + // 128-bit SIMD registers upper 64 bits + + CV_ARM64_Q0H = 350, + CV_ARM64_Q1H = 351, + CV_ARM64_Q2H = 352, + CV_ARM64_Q3H = 353, + CV_ARM64_Q4H = 354, + CV_ARM64_Q5H = 355, + CV_ARM64_Q6H = 356, + CV_ARM64_Q7H = 357, + CV_ARM64_Q8H = 358, + CV_ARM64_Q9H = 359, + CV_ARM64_Q10H = 360, + CV_ARM64_Q11H = 361, + CV_ARM64_Q12H = 362, + CV_ARM64_Q13H = 363, + CV_ARM64_Q14H = 364, + CV_ARM64_Q15H = 365, + CV_ARM64_Q16H = 366, + CV_ARM64_Q17H = 367, + CV_ARM64_Q18H = 368, + CV_ARM64_Q19H = 369, + CV_ARM64_Q20H = 370, + CV_ARM64_Q21H = 371, + CV_ARM64_Q22H = 372, + CV_ARM64_Q23H = 373, + CV_ARM64_Q24H = 374, + CV_ARM64_Q25H = 375, + CV_ARM64_Q26H = 376, + CV_ARM64_Q27H = 377, + CV_ARM64_Q28H = 378, + CV_ARM64_Q29H = 379, + CV_ARM64_Q30H = 380, + CV_ARM64_Q31H = 381, + + // + // Register set for Intel IA64 + // + + CV_IA64_NOREG = CV_REG_NONE, + + // Branch Registers + + CV_IA64_Br0 = 512, + CV_IA64_Br1 = 513, + CV_IA64_Br2 = 514, + CV_IA64_Br3 = 515, + CV_IA64_Br4 = 516, + CV_IA64_Br5 = 517, + CV_IA64_Br6 = 518, + CV_IA64_Br7 = 519, + + // Predicate Registers + + CV_IA64_P0 = 704, + CV_IA64_P1 = 705, + CV_IA64_P2 = 706, + CV_IA64_P3 = 707, + CV_IA64_P4 = 708, + CV_IA64_P5 = 709, + CV_IA64_P6 = 710, + CV_IA64_P7 = 711, + CV_IA64_P8 = 712, + CV_IA64_P9 = 713, + CV_IA64_P10 = 714, + CV_IA64_P11 = 715, + CV_IA64_P12 = 716, + CV_IA64_P13 = 717, + CV_IA64_P14 = 718, + CV_IA64_P15 = 719, + CV_IA64_P16 = 720, + CV_IA64_P17 = 721, + CV_IA64_P18 = 722, + CV_IA64_P19 = 723, + CV_IA64_P20 = 724, + CV_IA64_P21 = 725, + CV_IA64_P22 = 726, + CV_IA64_P23 = 727, + CV_IA64_P24 = 728, + CV_IA64_P25 = 729, + CV_IA64_P26 = 730, + CV_IA64_P27 = 731, + CV_IA64_P28 = 732, + CV_IA64_P29 = 733, + CV_IA64_P30 = 734, + CV_IA64_P31 = 735, + CV_IA64_P32 = 736, + CV_IA64_P33 = 737, + CV_IA64_P34 = 738, + CV_IA64_P35 = 739, + CV_IA64_P36 = 740, + CV_IA64_P37 = 741, + CV_IA64_P38 = 742, + CV_IA64_P39 = 743, + CV_IA64_P40 = 744, + CV_IA64_P41 = 745, + CV_IA64_P42 = 746, + CV_IA64_P43 = 747, + CV_IA64_P44 = 748, + CV_IA64_P45 = 749, + CV_IA64_P46 = 750, + CV_IA64_P47 = 751, + CV_IA64_P48 = 752, + CV_IA64_P49 = 753, + CV_IA64_P50 = 754, + CV_IA64_P51 = 755, + CV_IA64_P52 = 756, + CV_IA64_P53 = 757, + CV_IA64_P54 = 758, + CV_IA64_P55 = 759, + CV_IA64_P56 = 760, + CV_IA64_P57 = 761, + CV_IA64_P58 = 762, + CV_IA64_P59 = 763, + CV_IA64_P60 = 764, + CV_IA64_P61 = 765, + CV_IA64_P62 = 766, + CV_IA64_P63 = 767, + + CV_IA64_Preds = 768, + + // Banked General Registers + + CV_IA64_IntH0 = 832, + CV_IA64_IntH1 = 833, + CV_IA64_IntH2 = 834, + CV_IA64_IntH3 = 835, + CV_IA64_IntH4 = 836, + CV_IA64_IntH5 = 837, + CV_IA64_IntH6 = 838, + CV_IA64_IntH7 = 839, + CV_IA64_IntH8 = 840, + CV_IA64_IntH9 = 841, + CV_IA64_IntH10 = 842, + CV_IA64_IntH11 = 843, + CV_IA64_IntH12 = 844, + CV_IA64_IntH13 = 845, + CV_IA64_IntH14 = 846, + CV_IA64_IntH15 = 847, + + // Special Registers + + CV_IA64_Ip = 1016, + CV_IA64_Umask = 1017, + CV_IA64_Cfm = 1018, + CV_IA64_Psr = 1019, + + // Banked General Registers + + CV_IA64_Nats = 1020, + CV_IA64_Nats2 = 1021, + CV_IA64_Nats3 = 1022, + + // General-Purpose Registers + + // Integer registers + CV_IA64_IntR0 = 1024, + CV_IA64_IntR1 = 1025, + CV_IA64_IntR2 = 1026, + CV_IA64_IntR3 = 1027, + CV_IA64_IntR4 = 1028, + CV_IA64_IntR5 = 1029, + CV_IA64_IntR6 = 1030, + CV_IA64_IntR7 = 1031, + CV_IA64_IntR8 = 1032, + CV_IA64_IntR9 = 1033, + CV_IA64_IntR10 = 1034, + CV_IA64_IntR11 = 1035, + CV_IA64_IntR12 = 1036, + CV_IA64_IntR13 = 1037, + CV_IA64_IntR14 = 1038, + CV_IA64_IntR15 = 1039, + CV_IA64_IntR16 = 1040, + CV_IA64_IntR17 = 1041, + CV_IA64_IntR18 = 1042, + CV_IA64_IntR19 = 1043, + CV_IA64_IntR20 = 1044, + CV_IA64_IntR21 = 1045, + CV_IA64_IntR22 = 1046, + CV_IA64_IntR23 = 1047, + CV_IA64_IntR24 = 1048, + CV_IA64_IntR25 = 1049, + CV_IA64_IntR26 = 1050, + CV_IA64_IntR27 = 1051, + CV_IA64_IntR28 = 1052, + CV_IA64_IntR29 = 1053, + CV_IA64_IntR30 = 1054, + CV_IA64_IntR31 = 1055, + + // Register Stack + CV_IA64_IntR32 = 1056, + CV_IA64_IntR33 = 1057, + CV_IA64_IntR34 = 1058, + CV_IA64_IntR35 = 1059, + CV_IA64_IntR36 = 1060, + CV_IA64_IntR37 = 1061, + CV_IA64_IntR38 = 1062, + CV_IA64_IntR39 = 1063, + CV_IA64_IntR40 = 1064, + CV_IA64_IntR41 = 1065, + CV_IA64_IntR42 = 1066, + CV_IA64_IntR43 = 1067, + CV_IA64_IntR44 = 1068, + CV_IA64_IntR45 = 1069, + CV_IA64_IntR46 = 1070, + CV_IA64_IntR47 = 1071, + CV_IA64_IntR48 = 1072, + CV_IA64_IntR49 = 1073, + CV_IA64_IntR50 = 1074, + CV_IA64_IntR51 = 1075, + CV_IA64_IntR52 = 1076, + CV_IA64_IntR53 = 1077, + CV_IA64_IntR54 = 1078, + CV_IA64_IntR55 = 1079, + CV_IA64_IntR56 = 1080, + CV_IA64_IntR57 = 1081, + CV_IA64_IntR58 = 1082, + CV_IA64_IntR59 = 1083, + CV_IA64_IntR60 = 1084, + CV_IA64_IntR61 = 1085, + CV_IA64_IntR62 = 1086, + CV_IA64_IntR63 = 1087, + CV_IA64_IntR64 = 1088, + CV_IA64_IntR65 = 1089, + CV_IA64_IntR66 = 1090, + CV_IA64_IntR67 = 1091, + CV_IA64_IntR68 = 1092, + CV_IA64_IntR69 = 1093, + CV_IA64_IntR70 = 1094, + CV_IA64_IntR71 = 1095, + CV_IA64_IntR72 = 1096, + CV_IA64_IntR73 = 1097, + CV_IA64_IntR74 = 1098, + CV_IA64_IntR75 = 1099, + CV_IA64_IntR76 = 1100, + CV_IA64_IntR77 = 1101, + CV_IA64_IntR78 = 1102, + CV_IA64_IntR79 = 1103, + CV_IA64_IntR80 = 1104, + CV_IA64_IntR81 = 1105, + CV_IA64_IntR82 = 1106, + CV_IA64_IntR83 = 1107, + CV_IA64_IntR84 = 1108, + CV_IA64_IntR85 = 1109, + CV_IA64_IntR86 = 1110, + CV_IA64_IntR87 = 1111, + CV_IA64_IntR88 = 1112, + CV_IA64_IntR89 = 1113, + CV_IA64_IntR90 = 1114, + CV_IA64_IntR91 = 1115, + CV_IA64_IntR92 = 1116, + CV_IA64_IntR93 = 1117, + CV_IA64_IntR94 = 1118, + CV_IA64_IntR95 = 1119, + CV_IA64_IntR96 = 1120, + CV_IA64_IntR97 = 1121, + CV_IA64_IntR98 = 1122, + CV_IA64_IntR99 = 1123, + CV_IA64_IntR100 = 1124, + CV_IA64_IntR101 = 1125, + CV_IA64_IntR102 = 1126, + CV_IA64_IntR103 = 1127, + CV_IA64_IntR104 = 1128, + CV_IA64_IntR105 = 1129, + CV_IA64_IntR106 = 1130, + CV_IA64_IntR107 = 1131, + CV_IA64_IntR108 = 1132, + CV_IA64_IntR109 = 1133, + CV_IA64_IntR110 = 1134, + CV_IA64_IntR111 = 1135, + CV_IA64_IntR112 = 1136, + CV_IA64_IntR113 = 1137, + CV_IA64_IntR114 = 1138, + CV_IA64_IntR115 = 1139, + CV_IA64_IntR116 = 1140, + CV_IA64_IntR117 = 1141, + CV_IA64_IntR118 = 1142, + CV_IA64_IntR119 = 1143, + CV_IA64_IntR120 = 1144, + CV_IA64_IntR121 = 1145, + CV_IA64_IntR122 = 1146, + CV_IA64_IntR123 = 1147, + CV_IA64_IntR124 = 1148, + CV_IA64_IntR125 = 1149, + CV_IA64_IntR126 = 1150, + CV_IA64_IntR127 = 1151, + + // Floating-Point Registers + + // Low Floating Point Registers + CV_IA64_FltF0 = 2048, + CV_IA64_FltF1 = 2049, + CV_IA64_FltF2 = 2050, + CV_IA64_FltF3 = 2051, + CV_IA64_FltF4 = 2052, + CV_IA64_FltF5 = 2053, + CV_IA64_FltF6 = 2054, + CV_IA64_FltF7 = 2055, + CV_IA64_FltF8 = 2056, + CV_IA64_FltF9 = 2057, + CV_IA64_FltF10 = 2058, + CV_IA64_FltF11 = 2059, + CV_IA64_FltF12 = 2060, + CV_IA64_FltF13 = 2061, + CV_IA64_FltF14 = 2062, + CV_IA64_FltF15 = 2063, + CV_IA64_FltF16 = 2064, + CV_IA64_FltF17 = 2065, + CV_IA64_FltF18 = 2066, + CV_IA64_FltF19 = 2067, + CV_IA64_FltF20 = 2068, + CV_IA64_FltF21 = 2069, + CV_IA64_FltF22 = 2070, + CV_IA64_FltF23 = 2071, + CV_IA64_FltF24 = 2072, + CV_IA64_FltF25 = 2073, + CV_IA64_FltF26 = 2074, + CV_IA64_FltF27 = 2075, + CV_IA64_FltF28 = 2076, + CV_IA64_FltF29 = 2077, + CV_IA64_FltF30 = 2078, + CV_IA64_FltF31 = 2079, + + // High Floating Point Registers + CV_IA64_FltF32 = 2080, + CV_IA64_FltF33 = 2081, + CV_IA64_FltF34 = 2082, + CV_IA64_FltF35 = 2083, + CV_IA64_FltF36 = 2084, + CV_IA64_FltF37 = 2085, + CV_IA64_FltF38 = 2086, + CV_IA64_FltF39 = 2087, + CV_IA64_FltF40 = 2088, + CV_IA64_FltF41 = 2089, + CV_IA64_FltF42 = 2090, + CV_IA64_FltF43 = 2091, + CV_IA64_FltF44 = 2092, + CV_IA64_FltF45 = 2093, + CV_IA64_FltF46 = 2094, + CV_IA64_FltF47 = 2095, + CV_IA64_FltF48 = 2096, + CV_IA64_FltF49 = 2097, + CV_IA64_FltF50 = 2098, + CV_IA64_FltF51 = 2099, + CV_IA64_FltF52 = 2100, + CV_IA64_FltF53 = 2101, + CV_IA64_FltF54 = 2102, + CV_IA64_FltF55 = 2103, + CV_IA64_FltF56 = 2104, + CV_IA64_FltF57 = 2105, + CV_IA64_FltF58 = 2106, + CV_IA64_FltF59 = 2107, + CV_IA64_FltF60 = 2108, + CV_IA64_FltF61 = 2109, + CV_IA64_FltF62 = 2110, + CV_IA64_FltF63 = 2111, + CV_IA64_FltF64 = 2112, + CV_IA64_FltF65 = 2113, + CV_IA64_FltF66 = 2114, + CV_IA64_FltF67 = 2115, + CV_IA64_FltF68 = 2116, + CV_IA64_FltF69 = 2117, + CV_IA64_FltF70 = 2118, + CV_IA64_FltF71 = 2119, + CV_IA64_FltF72 = 2120, + CV_IA64_FltF73 = 2121, + CV_IA64_FltF74 = 2122, + CV_IA64_FltF75 = 2123, + CV_IA64_FltF76 = 2124, + CV_IA64_FltF77 = 2125, + CV_IA64_FltF78 = 2126, + CV_IA64_FltF79 = 2127, + CV_IA64_FltF80 = 2128, + CV_IA64_FltF81 = 2129, + CV_IA64_FltF82 = 2130, + CV_IA64_FltF83 = 2131, + CV_IA64_FltF84 = 2132, + CV_IA64_FltF85 = 2133, + CV_IA64_FltF86 = 2134, + CV_IA64_FltF87 = 2135, + CV_IA64_FltF88 = 2136, + CV_IA64_FltF89 = 2137, + CV_IA64_FltF90 = 2138, + CV_IA64_FltF91 = 2139, + CV_IA64_FltF92 = 2140, + CV_IA64_FltF93 = 2141, + CV_IA64_FltF94 = 2142, + CV_IA64_FltF95 = 2143, + CV_IA64_FltF96 = 2144, + CV_IA64_FltF97 = 2145, + CV_IA64_FltF98 = 2146, + CV_IA64_FltF99 = 2147, + CV_IA64_FltF100 = 2148, + CV_IA64_FltF101 = 2149, + CV_IA64_FltF102 = 2150, + CV_IA64_FltF103 = 2151, + CV_IA64_FltF104 = 2152, + CV_IA64_FltF105 = 2153, + CV_IA64_FltF106 = 2154, + CV_IA64_FltF107 = 2155, + CV_IA64_FltF108 = 2156, + CV_IA64_FltF109 = 2157, + CV_IA64_FltF110 = 2158, + CV_IA64_FltF111 = 2159, + CV_IA64_FltF112 = 2160, + CV_IA64_FltF113 = 2161, + CV_IA64_FltF114 = 2162, + CV_IA64_FltF115 = 2163, + CV_IA64_FltF116 = 2164, + CV_IA64_FltF117 = 2165, + CV_IA64_FltF118 = 2166, + CV_IA64_FltF119 = 2167, + CV_IA64_FltF120 = 2168, + CV_IA64_FltF121 = 2169, + CV_IA64_FltF122 = 2170, + CV_IA64_FltF123 = 2171, + CV_IA64_FltF124 = 2172, + CV_IA64_FltF125 = 2173, + CV_IA64_FltF126 = 2174, + CV_IA64_FltF127 = 2175, + + // Application Registers + + CV_IA64_ApKR0 = 3072, + CV_IA64_ApKR1 = 3073, + CV_IA64_ApKR2 = 3074, + CV_IA64_ApKR3 = 3075, + CV_IA64_ApKR4 = 3076, + CV_IA64_ApKR5 = 3077, + CV_IA64_ApKR6 = 3078, + CV_IA64_ApKR7 = 3079, + CV_IA64_AR8 = 3080, + CV_IA64_AR9 = 3081, + CV_IA64_AR10 = 3082, + CV_IA64_AR11 = 3083, + CV_IA64_AR12 = 3084, + CV_IA64_AR13 = 3085, + CV_IA64_AR14 = 3086, + CV_IA64_AR15 = 3087, + CV_IA64_RsRSC = 3088, + CV_IA64_RsBSP = 3089, + CV_IA64_RsBSPSTORE = 3090, + CV_IA64_RsRNAT = 3091, + CV_IA64_AR20 = 3092, + CV_IA64_StFCR = 3093, + CV_IA64_AR22 = 3094, + CV_IA64_AR23 = 3095, + CV_IA64_EFLAG = 3096, + CV_IA64_CSD = 3097, + CV_IA64_SSD = 3098, + CV_IA64_CFLG = 3099, + CV_IA64_StFSR = 3100, + CV_IA64_StFIR = 3101, + CV_IA64_StFDR = 3102, + CV_IA64_AR31 = 3103, + CV_IA64_ApCCV = 3104, + CV_IA64_AR33 = 3105, + CV_IA64_AR34 = 3106, + CV_IA64_AR35 = 3107, + CV_IA64_ApUNAT = 3108, + CV_IA64_AR37 = 3109, + CV_IA64_AR38 = 3110, + CV_IA64_AR39 = 3111, + CV_IA64_StFPSR = 3112, + CV_IA64_AR41 = 3113, + CV_IA64_AR42 = 3114, + CV_IA64_AR43 = 3115, + CV_IA64_ApITC = 3116, + CV_IA64_AR45 = 3117, + CV_IA64_AR46 = 3118, + CV_IA64_AR47 = 3119, + CV_IA64_AR48 = 3120, + CV_IA64_AR49 = 3121, + CV_IA64_AR50 = 3122, + CV_IA64_AR51 = 3123, + CV_IA64_AR52 = 3124, + CV_IA64_AR53 = 3125, + CV_IA64_AR54 = 3126, + CV_IA64_AR55 = 3127, + CV_IA64_AR56 = 3128, + CV_IA64_AR57 = 3129, + CV_IA64_AR58 = 3130, + CV_IA64_AR59 = 3131, + CV_IA64_AR60 = 3132, + CV_IA64_AR61 = 3133, + CV_IA64_AR62 = 3134, + CV_IA64_AR63 = 3135, + CV_IA64_RsPFS = 3136, + CV_IA64_ApLC = 3137, + CV_IA64_ApEC = 3138, + CV_IA64_AR67 = 3139, + CV_IA64_AR68 = 3140, + CV_IA64_AR69 = 3141, + CV_IA64_AR70 = 3142, + CV_IA64_AR71 = 3143, + CV_IA64_AR72 = 3144, + CV_IA64_AR73 = 3145, + CV_IA64_AR74 = 3146, + CV_IA64_AR75 = 3147, + CV_IA64_AR76 = 3148, + CV_IA64_AR77 = 3149, + CV_IA64_AR78 = 3150, + CV_IA64_AR79 = 3151, + CV_IA64_AR80 = 3152, + CV_IA64_AR81 = 3153, + CV_IA64_AR82 = 3154, + CV_IA64_AR83 = 3155, + CV_IA64_AR84 = 3156, + CV_IA64_AR85 = 3157, + CV_IA64_AR86 = 3158, + CV_IA64_AR87 = 3159, + CV_IA64_AR88 = 3160, + CV_IA64_AR89 = 3161, + CV_IA64_AR90 = 3162, + CV_IA64_AR91 = 3163, + CV_IA64_AR92 = 3164, + CV_IA64_AR93 = 3165, + CV_IA64_AR94 = 3166, + CV_IA64_AR95 = 3167, + CV_IA64_AR96 = 3168, + CV_IA64_AR97 = 3169, + CV_IA64_AR98 = 3170, + CV_IA64_AR99 = 3171, + CV_IA64_AR100 = 3172, + CV_IA64_AR101 = 3173, + CV_IA64_AR102 = 3174, + CV_IA64_AR103 = 3175, + CV_IA64_AR104 = 3176, + CV_IA64_AR105 = 3177, + CV_IA64_AR106 = 3178, + CV_IA64_AR107 = 3179, + CV_IA64_AR108 = 3180, + CV_IA64_AR109 = 3181, + CV_IA64_AR110 = 3182, + CV_IA64_AR111 = 3183, + CV_IA64_AR112 = 3184, + CV_IA64_AR113 = 3185, + CV_IA64_AR114 = 3186, + CV_IA64_AR115 = 3187, + CV_IA64_AR116 = 3188, + CV_IA64_AR117 = 3189, + CV_IA64_AR118 = 3190, + CV_IA64_AR119 = 3191, + CV_IA64_AR120 = 3192, + CV_IA64_AR121 = 3193, + CV_IA64_AR122 = 3194, + CV_IA64_AR123 = 3195, + CV_IA64_AR124 = 3196, + CV_IA64_AR125 = 3197, + CV_IA64_AR126 = 3198, + CV_IA64_AR127 = 3199, + + // CPUID Registers + + CV_IA64_CPUID0 = 3328, + CV_IA64_CPUID1 = 3329, + CV_IA64_CPUID2 = 3330, + CV_IA64_CPUID3 = 3331, + CV_IA64_CPUID4 = 3332, + + // Control Registers + + CV_IA64_ApDCR = 4096, + CV_IA64_ApITM = 4097, + CV_IA64_ApIVA = 4098, + CV_IA64_CR3 = 4099, + CV_IA64_CR4 = 4100, + CV_IA64_CR5 = 4101, + CV_IA64_CR6 = 4102, + CV_IA64_CR7 = 4103, + CV_IA64_ApPTA = 4104, + CV_IA64_ApGPTA = 4105, + CV_IA64_CR10 = 4106, + CV_IA64_CR11 = 4107, + CV_IA64_CR12 = 4108, + CV_IA64_CR13 = 4109, + CV_IA64_CR14 = 4110, + CV_IA64_CR15 = 4111, + CV_IA64_StIPSR = 4112, + CV_IA64_StISR = 4113, + CV_IA64_CR18 = 4114, + CV_IA64_StIIP = 4115, + CV_IA64_StIFA = 4116, + CV_IA64_StITIR = 4117, + CV_IA64_StIIPA = 4118, + CV_IA64_StIFS = 4119, + CV_IA64_StIIM = 4120, + CV_IA64_StIHA = 4121, + CV_IA64_CR26 = 4122, + CV_IA64_CR27 = 4123, + CV_IA64_CR28 = 4124, + CV_IA64_CR29 = 4125, + CV_IA64_CR30 = 4126, + CV_IA64_CR31 = 4127, + CV_IA64_CR32 = 4128, + CV_IA64_CR33 = 4129, + CV_IA64_CR34 = 4130, + CV_IA64_CR35 = 4131, + CV_IA64_CR36 = 4132, + CV_IA64_CR37 = 4133, + CV_IA64_CR38 = 4134, + CV_IA64_CR39 = 4135, + CV_IA64_CR40 = 4136, + CV_IA64_CR41 = 4137, + CV_IA64_CR42 = 4138, + CV_IA64_CR43 = 4139, + CV_IA64_CR44 = 4140, + CV_IA64_CR45 = 4141, + CV_IA64_CR46 = 4142, + CV_IA64_CR47 = 4143, + CV_IA64_CR48 = 4144, + CV_IA64_CR49 = 4145, + CV_IA64_CR50 = 4146, + CV_IA64_CR51 = 4147, + CV_IA64_CR52 = 4148, + CV_IA64_CR53 = 4149, + CV_IA64_CR54 = 4150, + CV_IA64_CR55 = 4151, + CV_IA64_CR56 = 4152, + CV_IA64_CR57 = 4153, + CV_IA64_CR58 = 4154, + CV_IA64_CR59 = 4155, + CV_IA64_CR60 = 4156, + CV_IA64_CR61 = 4157, + CV_IA64_CR62 = 4158, + CV_IA64_CR63 = 4159, + CV_IA64_SaLID = 4160, + CV_IA64_SaIVR = 4161, + CV_IA64_SaTPR = 4162, + CV_IA64_SaEOI = 4163, + CV_IA64_SaIRR0 = 4164, + CV_IA64_SaIRR1 = 4165, + CV_IA64_SaIRR2 = 4166, + CV_IA64_SaIRR3 = 4167, + CV_IA64_SaITV = 4168, + CV_IA64_SaPMV = 4169, + CV_IA64_SaCMCV = 4170, + CV_IA64_CR75 = 4171, + CV_IA64_CR76 = 4172, + CV_IA64_CR77 = 4173, + CV_IA64_CR78 = 4174, + CV_IA64_CR79 = 4175, + CV_IA64_SaLRR0 = 4176, + CV_IA64_SaLRR1 = 4177, + CV_IA64_CR82 = 4178, + CV_IA64_CR83 = 4179, + CV_IA64_CR84 = 4180, + CV_IA64_CR85 = 4181, + CV_IA64_CR86 = 4182, + CV_IA64_CR87 = 4183, + CV_IA64_CR88 = 4184, + CV_IA64_CR89 = 4185, + CV_IA64_CR90 = 4186, + CV_IA64_CR91 = 4187, + CV_IA64_CR92 = 4188, + CV_IA64_CR93 = 4189, + CV_IA64_CR94 = 4190, + CV_IA64_CR95 = 4191, + CV_IA64_CR96 = 4192, + CV_IA64_CR97 = 4193, + CV_IA64_CR98 = 4194, + CV_IA64_CR99 = 4195, + CV_IA64_CR100 = 4196, + CV_IA64_CR101 = 4197, + CV_IA64_CR102 = 4198, + CV_IA64_CR103 = 4199, + CV_IA64_CR104 = 4200, + CV_IA64_CR105 = 4201, + CV_IA64_CR106 = 4202, + CV_IA64_CR107 = 4203, + CV_IA64_CR108 = 4204, + CV_IA64_CR109 = 4205, + CV_IA64_CR110 = 4206, + CV_IA64_CR111 = 4207, + CV_IA64_CR112 = 4208, + CV_IA64_CR113 = 4209, + CV_IA64_CR114 = 4210, + CV_IA64_CR115 = 4211, + CV_IA64_CR116 = 4212, + CV_IA64_CR117 = 4213, + CV_IA64_CR118 = 4214, + CV_IA64_CR119 = 4215, + CV_IA64_CR120 = 4216, + CV_IA64_CR121 = 4217, + CV_IA64_CR122 = 4218, + CV_IA64_CR123 = 4219, + CV_IA64_CR124 = 4220, + CV_IA64_CR125 = 4221, + CV_IA64_CR126 = 4222, + CV_IA64_CR127 = 4223, + + // Protection Key Registers + + CV_IA64_Pkr0 = 5120, + CV_IA64_Pkr1 = 5121, + CV_IA64_Pkr2 = 5122, + CV_IA64_Pkr3 = 5123, + CV_IA64_Pkr4 = 5124, + CV_IA64_Pkr5 = 5125, + CV_IA64_Pkr6 = 5126, + CV_IA64_Pkr7 = 5127, + CV_IA64_Pkr8 = 5128, + CV_IA64_Pkr9 = 5129, + CV_IA64_Pkr10 = 5130, + CV_IA64_Pkr11 = 5131, + CV_IA64_Pkr12 = 5132, + CV_IA64_Pkr13 = 5133, + CV_IA64_Pkr14 = 5134, + CV_IA64_Pkr15 = 5135, + + // Region Registers + + CV_IA64_Rr0 = 6144, + CV_IA64_Rr1 = 6145, + CV_IA64_Rr2 = 6146, + CV_IA64_Rr3 = 6147, + CV_IA64_Rr4 = 6148, + CV_IA64_Rr5 = 6149, + CV_IA64_Rr6 = 6150, + CV_IA64_Rr7 = 6151, + + // Performance Monitor Data Registers + + CV_IA64_PFD0 = 7168, + CV_IA64_PFD1 = 7169, + CV_IA64_PFD2 = 7170, + CV_IA64_PFD3 = 7171, + CV_IA64_PFD4 = 7172, + CV_IA64_PFD5 = 7173, + CV_IA64_PFD6 = 7174, + CV_IA64_PFD7 = 7175, + CV_IA64_PFD8 = 7176, + CV_IA64_PFD9 = 7177, + CV_IA64_PFD10 = 7178, + CV_IA64_PFD11 = 7179, + CV_IA64_PFD12 = 7180, + CV_IA64_PFD13 = 7181, + CV_IA64_PFD14 = 7182, + CV_IA64_PFD15 = 7183, + CV_IA64_PFD16 = 7184, + CV_IA64_PFD17 = 7185, + + // Performance Monitor Config Registers + + CV_IA64_PFC0 = 7424, + CV_IA64_PFC1 = 7425, + CV_IA64_PFC2 = 7426, + CV_IA64_PFC3 = 7427, + CV_IA64_PFC4 = 7428, + CV_IA64_PFC5 = 7429, + CV_IA64_PFC6 = 7430, + CV_IA64_PFC7 = 7431, + CV_IA64_PFC8 = 7432, + CV_IA64_PFC9 = 7433, + CV_IA64_PFC10 = 7434, + CV_IA64_PFC11 = 7435, + CV_IA64_PFC12 = 7436, + CV_IA64_PFC13 = 7437, + CV_IA64_PFC14 = 7438, + CV_IA64_PFC15 = 7439, + + // Instruction Translation Registers + + CV_IA64_TrI0 = 8192, + CV_IA64_TrI1 = 8193, + CV_IA64_TrI2 = 8194, + CV_IA64_TrI3 = 8195, + CV_IA64_TrI4 = 8196, + CV_IA64_TrI5 = 8197, + CV_IA64_TrI6 = 8198, + CV_IA64_TrI7 = 8199, + + // Data Translation Registers + + CV_IA64_TrD0 = 8320, + CV_IA64_TrD1 = 8321, + CV_IA64_TrD2 = 8322, + CV_IA64_TrD3 = 8323, + CV_IA64_TrD4 = 8324, + CV_IA64_TrD5 = 8325, + CV_IA64_TrD6 = 8326, + CV_IA64_TrD7 = 8327, + + // Instruction Breakpoint Registers + + CV_IA64_DbI0 = 8448, + CV_IA64_DbI1 = 8449, + CV_IA64_DbI2 = 8450, + CV_IA64_DbI3 = 8451, + CV_IA64_DbI4 = 8452, + CV_IA64_DbI5 = 8453, + CV_IA64_DbI6 = 8454, + CV_IA64_DbI7 = 8455, + + // Data Breakpoint Registers + + CV_IA64_DbD0 = 8576, + CV_IA64_DbD1 = 8577, + CV_IA64_DbD2 = 8578, + CV_IA64_DbD3 = 8579, + CV_IA64_DbD4 = 8580, + CV_IA64_DbD5 = 8581, + CV_IA64_DbD6 = 8582, + CV_IA64_DbD7 = 8583, + + // + // Register set for the TriCore processor. + // + + CV_TRI_NOREG = CV_REG_NONE, + + // General Purpose Data Registers + + CV_TRI_D0 = 10, + CV_TRI_D1 = 11, + CV_TRI_D2 = 12, + CV_TRI_D3 = 13, + CV_TRI_D4 = 14, + CV_TRI_D5 = 15, + CV_TRI_D6 = 16, + CV_TRI_D7 = 17, + CV_TRI_D8 = 18, + CV_TRI_D9 = 19, + CV_TRI_D10 = 20, + CV_TRI_D11 = 21, + CV_TRI_D12 = 22, + CV_TRI_D13 = 23, + CV_TRI_D14 = 24, + CV_TRI_D15 = 25, + + // General Purpose Address Registers + + CV_TRI_A0 = 26, + CV_TRI_A1 = 27, + CV_TRI_A2 = 28, + CV_TRI_A3 = 29, + CV_TRI_A4 = 30, + CV_TRI_A5 = 31, + CV_TRI_A6 = 32, + CV_TRI_A7 = 33, + CV_TRI_A8 = 34, + CV_TRI_A9 = 35, + CV_TRI_A10 = 36, + CV_TRI_A11 = 37, + CV_TRI_A12 = 38, + CV_TRI_A13 = 39, + CV_TRI_A14 = 40, + CV_TRI_A15 = 41, + + // Extended (64-bit) data registers + + CV_TRI_E0 = 42, + CV_TRI_E2 = 43, + CV_TRI_E4 = 44, + CV_TRI_E6 = 45, + CV_TRI_E8 = 46, + CV_TRI_E10 = 47, + CV_TRI_E12 = 48, + CV_TRI_E14 = 49, + + // Extended (64-bit) address registers + + CV_TRI_EA0 = 50, + CV_TRI_EA2 = 51, + CV_TRI_EA4 = 52, + CV_TRI_EA6 = 53, + CV_TRI_EA8 = 54, + CV_TRI_EA10 = 55, + CV_TRI_EA12 = 56, + CV_TRI_EA14 = 57, + + CV_TRI_PSW = 58, + CV_TRI_PCXI = 59, + CV_TRI_PC = 60, + CV_TRI_FCX = 61, + CV_TRI_LCX = 62, + CV_TRI_ISP = 63, + CV_TRI_ICR = 64, + CV_TRI_BIV = 65, + CV_TRI_BTV = 66, + CV_TRI_SYSCON = 67, + CV_TRI_DPRx_0 = 68, + CV_TRI_DPRx_1 = 69, + CV_TRI_DPRx_2 = 70, + CV_TRI_DPRx_3 = 71, + CV_TRI_CPRx_0 = 68, + CV_TRI_CPRx_1 = 69, + CV_TRI_CPRx_2 = 70, + CV_TRI_CPRx_3 = 71, + CV_TRI_DPMx_0 = 68, + CV_TRI_DPMx_1 = 69, + CV_TRI_DPMx_2 = 70, + CV_TRI_DPMx_3 = 71, + CV_TRI_CPMx_0 = 68, + CV_TRI_CPMx_1 = 69, + CV_TRI_CPMx_2 = 70, + CV_TRI_CPMx_3 = 71, + CV_TRI_DBGSSR = 72, + CV_TRI_EXEVT = 73, + CV_TRI_SWEVT = 74, + CV_TRI_CREVT = 75, + CV_TRI_TRnEVT = 76, + CV_TRI_MMUCON = 77, + CV_TRI_ASI = 78, + CV_TRI_TVA = 79, + CV_TRI_TPA = 80, + CV_TRI_TPX = 81, + CV_TRI_TFA = 82, + + // + // Register set for the AM33 and related processors. + // + + CV_AM33_NOREG = CV_REG_NONE, + + // "Extended" (general purpose integer) registers + CV_AM33_E0 = 10, + CV_AM33_E1 = 11, + CV_AM33_E2 = 12, + CV_AM33_E3 = 13, + CV_AM33_E4 = 14, + CV_AM33_E5 = 15, + CV_AM33_E6 = 16, + CV_AM33_E7 = 17, + + // Address registers + CV_AM33_A0 = 20, + CV_AM33_A1 = 21, + CV_AM33_A2 = 22, + CV_AM33_A3 = 23, + + // Integer data registers + CV_AM33_D0 = 30, + CV_AM33_D1 = 31, + CV_AM33_D2 = 32, + CV_AM33_D3 = 33, + + // (Single-precision) floating-point registers + CV_AM33_FS0 = 40, + CV_AM33_FS1 = 41, + CV_AM33_FS2 = 42, + CV_AM33_FS3 = 43, + CV_AM33_FS4 = 44, + CV_AM33_FS5 = 45, + CV_AM33_FS6 = 46, + CV_AM33_FS7 = 47, + CV_AM33_FS8 = 48, + CV_AM33_FS9 = 49, + CV_AM33_FS10 = 50, + CV_AM33_FS11 = 51, + CV_AM33_FS12 = 52, + CV_AM33_FS13 = 53, + CV_AM33_FS14 = 54, + CV_AM33_FS15 = 55, + CV_AM33_FS16 = 56, + CV_AM33_FS17 = 57, + CV_AM33_FS18 = 58, + CV_AM33_FS19 = 59, + CV_AM33_FS20 = 60, + CV_AM33_FS21 = 61, + CV_AM33_FS22 = 62, + CV_AM33_FS23 = 63, + CV_AM33_FS24 = 64, + CV_AM33_FS25 = 65, + CV_AM33_FS26 = 66, + CV_AM33_FS27 = 67, + CV_AM33_FS28 = 68, + CV_AM33_FS29 = 69, + CV_AM33_FS30 = 70, + CV_AM33_FS31 = 71, + + // Special purpose registers + + // Stack pointer + CV_AM33_SP = 80, + + // Program counter + CV_AM33_PC = 81, + + // Multiply-divide/accumulate registers + CV_AM33_MDR = 82, + CV_AM33_MDRQ = 83, + CV_AM33_MCRH = 84, + CV_AM33_MCRL = 85, + CV_AM33_MCVF = 86, + + // CPU status words + CV_AM33_EPSW = 87, + CV_AM33_FPCR = 88, + + // Loop buffer registers + CV_AM33_LIR = 89, + CV_AM33_LAR = 90, + + // + // Register set for the Mitsubishi M32R + // + + CV_M32R_NOREG = CV_REG_NONE, + + CV_M32R_R0 = 10, + CV_M32R_R1 = 11, + CV_M32R_R2 = 12, + CV_M32R_R3 = 13, + CV_M32R_R4 = 14, + CV_M32R_R5 = 15, + CV_M32R_R6 = 16, + CV_M32R_R7 = 17, + CV_M32R_R8 = 18, + CV_M32R_R9 = 19, + CV_M32R_R10 = 20, + CV_M32R_R11 = 21, + CV_M32R_R12 = 22, // Gloabal Pointer, if used + CV_M32R_R13 = 23, // Frame Pointer, if allocated + CV_M32R_R14 = 24, // Link Register + CV_M32R_R15 = 25, // Stack Pointer + CV_M32R_PSW = 26, // Preocessor Status Register + CV_M32R_CBR = 27, // Condition Bit Register + CV_M32R_SPI = 28, // Interrupt Stack Pointer + CV_M32R_SPU = 29, // User Stack Pointer + CV_M32R_SPO = 30, // OS Stack Pointer + CV_M32R_BPC = 31, // Backup Program Counter + CV_M32R_ACHI = 32, // Accumulator High + CV_M32R_ACLO = 33, // Accumulator Low + CV_M32R_PC = 34, // Program Counter + + // + // Register set for the SuperH SHMedia processor including compact + // mode + // + + // Integer - 64 bit general registers + CV_SHMEDIA_NOREG = CV_REG_NONE, + CV_SHMEDIA_R0 = 10, + CV_SHMEDIA_R1 = 11, + CV_SHMEDIA_R2 = 12, + CV_SHMEDIA_R3 = 13, + CV_SHMEDIA_R4 = 14, + CV_SHMEDIA_R5 = 15, + CV_SHMEDIA_R6 = 16, + CV_SHMEDIA_R7 = 17, + CV_SHMEDIA_R8 = 18, + CV_SHMEDIA_R9 = 19, + CV_SHMEDIA_R10 = 20, + CV_SHMEDIA_R11 = 21, + CV_SHMEDIA_R12 = 22, + CV_SHMEDIA_R13 = 23, + CV_SHMEDIA_R14 = 24, + CV_SHMEDIA_R15 = 25, + CV_SHMEDIA_R16 = 26, + CV_SHMEDIA_R17 = 27, + CV_SHMEDIA_R18 = 28, + CV_SHMEDIA_R19 = 29, + CV_SHMEDIA_R20 = 30, + CV_SHMEDIA_R21 = 31, + CV_SHMEDIA_R22 = 32, + CV_SHMEDIA_R23 = 33, + CV_SHMEDIA_R24 = 34, + CV_SHMEDIA_R25 = 35, + CV_SHMEDIA_R26 = 36, + CV_SHMEDIA_R27 = 37, + CV_SHMEDIA_R28 = 38, + CV_SHMEDIA_R29 = 39, + CV_SHMEDIA_R30 = 40, + CV_SHMEDIA_R31 = 41, + CV_SHMEDIA_R32 = 42, + CV_SHMEDIA_R33 = 43, + CV_SHMEDIA_R34 = 44, + CV_SHMEDIA_R35 = 45, + CV_SHMEDIA_R36 = 46, + CV_SHMEDIA_R37 = 47, + CV_SHMEDIA_R38 = 48, + CV_SHMEDIA_R39 = 49, + CV_SHMEDIA_R40 = 50, + CV_SHMEDIA_R41 = 51, + CV_SHMEDIA_R42 = 52, + CV_SHMEDIA_R43 = 53, + CV_SHMEDIA_R44 = 54, + CV_SHMEDIA_R45 = 55, + CV_SHMEDIA_R46 = 56, + CV_SHMEDIA_R47 = 57, + CV_SHMEDIA_R48 = 58, + CV_SHMEDIA_R49 = 59, + CV_SHMEDIA_R50 = 60, + CV_SHMEDIA_R51 = 61, + CV_SHMEDIA_R52 = 62, + CV_SHMEDIA_R53 = 63, + CV_SHMEDIA_R54 = 64, + CV_SHMEDIA_R55 = 65, + CV_SHMEDIA_R56 = 66, + CV_SHMEDIA_R57 = 67, + CV_SHMEDIA_R58 = 68, + CV_SHMEDIA_R59 = 69, + CV_SHMEDIA_R60 = 70, + CV_SHMEDIA_R61 = 71, + CV_SHMEDIA_R62 = 72, + CV_SHMEDIA_R63 = 73, + + // Target Registers - 32 bit + CV_SHMEDIA_TR0 = 74, + CV_SHMEDIA_TR1 = 75, + CV_SHMEDIA_TR2 = 76, + CV_SHMEDIA_TR3 = 77, + CV_SHMEDIA_TR4 = 78, + CV_SHMEDIA_TR5 = 79, + CV_SHMEDIA_TR6 = 80, + CV_SHMEDIA_TR7 = 81, + CV_SHMEDIA_TR8 = 82, // future-proof + CV_SHMEDIA_TR9 = 83, // future-proof + CV_SHMEDIA_TR10 = 84, // future-proof + CV_SHMEDIA_TR11 = 85, // future-proof + CV_SHMEDIA_TR12 = 86, // future-proof + CV_SHMEDIA_TR13 = 87, // future-proof + CV_SHMEDIA_TR14 = 88, // future-proof + CV_SHMEDIA_TR15 = 89, // future-proof + + // Single - 32 bit fp registers + CV_SHMEDIA_FR0 = 128, + CV_SHMEDIA_FR1 = 129, + CV_SHMEDIA_FR2 = 130, + CV_SHMEDIA_FR3 = 131, + CV_SHMEDIA_FR4 = 132, + CV_SHMEDIA_FR5 = 133, + CV_SHMEDIA_FR6 = 134, + CV_SHMEDIA_FR7 = 135, + CV_SHMEDIA_FR8 = 136, + CV_SHMEDIA_FR9 = 137, + CV_SHMEDIA_FR10 = 138, + CV_SHMEDIA_FR11 = 139, + CV_SHMEDIA_FR12 = 140, + CV_SHMEDIA_FR13 = 141, + CV_SHMEDIA_FR14 = 142, + CV_SHMEDIA_FR15 = 143, + CV_SHMEDIA_FR16 = 144, + CV_SHMEDIA_FR17 = 145, + CV_SHMEDIA_FR18 = 146, + CV_SHMEDIA_FR19 = 147, + CV_SHMEDIA_FR20 = 148, + CV_SHMEDIA_FR21 = 149, + CV_SHMEDIA_FR22 = 150, + CV_SHMEDIA_FR23 = 151, + CV_SHMEDIA_FR24 = 152, + CV_SHMEDIA_FR25 = 153, + CV_SHMEDIA_FR26 = 154, + CV_SHMEDIA_FR27 = 155, + CV_SHMEDIA_FR28 = 156, + CV_SHMEDIA_FR29 = 157, + CV_SHMEDIA_FR30 = 158, + CV_SHMEDIA_FR31 = 159, + CV_SHMEDIA_FR32 = 160, + CV_SHMEDIA_FR33 = 161, + CV_SHMEDIA_FR34 = 162, + CV_SHMEDIA_FR35 = 163, + CV_SHMEDIA_FR36 = 164, + CV_SHMEDIA_FR37 = 165, + CV_SHMEDIA_FR38 = 166, + CV_SHMEDIA_FR39 = 167, + CV_SHMEDIA_FR40 = 168, + CV_SHMEDIA_FR41 = 169, + CV_SHMEDIA_FR42 = 170, + CV_SHMEDIA_FR43 = 171, + CV_SHMEDIA_FR44 = 172, + CV_SHMEDIA_FR45 = 173, + CV_SHMEDIA_FR46 = 174, + CV_SHMEDIA_FR47 = 175, + CV_SHMEDIA_FR48 = 176, + CV_SHMEDIA_FR49 = 177, + CV_SHMEDIA_FR50 = 178, + CV_SHMEDIA_FR51 = 179, + CV_SHMEDIA_FR52 = 180, + CV_SHMEDIA_FR53 = 181, + CV_SHMEDIA_FR54 = 182, + CV_SHMEDIA_FR55 = 183, + CV_SHMEDIA_FR56 = 184, + CV_SHMEDIA_FR57 = 185, + CV_SHMEDIA_FR58 = 186, + CV_SHMEDIA_FR59 = 187, + CV_SHMEDIA_FR60 = 188, + CV_SHMEDIA_FR61 = 189, + CV_SHMEDIA_FR62 = 190, + CV_SHMEDIA_FR63 = 191, + + // Double - 64 bit synonyms for 32bit fp register pairs + // subtract 128 to find first base single register + CV_SHMEDIA_DR0 = 256, + CV_SHMEDIA_DR2 = 258, + CV_SHMEDIA_DR4 = 260, + CV_SHMEDIA_DR6 = 262, + CV_SHMEDIA_DR8 = 264, + CV_SHMEDIA_DR10 = 266, + CV_SHMEDIA_DR12 = 268, + CV_SHMEDIA_DR14 = 270, + CV_SHMEDIA_DR16 = 272, + CV_SHMEDIA_DR18 = 274, + CV_SHMEDIA_DR20 = 276, + CV_SHMEDIA_DR22 = 278, + CV_SHMEDIA_DR24 = 280, + CV_SHMEDIA_DR26 = 282, + CV_SHMEDIA_DR28 = 284, + CV_SHMEDIA_DR30 = 286, + CV_SHMEDIA_DR32 = 288, + CV_SHMEDIA_DR34 = 290, + CV_SHMEDIA_DR36 = 292, + CV_SHMEDIA_DR38 = 294, + CV_SHMEDIA_DR40 = 296, + CV_SHMEDIA_DR42 = 298, + CV_SHMEDIA_DR44 = 300, + CV_SHMEDIA_DR46 = 302, + CV_SHMEDIA_DR48 = 304, + CV_SHMEDIA_DR50 = 306, + CV_SHMEDIA_DR52 = 308, + CV_SHMEDIA_DR54 = 310, + CV_SHMEDIA_DR56 = 312, + CV_SHMEDIA_DR58 = 314, + CV_SHMEDIA_DR60 = 316, + CV_SHMEDIA_DR62 = 318, + + // Vector - 128 bit synonyms for 32bit fp register quads + // subtract 384 to find first base single register + CV_SHMEDIA_FV0 = 512, + CV_SHMEDIA_FV4 = 516, + CV_SHMEDIA_FV8 = 520, + CV_SHMEDIA_FV12 = 524, + CV_SHMEDIA_FV16 = 528, + CV_SHMEDIA_FV20 = 532, + CV_SHMEDIA_FV24 = 536, + CV_SHMEDIA_FV28 = 540, + CV_SHMEDIA_FV32 = 544, + CV_SHMEDIA_FV36 = 548, + CV_SHMEDIA_FV40 = 552, + CV_SHMEDIA_FV44 = 556, + CV_SHMEDIA_FV48 = 560, + CV_SHMEDIA_FV52 = 564, + CV_SHMEDIA_FV56 = 568, + CV_SHMEDIA_FV60 = 572, + + // Matrix - 512 bit synonyms for 16 adjacent 32bit fp registers + // subtract 896 to find first base single register + CV_SHMEDIA_MTRX0 = 1024, + CV_SHMEDIA_MTRX16 = 1040, + CV_SHMEDIA_MTRX32 = 1056, + CV_SHMEDIA_MTRX48 = 1072, + + // Control - Implementation defined 64bit control registers + CV_SHMEDIA_CR0 = 2000, + CV_SHMEDIA_CR1 = 2001, + CV_SHMEDIA_CR2 = 2002, + CV_SHMEDIA_CR3 = 2003, + CV_SHMEDIA_CR4 = 2004, + CV_SHMEDIA_CR5 = 2005, + CV_SHMEDIA_CR6 = 2006, + CV_SHMEDIA_CR7 = 2007, + CV_SHMEDIA_CR8 = 2008, + CV_SHMEDIA_CR9 = 2009, + CV_SHMEDIA_CR10 = 2010, + CV_SHMEDIA_CR11 = 2011, + CV_SHMEDIA_CR12 = 2012, + CV_SHMEDIA_CR13 = 2013, + CV_SHMEDIA_CR14 = 2014, + CV_SHMEDIA_CR15 = 2015, + CV_SHMEDIA_CR16 = 2016, + CV_SHMEDIA_CR17 = 2017, + CV_SHMEDIA_CR18 = 2018, + CV_SHMEDIA_CR19 = 2019, + CV_SHMEDIA_CR20 = 2020, + CV_SHMEDIA_CR21 = 2021, + CV_SHMEDIA_CR22 = 2022, + CV_SHMEDIA_CR23 = 2023, + CV_SHMEDIA_CR24 = 2024, + CV_SHMEDIA_CR25 = 2025, + CV_SHMEDIA_CR26 = 2026, + CV_SHMEDIA_CR27 = 2027, + CV_SHMEDIA_CR28 = 2028, + CV_SHMEDIA_CR29 = 2029, + CV_SHMEDIA_CR30 = 2030, + CV_SHMEDIA_CR31 = 2031, + CV_SHMEDIA_CR32 = 2032, + CV_SHMEDIA_CR33 = 2033, + CV_SHMEDIA_CR34 = 2034, + CV_SHMEDIA_CR35 = 2035, + CV_SHMEDIA_CR36 = 2036, + CV_SHMEDIA_CR37 = 2037, + CV_SHMEDIA_CR38 = 2038, + CV_SHMEDIA_CR39 = 2039, + CV_SHMEDIA_CR40 = 2040, + CV_SHMEDIA_CR41 = 2041, + CV_SHMEDIA_CR42 = 2042, + CV_SHMEDIA_CR43 = 2043, + CV_SHMEDIA_CR44 = 2044, + CV_SHMEDIA_CR45 = 2045, + CV_SHMEDIA_CR46 = 2046, + CV_SHMEDIA_CR47 = 2047, + CV_SHMEDIA_CR48 = 2048, + CV_SHMEDIA_CR49 = 2049, + CV_SHMEDIA_CR50 = 2050, + CV_SHMEDIA_CR51 = 2051, + CV_SHMEDIA_CR52 = 2052, + CV_SHMEDIA_CR53 = 2053, + CV_SHMEDIA_CR54 = 2054, + CV_SHMEDIA_CR55 = 2055, + CV_SHMEDIA_CR56 = 2056, + CV_SHMEDIA_CR57 = 2057, + CV_SHMEDIA_CR58 = 2058, + CV_SHMEDIA_CR59 = 2059, + CV_SHMEDIA_CR60 = 2060, + CV_SHMEDIA_CR61 = 2061, + CV_SHMEDIA_CR62 = 2062, + CV_SHMEDIA_CR63 = 2063, + + CV_SHMEDIA_FPSCR = 2064, + + // Compact mode synonyms + CV_SHMEDIA_GBR = CV_SHMEDIA_R16, + CV_SHMEDIA_MACL = 90, // synonym for lower 32bits of media R17 + CV_SHMEDIA_MACH = 91, // synonym for upper 32bits of media R17 + CV_SHMEDIA_PR = CV_SHMEDIA_R18, + CV_SHMEDIA_T = 92, // synonym for lowest bit of media R19 + CV_SHMEDIA_FPUL = CV_SHMEDIA_FR32, + CV_SHMEDIA_PC = 93, + CV_SHMEDIA_SR = CV_SHMEDIA_CR0, + + // + // AMD64 registers + // + + CV_AMD64_AL = 1, + CV_AMD64_CL = 2, + CV_AMD64_DL = 3, + CV_AMD64_BL = 4, + CV_AMD64_AH = 5, + CV_AMD64_CH = 6, + CV_AMD64_DH = 7, + CV_AMD64_BH = 8, + CV_AMD64_AX = 9, + CV_AMD64_CX = 10, + CV_AMD64_DX = 11, + CV_AMD64_BX = 12, + CV_AMD64_SP = 13, + CV_AMD64_BP = 14, + CV_AMD64_SI = 15, + CV_AMD64_DI = 16, + CV_AMD64_EAX = 17, + CV_AMD64_ECX = 18, + CV_AMD64_EDX = 19, + CV_AMD64_EBX = 20, + CV_AMD64_ESP = 21, + CV_AMD64_EBP = 22, + CV_AMD64_ESI = 23, + CV_AMD64_EDI = 24, + CV_AMD64_ES = 25, + CV_AMD64_CS = 26, + CV_AMD64_SS = 27, + CV_AMD64_DS = 28, + CV_AMD64_FS = 29, + CV_AMD64_GS = 30, + CV_AMD64_FLAGS = 32, + CV_AMD64_RIP = 33, + CV_AMD64_EFLAGS = 34, + + // Control registers + CV_AMD64_CR0 = 80, + CV_AMD64_CR1 = 81, + CV_AMD64_CR2 = 82, + CV_AMD64_CR3 = 83, + CV_AMD64_CR4 = 84, + CV_AMD64_CR8 = 88, + + // Debug registers + CV_AMD64_DR0 = 90, + CV_AMD64_DR1 = 91, + CV_AMD64_DR2 = 92, + CV_AMD64_DR3 = 93, + CV_AMD64_DR4 = 94, + CV_AMD64_DR5 = 95, + CV_AMD64_DR6 = 96, + CV_AMD64_DR7 = 97, + CV_AMD64_DR8 = 98, + CV_AMD64_DR9 = 99, + CV_AMD64_DR10 = 100, + CV_AMD64_DR11 = 101, + CV_AMD64_DR12 = 102, + CV_AMD64_DR13 = 103, + CV_AMD64_DR14 = 104, + CV_AMD64_DR15 = 105, + + CV_AMD64_GDTR = 110, + CV_AMD64_GDTL = 111, + CV_AMD64_IDTR = 112, + CV_AMD64_IDTL = 113, + CV_AMD64_LDTR = 114, + CV_AMD64_TR = 115, + + CV_AMD64_ST0 = 128, + CV_AMD64_ST1 = 129, + CV_AMD64_ST2 = 130, + CV_AMD64_ST3 = 131, + CV_AMD64_ST4 = 132, + CV_AMD64_ST5 = 133, + CV_AMD64_ST6 = 134, + CV_AMD64_ST7 = 135, + CV_AMD64_CTRL = 136, + CV_AMD64_STAT = 137, + CV_AMD64_TAG = 138, + CV_AMD64_FPIP = 139, + CV_AMD64_FPCS = 140, + CV_AMD64_FPDO = 141, + CV_AMD64_FPDS = 142, + CV_AMD64_ISEM = 143, + CV_AMD64_FPEIP = 144, + CV_AMD64_FPEDO = 145, + + CV_AMD64_MM0 = 146, + CV_AMD64_MM1 = 147, + CV_AMD64_MM2 = 148, + CV_AMD64_MM3 = 149, + CV_AMD64_MM4 = 150, + CV_AMD64_MM5 = 151, + CV_AMD64_MM6 = 152, + CV_AMD64_MM7 = 153, + + CV_AMD64_XMM0 = 154, // KATMAI registers + CV_AMD64_XMM1 = 155, + CV_AMD64_XMM2 = 156, + CV_AMD64_XMM3 = 157, + CV_AMD64_XMM4 = 158, + CV_AMD64_XMM5 = 159, + CV_AMD64_XMM6 = 160, + CV_AMD64_XMM7 = 161, + + CV_AMD64_XMM0_0 = 162, // KATMAI sub-registers + CV_AMD64_XMM0_1 = 163, + CV_AMD64_XMM0_2 = 164, + CV_AMD64_XMM0_3 = 165, + CV_AMD64_XMM1_0 = 166, + CV_AMD64_XMM1_1 = 167, + CV_AMD64_XMM1_2 = 168, + CV_AMD64_XMM1_3 = 169, + CV_AMD64_XMM2_0 = 170, + CV_AMD64_XMM2_1 = 171, + CV_AMD64_XMM2_2 = 172, + CV_AMD64_XMM2_3 = 173, + CV_AMD64_XMM3_0 = 174, + CV_AMD64_XMM3_1 = 175, + CV_AMD64_XMM3_2 = 176, + CV_AMD64_XMM3_3 = 177, + CV_AMD64_XMM4_0 = 178, + CV_AMD64_XMM4_1 = 179, + CV_AMD64_XMM4_2 = 180, + CV_AMD64_XMM4_3 = 181, + CV_AMD64_XMM5_0 = 182, + CV_AMD64_XMM5_1 = 183, + CV_AMD64_XMM5_2 = 184, + CV_AMD64_XMM5_3 = 185, + CV_AMD64_XMM6_0 = 186, + CV_AMD64_XMM6_1 = 187, + CV_AMD64_XMM6_2 = 188, + CV_AMD64_XMM6_3 = 189, + CV_AMD64_XMM7_0 = 190, + CV_AMD64_XMM7_1 = 191, + CV_AMD64_XMM7_2 = 192, + CV_AMD64_XMM7_3 = 193, + + CV_AMD64_XMM0L = 194, + CV_AMD64_XMM1L = 195, + CV_AMD64_XMM2L = 196, + CV_AMD64_XMM3L = 197, + CV_AMD64_XMM4L = 198, + CV_AMD64_XMM5L = 199, + CV_AMD64_XMM6L = 200, + CV_AMD64_XMM7L = 201, + + CV_AMD64_XMM0H = 202, + CV_AMD64_XMM1H = 203, + CV_AMD64_XMM2H = 204, + CV_AMD64_XMM3H = 205, + CV_AMD64_XMM4H = 206, + CV_AMD64_XMM5H = 207, + CV_AMD64_XMM6H = 208, + CV_AMD64_XMM7H = 209, + + CV_AMD64_MXCSR = 211, // XMM status register + + CV_AMD64_EMM0L = 220, // XMM sub-registers (WNI integer) + CV_AMD64_EMM1L = 221, + CV_AMD64_EMM2L = 222, + CV_AMD64_EMM3L = 223, + CV_AMD64_EMM4L = 224, + CV_AMD64_EMM5L = 225, + CV_AMD64_EMM6L = 226, + CV_AMD64_EMM7L = 227, + + CV_AMD64_EMM0H = 228, + CV_AMD64_EMM1H = 229, + CV_AMD64_EMM2H = 230, + CV_AMD64_EMM3H = 231, + CV_AMD64_EMM4H = 232, + CV_AMD64_EMM5H = 233, + CV_AMD64_EMM6H = 234, + CV_AMD64_EMM7H = 235, + + // do not change the order of these regs, first one must be even too + CV_AMD64_MM00 = 236, + CV_AMD64_MM01 = 237, + CV_AMD64_MM10 = 238, + CV_AMD64_MM11 = 239, + CV_AMD64_MM20 = 240, + CV_AMD64_MM21 = 241, + CV_AMD64_MM30 = 242, + CV_AMD64_MM31 = 243, + CV_AMD64_MM40 = 244, + CV_AMD64_MM41 = 245, + CV_AMD64_MM50 = 246, + CV_AMD64_MM51 = 247, + CV_AMD64_MM60 = 248, + CV_AMD64_MM61 = 249, + CV_AMD64_MM70 = 250, + CV_AMD64_MM71 = 251, + + // Extended KATMAI registers + CV_AMD64_XMM8 = 252, // KATMAI registers + CV_AMD64_XMM9 = 253, + CV_AMD64_XMM10 = 254, + CV_AMD64_XMM11 = 255, + CV_AMD64_XMM12 = 256, + CV_AMD64_XMM13 = 257, + CV_AMD64_XMM14 = 258, + CV_AMD64_XMM15 = 259, + + CV_AMD64_XMM8_0 = 260, // KATMAI sub-registers + CV_AMD64_XMM8_1 = 261, + CV_AMD64_XMM8_2 = 262, + CV_AMD64_XMM8_3 = 263, + CV_AMD64_XMM9_0 = 264, + CV_AMD64_XMM9_1 = 265, + CV_AMD64_XMM9_2 = 266, + CV_AMD64_XMM9_3 = 267, + CV_AMD64_XMM10_0 = 268, + CV_AMD64_XMM10_1 = 269, + CV_AMD64_XMM10_2 = 270, + CV_AMD64_XMM10_3 = 271, + CV_AMD64_XMM11_0 = 272, + CV_AMD64_XMM11_1 = 273, + CV_AMD64_XMM11_2 = 274, + CV_AMD64_XMM11_3 = 275, + CV_AMD64_XMM12_0 = 276, + CV_AMD64_XMM12_1 = 277, + CV_AMD64_XMM12_2 = 278, + CV_AMD64_XMM12_3 = 279, + CV_AMD64_XMM13_0 = 280, + CV_AMD64_XMM13_1 = 281, + CV_AMD64_XMM13_2 = 282, + CV_AMD64_XMM13_3 = 283, + CV_AMD64_XMM14_0 = 284, + CV_AMD64_XMM14_1 = 285, + CV_AMD64_XMM14_2 = 286, + CV_AMD64_XMM14_3 = 287, + CV_AMD64_XMM15_0 = 288, + CV_AMD64_XMM15_1 = 289, + CV_AMD64_XMM15_2 = 290, + CV_AMD64_XMM15_3 = 291, + + CV_AMD64_XMM8L = 292, + CV_AMD64_XMM9L = 293, + CV_AMD64_XMM10L = 294, + CV_AMD64_XMM11L = 295, + CV_AMD64_XMM12L = 296, + CV_AMD64_XMM13L = 297, + CV_AMD64_XMM14L = 298, + CV_AMD64_XMM15L = 299, + + CV_AMD64_XMM8H = 300, + CV_AMD64_XMM9H = 301, + CV_AMD64_XMM10H = 302, + CV_AMD64_XMM11H = 303, + CV_AMD64_XMM12H = 304, + CV_AMD64_XMM13H = 305, + CV_AMD64_XMM14H = 306, + CV_AMD64_XMM15H = 307, + + CV_AMD64_EMM8L = 308, // XMM sub-registers (WNI integer) + CV_AMD64_EMM9L = 309, + CV_AMD64_EMM10L = 310, + CV_AMD64_EMM11L = 311, + CV_AMD64_EMM12L = 312, + CV_AMD64_EMM13L = 313, + CV_AMD64_EMM14L = 314, + CV_AMD64_EMM15L = 315, + + CV_AMD64_EMM8H = 316, + CV_AMD64_EMM9H = 317, + CV_AMD64_EMM10H = 318, + CV_AMD64_EMM11H = 319, + CV_AMD64_EMM12H = 320, + CV_AMD64_EMM13H = 321, + CV_AMD64_EMM14H = 322, + CV_AMD64_EMM15H = 323, + + // Low byte forms of some standard registers + CV_AMD64_SIL = 324, + CV_AMD64_DIL = 325, + CV_AMD64_BPL = 326, + CV_AMD64_SPL = 327, + + // 64-bit regular registers + CV_AMD64_RAX = 328, + CV_AMD64_RBX = 329, + CV_AMD64_RCX = 330, + CV_AMD64_RDX = 331, + CV_AMD64_RSI = 332, + CV_AMD64_RDI = 333, + CV_AMD64_RBP = 334, + CV_AMD64_RSP = 335, + + // 64-bit integer registers with 8-, 16-, and 32-bit forms (B, W, and D) + CV_AMD64_R8 = 336, + CV_AMD64_R9 = 337, + CV_AMD64_R10 = 338, + CV_AMD64_R11 = 339, + CV_AMD64_R12 = 340, + CV_AMD64_R13 = 341, + CV_AMD64_R14 = 342, + CV_AMD64_R15 = 343, + + CV_AMD64_R8B = 344, + CV_AMD64_R9B = 345, + CV_AMD64_R10B = 346, + CV_AMD64_R11B = 347, + CV_AMD64_R12B = 348, + CV_AMD64_R13B = 349, + CV_AMD64_R14B = 350, + CV_AMD64_R15B = 351, + + CV_AMD64_R8W = 352, + CV_AMD64_R9W = 353, + CV_AMD64_R10W = 354, + CV_AMD64_R11W = 355, + CV_AMD64_R12W = 356, + CV_AMD64_R13W = 357, + CV_AMD64_R14W = 358, + CV_AMD64_R15W = 359, + + CV_AMD64_R8D = 360, + CV_AMD64_R9D = 361, + CV_AMD64_R10D = 362, + CV_AMD64_R11D = 363, + CV_AMD64_R12D = 364, + CV_AMD64_R13D = 365, + CV_AMD64_R14D = 366, + CV_AMD64_R15D = 367, + + // AVX registers 256 bits + CV_AMD64_YMM0 = 368, + CV_AMD64_YMM1 = 369, + CV_AMD64_YMM2 = 370, + CV_AMD64_YMM3 = 371, + CV_AMD64_YMM4 = 372, + CV_AMD64_YMM5 = 373, + CV_AMD64_YMM6 = 374, + CV_AMD64_YMM7 = 375, + CV_AMD64_YMM8 = 376, + CV_AMD64_YMM9 = 377, + CV_AMD64_YMM10 = 378, + CV_AMD64_YMM11 = 379, + CV_AMD64_YMM12 = 380, + CV_AMD64_YMM13 = 381, + CV_AMD64_YMM14 = 382, + CV_AMD64_YMM15 = 383, + + // AVX registers upper 128 bits + CV_AMD64_YMM0H = 384, + CV_AMD64_YMM1H = 385, + CV_AMD64_YMM2H = 386, + CV_AMD64_YMM3H = 387, + CV_AMD64_YMM4H = 388, + CV_AMD64_YMM5H = 389, + CV_AMD64_YMM6H = 390, + CV_AMD64_YMM7H = 391, + CV_AMD64_YMM8H = 392, + CV_AMD64_YMM9H = 393, + CV_AMD64_YMM10H = 394, + CV_AMD64_YMM11H = 395, + CV_AMD64_YMM12H = 396, + CV_AMD64_YMM13H = 397, + CV_AMD64_YMM14H = 398, + CV_AMD64_YMM15H = 399, + + //Lower/upper 8 bytes of XMM registers. Unlike CV_AMD64_XMM, these + //values reprsesent the bit patterns of the registers as 64-bit integers, not + //the representation of these registers as a double. + CV_AMD64_XMM0IL = 400, + CV_AMD64_XMM1IL = 401, + CV_AMD64_XMM2IL = 402, + CV_AMD64_XMM3IL = 403, + CV_AMD64_XMM4IL = 404, + CV_AMD64_XMM5IL = 405, + CV_AMD64_XMM6IL = 406, + CV_AMD64_XMM7IL = 407, + CV_AMD64_XMM8IL = 408, + CV_AMD64_XMM9IL = 409, + CV_AMD64_XMM10IL = 410, + CV_AMD64_XMM11IL = 411, + CV_AMD64_XMM12IL = 412, + CV_AMD64_XMM13IL = 413, + CV_AMD64_XMM14IL = 414, + CV_AMD64_XMM15IL = 415, + + CV_AMD64_XMM0IH = 416, + CV_AMD64_XMM1IH = 417, + CV_AMD64_XMM2IH = 418, + CV_AMD64_XMM3IH = 419, + CV_AMD64_XMM4IH = 420, + CV_AMD64_XMM5IH = 421, + CV_AMD64_XMM6IH = 422, + CV_AMD64_XMM7IH = 423, + CV_AMD64_XMM8IH = 424, + CV_AMD64_XMM9IH = 425, + CV_AMD64_XMM10IH = 426, + CV_AMD64_XMM11IH = 427, + CV_AMD64_XMM12IH = 428, + CV_AMD64_XMM13IH = 429, + CV_AMD64_XMM14IH = 430, + CV_AMD64_XMM15IH = 431, + + CV_AMD64_YMM0I0 = 432, // AVX integer registers + CV_AMD64_YMM0I1 = 433, + CV_AMD64_YMM0I2 = 434, + CV_AMD64_YMM0I3 = 435, + CV_AMD64_YMM1I0 = 436, + CV_AMD64_YMM1I1 = 437, + CV_AMD64_YMM1I2 = 438, + CV_AMD64_YMM1I3 = 439, + CV_AMD64_YMM2I0 = 440, + CV_AMD64_YMM2I1 = 441, + CV_AMD64_YMM2I2 = 442, + CV_AMD64_YMM2I3 = 443, + CV_AMD64_YMM3I0 = 444, + CV_AMD64_YMM3I1 = 445, + CV_AMD64_YMM3I2 = 446, + CV_AMD64_YMM3I3 = 447, + CV_AMD64_YMM4I0 = 448, + CV_AMD64_YMM4I1 = 449, + CV_AMD64_YMM4I2 = 450, + CV_AMD64_YMM4I3 = 451, + CV_AMD64_YMM5I0 = 452, + CV_AMD64_YMM5I1 = 453, + CV_AMD64_YMM5I2 = 454, + CV_AMD64_YMM5I3 = 455, + CV_AMD64_YMM6I0 = 456, + CV_AMD64_YMM6I1 = 457, + CV_AMD64_YMM6I2 = 458, + CV_AMD64_YMM6I3 = 459, + CV_AMD64_YMM7I0 = 460, + CV_AMD64_YMM7I1 = 461, + CV_AMD64_YMM7I2 = 462, + CV_AMD64_YMM7I3 = 463, + CV_AMD64_YMM8I0 = 464, + CV_AMD64_YMM8I1 = 465, + CV_AMD64_YMM8I2 = 466, + CV_AMD64_YMM8I3 = 467, + CV_AMD64_YMM9I0 = 468, + CV_AMD64_YMM9I1 = 469, + CV_AMD64_YMM9I2 = 470, + CV_AMD64_YMM9I3 = 471, + CV_AMD64_YMM10I0 = 472, + CV_AMD64_YMM10I1 = 473, + CV_AMD64_YMM10I2 = 474, + CV_AMD64_YMM10I3 = 475, + CV_AMD64_YMM11I0 = 476, + CV_AMD64_YMM11I1 = 477, + CV_AMD64_YMM11I2 = 478, + CV_AMD64_YMM11I3 = 479, + CV_AMD64_YMM12I0 = 480, + CV_AMD64_YMM12I1 = 481, + CV_AMD64_YMM12I2 = 482, + CV_AMD64_YMM12I3 = 483, + CV_AMD64_YMM13I0 = 484, + CV_AMD64_YMM13I1 = 485, + CV_AMD64_YMM13I2 = 486, + CV_AMD64_YMM13I3 = 487, + CV_AMD64_YMM14I0 = 488, + CV_AMD64_YMM14I1 = 489, + CV_AMD64_YMM14I2 = 490, + CV_AMD64_YMM14I3 = 491, + CV_AMD64_YMM15I0 = 492, + CV_AMD64_YMM15I1 = 493, + CV_AMD64_YMM15I2 = 494, + CV_AMD64_YMM15I3 = 495, + + CV_AMD64_YMM0F0 = 496, // AVX floating-point single precise registers + CV_AMD64_YMM0F1 = 497, + CV_AMD64_YMM0F2 = 498, + CV_AMD64_YMM0F3 = 499, + CV_AMD64_YMM0F4 = 500, + CV_AMD64_YMM0F5 = 501, + CV_AMD64_YMM0F6 = 502, + CV_AMD64_YMM0F7 = 503, + CV_AMD64_YMM1F0 = 504, + CV_AMD64_YMM1F1 = 505, + CV_AMD64_YMM1F2 = 506, + CV_AMD64_YMM1F3 = 507, + CV_AMD64_YMM1F4 = 508, + CV_AMD64_YMM1F5 = 509, + CV_AMD64_YMM1F6 = 510, + CV_AMD64_YMM1F7 = 511, + CV_AMD64_YMM2F0 = 512, + CV_AMD64_YMM2F1 = 513, + CV_AMD64_YMM2F2 = 514, + CV_AMD64_YMM2F3 = 515, + CV_AMD64_YMM2F4 = 516, + CV_AMD64_YMM2F5 = 517, + CV_AMD64_YMM2F6 = 518, + CV_AMD64_YMM2F7 = 519, + CV_AMD64_YMM3F0 = 520, + CV_AMD64_YMM3F1 = 521, + CV_AMD64_YMM3F2 = 522, + CV_AMD64_YMM3F3 = 523, + CV_AMD64_YMM3F4 = 524, + CV_AMD64_YMM3F5 = 525, + CV_AMD64_YMM3F6 = 526, + CV_AMD64_YMM3F7 = 527, + CV_AMD64_YMM4F0 = 528, + CV_AMD64_YMM4F1 = 529, + CV_AMD64_YMM4F2 = 530, + CV_AMD64_YMM4F3 = 531, + CV_AMD64_YMM4F4 = 532, + CV_AMD64_YMM4F5 = 533, + CV_AMD64_YMM4F6 = 534, + CV_AMD64_YMM4F7 = 535, + CV_AMD64_YMM5F0 = 536, + CV_AMD64_YMM5F1 = 537, + CV_AMD64_YMM5F2 = 538, + CV_AMD64_YMM5F3 = 539, + CV_AMD64_YMM5F4 = 540, + CV_AMD64_YMM5F5 = 541, + CV_AMD64_YMM5F6 = 542, + CV_AMD64_YMM5F7 = 543, + CV_AMD64_YMM6F0 = 544, + CV_AMD64_YMM6F1 = 545, + CV_AMD64_YMM6F2 = 546, + CV_AMD64_YMM6F3 = 547, + CV_AMD64_YMM6F4 = 548, + CV_AMD64_YMM6F5 = 549, + CV_AMD64_YMM6F6 = 550, + CV_AMD64_YMM6F7 = 551, + CV_AMD64_YMM7F0 = 552, + CV_AMD64_YMM7F1 = 553, + CV_AMD64_YMM7F2 = 554, + CV_AMD64_YMM7F3 = 555, + CV_AMD64_YMM7F4 = 556, + CV_AMD64_YMM7F5 = 557, + CV_AMD64_YMM7F6 = 558, + CV_AMD64_YMM7F7 = 559, + CV_AMD64_YMM8F0 = 560, + CV_AMD64_YMM8F1 = 561, + CV_AMD64_YMM8F2 = 562, + CV_AMD64_YMM8F3 = 563, + CV_AMD64_YMM8F4 = 564, + CV_AMD64_YMM8F5 = 565, + CV_AMD64_YMM8F6 = 566, + CV_AMD64_YMM8F7 = 567, + CV_AMD64_YMM9F0 = 568, + CV_AMD64_YMM9F1 = 569, + CV_AMD64_YMM9F2 = 570, + CV_AMD64_YMM9F3 = 571, + CV_AMD64_YMM9F4 = 572, + CV_AMD64_YMM9F5 = 573, + CV_AMD64_YMM9F6 = 574, + CV_AMD64_YMM9F7 = 575, + CV_AMD64_YMM10F0 = 576, + CV_AMD64_YMM10F1 = 577, + CV_AMD64_YMM10F2 = 578, + CV_AMD64_YMM10F3 = 579, + CV_AMD64_YMM10F4 = 580, + CV_AMD64_YMM10F5 = 581, + CV_AMD64_YMM10F6 = 582, + CV_AMD64_YMM10F7 = 583, + CV_AMD64_YMM11F0 = 584, + CV_AMD64_YMM11F1 = 585, + CV_AMD64_YMM11F2 = 586, + CV_AMD64_YMM11F3 = 587, + CV_AMD64_YMM11F4 = 588, + CV_AMD64_YMM11F5 = 589, + CV_AMD64_YMM11F6 = 590, + CV_AMD64_YMM11F7 = 591, + CV_AMD64_YMM12F0 = 592, + CV_AMD64_YMM12F1 = 593, + CV_AMD64_YMM12F2 = 594, + CV_AMD64_YMM12F3 = 595, + CV_AMD64_YMM12F4 = 596, + CV_AMD64_YMM12F5 = 597, + CV_AMD64_YMM12F6 = 598, + CV_AMD64_YMM12F7 = 599, + CV_AMD64_YMM13F0 = 600, + CV_AMD64_YMM13F1 = 601, + CV_AMD64_YMM13F2 = 602, + CV_AMD64_YMM13F3 = 603, + CV_AMD64_YMM13F4 = 604, + CV_AMD64_YMM13F5 = 605, + CV_AMD64_YMM13F6 = 606, + CV_AMD64_YMM13F7 = 607, + CV_AMD64_YMM14F0 = 608, + CV_AMD64_YMM14F1 = 609, + CV_AMD64_YMM14F2 = 610, + CV_AMD64_YMM14F3 = 611, + CV_AMD64_YMM14F4 = 612, + CV_AMD64_YMM14F5 = 613, + CV_AMD64_YMM14F6 = 614, + CV_AMD64_YMM14F7 = 615, + CV_AMD64_YMM15F0 = 616, + CV_AMD64_YMM15F1 = 617, + CV_AMD64_YMM15F2 = 618, + CV_AMD64_YMM15F3 = 619, + CV_AMD64_YMM15F4 = 620, + CV_AMD64_YMM15F5 = 621, + CV_AMD64_YMM15F6 = 622, + CV_AMD64_YMM15F7 = 623, + + CV_AMD64_YMM0D0 = 624, // AVX floating-point double precise registers + CV_AMD64_YMM0D1 = 625, + CV_AMD64_YMM0D2 = 626, + CV_AMD64_YMM0D3 = 627, + CV_AMD64_YMM1D0 = 628, + CV_AMD64_YMM1D1 = 629, + CV_AMD64_YMM1D2 = 630, + CV_AMD64_YMM1D3 = 631, + CV_AMD64_YMM2D0 = 632, + CV_AMD64_YMM2D1 = 633, + CV_AMD64_YMM2D2 = 634, + CV_AMD64_YMM2D3 = 635, + CV_AMD64_YMM3D0 = 636, + CV_AMD64_YMM3D1 = 637, + CV_AMD64_YMM3D2 = 638, + CV_AMD64_YMM3D3 = 639, + CV_AMD64_YMM4D0 = 640, + CV_AMD64_YMM4D1 = 641, + CV_AMD64_YMM4D2 = 642, + CV_AMD64_YMM4D3 = 643, + CV_AMD64_YMM5D0 = 644, + CV_AMD64_YMM5D1 = 645, + CV_AMD64_YMM5D2 = 646, + CV_AMD64_YMM5D3 = 647, + CV_AMD64_YMM6D0 = 648, + CV_AMD64_YMM6D1 = 649, + CV_AMD64_YMM6D2 = 650, + CV_AMD64_YMM6D3 = 651, + CV_AMD64_YMM7D0 = 652, + CV_AMD64_YMM7D1 = 653, + CV_AMD64_YMM7D2 = 654, + CV_AMD64_YMM7D3 = 655, + CV_AMD64_YMM8D0 = 656, + CV_AMD64_YMM8D1 = 657, + CV_AMD64_YMM8D2 = 658, + CV_AMD64_YMM8D3 = 659, + CV_AMD64_YMM9D0 = 660, + CV_AMD64_YMM9D1 = 661, + CV_AMD64_YMM9D2 = 662, + CV_AMD64_YMM9D3 = 663, + CV_AMD64_YMM10D0 = 664, + CV_AMD64_YMM10D1 = 665, + CV_AMD64_YMM10D2 = 666, + CV_AMD64_YMM10D3 = 667, + CV_AMD64_YMM11D0 = 668, + CV_AMD64_YMM11D1 = 669, + CV_AMD64_YMM11D2 = 670, + CV_AMD64_YMM11D3 = 671, + CV_AMD64_YMM12D0 = 672, + CV_AMD64_YMM12D1 = 673, + CV_AMD64_YMM12D2 = 674, + CV_AMD64_YMM12D3 = 675, + CV_AMD64_YMM13D0 = 676, + CV_AMD64_YMM13D1 = 677, + CV_AMD64_YMM13D2 = 678, + CV_AMD64_YMM13D3 = 679, + CV_AMD64_YMM14D0 = 680, + CV_AMD64_YMM14D1 = 681, + CV_AMD64_YMM14D2 = 682, + CV_AMD64_YMM14D3 = 683, + CV_AMD64_YMM15D0 = 684, + CV_AMD64_YMM15D1 = 685, + CV_AMD64_YMM15D2 = 686, + CV_AMD64_YMM15D3 = 687, + + CV_AMD64_BND0 = 688, // AMD64 MPX bounds registers + CV_AMD64_BND1 = 689, + CV_AMD64_BND2 = 690, + CV_AMD64_BND3 = 691, + CV_AMD64_BNDCFGU = 692, + CV_AMD64_BNDSTATUS = 693, + + CV_AMD64_XMM16 = 694, // AVX-512 registers + CV_AMD64_XMM17 = 695, + CV_AMD64_XMM18 = 696, + CV_AMD64_XMM19 = 697, + CV_AMD64_XMM20 = 698, + CV_AMD64_XMM21 = 699, + CV_AMD64_XMM22 = 700, + CV_AMD64_XMM23 = 701, + CV_AMD64_XMM24 = 702, + CV_AMD64_XMM25 = 703, + CV_AMD64_XMM26 = 704, + CV_AMD64_XMM27 = 705, + CV_AMD64_XMM28 = 706, + CV_AMD64_XMM29 = 707, + CV_AMD64_XMM30 = 708, + CV_AMD64_XMM31 = 709, + + CV_AMD64_YMM16 = 710, + CV_AMD64_YMM17 = 711, + CV_AMD64_YMM18 = 712, + CV_AMD64_YMM19 = 713, + CV_AMD64_YMM20 = 714, + CV_AMD64_YMM21 = 715, + CV_AMD64_YMM22 = 716, + CV_AMD64_YMM23 = 717, + CV_AMD64_YMM24 = 718, + CV_AMD64_YMM25 = 719, + CV_AMD64_YMM26 = 720, + CV_AMD64_YMM27 = 721, + CV_AMD64_YMM28 = 722, + CV_AMD64_YMM29 = 723, + CV_AMD64_YMM30 = 724, + CV_AMD64_YMM31 = 725, + + CV_AMD64_ZMM0 = 726, + CV_AMD64_ZMM1 = 727, + CV_AMD64_ZMM2 = 728, + CV_AMD64_ZMM3 = 729, + CV_AMD64_ZMM4 = 730, + CV_AMD64_ZMM5 = 731, + CV_AMD64_ZMM6 = 732, + CV_AMD64_ZMM7 = 733, + CV_AMD64_ZMM8 = 734, + CV_AMD64_ZMM9 = 735, + CV_AMD64_ZMM10 = 736, + CV_AMD64_ZMM11 = 737, + CV_AMD64_ZMM12 = 738, + CV_AMD64_ZMM13 = 739, + CV_AMD64_ZMM14 = 740, + CV_AMD64_ZMM15 = 741, + CV_AMD64_ZMM16 = 742, + CV_AMD64_ZMM17 = 743, + CV_AMD64_ZMM18 = 744, + CV_AMD64_ZMM19 = 745, + CV_AMD64_ZMM20 = 746, + CV_AMD64_ZMM21 = 747, + CV_AMD64_ZMM22 = 748, + CV_AMD64_ZMM23 = 749, + CV_AMD64_ZMM24 = 750, + CV_AMD64_ZMM25 = 751, + CV_AMD64_ZMM26 = 752, + CV_AMD64_ZMM27 = 753, + CV_AMD64_ZMM28 = 754, + CV_AMD64_ZMM29 = 755, + CV_AMD64_ZMM30 = 756, + CV_AMD64_ZMM31 = 757, + + CV_AMD64_K0 = 758, + CV_AMD64_K1 = 759, + CV_AMD64_K2 = 760, + CV_AMD64_K3 = 761, + CV_AMD64_K4 = 762, + CV_AMD64_K5 = 763, + CV_AMD64_K6 = 764, + CV_AMD64_K7 = 765, + + CV_AMD64_ZMM0H = 766, // upper 256 bits of the first 16 AMD64 AVX-512 registers + CV_AMD64_ZMM1H = 767, + CV_AMD64_ZMM2H = 768, + CV_AMD64_ZMM3H = 769, + CV_AMD64_ZMM4H = 770, + CV_AMD64_ZMM5H = 771, + CV_AMD64_ZMM6H = 772, + CV_AMD64_ZMM7H = 773, + CV_AMD64_ZMM8H = 774, + CV_AMD64_ZMM9H = 775, + CV_AMD64_ZMM10H = 776, + CV_AMD64_ZMM11H = 777, + CV_AMD64_ZMM12H = 778, + CV_AMD64_ZMM13H = 779, + CV_AMD64_ZMM14H = 780, + CV_AMD64_ZMM15H = 781, + + CV_AMD64_XMM16L = 782, // extended KATMAI registers + CV_AMD64_XMM17L = 783, + CV_AMD64_XMM18L = 784, + CV_AMD64_XMM19L = 785, + CV_AMD64_XMM20L = 786, + CV_AMD64_XMM21L = 787, + CV_AMD64_XMM22L = 788, + CV_AMD64_XMM23L = 789, + CV_AMD64_XMM24L = 790, + CV_AMD64_XMM25L = 791, + CV_AMD64_XMM26L = 792, + CV_AMD64_XMM27L = 793, + CV_AMD64_XMM28L = 794, + CV_AMD64_XMM29L = 795, + CV_AMD64_XMM30L = 796, + CV_AMD64_XMM31L = 797, + + CV_AMD64_XMM16_0 = 798, + CV_AMD64_XMM17_0 = 799, + CV_AMD64_XMM18_0 = 800, + CV_AMD64_XMM19_0 = 801, + CV_AMD64_XMM20_0 = 802, + CV_AMD64_XMM21_0 = 803, + CV_AMD64_XMM22_0 = 804, + CV_AMD64_XMM23_0 = 805, + CV_AMD64_XMM24_0 = 806, + CV_AMD64_XMM25_0 = 807, + CV_AMD64_XMM26_0 = 808, + CV_AMD64_XMM27_0 = 809, + CV_AMD64_XMM28_0 = 810, + CV_AMD64_XMM29_0 = 811, + CV_AMD64_XMM30_0 = 812, + CV_AMD64_XMM31_0 = 813, + + CV_AMD64_XMM16H = 814, + CV_AMD64_XMM17H = 815, + CV_AMD64_XMM18H = 816, + CV_AMD64_XMM19H = 817, + CV_AMD64_XMM20H = 818, + CV_AMD64_XMM21H = 819, + CV_AMD64_XMM22H = 820, + CV_AMD64_XMM23H = 821, + CV_AMD64_XMM24H = 822, + CV_AMD64_XMM25H = 823, + CV_AMD64_XMM26H = 824, + CV_AMD64_XMM27H = 825, + CV_AMD64_XMM28H = 826, + CV_AMD64_XMM29H = 827, + CV_AMD64_XMM30H = 828, + CV_AMD64_XMM31H = 829, + + CV_AMD64_EMM16H = 830, + CV_AMD64_EMM17H = 831, + CV_AMD64_EMM18H = 832, + CV_AMD64_EMM19H = 833, + CV_AMD64_EMM20H = 834, + CV_AMD64_EMM21H = 835, + CV_AMD64_EMM22H = 836, + CV_AMD64_EMM23H = 837, + CV_AMD64_EMM24H = 838, + CV_AMD64_EMM25H = 839, + CV_AMD64_EMM26H = 840, + CV_AMD64_EMM27H = 841, + CV_AMD64_EMM28H = 842, + CV_AMD64_EMM29H = 843, + CV_AMD64_EMM30H = 844, + CV_AMD64_EMM31H = 845, + + // Note: Next set of platform registers need to go into a new enum... + // this one is above 44K now. + +} CV_HREG_e; + +typedef enum CV_HLSLREG_e +{ + CV_HLSLREG_TEMP = 0, + CV_HLSLREG_INPUT = 1, + CV_HLSLREG_OUTPUT = 2, + CV_HLSLREG_INDEXABLE_TEMP = 3, + CV_HLSLREG_IMMEDIATE32 = 4, + CV_HLSLREG_IMMEDIATE64 = 5, + CV_HLSLREG_SAMPLER = 6, + CV_HLSLREG_RESOURCE = 7, + CV_HLSLREG_CONSTANT_BUFFER = 8, + CV_HLSLREG_IMMEDIATE_CONSTANT_BUFFER = 9, + CV_HLSLREG_LABEL = 10, + CV_HLSLREG_INPUT_PRIMITIVEID = 11, + CV_HLSLREG_OUTPUT_DEPTH = 12, + CV_HLSLREG_NULL = 13, + CV_HLSLREG_RASTERIZER = 14, + CV_HLSLREG_OUTPUT_COVERAGE_MASK = 15, + CV_HLSLREG_STREAM = 16, + CV_HLSLREG_FUNCTION_BODY = 17, + CV_HLSLREG_FUNCTION_TABLE = 18, + CV_HLSLREG_INTERFACE = 19, + CV_HLSLREG_FUNCTION_INPUT = 20, + CV_HLSLREG_FUNCTION_OUTPUT = 21, + CV_HLSLREG_OUTPUT_CONTROL_POINT_ID = 22, + CV_HLSLREG_INPUT_FORK_INSTANCE_ID = 23, + CV_HLSLREG_INPUT_JOIN_INSTANCE_ID = 24, + CV_HLSLREG_INPUT_CONTROL_POINT = 25, + CV_HLSLREG_OUTPUT_CONTROL_POINT = 26, + CV_HLSLREG_INPUT_PATCH_CONSTANT = 27, + CV_HLSLREG_INPUT_DOMAIN_POINT = 28, + CV_HLSLREG_THIS_POINTER = 29, + CV_HLSLREG_UNORDERED_ACCESS_VIEW = 30, + CV_HLSLREG_THREAD_GROUP_SHARED_MEMORY = 31, + CV_HLSLREG_INPUT_THREAD_ID = 32, + CV_HLSLREG_INPUT_THREAD_GROUP_ID = 33, + CV_HLSLREG_INPUT_THREAD_ID_IN_GROUP = 34, + CV_HLSLREG_INPUT_COVERAGE_MASK = 35, + CV_HLSLREG_INPUT_THREAD_ID_IN_GROUP_FLATTENED = 36, + CV_HLSLREG_INPUT_GS_INSTANCE_ID = 37, + CV_HLSLREG_OUTPUT_DEPTH_GREATER_EQUAL = 38, + CV_HLSLREG_OUTPUT_DEPTH_LESS_EQUAL = 39, + CV_HLSLREG_CYCLE_COUNTER = 40, +} CV_HLSLREG_e; + +enum StackFrameTypeEnum +{ + FrameTypeFPO, // Frame pointer omitted, FPO info available + FrameTypeTrap, // Kernel Trap frame + FrameTypeTSS, // Kernel Trap frame + FrameTypeStandard, // Standard EBP stackframe + FrameTypeFrameData, // Frame pointer omitted, FrameData info available + + FrameTypeUnknown = -1, // Frame which does not have any debug info +}; + +enum MemoryTypeEnum +{ + MemTypeCode, // Read only code memory + MemTypeData, // Read only data/stack memory + MemTypeStack, // Read only stack memory + MemTypeCodeOnHeap, // Read only memory for code generated on heap by runtime + + MemTypeAny = -1, +}; + +typedef enum CV_HLSLMemorySpace_e +{ + // HLSL specific memory spaces + + CV_HLSL_MEMSPACE_DATA = 0x00, + CV_HLSL_MEMSPACE_SAMPLER = 0x01, + CV_HLSL_MEMSPACE_RESOURCE = 0x02, + CV_HLSL_MEMSPACE_RWRESOURCE = 0x03, + + CV_HLSL_MEMSPACE_MAX = 0x0F, +} CV_HLSLMemorySpace_e; + +enum +{ + NAMEHASH_BUILD_START, + NAMEHASH_BUILD_PAUSE, + NAMEHASH_BUILD_RESUME, + NAMEHASH_BUILD_COMPLETE, + NAMEHASH_BUILD_ERROR, + NAMEHASH_BUILD_OOM = NAMEHASH_BUILD_ERROR, + NAMEHASH_BUILD_FAIL_TO_OPEN_MOD, +}; + +#endif diff --git a/third/Blackbone/src/3rd_party/DIA/dia2.h b/third/Blackbone/src/3rd_party/DIA/dia2.h new file mode 100644 index 0000000000000000000000000000000000000000..313b4468bf4f2c65413c795c6d6e3a612b96c273 --- /dev/null +++ b/third/Blackbone/src/3rd_party/DIA/dia2.h @@ -0,0 +1,10646 @@ + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.01.0622 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCSAL_H_VERSION__ +#define __REQUIRED_RPCSAL_H_VERSION__ 100 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif /* __RPCNDR_H_VERSION__ */ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __dia2_h__ +#define __dia2_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __IDiaLoadCallback_FWD_DEFINED__ +#define __IDiaLoadCallback_FWD_DEFINED__ +typedef interface IDiaLoadCallback IDiaLoadCallback; + +#endif /* __IDiaLoadCallback_FWD_DEFINED__ */ + + +#ifndef __IDiaLoadCallback2_FWD_DEFINED__ +#define __IDiaLoadCallback2_FWD_DEFINED__ +typedef interface IDiaLoadCallback2 IDiaLoadCallback2; + +#endif /* __IDiaLoadCallback2_FWD_DEFINED__ */ + + +#ifndef __IDiaReadExeAtOffsetCallback_FWD_DEFINED__ +#define __IDiaReadExeAtOffsetCallback_FWD_DEFINED__ +typedef interface IDiaReadExeAtOffsetCallback IDiaReadExeAtOffsetCallback; + +#endif /* __IDiaReadExeAtOffsetCallback_FWD_DEFINED__ */ + + +#ifndef __IDiaReadExeAtRVACallback_FWD_DEFINED__ +#define __IDiaReadExeAtRVACallback_FWD_DEFINED__ +typedef interface IDiaReadExeAtRVACallback IDiaReadExeAtRVACallback; + +#endif /* __IDiaReadExeAtRVACallback_FWD_DEFINED__ */ + + +#ifndef __IDiaDataSource_FWD_DEFINED__ +#define __IDiaDataSource_FWD_DEFINED__ +typedef interface IDiaDataSource IDiaDataSource; + +#endif /* __IDiaDataSource_FWD_DEFINED__ */ + + +#ifndef __IDiaEnumSymbols_FWD_DEFINED__ +#define __IDiaEnumSymbols_FWD_DEFINED__ +typedef interface IDiaEnumSymbols IDiaEnumSymbols; + +#endif /* __IDiaEnumSymbols_FWD_DEFINED__ */ + + +#ifndef __IDiaEnumSymbolsByAddr_FWD_DEFINED__ +#define __IDiaEnumSymbolsByAddr_FWD_DEFINED__ +typedef interface IDiaEnumSymbolsByAddr IDiaEnumSymbolsByAddr; + +#endif /* __IDiaEnumSymbolsByAddr_FWD_DEFINED__ */ + + +#ifndef __IDiaEnumSourceFiles_FWD_DEFINED__ +#define __IDiaEnumSourceFiles_FWD_DEFINED__ +typedef interface IDiaEnumSourceFiles IDiaEnumSourceFiles; + +#endif /* __IDiaEnumSourceFiles_FWD_DEFINED__ */ + + +#ifndef __IDiaEnumInputAssemblyFiles_FWD_DEFINED__ +#define __IDiaEnumInputAssemblyFiles_FWD_DEFINED__ +typedef interface IDiaEnumInputAssemblyFiles IDiaEnumInputAssemblyFiles; + +#endif /* __IDiaEnumInputAssemblyFiles_FWD_DEFINED__ */ + + +#ifndef __IDiaEnumLineNumbers_FWD_DEFINED__ +#define __IDiaEnumLineNumbers_FWD_DEFINED__ +typedef interface IDiaEnumLineNumbers IDiaEnumLineNumbers; + +#endif /* __IDiaEnumLineNumbers_FWD_DEFINED__ */ + + +#ifndef __IDiaEnumInjectedSources_FWD_DEFINED__ +#define __IDiaEnumInjectedSources_FWD_DEFINED__ +typedef interface IDiaEnumInjectedSources IDiaEnumInjectedSources; + +#endif /* __IDiaEnumInjectedSources_FWD_DEFINED__ */ + + +#ifndef __IDiaEnumSegments_FWD_DEFINED__ +#define __IDiaEnumSegments_FWD_DEFINED__ +typedef interface IDiaEnumSegments IDiaEnumSegments; + +#endif /* __IDiaEnumSegments_FWD_DEFINED__ */ + + +#ifndef __IDiaEnumSectionContribs_FWD_DEFINED__ +#define __IDiaEnumSectionContribs_FWD_DEFINED__ +typedef interface IDiaEnumSectionContribs IDiaEnumSectionContribs; + +#endif /* __IDiaEnumSectionContribs_FWD_DEFINED__ */ + + +#ifndef __IDiaEnumFrameData_FWD_DEFINED__ +#define __IDiaEnumFrameData_FWD_DEFINED__ +typedef interface IDiaEnumFrameData IDiaEnumFrameData; + +#endif /* __IDiaEnumFrameData_FWD_DEFINED__ */ + + +#ifndef __IDiaEnumDebugStreamData_FWD_DEFINED__ +#define __IDiaEnumDebugStreamData_FWD_DEFINED__ +typedef interface IDiaEnumDebugStreamData IDiaEnumDebugStreamData; + +#endif /* __IDiaEnumDebugStreamData_FWD_DEFINED__ */ + + +#ifndef __IDiaEnumDebugStreams_FWD_DEFINED__ +#define __IDiaEnumDebugStreams_FWD_DEFINED__ +typedef interface IDiaEnumDebugStreams IDiaEnumDebugStreams; + +#endif /* __IDiaEnumDebugStreams_FWD_DEFINED__ */ + + +#ifndef __IDiaAddressMap_FWD_DEFINED__ +#define __IDiaAddressMap_FWD_DEFINED__ +typedef interface IDiaAddressMap IDiaAddressMap; + +#endif /* __IDiaAddressMap_FWD_DEFINED__ */ + + +#ifndef __IDiaSession_FWD_DEFINED__ +#define __IDiaSession_FWD_DEFINED__ +typedef interface IDiaSession IDiaSession; + +#endif /* __IDiaSession_FWD_DEFINED__ */ + + +#ifndef __IDiaSymbol_FWD_DEFINED__ +#define __IDiaSymbol_FWD_DEFINED__ +typedef interface IDiaSymbol IDiaSymbol; + +#endif /* __IDiaSymbol_FWD_DEFINED__ */ + + +#ifndef __IDiaSourceFile_FWD_DEFINED__ +#define __IDiaSourceFile_FWD_DEFINED__ +typedef interface IDiaSourceFile IDiaSourceFile; + +#endif /* __IDiaSourceFile_FWD_DEFINED__ */ + + +#ifndef __IDiaInputAssemblyFile_FWD_DEFINED__ +#define __IDiaInputAssemblyFile_FWD_DEFINED__ +typedef interface IDiaInputAssemblyFile IDiaInputAssemblyFile; + +#endif /* __IDiaInputAssemblyFile_FWD_DEFINED__ */ + + +#ifndef __IDiaLineNumber_FWD_DEFINED__ +#define __IDiaLineNumber_FWD_DEFINED__ +typedef interface IDiaLineNumber IDiaLineNumber; + +#endif /* __IDiaLineNumber_FWD_DEFINED__ */ + + +#ifndef __IDiaSectionContrib_FWD_DEFINED__ +#define __IDiaSectionContrib_FWD_DEFINED__ +typedef interface IDiaSectionContrib IDiaSectionContrib; + +#endif /* __IDiaSectionContrib_FWD_DEFINED__ */ + + +#ifndef __IDiaSegment_FWD_DEFINED__ +#define __IDiaSegment_FWD_DEFINED__ +typedef interface IDiaSegment IDiaSegment; + +#endif /* __IDiaSegment_FWD_DEFINED__ */ + + +#ifndef __IDiaInjectedSource_FWD_DEFINED__ +#define __IDiaInjectedSource_FWD_DEFINED__ +typedef interface IDiaInjectedSource IDiaInjectedSource; + +#endif /* __IDiaInjectedSource_FWD_DEFINED__ */ + + +#ifndef __IDiaStackWalkFrame_FWD_DEFINED__ +#define __IDiaStackWalkFrame_FWD_DEFINED__ +typedef interface IDiaStackWalkFrame IDiaStackWalkFrame; + +#endif /* __IDiaStackWalkFrame_FWD_DEFINED__ */ + + +#ifndef __IDiaFrameData_FWD_DEFINED__ +#define __IDiaFrameData_FWD_DEFINED__ +typedef interface IDiaFrameData IDiaFrameData; + +#endif /* __IDiaFrameData_FWD_DEFINED__ */ + + +#ifndef __IDiaImageData_FWD_DEFINED__ +#define __IDiaImageData_FWD_DEFINED__ +typedef interface IDiaImageData IDiaImageData; + +#endif /* __IDiaImageData_FWD_DEFINED__ */ + + +#ifndef __IDiaTable_FWD_DEFINED__ +#define __IDiaTable_FWD_DEFINED__ +typedef interface IDiaTable IDiaTable; + +#endif /* __IDiaTable_FWD_DEFINED__ */ + + +#ifndef __IDiaEnumTables_FWD_DEFINED__ +#define __IDiaEnumTables_FWD_DEFINED__ +typedef interface IDiaEnumTables IDiaEnumTables; + +#endif /* __IDiaEnumTables_FWD_DEFINED__ */ + + +#ifndef __DiaSource_FWD_DEFINED__ +#define __DiaSource_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class DiaSource DiaSource; +#else +typedef struct DiaSource DiaSource; +#endif /* __cplusplus */ + +#endif /* __DiaSource_FWD_DEFINED__ */ + + +#ifndef __DiaSourceAlt_FWD_DEFINED__ +#define __DiaSourceAlt_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class DiaSourceAlt DiaSourceAlt; +#else +typedef struct DiaSourceAlt DiaSourceAlt; +#endif /* __cplusplus */ + +#endif /* __DiaSourceAlt_FWD_DEFINED__ */ + + +#ifndef __DiaStackWalker_FWD_DEFINED__ +#define __DiaStackWalker_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class DiaStackWalker DiaStackWalker; +#else +typedef struct DiaStackWalker DiaStackWalker; +#endif /* __cplusplus */ + +#endif /* __DiaStackWalker_FWD_DEFINED__ */ + + +#ifndef __IDiaPropertyStorage_FWD_DEFINED__ +#define __IDiaPropertyStorage_FWD_DEFINED__ +typedef interface IDiaPropertyStorage IDiaPropertyStorage; + +#endif /* __IDiaPropertyStorage_FWD_DEFINED__ */ + + +#ifndef __IDiaStackFrame_FWD_DEFINED__ +#define __IDiaStackFrame_FWD_DEFINED__ +typedef interface IDiaStackFrame IDiaStackFrame; + +#endif /* __IDiaStackFrame_FWD_DEFINED__ */ + + +#ifndef __IDiaEnumStackFrames_FWD_DEFINED__ +#define __IDiaEnumStackFrames_FWD_DEFINED__ +typedef interface IDiaEnumStackFrames IDiaEnumStackFrames; + +#endif /* __IDiaEnumStackFrames_FWD_DEFINED__ */ + + +#ifndef __IDiaStackWalkHelper_FWD_DEFINED__ +#define __IDiaStackWalkHelper_FWD_DEFINED__ +typedef interface IDiaStackWalkHelper IDiaStackWalkHelper; + +#endif /* __IDiaStackWalkHelper_FWD_DEFINED__ */ + + +#ifndef __IDiaStackWalker_FWD_DEFINED__ +#define __IDiaStackWalker_FWD_DEFINED__ +typedef interface IDiaStackWalker IDiaStackWalker; + +#endif /* __IDiaStackWalker_FWD_DEFINED__ */ + + +#ifndef __IDiaStackWalkHelper2_FWD_DEFINED__ +#define __IDiaStackWalkHelper2_FWD_DEFINED__ +typedef interface IDiaStackWalkHelper2 IDiaStackWalkHelper2; + +#endif /* __IDiaStackWalkHelper2_FWD_DEFINED__ */ + + +#ifndef __IDiaStackWalker2_FWD_DEFINED__ +#define __IDiaStackWalker2_FWD_DEFINED__ +typedef interface IDiaStackWalker2 IDiaStackWalker2; + +#endif /* __IDiaStackWalker2_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "objidl.h" +#include "oaidl.h" +#include "propidl.h" +#include "cvconst.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_dia2_0000_0000 */ +/* [local] */ + + +enum NameSearchOptions + { + nsNone = 0, + nsfCaseSensitive = 0x1, + nsfCaseInsensitive = 0x2, + nsfFNameExt = 0x4, + nsfRegularExpression = 0x8, + nsfUndecoratedName = 0x10, + nsCaseSensitive = nsfCaseSensitive, + nsCaseInsensitive = nsfCaseInsensitive, + nsFNameExt = ( nsfCaseInsensitive | nsfFNameExt ) , + nsRegularExpression = ( nsfRegularExpression | nsfCaseSensitive ) , + nsCaseInRegularExpression = ( nsfRegularExpression | nsfCaseInsensitive ) + } ; + +enum __MIDL___MIDL_itf_dia2_0000_0000_0001 + { + E_PDB_OK = ( HRESULT )(( ( ( ( unsigned long )1 << 31 ) | ( ( unsigned long )( LONG )0x6d << 16 ) ) | ( unsigned long )1 ) ), + E_PDB_USAGE = ( E_PDB_OK + 1 ) , + E_PDB_OUT_OF_MEMORY = ( E_PDB_USAGE + 1 ) , + E_PDB_FILE_SYSTEM = ( E_PDB_OUT_OF_MEMORY + 1 ) , + E_PDB_NOT_FOUND = ( E_PDB_FILE_SYSTEM + 1 ) , + E_PDB_INVALID_SIG = ( E_PDB_NOT_FOUND + 1 ) , + E_PDB_INVALID_AGE = ( E_PDB_INVALID_SIG + 1 ) , + E_PDB_PRECOMP_REQUIRED = ( E_PDB_INVALID_AGE + 1 ) , + E_PDB_OUT_OF_TI = ( E_PDB_PRECOMP_REQUIRED + 1 ) , + E_PDB_NOT_IMPLEMENTED = ( E_PDB_OUT_OF_TI + 1 ) , + E_PDB_V1_PDB = ( E_PDB_NOT_IMPLEMENTED + 1 ) , + E_PDB_FORMAT = ( E_PDB_V1_PDB + 1 ) , + E_PDB_LIMIT = ( E_PDB_FORMAT + 1 ) , + E_PDB_CORRUPT = ( E_PDB_LIMIT + 1 ) , + E_PDB_TI16 = ( E_PDB_CORRUPT + 1 ) , + E_PDB_ACCESS_DENIED = ( E_PDB_TI16 + 1 ) , + E_PDB_ILLEGAL_TYPE_EDIT = ( E_PDB_ACCESS_DENIED + 1 ) , + E_PDB_INVALID_EXECUTABLE = ( E_PDB_ILLEGAL_TYPE_EDIT + 1 ) , + E_PDB_DBG_NOT_FOUND = ( E_PDB_INVALID_EXECUTABLE + 1 ) , + E_PDB_NO_DEBUG_INFO = ( E_PDB_DBG_NOT_FOUND + 1 ) , + E_PDB_INVALID_EXE_TIMESTAMP = ( E_PDB_NO_DEBUG_INFO + 1 ) , + E_PDB_RESERVED = ( E_PDB_INVALID_EXE_TIMESTAMP + 1 ) , + E_PDB_DEBUG_INFO_NOT_IN_PDB = ( E_PDB_RESERVED + 1 ) , + E_PDB_SYMSRV_BAD_CACHE_PATH = ( E_PDB_DEBUG_INFO_NOT_IN_PDB + 1 ) , + E_PDB_SYMSRV_CACHE_FULL = ( E_PDB_SYMSRV_BAD_CACHE_PATH + 1 ) , + E_PDB_OBJECT_DISPOSED = ( E_PDB_SYMSRV_CACHE_FULL + 1 ) , + E_PDB_MAX = ( E_PDB_OBJECT_DISPOSED + 1 ) + } ; +typedef void ( __cdecl *PfnPDBDebugDirV )( + BOOL __MIDL____MIDL_itf_dia2_0000_00000000, + void *__MIDL____MIDL_itf_dia2_0000_00000001); + + + + + + + + + + + + + + + + + + + + +extern RPC_IF_HANDLE __MIDL_itf_dia2_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_dia2_0000_0000_v0_0_s_ifspec; + +#ifndef __IDiaLoadCallback_INTERFACE_DEFINED__ +#define __IDiaLoadCallback_INTERFACE_DEFINED__ + +/* interface IDiaLoadCallback */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaLoadCallback; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("C32ADB82-73F4-421b-95D5-A4706EDF5DBE") + IDiaLoadCallback : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE NotifyDebugDir( + /* [in] */ BOOL fExecutable, + /* [in] */ DWORD cbData, + /* [size_is][in] */ BYTE *pbData) = 0; + + virtual HRESULT STDMETHODCALLTYPE NotifyOpenDBG( + /* [in] */ LPCOLESTR dbgPath, + /* [in] */ HRESULT resultCode) = 0; + + virtual HRESULT STDMETHODCALLTYPE NotifyOpenPDB( + /* [in] */ LPCOLESTR pdbPath, + /* [in] */ HRESULT resultCode) = 0; + + virtual HRESULT STDMETHODCALLTYPE RestrictRegistryAccess( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE RestrictSymbolServerAccess( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaLoadCallbackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaLoadCallback * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaLoadCallback * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaLoadCallback * This); + + HRESULT ( STDMETHODCALLTYPE *NotifyDebugDir )( + IDiaLoadCallback * This, + /* [in] */ BOOL fExecutable, + /* [in] */ DWORD cbData, + /* [size_is][in] */ BYTE *pbData); + + HRESULT ( STDMETHODCALLTYPE *NotifyOpenDBG )( + IDiaLoadCallback * This, + /* [in] */ LPCOLESTR dbgPath, + /* [in] */ HRESULT resultCode); + + HRESULT ( STDMETHODCALLTYPE *NotifyOpenPDB )( + IDiaLoadCallback * This, + /* [in] */ LPCOLESTR pdbPath, + /* [in] */ HRESULT resultCode); + + HRESULT ( STDMETHODCALLTYPE *RestrictRegistryAccess )( + IDiaLoadCallback * This); + + HRESULT ( STDMETHODCALLTYPE *RestrictSymbolServerAccess )( + IDiaLoadCallback * This); + + END_INTERFACE + } IDiaLoadCallbackVtbl; + + interface IDiaLoadCallback + { + CONST_VTBL struct IDiaLoadCallbackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaLoadCallback_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaLoadCallback_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaLoadCallback_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaLoadCallback_NotifyDebugDir(This,fExecutable,cbData,pbData) \ + ( (This)->lpVtbl -> NotifyDebugDir(This,fExecutable,cbData,pbData) ) + +#define IDiaLoadCallback_NotifyOpenDBG(This,dbgPath,resultCode) \ + ( (This)->lpVtbl -> NotifyOpenDBG(This,dbgPath,resultCode) ) + +#define IDiaLoadCallback_NotifyOpenPDB(This,pdbPath,resultCode) \ + ( (This)->lpVtbl -> NotifyOpenPDB(This,pdbPath,resultCode) ) + +#define IDiaLoadCallback_RestrictRegistryAccess(This) \ + ( (This)->lpVtbl -> RestrictRegistryAccess(This) ) + +#define IDiaLoadCallback_RestrictSymbolServerAccess(This) \ + ( (This)->lpVtbl -> RestrictSymbolServerAccess(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaLoadCallback_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaLoadCallback2_INTERFACE_DEFINED__ +#define __IDiaLoadCallback2_INTERFACE_DEFINED__ + +/* interface IDiaLoadCallback2 */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaLoadCallback2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("4688a074-5a4d-4486-aea8-7b90711d9f7c") + IDiaLoadCallback2 : public IDiaLoadCallback + { + public: + virtual HRESULT STDMETHODCALLTYPE RestrictOriginalPathAccess( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE RestrictReferencePathAccess( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE RestrictDBGAccess( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE RestrictSystemRootAccess( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaLoadCallback2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaLoadCallback2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaLoadCallback2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaLoadCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *NotifyDebugDir )( + IDiaLoadCallback2 * This, + /* [in] */ BOOL fExecutable, + /* [in] */ DWORD cbData, + /* [size_is][in] */ BYTE *pbData); + + HRESULT ( STDMETHODCALLTYPE *NotifyOpenDBG )( + IDiaLoadCallback2 * This, + /* [in] */ LPCOLESTR dbgPath, + /* [in] */ HRESULT resultCode); + + HRESULT ( STDMETHODCALLTYPE *NotifyOpenPDB )( + IDiaLoadCallback2 * This, + /* [in] */ LPCOLESTR pdbPath, + /* [in] */ HRESULT resultCode); + + HRESULT ( STDMETHODCALLTYPE *RestrictRegistryAccess )( + IDiaLoadCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *RestrictSymbolServerAccess )( + IDiaLoadCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *RestrictOriginalPathAccess )( + IDiaLoadCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *RestrictReferencePathAccess )( + IDiaLoadCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *RestrictDBGAccess )( + IDiaLoadCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *RestrictSystemRootAccess )( + IDiaLoadCallback2 * This); + + END_INTERFACE + } IDiaLoadCallback2Vtbl; + + interface IDiaLoadCallback2 + { + CONST_VTBL struct IDiaLoadCallback2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaLoadCallback2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaLoadCallback2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaLoadCallback2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaLoadCallback2_NotifyDebugDir(This,fExecutable,cbData,pbData) \ + ( (This)->lpVtbl -> NotifyDebugDir(This,fExecutable,cbData,pbData) ) + +#define IDiaLoadCallback2_NotifyOpenDBG(This,dbgPath,resultCode) \ + ( (This)->lpVtbl -> NotifyOpenDBG(This,dbgPath,resultCode) ) + +#define IDiaLoadCallback2_NotifyOpenPDB(This,pdbPath,resultCode) \ + ( (This)->lpVtbl -> NotifyOpenPDB(This,pdbPath,resultCode) ) + +#define IDiaLoadCallback2_RestrictRegistryAccess(This) \ + ( (This)->lpVtbl -> RestrictRegistryAccess(This) ) + +#define IDiaLoadCallback2_RestrictSymbolServerAccess(This) \ + ( (This)->lpVtbl -> RestrictSymbolServerAccess(This) ) + + +#define IDiaLoadCallback2_RestrictOriginalPathAccess(This) \ + ( (This)->lpVtbl -> RestrictOriginalPathAccess(This) ) + +#define IDiaLoadCallback2_RestrictReferencePathAccess(This) \ + ( (This)->lpVtbl -> RestrictReferencePathAccess(This) ) + +#define IDiaLoadCallback2_RestrictDBGAccess(This) \ + ( (This)->lpVtbl -> RestrictDBGAccess(This) ) + +#define IDiaLoadCallback2_RestrictSystemRootAccess(This) \ + ( (This)->lpVtbl -> RestrictSystemRootAccess(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaLoadCallback2_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaReadExeAtOffsetCallback_INTERFACE_DEFINED__ +#define __IDiaReadExeAtOffsetCallback_INTERFACE_DEFINED__ + +/* interface IDiaReadExeAtOffsetCallback */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaReadExeAtOffsetCallback; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("587A461C-B80B-4f54-9194-5032589A6319") + IDiaReadExeAtOffsetCallback : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE ReadExecutableAt( + /* [in] */ DWORDLONG fileOffset, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaReadExeAtOffsetCallbackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaReadExeAtOffsetCallback * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaReadExeAtOffsetCallback * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaReadExeAtOffsetCallback * This); + + HRESULT ( STDMETHODCALLTYPE *ReadExecutableAt )( + IDiaReadExeAtOffsetCallback * This, + /* [in] */ DWORDLONG fileOffset, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData); + + END_INTERFACE + } IDiaReadExeAtOffsetCallbackVtbl; + + interface IDiaReadExeAtOffsetCallback + { + CONST_VTBL struct IDiaReadExeAtOffsetCallbackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaReadExeAtOffsetCallback_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaReadExeAtOffsetCallback_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaReadExeAtOffsetCallback_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaReadExeAtOffsetCallback_ReadExecutableAt(This,fileOffset,cbData,pcbData,pbData) \ + ( (This)->lpVtbl -> ReadExecutableAt(This,fileOffset,cbData,pcbData,pbData) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaReadExeAtOffsetCallback_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaReadExeAtRVACallback_INTERFACE_DEFINED__ +#define __IDiaReadExeAtRVACallback_INTERFACE_DEFINED__ + +/* interface IDiaReadExeAtRVACallback */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaReadExeAtRVACallback; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("8E3F80CA-7517-432a-BA07-285134AAEA8E") + IDiaReadExeAtRVACallback : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE ReadExecutableAtRVA( + /* [in] */ DWORD relativeVirtualAddress, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaReadExeAtRVACallbackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaReadExeAtRVACallback * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaReadExeAtRVACallback * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaReadExeAtRVACallback * This); + + HRESULT ( STDMETHODCALLTYPE *ReadExecutableAtRVA )( + IDiaReadExeAtRVACallback * This, + /* [in] */ DWORD relativeVirtualAddress, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData); + + END_INTERFACE + } IDiaReadExeAtRVACallbackVtbl; + + interface IDiaReadExeAtRVACallback + { + CONST_VTBL struct IDiaReadExeAtRVACallbackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaReadExeAtRVACallback_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaReadExeAtRVACallback_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaReadExeAtRVACallback_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaReadExeAtRVACallback_ReadExecutableAtRVA(This,relativeVirtualAddress,cbData,pcbData,pbData) \ + ( (This)->lpVtbl -> ReadExecutableAtRVA(This,relativeVirtualAddress,cbData,pcbData,pbData) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaReadExeAtRVACallback_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaDataSource_INTERFACE_DEFINED__ +#define __IDiaDataSource_INTERFACE_DEFINED__ + +/* interface IDiaDataSource */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaDataSource; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("79F1BB5F-B66E-48e5-B6A9-1545C323CA3D") + IDiaDataSource : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_lastError( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE loadDataFromPdb( + /* [in] */ LPCOLESTR pdbPath) = 0; + + virtual HRESULT STDMETHODCALLTYPE loadAndValidateDataFromPdb( + /* [in] */ LPCOLESTR pdbPath, + /* [in] */ GUID *pcsig70, + /* [in] */ DWORD sig, + /* [in] */ DWORD age) = 0; + + virtual HRESULT STDMETHODCALLTYPE loadDataForExe( + /* [in] */ LPCOLESTR executable, + /* [in] */ LPCOLESTR searchPath, + /* [in] */ IUnknown *pCallback) = 0; + + virtual HRESULT STDMETHODCALLTYPE loadDataFromIStream( + /* [in] */ IStream *pIStream) = 0; + + virtual HRESULT STDMETHODCALLTYPE openSession( + /* [out] */ IDiaSession **ppSession) = 0; + + virtual HRESULT STDMETHODCALLTYPE loadDataFromCodeViewInfo( + /* [in] */ LPCOLESTR executable, + /* [in] */ LPCOLESTR searchPath, + /* [in] */ DWORD cbCvInfo, + /* [size_is][in] */ BYTE *pbCvInfo, + /* [in] */ IUnknown *pCallback) = 0; + + virtual HRESULT STDMETHODCALLTYPE loadDataFromMiscInfo( + /* [in] */ LPCOLESTR executable, + /* [in] */ LPCOLESTR searchPath, + /* [in] */ DWORD timeStampExe, + /* [in] */ DWORD timeStampDbg, + /* [in] */ DWORD sizeOfExe, + /* [in] */ DWORD cbMiscInfo, + /* [size_is][in] */ BYTE *pbMiscInfo, + /* [in] */ IUnknown *pCallback) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaDataSourceVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaDataSource * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaDataSource * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaDataSource * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_lastError )( + IDiaDataSource * This, + /* [retval][out] */ BSTR *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *loadDataFromPdb )( + IDiaDataSource * This, + /* [in] */ LPCOLESTR pdbPath); + + HRESULT ( STDMETHODCALLTYPE *loadAndValidateDataFromPdb )( + IDiaDataSource * This, + /* [in] */ LPCOLESTR pdbPath, + /* [in] */ GUID *pcsig70, + /* [in] */ DWORD sig, + /* [in] */ DWORD age); + + HRESULT ( STDMETHODCALLTYPE *loadDataForExe )( + IDiaDataSource * This, + /* [in] */ LPCOLESTR executable, + /* [in] */ LPCOLESTR searchPath, + /* [in] */ IUnknown *pCallback); + + HRESULT ( STDMETHODCALLTYPE *loadDataFromIStream )( + IDiaDataSource * This, + /* [in] */ IStream *pIStream); + + HRESULT ( STDMETHODCALLTYPE *openSession )( + IDiaDataSource * This, + /* [out] */ IDiaSession **ppSession); + + HRESULT ( STDMETHODCALLTYPE *loadDataFromCodeViewInfo )( + IDiaDataSource * This, + /* [in] */ LPCOLESTR executable, + /* [in] */ LPCOLESTR searchPath, + /* [in] */ DWORD cbCvInfo, + /* [size_is][in] */ BYTE *pbCvInfo, + /* [in] */ IUnknown *pCallback); + + HRESULT ( STDMETHODCALLTYPE *loadDataFromMiscInfo )( + IDiaDataSource * This, + /* [in] */ LPCOLESTR executable, + /* [in] */ LPCOLESTR searchPath, + /* [in] */ DWORD timeStampExe, + /* [in] */ DWORD timeStampDbg, + /* [in] */ DWORD sizeOfExe, + /* [in] */ DWORD cbMiscInfo, + /* [size_is][in] */ BYTE *pbMiscInfo, + /* [in] */ IUnknown *pCallback); + + END_INTERFACE + } IDiaDataSourceVtbl; + + interface IDiaDataSource + { + CONST_VTBL struct IDiaDataSourceVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaDataSource_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaDataSource_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaDataSource_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaDataSource_get_lastError(This,pRetVal) \ + ( (This)->lpVtbl -> get_lastError(This,pRetVal) ) + +#define IDiaDataSource_loadDataFromPdb(This,pdbPath) \ + ( (This)->lpVtbl -> loadDataFromPdb(This,pdbPath) ) + +#define IDiaDataSource_loadAndValidateDataFromPdb(This,pdbPath,pcsig70,sig,age) \ + ( (This)->lpVtbl -> loadAndValidateDataFromPdb(This,pdbPath,pcsig70,sig,age) ) + +#define IDiaDataSource_loadDataForExe(This,executable,searchPath,pCallback) \ + ( (This)->lpVtbl -> loadDataForExe(This,executable,searchPath,pCallback) ) + +#define IDiaDataSource_loadDataFromIStream(This,pIStream) \ + ( (This)->lpVtbl -> loadDataFromIStream(This,pIStream) ) + +#define IDiaDataSource_openSession(This,ppSession) \ + ( (This)->lpVtbl -> openSession(This,ppSession) ) + +#define IDiaDataSource_loadDataFromCodeViewInfo(This,executable,searchPath,cbCvInfo,pbCvInfo,pCallback) \ + ( (This)->lpVtbl -> loadDataFromCodeViewInfo(This,executable,searchPath,cbCvInfo,pbCvInfo,pCallback) ) + +#define IDiaDataSource_loadDataFromMiscInfo(This,executable,searchPath,timeStampExe,timeStampDbg,sizeOfExe,cbMiscInfo,pbMiscInfo,pCallback) \ + ( (This)->lpVtbl -> loadDataFromMiscInfo(This,executable,searchPath,timeStampExe,timeStampDbg,sizeOfExe,cbMiscInfo,pbMiscInfo,pCallback) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaDataSource_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaEnumSymbols_INTERFACE_DEFINED__ +#define __IDiaEnumSymbols_INTERFACE_DEFINED__ + +/* interface IDiaEnumSymbols */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaEnumSymbols; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CAB72C48-443B-48f5-9B0B-42F0820AB29A") + IDiaEnumSymbols : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ LONG *pRetVal) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Item( + /* [in] */ DWORD index, + /* [retval][out] */ IDiaSymbol **symbol) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [out] */ IDiaSymbol **rgelt, + /* [out] */ ULONG *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ IDiaEnumSymbols **ppenum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaEnumSymbolsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaEnumSymbols * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaEnumSymbols * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaEnumSymbols * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IDiaEnumSymbols * This, + /* [retval][out] */ IUnknown **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IDiaEnumSymbols * This, + /* [retval][out] */ LONG *pRetVal); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Item )( + IDiaEnumSymbols * This, + /* [in] */ DWORD index, + /* [retval][out] */ IDiaSymbol **symbol); + + HRESULT ( STDMETHODCALLTYPE *Next )( + IDiaEnumSymbols * This, + /* [in] */ ULONG celt, + /* [out] */ IDiaSymbol **rgelt, + /* [out] */ ULONG *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + IDiaEnumSymbols * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + IDiaEnumSymbols * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + IDiaEnumSymbols * This, + /* [out] */ IDiaEnumSymbols **ppenum); + + END_INTERFACE + } IDiaEnumSymbolsVtbl; + + interface IDiaEnumSymbols + { + CONST_VTBL struct IDiaEnumSymbolsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaEnumSymbols_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaEnumSymbols_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaEnumSymbols_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaEnumSymbols_get__NewEnum(This,pRetVal) \ + ( (This)->lpVtbl -> get__NewEnum(This,pRetVal) ) + +#define IDiaEnumSymbols_get_Count(This,pRetVal) \ + ( (This)->lpVtbl -> get_Count(This,pRetVal) ) + +#define IDiaEnumSymbols_Item(This,index,symbol) \ + ( (This)->lpVtbl -> Item(This,index,symbol) ) + +#define IDiaEnumSymbols_Next(This,celt,rgelt,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched) ) + +#define IDiaEnumSymbols_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define IDiaEnumSymbols_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define IDiaEnumSymbols_Clone(This,ppenum) \ + ( (This)->lpVtbl -> Clone(This,ppenum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaEnumSymbols_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaEnumSymbolsByAddr_INTERFACE_DEFINED__ +#define __IDiaEnumSymbolsByAddr_INTERFACE_DEFINED__ + +/* interface IDiaEnumSymbolsByAddr */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaEnumSymbolsByAddr; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("624B7D9C-24EA-4421-9D06-3B577471C1FA") + IDiaEnumSymbolsByAddr : public IUnknown + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE symbolByAddr( + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [retval][out] */ IDiaSymbol **ppSymbol) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE symbolByRVA( + /* [in] */ DWORD relativeVirtualAddress, + /* [retval][out] */ IDiaSymbol **ppSymbol) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE symbolByVA( + /* [in] */ ULONGLONG virtualAddress, + /* [retval][out] */ IDiaSymbol **ppSymbol) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [out] */ IDiaSymbol **rgelt, + /* [out] */ ULONG *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE Prev( + /* [in] */ ULONG celt, + /* [out] */ IDiaSymbol **rgelt, + /* [out] */ ULONG *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ IDiaEnumSymbolsByAddr **ppenum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaEnumSymbolsByAddrVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaEnumSymbolsByAddr * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaEnumSymbolsByAddr * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaEnumSymbolsByAddr * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *symbolByAddr )( + IDiaEnumSymbolsByAddr * This, + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [retval][out] */ IDiaSymbol **ppSymbol); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *symbolByRVA )( + IDiaEnumSymbolsByAddr * This, + /* [in] */ DWORD relativeVirtualAddress, + /* [retval][out] */ IDiaSymbol **ppSymbol); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *symbolByVA )( + IDiaEnumSymbolsByAddr * This, + /* [in] */ ULONGLONG virtualAddress, + /* [retval][out] */ IDiaSymbol **ppSymbol); + + HRESULT ( STDMETHODCALLTYPE *Next )( + IDiaEnumSymbolsByAddr * This, + /* [in] */ ULONG celt, + /* [out] */ IDiaSymbol **rgelt, + /* [out] */ ULONG *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE *Prev )( + IDiaEnumSymbolsByAddr * This, + /* [in] */ ULONG celt, + /* [out] */ IDiaSymbol **rgelt, + /* [out] */ ULONG *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + IDiaEnumSymbolsByAddr * This, + /* [out] */ IDiaEnumSymbolsByAddr **ppenum); + + END_INTERFACE + } IDiaEnumSymbolsByAddrVtbl; + + interface IDiaEnumSymbolsByAddr + { + CONST_VTBL struct IDiaEnumSymbolsByAddrVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaEnumSymbolsByAddr_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaEnumSymbolsByAddr_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaEnumSymbolsByAddr_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaEnumSymbolsByAddr_symbolByAddr(This,isect,offset,ppSymbol) \ + ( (This)->lpVtbl -> symbolByAddr(This,isect,offset,ppSymbol) ) + +#define IDiaEnumSymbolsByAddr_symbolByRVA(This,relativeVirtualAddress,ppSymbol) \ + ( (This)->lpVtbl -> symbolByRVA(This,relativeVirtualAddress,ppSymbol) ) + +#define IDiaEnumSymbolsByAddr_symbolByVA(This,virtualAddress,ppSymbol) \ + ( (This)->lpVtbl -> symbolByVA(This,virtualAddress,ppSymbol) ) + +#define IDiaEnumSymbolsByAddr_Next(This,celt,rgelt,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched) ) + +#define IDiaEnumSymbolsByAddr_Prev(This,celt,rgelt,pceltFetched) \ + ( (This)->lpVtbl -> Prev(This,celt,rgelt,pceltFetched) ) + +#define IDiaEnumSymbolsByAddr_Clone(This,ppenum) \ + ( (This)->lpVtbl -> Clone(This,ppenum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaEnumSymbolsByAddr_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaEnumSourceFiles_INTERFACE_DEFINED__ +#define __IDiaEnumSourceFiles_INTERFACE_DEFINED__ + +/* interface IDiaEnumSourceFiles */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaEnumSourceFiles; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("10F3DBD9-664F-4469-B808-9471C7A50538") + IDiaEnumSourceFiles : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ LONG *pRetVal) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Item( + /* [in] */ DWORD index, + /* [retval][out] */ IDiaSourceFile **sourceFile) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [out] */ IDiaSourceFile **rgelt, + /* [out] */ ULONG *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ IDiaEnumSourceFiles **ppenum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaEnumSourceFilesVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaEnumSourceFiles * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaEnumSourceFiles * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaEnumSourceFiles * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IDiaEnumSourceFiles * This, + /* [retval][out] */ IUnknown **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IDiaEnumSourceFiles * This, + /* [retval][out] */ LONG *pRetVal); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Item )( + IDiaEnumSourceFiles * This, + /* [in] */ DWORD index, + /* [retval][out] */ IDiaSourceFile **sourceFile); + + HRESULT ( STDMETHODCALLTYPE *Next )( + IDiaEnumSourceFiles * This, + /* [in] */ ULONG celt, + /* [out] */ IDiaSourceFile **rgelt, + /* [out] */ ULONG *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + IDiaEnumSourceFiles * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + IDiaEnumSourceFiles * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + IDiaEnumSourceFiles * This, + /* [out] */ IDiaEnumSourceFiles **ppenum); + + END_INTERFACE + } IDiaEnumSourceFilesVtbl; + + interface IDiaEnumSourceFiles + { + CONST_VTBL struct IDiaEnumSourceFilesVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaEnumSourceFiles_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaEnumSourceFiles_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaEnumSourceFiles_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaEnumSourceFiles_get__NewEnum(This,pRetVal) \ + ( (This)->lpVtbl -> get__NewEnum(This,pRetVal) ) + +#define IDiaEnumSourceFiles_get_Count(This,pRetVal) \ + ( (This)->lpVtbl -> get_Count(This,pRetVal) ) + +#define IDiaEnumSourceFiles_Item(This,index,sourceFile) \ + ( (This)->lpVtbl -> Item(This,index,sourceFile) ) + +#define IDiaEnumSourceFiles_Next(This,celt,rgelt,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched) ) + +#define IDiaEnumSourceFiles_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define IDiaEnumSourceFiles_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define IDiaEnumSourceFiles_Clone(This,ppenum) \ + ( (This)->lpVtbl -> Clone(This,ppenum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaEnumSourceFiles_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaEnumInputAssemblyFiles_INTERFACE_DEFINED__ +#define __IDiaEnumInputAssemblyFiles_INTERFACE_DEFINED__ + +/* interface IDiaEnumInputAssemblyFiles */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaEnumInputAssemblyFiles; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("1C7FF653-51F7-457E-8419-B20F57EF7E4D") + IDiaEnumInputAssemblyFiles : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ LONG *pRetVal) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Item( + /* [in] */ DWORD index, + /* [retval][out] */ IDiaInputAssemblyFile **file) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [out] */ IDiaInputAssemblyFile **rgelt, + /* [out] */ ULONG *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ IDiaEnumInputAssemblyFiles **ppenum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaEnumInputAssemblyFilesVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaEnumInputAssemblyFiles * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaEnumInputAssemblyFiles * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaEnumInputAssemblyFiles * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IDiaEnumInputAssemblyFiles * This, + /* [retval][out] */ IUnknown **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IDiaEnumInputAssemblyFiles * This, + /* [retval][out] */ LONG *pRetVal); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Item )( + IDiaEnumInputAssemblyFiles * This, + /* [in] */ DWORD index, + /* [retval][out] */ IDiaInputAssemblyFile **file); + + HRESULT ( STDMETHODCALLTYPE *Next )( + IDiaEnumInputAssemblyFiles * This, + /* [in] */ ULONG celt, + /* [out] */ IDiaInputAssemblyFile **rgelt, + /* [out] */ ULONG *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + IDiaEnumInputAssemblyFiles * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + IDiaEnumInputAssemblyFiles * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + IDiaEnumInputAssemblyFiles * This, + /* [out] */ IDiaEnumInputAssemblyFiles **ppenum); + + END_INTERFACE + } IDiaEnumInputAssemblyFilesVtbl; + + interface IDiaEnumInputAssemblyFiles + { + CONST_VTBL struct IDiaEnumInputAssemblyFilesVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaEnumInputAssemblyFiles_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaEnumInputAssemblyFiles_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaEnumInputAssemblyFiles_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaEnumInputAssemblyFiles_get__NewEnum(This,pRetVal) \ + ( (This)->lpVtbl -> get__NewEnum(This,pRetVal) ) + +#define IDiaEnumInputAssemblyFiles_get_Count(This,pRetVal) \ + ( (This)->lpVtbl -> get_Count(This,pRetVal) ) + +#define IDiaEnumInputAssemblyFiles_Item(This,index,file) \ + ( (This)->lpVtbl -> Item(This,index,file) ) + +#define IDiaEnumInputAssemblyFiles_Next(This,celt,rgelt,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched) ) + +#define IDiaEnumInputAssemblyFiles_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define IDiaEnumInputAssemblyFiles_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define IDiaEnumInputAssemblyFiles_Clone(This,ppenum) \ + ( (This)->lpVtbl -> Clone(This,ppenum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaEnumInputAssemblyFiles_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaEnumLineNumbers_INTERFACE_DEFINED__ +#define __IDiaEnumLineNumbers_INTERFACE_DEFINED__ + +/* interface IDiaEnumLineNumbers */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaEnumLineNumbers; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("FE30E878-54AC-44f1-81BA-39DE940F6052") + IDiaEnumLineNumbers : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ LONG *pRetVal) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Item( + /* [in] */ DWORD index, + /* [retval][out] */ IDiaLineNumber **lineNumber) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [out] */ IDiaLineNumber **rgelt, + /* [out] */ ULONG *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ IDiaEnumLineNumbers **ppenum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaEnumLineNumbersVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaEnumLineNumbers * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaEnumLineNumbers * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaEnumLineNumbers * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IDiaEnumLineNumbers * This, + /* [retval][out] */ IUnknown **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IDiaEnumLineNumbers * This, + /* [retval][out] */ LONG *pRetVal); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Item )( + IDiaEnumLineNumbers * This, + /* [in] */ DWORD index, + /* [retval][out] */ IDiaLineNumber **lineNumber); + + HRESULT ( STDMETHODCALLTYPE *Next )( + IDiaEnumLineNumbers * This, + /* [in] */ ULONG celt, + /* [out] */ IDiaLineNumber **rgelt, + /* [out] */ ULONG *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + IDiaEnumLineNumbers * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + IDiaEnumLineNumbers * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + IDiaEnumLineNumbers * This, + /* [out] */ IDiaEnumLineNumbers **ppenum); + + END_INTERFACE + } IDiaEnumLineNumbersVtbl; + + interface IDiaEnumLineNumbers + { + CONST_VTBL struct IDiaEnumLineNumbersVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaEnumLineNumbers_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaEnumLineNumbers_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaEnumLineNumbers_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaEnumLineNumbers_get__NewEnum(This,pRetVal) \ + ( (This)->lpVtbl -> get__NewEnum(This,pRetVal) ) + +#define IDiaEnumLineNumbers_get_Count(This,pRetVal) \ + ( (This)->lpVtbl -> get_Count(This,pRetVal) ) + +#define IDiaEnumLineNumbers_Item(This,index,lineNumber) \ + ( (This)->lpVtbl -> Item(This,index,lineNumber) ) + +#define IDiaEnumLineNumbers_Next(This,celt,rgelt,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched) ) + +#define IDiaEnumLineNumbers_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define IDiaEnumLineNumbers_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define IDiaEnumLineNumbers_Clone(This,ppenum) \ + ( (This)->lpVtbl -> Clone(This,ppenum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaEnumLineNumbers_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaEnumInjectedSources_INTERFACE_DEFINED__ +#define __IDiaEnumInjectedSources_INTERFACE_DEFINED__ + +/* interface IDiaEnumInjectedSources */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaEnumInjectedSources; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("D5612573-6925-4468-8883-98CDEC8C384A") + IDiaEnumInjectedSources : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ LONG *pRetVal) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Item( + /* [in] */ DWORD index, + /* [retval][out] */ IDiaInjectedSource **injectedSource) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [out] */ IDiaInjectedSource **rgelt, + /* [out] */ ULONG *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ IDiaEnumInjectedSources **ppenum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaEnumInjectedSourcesVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaEnumInjectedSources * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaEnumInjectedSources * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaEnumInjectedSources * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IDiaEnumInjectedSources * This, + /* [retval][out] */ IUnknown **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IDiaEnumInjectedSources * This, + /* [retval][out] */ LONG *pRetVal); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Item )( + IDiaEnumInjectedSources * This, + /* [in] */ DWORD index, + /* [retval][out] */ IDiaInjectedSource **injectedSource); + + HRESULT ( STDMETHODCALLTYPE *Next )( + IDiaEnumInjectedSources * This, + /* [in] */ ULONG celt, + /* [out] */ IDiaInjectedSource **rgelt, + /* [out] */ ULONG *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + IDiaEnumInjectedSources * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + IDiaEnumInjectedSources * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + IDiaEnumInjectedSources * This, + /* [out] */ IDiaEnumInjectedSources **ppenum); + + END_INTERFACE + } IDiaEnumInjectedSourcesVtbl; + + interface IDiaEnumInjectedSources + { + CONST_VTBL struct IDiaEnumInjectedSourcesVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaEnumInjectedSources_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaEnumInjectedSources_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaEnumInjectedSources_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaEnumInjectedSources_get__NewEnum(This,pRetVal) \ + ( (This)->lpVtbl -> get__NewEnum(This,pRetVal) ) + +#define IDiaEnumInjectedSources_get_Count(This,pRetVal) \ + ( (This)->lpVtbl -> get_Count(This,pRetVal) ) + +#define IDiaEnumInjectedSources_Item(This,index,injectedSource) \ + ( (This)->lpVtbl -> Item(This,index,injectedSource) ) + +#define IDiaEnumInjectedSources_Next(This,celt,rgelt,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched) ) + +#define IDiaEnumInjectedSources_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define IDiaEnumInjectedSources_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define IDiaEnumInjectedSources_Clone(This,ppenum) \ + ( (This)->lpVtbl -> Clone(This,ppenum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaEnumInjectedSources_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaEnumSegments_INTERFACE_DEFINED__ +#define __IDiaEnumSegments_INTERFACE_DEFINED__ + +/* interface IDiaEnumSegments */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaEnumSegments; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("E8368CA9-01D1-419d-AC0C-E31235DBDA9F") + IDiaEnumSegments : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ LONG *pRetVal) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Item( + /* [in] */ DWORD index, + /* [retval][out] */ IDiaSegment **segment) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [out] */ IDiaSegment **rgelt, + /* [out] */ ULONG *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ IDiaEnumSegments **ppenum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaEnumSegmentsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaEnumSegments * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaEnumSegments * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaEnumSegments * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IDiaEnumSegments * This, + /* [retval][out] */ IUnknown **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IDiaEnumSegments * This, + /* [retval][out] */ LONG *pRetVal); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Item )( + IDiaEnumSegments * This, + /* [in] */ DWORD index, + /* [retval][out] */ IDiaSegment **segment); + + HRESULT ( STDMETHODCALLTYPE *Next )( + IDiaEnumSegments * This, + /* [in] */ ULONG celt, + /* [out] */ IDiaSegment **rgelt, + /* [out] */ ULONG *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + IDiaEnumSegments * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + IDiaEnumSegments * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + IDiaEnumSegments * This, + /* [out] */ IDiaEnumSegments **ppenum); + + END_INTERFACE + } IDiaEnumSegmentsVtbl; + + interface IDiaEnumSegments + { + CONST_VTBL struct IDiaEnumSegmentsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaEnumSegments_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaEnumSegments_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaEnumSegments_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaEnumSegments_get__NewEnum(This,pRetVal) \ + ( (This)->lpVtbl -> get__NewEnum(This,pRetVal) ) + +#define IDiaEnumSegments_get_Count(This,pRetVal) \ + ( (This)->lpVtbl -> get_Count(This,pRetVal) ) + +#define IDiaEnumSegments_Item(This,index,segment) \ + ( (This)->lpVtbl -> Item(This,index,segment) ) + +#define IDiaEnumSegments_Next(This,celt,rgelt,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched) ) + +#define IDiaEnumSegments_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define IDiaEnumSegments_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define IDiaEnumSegments_Clone(This,ppenum) \ + ( (This)->lpVtbl -> Clone(This,ppenum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaEnumSegments_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaEnumSectionContribs_INTERFACE_DEFINED__ +#define __IDiaEnumSectionContribs_INTERFACE_DEFINED__ + +/* interface IDiaEnumSectionContribs */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaEnumSectionContribs; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("1994DEB2-2C82-4b1d-A57F-AFF424D54A68") + IDiaEnumSectionContribs : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ LONG *pRetVal) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Item( + /* [in] */ DWORD index, + /* [retval][out] */ IDiaSectionContrib **section) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [out] */ IDiaSectionContrib **rgelt, + /* [out] */ ULONG *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ IDiaEnumSectionContribs **ppenum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaEnumSectionContribsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaEnumSectionContribs * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaEnumSectionContribs * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaEnumSectionContribs * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IDiaEnumSectionContribs * This, + /* [retval][out] */ IUnknown **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IDiaEnumSectionContribs * This, + /* [retval][out] */ LONG *pRetVal); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Item )( + IDiaEnumSectionContribs * This, + /* [in] */ DWORD index, + /* [retval][out] */ IDiaSectionContrib **section); + + HRESULT ( STDMETHODCALLTYPE *Next )( + IDiaEnumSectionContribs * This, + /* [in] */ ULONG celt, + /* [out] */ IDiaSectionContrib **rgelt, + /* [out] */ ULONG *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + IDiaEnumSectionContribs * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + IDiaEnumSectionContribs * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + IDiaEnumSectionContribs * This, + /* [out] */ IDiaEnumSectionContribs **ppenum); + + END_INTERFACE + } IDiaEnumSectionContribsVtbl; + + interface IDiaEnumSectionContribs + { + CONST_VTBL struct IDiaEnumSectionContribsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaEnumSectionContribs_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaEnumSectionContribs_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaEnumSectionContribs_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaEnumSectionContribs_get__NewEnum(This,pRetVal) \ + ( (This)->lpVtbl -> get__NewEnum(This,pRetVal) ) + +#define IDiaEnumSectionContribs_get_Count(This,pRetVal) \ + ( (This)->lpVtbl -> get_Count(This,pRetVal) ) + +#define IDiaEnumSectionContribs_Item(This,index,section) \ + ( (This)->lpVtbl -> Item(This,index,section) ) + +#define IDiaEnumSectionContribs_Next(This,celt,rgelt,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched) ) + +#define IDiaEnumSectionContribs_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define IDiaEnumSectionContribs_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define IDiaEnumSectionContribs_Clone(This,ppenum) \ + ( (This)->lpVtbl -> Clone(This,ppenum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaEnumSectionContribs_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaEnumFrameData_INTERFACE_DEFINED__ +#define __IDiaEnumFrameData_INTERFACE_DEFINED__ + +/* interface IDiaEnumFrameData */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaEnumFrameData; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9FC77A4B-3C1C-44ed-A798-6C1DEEA53E1F") + IDiaEnumFrameData : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ LONG *pRetVal) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Item( + /* [in] */ DWORD index, + /* [retval][out] */ IDiaFrameData **frame) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [out] */ IDiaFrameData **rgelt, + /* [out] */ ULONG *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ IDiaEnumFrameData **ppenum) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE frameByRVA( + /* [in] */ DWORD relativeVirtualAddress, + /* [retval][out] */ IDiaFrameData **frame) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE frameByVA( + /* [in] */ ULONGLONG virtualAddress, + /* [retval][out] */ IDiaFrameData **frame) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaEnumFrameDataVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaEnumFrameData * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaEnumFrameData * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaEnumFrameData * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IDiaEnumFrameData * This, + /* [retval][out] */ IUnknown **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IDiaEnumFrameData * This, + /* [retval][out] */ LONG *pRetVal); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Item )( + IDiaEnumFrameData * This, + /* [in] */ DWORD index, + /* [retval][out] */ IDiaFrameData **frame); + + HRESULT ( STDMETHODCALLTYPE *Next )( + IDiaEnumFrameData * This, + /* [in] */ ULONG celt, + /* [out] */ IDiaFrameData **rgelt, + /* [out] */ ULONG *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + IDiaEnumFrameData * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + IDiaEnumFrameData * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + IDiaEnumFrameData * This, + /* [out] */ IDiaEnumFrameData **ppenum); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *frameByRVA )( + IDiaEnumFrameData * This, + /* [in] */ DWORD relativeVirtualAddress, + /* [retval][out] */ IDiaFrameData **frame); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *frameByVA )( + IDiaEnumFrameData * This, + /* [in] */ ULONGLONG virtualAddress, + /* [retval][out] */ IDiaFrameData **frame); + + END_INTERFACE + } IDiaEnumFrameDataVtbl; + + interface IDiaEnumFrameData + { + CONST_VTBL struct IDiaEnumFrameDataVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaEnumFrameData_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaEnumFrameData_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaEnumFrameData_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaEnumFrameData_get__NewEnum(This,pRetVal) \ + ( (This)->lpVtbl -> get__NewEnum(This,pRetVal) ) + +#define IDiaEnumFrameData_get_Count(This,pRetVal) \ + ( (This)->lpVtbl -> get_Count(This,pRetVal) ) + +#define IDiaEnumFrameData_Item(This,index,frame) \ + ( (This)->lpVtbl -> Item(This,index,frame) ) + +#define IDiaEnumFrameData_Next(This,celt,rgelt,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched) ) + +#define IDiaEnumFrameData_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define IDiaEnumFrameData_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define IDiaEnumFrameData_Clone(This,ppenum) \ + ( (This)->lpVtbl -> Clone(This,ppenum) ) + +#define IDiaEnumFrameData_frameByRVA(This,relativeVirtualAddress,frame) \ + ( (This)->lpVtbl -> frameByRVA(This,relativeVirtualAddress,frame) ) + +#define IDiaEnumFrameData_frameByVA(This,virtualAddress,frame) \ + ( (This)->lpVtbl -> frameByVA(This,virtualAddress,frame) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaEnumFrameData_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaEnumDebugStreamData_INTERFACE_DEFINED__ +#define __IDiaEnumDebugStreamData_INTERFACE_DEFINED__ + +/* interface IDiaEnumDebugStreamData */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaEnumDebugStreamData; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("486943E8-D187-4a6b-A3C4-291259FFF60D") + IDiaEnumDebugStreamData : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ LONG *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_name( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Item( + /* [in] */ DWORD index, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData, + /* [out] */ ULONG *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ IDiaEnumDebugStreamData **ppenum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaEnumDebugStreamDataVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaEnumDebugStreamData * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaEnumDebugStreamData * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaEnumDebugStreamData * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IDiaEnumDebugStreamData * This, + /* [retval][out] */ IUnknown **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IDiaEnumDebugStreamData * This, + /* [retval][out] */ LONG *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_name )( + IDiaEnumDebugStreamData * This, + /* [retval][out] */ BSTR *pRetVal); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Item )( + IDiaEnumDebugStreamData * This, + /* [in] */ DWORD index, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData); + + HRESULT ( STDMETHODCALLTYPE *Next )( + IDiaEnumDebugStreamData * This, + /* [in] */ ULONG celt, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData, + /* [out] */ ULONG *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + IDiaEnumDebugStreamData * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + IDiaEnumDebugStreamData * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + IDiaEnumDebugStreamData * This, + /* [out] */ IDiaEnumDebugStreamData **ppenum); + + END_INTERFACE + } IDiaEnumDebugStreamDataVtbl; + + interface IDiaEnumDebugStreamData + { + CONST_VTBL struct IDiaEnumDebugStreamDataVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaEnumDebugStreamData_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaEnumDebugStreamData_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaEnumDebugStreamData_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaEnumDebugStreamData_get__NewEnum(This,pRetVal) \ + ( (This)->lpVtbl -> get__NewEnum(This,pRetVal) ) + +#define IDiaEnumDebugStreamData_get_Count(This,pRetVal) \ + ( (This)->lpVtbl -> get_Count(This,pRetVal) ) + +#define IDiaEnumDebugStreamData_get_name(This,pRetVal) \ + ( (This)->lpVtbl -> get_name(This,pRetVal) ) + +#define IDiaEnumDebugStreamData_Item(This,index,cbData,pcbData,pbData) \ + ( (This)->lpVtbl -> Item(This,index,cbData,pcbData,pbData) ) + +#define IDiaEnumDebugStreamData_Next(This,celt,cbData,pcbData,pbData,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,cbData,pcbData,pbData,pceltFetched) ) + +#define IDiaEnumDebugStreamData_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define IDiaEnumDebugStreamData_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define IDiaEnumDebugStreamData_Clone(This,ppenum) \ + ( (This)->lpVtbl -> Clone(This,ppenum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaEnumDebugStreamData_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaEnumDebugStreams_INTERFACE_DEFINED__ +#define __IDiaEnumDebugStreams_INTERFACE_DEFINED__ + +/* interface IDiaEnumDebugStreams */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaEnumDebugStreams; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("08CBB41E-47A6-4f87-92F1-1C9C87CED044") + IDiaEnumDebugStreams : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ LONG *pRetVal) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Item( + /* [in] */ VARIANT index, + /* [retval][out] */ IDiaEnumDebugStreamData **stream) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [out] */ IDiaEnumDebugStreamData **rgelt, + /* [out] */ ULONG *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ IDiaEnumDebugStreams **ppenum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaEnumDebugStreamsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaEnumDebugStreams * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaEnumDebugStreams * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaEnumDebugStreams * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IDiaEnumDebugStreams * This, + /* [retval][out] */ IUnknown **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IDiaEnumDebugStreams * This, + /* [retval][out] */ LONG *pRetVal); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Item )( + IDiaEnumDebugStreams * This, + /* [in] */ VARIANT index, + /* [retval][out] */ IDiaEnumDebugStreamData **stream); + + HRESULT ( STDMETHODCALLTYPE *Next )( + IDiaEnumDebugStreams * This, + /* [in] */ ULONG celt, + /* [out] */ IDiaEnumDebugStreamData **rgelt, + /* [out] */ ULONG *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + IDiaEnumDebugStreams * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + IDiaEnumDebugStreams * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + IDiaEnumDebugStreams * This, + /* [out] */ IDiaEnumDebugStreams **ppenum); + + END_INTERFACE + } IDiaEnumDebugStreamsVtbl; + + interface IDiaEnumDebugStreams + { + CONST_VTBL struct IDiaEnumDebugStreamsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaEnumDebugStreams_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaEnumDebugStreams_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaEnumDebugStreams_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaEnumDebugStreams_get__NewEnum(This,pRetVal) \ + ( (This)->lpVtbl -> get__NewEnum(This,pRetVal) ) + +#define IDiaEnumDebugStreams_get_Count(This,pRetVal) \ + ( (This)->lpVtbl -> get_Count(This,pRetVal) ) + +#define IDiaEnumDebugStreams_Item(This,index,stream) \ + ( (This)->lpVtbl -> Item(This,index,stream) ) + +#define IDiaEnumDebugStreams_Next(This,celt,rgelt,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched) ) + +#define IDiaEnumDebugStreams_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define IDiaEnumDebugStreams_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define IDiaEnumDebugStreams_Clone(This,ppenum) \ + ( (This)->lpVtbl -> Clone(This,ppenum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaEnumDebugStreams_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_dia2_0000_0016 */ +/* [local] */ + +struct DiaAddressMapEntry + { + DWORD rva; + DWORD rvaTo; + } ; + + +extern RPC_IF_HANDLE __MIDL_itf_dia2_0000_0016_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_dia2_0000_0016_v0_0_s_ifspec; + +#ifndef __IDiaAddressMap_INTERFACE_DEFINED__ +#define __IDiaAddressMap_INTERFACE_DEFINED__ + +/* interface IDiaAddressMap */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaAddressMap; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B62A2E7A-067A-4ea3-B598-04C09717502C") + IDiaAddressMap : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_addressMapEnabled( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_addressMapEnabled( + /* [in] */ BOOL NewVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_relativeVirtualAddressEnabled( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_relativeVirtualAddressEnabled( + /* [in] */ BOOL NewVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_imageAlign( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_imageAlign( + /* [in] */ DWORD NewVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE set_imageHeaders( + /* [in] */ DWORD cbData, + /* [size_is][in] */ BYTE *pbData, + /* [in] */ BOOL originalHeaders) = 0; + + virtual HRESULT STDMETHODCALLTYPE set_addressMap( + /* [in] */ DWORD cData, + /* [size_is][in] */ struct DiaAddressMapEntry *pData, + /* [in] */ BOOL imageToSymbols) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaAddressMapVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaAddressMap * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaAddressMap * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaAddressMap * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_addressMapEnabled )( + IDiaAddressMap * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_addressMapEnabled )( + IDiaAddressMap * This, + /* [in] */ BOOL NewVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_relativeVirtualAddressEnabled )( + IDiaAddressMap * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_relativeVirtualAddressEnabled )( + IDiaAddressMap * This, + /* [in] */ BOOL NewVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_imageAlign )( + IDiaAddressMap * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_imageAlign )( + IDiaAddressMap * This, + /* [in] */ DWORD NewVal); + + HRESULT ( STDMETHODCALLTYPE *set_imageHeaders )( + IDiaAddressMap * This, + /* [in] */ DWORD cbData, + /* [size_is][in] */ BYTE *pbData, + /* [in] */ BOOL originalHeaders); + + HRESULT ( STDMETHODCALLTYPE *set_addressMap )( + IDiaAddressMap * This, + /* [in] */ DWORD cData, + /* [size_is][in] */ struct DiaAddressMapEntry *pData, + /* [in] */ BOOL imageToSymbols); + + END_INTERFACE + } IDiaAddressMapVtbl; + + interface IDiaAddressMap + { + CONST_VTBL struct IDiaAddressMapVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaAddressMap_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaAddressMap_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaAddressMap_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaAddressMap_get_addressMapEnabled(This,pRetVal) \ + ( (This)->lpVtbl -> get_addressMapEnabled(This,pRetVal) ) + +#define IDiaAddressMap_put_addressMapEnabled(This,NewVal) \ + ( (This)->lpVtbl -> put_addressMapEnabled(This,NewVal) ) + +#define IDiaAddressMap_get_relativeVirtualAddressEnabled(This,pRetVal) \ + ( (This)->lpVtbl -> get_relativeVirtualAddressEnabled(This,pRetVal) ) + +#define IDiaAddressMap_put_relativeVirtualAddressEnabled(This,NewVal) \ + ( (This)->lpVtbl -> put_relativeVirtualAddressEnabled(This,NewVal) ) + +#define IDiaAddressMap_get_imageAlign(This,pRetVal) \ + ( (This)->lpVtbl -> get_imageAlign(This,pRetVal) ) + +#define IDiaAddressMap_put_imageAlign(This,NewVal) \ + ( (This)->lpVtbl -> put_imageAlign(This,NewVal) ) + +#define IDiaAddressMap_set_imageHeaders(This,cbData,pbData,originalHeaders) \ + ( (This)->lpVtbl -> set_imageHeaders(This,cbData,pbData,originalHeaders) ) + +#define IDiaAddressMap_set_addressMap(This,cData,pData,imageToSymbols) \ + ( (This)->lpVtbl -> set_addressMap(This,cData,pData,imageToSymbols) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaAddressMap_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaSession_INTERFACE_DEFINED__ +#define __IDiaSession_INTERFACE_DEFINED__ + +/* interface IDiaSession */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaSession; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2F609EE1-D1C8-4E24-8288-3326BADCD211") + IDiaSession : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_loadAddress( + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_loadAddress( + /* [in] */ ULONGLONG NewVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_globalScope( + /* [retval][out] */ IDiaSymbol **pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE getEnumTables( + /* [out] */ IDiaEnumTables **ppEnumTables) = 0; + + virtual HRESULT STDMETHODCALLTYPE getSymbolsByAddr( + /* [out] */ IDiaEnumSymbolsByAddr **ppEnumbyAddr) = 0; + + virtual HRESULT STDMETHODCALLTYPE findChildren( + /* [in] */ IDiaSymbol *parent, + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findChildrenEx( + /* [in] */ IDiaSymbol *parent, + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findChildrenExByAddr( + /* [in] */ IDiaSymbol *parent, + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findChildrenExByVA( + /* [in] */ IDiaSymbol *parent, + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [in] */ ULONGLONG va, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findChildrenExByRVA( + /* [in] */ IDiaSymbol *parent, + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [in] */ DWORD rva, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findSymbolByAddr( + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [in] */ enum SymTagEnum symtag, + /* [out] */ IDiaSymbol **ppSymbol) = 0; + + virtual HRESULT STDMETHODCALLTYPE findSymbolByRVA( + /* [in] */ DWORD rva, + /* [in] */ enum SymTagEnum symtag, + /* [out] */ IDiaSymbol **ppSymbol) = 0; + + virtual HRESULT STDMETHODCALLTYPE findSymbolByVA( + /* [in] */ ULONGLONG va, + /* [in] */ enum SymTagEnum symtag, + /* [out] */ IDiaSymbol **ppSymbol) = 0; + + virtual HRESULT STDMETHODCALLTYPE findSymbolByToken( + /* [in] */ ULONG token, + /* [in] */ enum SymTagEnum symtag, + /* [out] */ IDiaSymbol **ppSymbol) = 0; + + virtual HRESULT STDMETHODCALLTYPE symsAreEquiv( + /* [in] */ IDiaSymbol *symbolA, + /* [in] */ IDiaSymbol *symbolB) = 0; + + virtual HRESULT STDMETHODCALLTYPE symbolById( + /* [in] */ DWORD id, + /* [out] */ IDiaSymbol **ppSymbol) = 0; + + virtual HRESULT STDMETHODCALLTYPE findSymbolByRVAEx( + /* [in] */ DWORD rva, + /* [in] */ enum SymTagEnum symtag, + /* [out] */ IDiaSymbol **ppSymbol, + /* [out] */ long *displacement) = 0; + + virtual HRESULT STDMETHODCALLTYPE findSymbolByVAEx( + /* [in] */ ULONGLONG va, + /* [in] */ enum SymTagEnum symtag, + /* [out] */ IDiaSymbol **ppSymbol, + /* [out] */ long *displacement) = 0; + + virtual HRESULT STDMETHODCALLTYPE findFile( + /* [in] */ IDiaSymbol *pCompiland, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [out] */ IDiaEnumSourceFiles **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findFileById( + /* [in] */ DWORD uniqueId, + /* [out] */ IDiaSourceFile **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findLines( + /* [in] */ IDiaSymbol *compiland, + /* [in] */ IDiaSourceFile *file, + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findLinesByAddr( + /* [in] */ DWORD seg, + /* [in] */ DWORD offset, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findLinesByRVA( + /* [in] */ DWORD rva, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findLinesByVA( + /* [in] */ ULONGLONG va, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findLinesByLinenum( + /* [in] */ IDiaSymbol *compiland, + /* [in] */ IDiaSourceFile *file, + /* [in] */ DWORD linenum, + /* [in] */ DWORD column, + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInjectedSource( + /* [in] */ LPCOLESTR srcFile, + /* [out] */ IDiaEnumInjectedSources **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE getEnumDebugStreams( + /* [out] */ IDiaEnumDebugStreams **ppEnumDebugStreams) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInlineFramesByAddr( + /* [in] */ IDiaSymbol *parent, + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInlineFramesByRVA( + /* [in] */ IDiaSymbol *parent, + /* [in] */ DWORD rva, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInlineFramesByVA( + /* [in] */ IDiaSymbol *parent, + /* [in] */ ULONGLONG va, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInlineeLines( + /* [in] */ IDiaSymbol *parent, + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInlineeLinesByAddr( + /* [in] */ IDiaSymbol *parent, + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInlineeLinesByRVA( + /* [in] */ IDiaSymbol *parent, + /* [in] */ DWORD rva, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInlineeLinesByVA( + /* [in] */ IDiaSymbol *parent, + /* [in] */ ULONGLONG va, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInlineeLinesByLinenum( + /* [in] */ IDiaSymbol *compiland, + /* [in] */ IDiaSourceFile *file, + /* [in] */ DWORD linenum, + /* [in] */ DWORD column, + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInlineesByName( + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD option, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findAcceleratorInlineeLinesByLinenum( + /* [in] */ IDiaSymbol *parent, + /* [in] */ IDiaSourceFile *file, + /* [in] */ DWORD linenum, + /* [in] */ DWORD column, + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findSymbolsForAcceleratorPointerTag( + /* [in] */ IDiaSymbol *parent, + /* [in] */ DWORD tagValue, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findSymbolsByRVAForAcceleratorPointerTag( + /* [in] */ IDiaSymbol *parent, + /* [in] */ DWORD tagValue, + /* [in] */ DWORD rva, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findAcceleratorInlineesByName( + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD option, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE addressForVA( + /* [in] */ ULONGLONG va, + /* [out] */ DWORD *pISect, + /* [out] */ DWORD *pOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE addressForRVA( + /* [in] */ DWORD rva, + /* [out] */ DWORD *pISect, + /* [out] */ DWORD *pOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE findILOffsetsByAddr( + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findILOffsetsByRVA( + /* [in] */ DWORD rva, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findILOffsetsByVA( + /* [in] */ ULONGLONG va, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInputAssemblyFiles( + /* [out] */ IDiaEnumInputAssemblyFiles **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInputAssembly( + /* [in] */ DWORD index, + /* [out] */ IDiaInputAssemblyFile **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInputAssemblyById( + /* [in] */ DWORD uniqueId, + /* [out] */ IDiaInputAssemblyFile **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE getFuncMDTokenMapSize( + /* [out] */ DWORD *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE getFuncMDTokenMap( + /* [in] */ DWORD cb, + /* [out] */ DWORD *pcb, + /* [size_is][out] */ BYTE *pb) = 0; + + virtual HRESULT STDMETHODCALLTYPE getTypeMDTokenMapSize( + /* [out] */ DWORD *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE getTypeMDTokenMap( + /* [in] */ DWORD cb, + /* [out] */ DWORD *pcb, + /* [size_is][out] */ BYTE *pb) = 0; + + virtual HRESULT STDMETHODCALLTYPE getNumberOfFunctionFragments_VA( + /* [in] */ ULONGLONG vaFunc, + /* [in] */ DWORD cbFunc, + /* [out] */ DWORD *pNumFragments) = 0; + + virtual HRESULT STDMETHODCALLTYPE getNumberOfFunctionFragments_RVA( + /* [in] */ DWORD rvaFunc, + /* [in] */ DWORD cbFunc, + /* [out] */ DWORD *pNumFragments) = 0; + + virtual HRESULT STDMETHODCALLTYPE getFunctionFragments_VA( + /* [in] */ ULONGLONG vaFunc, + /* [in] */ DWORD cbFunc, + /* [in] */ DWORD cFragments, + /* [size_is][out] */ ULONGLONG *pVaFragment, + /* [size_is][out] */ DWORD *pLenFragment) = 0; + + virtual HRESULT STDMETHODCALLTYPE getFunctionFragments_RVA( + /* [in] */ DWORD rvaFunc, + /* [in] */ DWORD cbFunc, + /* [in] */ DWORD cFragments, + /* [size_is][out] */ DWORD *pRvaFragment, + /* [size_is][out] */ DWORD *pLenFragment) = 0; + + virtual HRESULT STDMETHODCALLTYPE getExports( + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE getHeapAllocationSites( + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInputAssemblyFile( + /* [in] */ IDiaSymbol *pSymbol, + /* [out] */ IDiaInputAssemblyFile **ppResult) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaSessionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaSession * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaSession * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaSession * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_loadAddress )( + IDiaSession * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_loadAddress )( + IDiaSession * This, + /* [in] */ ULONGLONG NewVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_globalScope )( + IDiaSession * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *getEnumTables )( + IDiaSession * This, + /* [out] */ IDiaEnumTables **ppEnumTables); + + HRESULT ( STDMETHODCALLTYPE *getSymbolsByAddr )( + IDiaSession * This, + /* [out] */ IDiaEnumSymbolsByAddr **ppEnumbyAddr); + + HRESULT ( STDMETHODCALLTYPE *findChildren )( + IDiaSession * This, + /* [in] */ IDiaSymbol *parent, + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findChildrenEx )( + IDiaSession * This, + /* [in] */ IDiaSymbol *parent, + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findChildrenExByAddr )( + IDiaSession * This, + /* [in] */ IDiaSymbol *parent, + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findChildrenExByVA )( + IDiaSession * This, + /* [in] */ IDiaSymbol *parent, + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [in] */ ULONGLONG va, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findChildrenExByRVA )( + IDiaSession * This, + /* [in] */ IDiaSymbol *parent, + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [in] */ DWORD rva, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findSymbolByAddr )( + IDiaSession * This, + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [in] */ enum SymTagEnum symtag, + /* [out] */ IDiaSymbol **ppSymbol); + + HRESULT ( STDMETHODCALLTYPE *findSymbolByRVA )( + IDiaSession * This, + /* [in] */ DWORD rva, + /* [in] */ enum SymTagEnum symtag, + /* [out] */ IDiaSymbol **ppSymbol); + + HRESULT ( STDMETHODCALLTYPE *findSymbolByVA )( + IDiaSession * This, + /* [in] */ ULONGLONG va, + /* [in] */ enum SymTagEnum symtag, + /* [out] */ IDiaSymbol **ppSymbol); + + HRESULT ( STDMETHODCALLTYPE *findSymbolByToken )( + IDiaSession * This, + /* [in] */ ULONG token, + /* [in] */ enum SymTagEnum symtag, + /* [out] */ IDiaSymbol **ppSymbol); + + HRESULT ( STDMETHODCALLTYPE *symsAreEquiv )( + IDiaSession * This, + /* [in] */ IDiaSymbol *symbolA, + /* [in] */ IDiaSymbol *symbolB); + + HRESULT ( STDMETHODCALLTYPE *symbolById )( + IDiaSession * This, + /* [in] */ DWORD id, + /* [out] */ IDiaSymbol **ppSymbol); + + HRESULT ( STDMETHODCALLTYPE *findSymbolByRVAEx )( + IDiaSession * This, + /* [in] */ DWORD rva, + /* [in] */ enum SymTagEnum symtag, + /* [out] */ IDiaSymbol **ppSymbol, + /* [out] */ long *displacement); + + HRESULT ( STDMETHODCALLTYPE *findSymbolByVAEx )( + IDiaSession * This, + /* [in] */ ULONGLONG va, + /* [in] */ enum SymTagEnum symtag, + /* [out] */ IDiaSymbol **ppSymbol, + /* [out] */ long *displacement); + + HRESULT ( STDMETHODCALLTYPE *findFile )( + IDiaSession * This, + /* [in] */ IDiaSymbol *pCompiland, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [out] */ IDiaEnumSourceFiles **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findFileById )( + IDiaSession * This, + /* [in] */ DWORD uniqueId, + /* [out] */ IDiaSourceFile **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findLines )( + IDiaSession * This, + /* [in] */ IDiaSymbol *compiland, + /* [in] */ IDiaSourceFile *file, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findLinesByAddr )( + IDiaSession * This, + /* [in] */ DWORD seg, + /* [in] */ DWORD offset, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findLinesByRVA )( + IDiaSession * This, + /* [in] */ DWORD rva, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findLinesByVA )( + IDiaSession * This, + /* [in] */ ULONGLONG va, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findLinesByLinenum )( + IDiaSession * This, + /* [in] */ IDiaSymbol *compiland, + /* [in] */ IDiaSourceFile *file, + /* [in] */ DWORD linenum, + /* [in] */ DWORD column, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInjectedSource )( + IDiaSession * This, + /* [in] */ LPCOLESTR srcFile, + /* [out] */ IDiaEnumInjectedSources **ppResult); + + HRESULT ( STDMETHODCALLTYPE *getEnumDebugStreams )( + IDiaSession * This, + /* [out] */ IDiaEnumDebugStreams **ppEnumDebugStreams); + + HRESULT ( STDMETHODCALLTYPE *findInlineFramesByAddr )( + IDiaSession * This, + /* [in] */ IDiaSymbol *parent, + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInlineFramesByRVA )( + IDiaSession * This, + /* [in] */ IDiaSymbol *parent, + /* [in] */ DWORD rva, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInlineFramesByVA )( + IDiaSession * This, + /* [in] */ IDiaSymbol *parent, + /* [in] */ ULONGLONG va, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInlineeLines )( + IDiaSession * This, + /* [in] */ IDiaSymbol *parent, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInlineeLinesByAddr )( + IDiaSession * This, + /* [in] */ IDiaSymbol *parent, + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInlineeLinesByRVA )( + IDiaSession * This, + /* [in] */ IDiaSymbol *parent, + /* [in] */ DWORD rva, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInlineeLinesByVA )( + IDiaSession * This, + /* [in] */ IDiaSymbol *parent, + /* [in] */ ULONGLONG va, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInlineeLinesByLinenum )( + IDiaSession * This, + /* [in] */ IDiaSymbol *compiland, + /* [in] */ IDiaSourceFile *file, + /* [in] */ DWORD linenum, + /* [in] */ DWORD column, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInlineesByName )( + IDiaSession * This, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD option, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findAcceleratorInlineeLinesByLinenum )( + IDiaSession * This, + /* [in] */ IDiaSymbol *parent, + /* [in] */ IDiaSourceFile *file, + /* [in] */ DWORD linenum, + /* [in] */ DWORD column, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findSymbolsForAcceleratorPointerTag )( + IDiaSession * This, + /* [in] */ IDiaSymbol *parent, + /* [in] */ DWORD tagValue, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findSymbolsByRVAForAcceleratorPointerTag )( + IDiaSession * This, + /* [in] */ IDiaSymbol *parent, + /* [in] */ DWORD tagValue, + /* [in] */ DWORD rva, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findAcceleratorInlineesByName )( + IDiaSession * This, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD option, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *addressForVA )( + IDiaSession * This, + /* [in] */ ULONGLONG va, + /* [out] */ DWORD *pISect, + /* [out] */ DWORD *pOffset); + + HRESULT ( STDMETHODCALLTYPE *addressForRVA )( + IDiaSession * This, + /* [in] */ DWORD rva, + /* [out] */ DWORD *pISect, + /* [out] */ DWORD *pOffset); + + HRESULT ( STDMETHODCALLTYPE *findILOffsetsByAddr )( + IDiaSession * This, + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findILOffsetsByRVA )( + IDiaSession * This, + /* [in] */ DWORD rva, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findILOffsetsByVA )( + IDiaSession * This, + /* [in] */ ULONGLONG va, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInputAssemblyFiles )( + IDiaSession * This, + /* [out] */ IDiaEnumInputAssemblyFiles **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInputAssembly )( + IDiaSession * This, + /* [in] */ DWORD index, + /* [out] */ IDiaInputAssemblyFile **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInputAssemblyById )( + IDiaSession * This, + /* [in] */ DWORD uniqueId, + /* [out] */ IDiaInputAssemblyFile **ppResult); + + HRESULT ( STDMETHODCALLTYPE *getFuncMDTokenMapSize )( + IDiaSession * This, + /* [out] */ DWORD *pcb); + + HRESULT ( STDMETHODCALLTYPE *getFuncMDTokenMap )( + IDiaSession * This, + /* [in] */ DWORD cb, + /* [out] */ DWORD *pcb, + /* [size_is][out] */ BYTE *pb); + + HRESULT ( STDMETHODCALLTYPE *getTypeMDTokenMapSize )( + IDiaSession * This, + /* [out] */ DWORD *pcb); + + HRESULT ( STDMETHODCALLTYPE *getTypeMDTokenMap )( + IDiaSession * This, + /* [in] */ DWORD cb, + /* [out] */ DWORD *pcb, + /* [size_is][out] */ BYTE *pb); + + HRESULT ( STDMETHODCALLTYPE *getNumberOfFunctionFragments_VA )( + IDiaSession * This, + /* [in] */ ULONGLONG vaFunc, + /* [in] */ DWORD cbFunc, + /* [out] */ DWORD *pNumFragments); + + HRESULT ( STDMETHODCALLTYPE *getNumberOfFunctionFragments_RVA )( + IDiaSession * This, + /* [in] */ DWORD rvaFunc, + /* [in] */ DWORD cbFunc, + /* [out] */ DWORD *pNumFragments); + + HRESULT ( STDMETHODCALLTYPE *getFunctionFragments_VA )( + IDiaSession * This, + /* [in] */ ULONGLONG vaFunc, + /* [in] */ DWORD cbFunc, + /* [in] */ DWORD cFragments, + /* [size_is][out] */ ULONGLONG *pVaFragment, + /* [size_is][out] */ DWORD *pLenFragment); + + HRESULT ( STDMETHODCALLTYPE *getFunctionFragments_RVA )( + IDiaSession * This, + /* [in] */ DWORD rvaFunc, + /* [in] */ DWORD cbFunc, + /* [in] */ DWORD cFragments, + /* [size_is][out] */ DWORD *pRvaFragment, + /* [size_is][out] */ DWORD *pLenFragment); + + HRESULT ( STDMETHODCALLTYPE *getExports )( + IDiaSession * This, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *getHeapAllocationSites )( + IDiaSession * This, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInputAssemblyFile )( + IDiaSession * This, + /* [in] */ IDiaSymbol *pSymbol, + /* [out] */ IDiaInputAssemblyFile **ppResult); + + END_INTERFACE + } IDiaSessionVtbl; + + interface IDiaSession + { + CONST_VTBL struct IDiaSessionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaSession_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaSession_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaSession_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaSession_get_loadAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_loadAddress(This,pRetVal) ) + +#define IDiaSession_put_loadAddress(This,NewVal) \ + ( (This)->lpVtbl -> put_loadAddress(This,NewVal) ) + +#define IDiaSession_get_globalScope(This,pRetVal) \ + ( (This)->lpVtbl -> get_globalScope(This,pRetVal) ) + +#define IDiaSession_getEnumTables(This,ppEnumTables) \ + ( (This)->lpVtbl -> getEnumTables(This,ppEnumTables) ) + +#define IDiaSession_getSymbolsByAddr(This,ppEnumbyAddr) \ + ( (This)->lpVtbl -> getSymbolsByAddr(This,ppEnumbyAddr) ) + +#define IDiaSession_findChildren(This,parent,symtag,name,compareFlags,ppResult) \ + ( (This)->lpVtbl -> findChildren(This,parent,symtag,name,compareFlags,ppResult) ) + +#define IDiaSession_findChildrenEx(This,parent,symtag,name,compareFlags,ppResult) \ + ( (This)->lpVtbl -> findChildrenEx(This,parent,symtag,name,compareFlags,ppResult) ) + +#define IDiaSession_findChildrenExByAddr(This,parent,symtag,name,compareFlags,isect,offset,ppResult) \ + ( (This)->lpVtbl -> findChildrenExByAddr(This,parent,symtag,name,compareFlags,isect,offset,ppResult) ) + +#define IDiaSession_findChildrenExByVA(This,parent,symtag,name,compareFlags,va,ppResult) \ + ( (This)->lpVtbl -> findChildrenExByVA(This,parent,symtag,name,compareFlags,va,ppResult) ) + +#define IDiaSession_findChildrenExByRVA(This,parent,symtag,name,compareFlags,rva,ppResult) \ + ( (This)->lpVtbl -> findChildrenExByRVA(This,parent,symtag,name,compareFlags,rva,ppResult) ) + +#define IDiaSession_findSymbolByAddr(This,isect,offset,symtag,ppSymbol) \ + ( (This)->lpVtbl -> findSymbolByAddr(This,isect,offset,symtag,ppSymbol) ) + +#define IDiaSession_findSymbolByRVA(This,rva,symtag,ppSymbol) \ + ( (This)->lpVtbl -> findSymbolByRVA(This,rva,symtag,ppSymbol) ) + +#define IDiaSession_findSymbolByVA(This,va,symtag,ppSymbol) \ + ( (This)->lpVtbl -> findSymbolByVA(This,va,symtag,ppSymbol) ) + +#define IDiaSession_findSymbolByToken(This,token,symtag,ppSymbol) \ + ( (This)->lpVtbl -> findSymbolByToken(This,token,symtag,ppSymbol) ) + +#define IDiaSession_symsAreEquiv(This,symbolA,symbolB) \ + ( (This)->lpVtbl -> symsAreEquiv(This,symbolA,symbolB) ) + +#define IDiaSession_symbolById(This,id,ppSymbol) \ + ( (This)->lpVtbl -> symbolById(This,id,ppSymbol) ) + +#define IDiaSession_findSymbolByRVAEx(This,rva,symtag,ppSymbol,displacement) \ + ( (This)->lpVtbl -> findSymbolByRVAEx(This,rva,symtag,ppSymbol,displacement) ) + +#define IDiaSession_findSymbolByVAEx(This,va,symtag,ppSymbol,displacement) \ + ( (This)->lpVtbl -> findSymbolByVAEx(This,va,symtag,ppSymbol,displacement) ) + +#define IDiaSession_findFile(This,pCompiland,name,compareFlags,ppResult) \ + ( (This)->lpVtbl -> findFile(This,pCompiland,name,compareFlags,ppResult) ) + +#define IDiaSession_findFileById(This,uniqueId,ppResult) \ + ( (This)->lpVtbl -> findFileById(This,uniqueId,ppResult) ) + +#define IDiaSession_findLines(This,compiland,file,ppResult) \ + ( (This)->lpVtbl -> findLines(This,compiland,file,ppResult) ) + +#define IDiaSession_findLinesByAddr(This,seg,offset,length,ppResult) \ + ( (This)->lpVtbl -> findLinesByAddr(This,seg,offset,length,ppResult) ) + +#define IDiaSession_findLinesByRVA(This,rva,length,ppResult) \ + ( (This)->lpVtbl -> findLinesByRVA(This,rva,length,ppResult) ) + +#define IDiaSession_findLinesByVA(This,va,length,ppResult) \ + ( (This)->lpVtbl -> findLinesByVA(This,va,length,ppResult) ) + +#define IDiaSession_findLinesByLinenum(This,compiland,file,linenum,column,ppResult) \ + ( (This)->lpVtbl -> findLinesByLinenum(This,compiland,file,linenum,column,ppResult) ) + +#define IDiaSession_findInjectedSource(This,srcFile,ppResult) \ + ( (This)->lpVtbl -> findInjectedSource(This,srcFile,ppResult) ) + +#define IDiaSession_getEnumDebugStreams(This,ppEnumDebugStreams) \ + ( (This)->lpVtbl -> getEnumDebugStreams(This,ppEnumDebugStreams) ) + +#define IDiaSession_findInlineFramesByAddr(This,parent,isect,offset,ppResult) \ + ( (This)->lpVtbl -> findInlineFramesByAddr(This,parent,isect,offset,ppResult) ) + +#define IDiaSession_findInlineFramesByRVA(This,parent,rva,ppResult) \ + ( (This)->lpVtbl -> findInlineFramesByRVA(This,parent,rva,ppResult) ) + +#define IDiaSession_findInlineFramesByVA(This,parent,va,ppResult) \ + ( (This)->lpVtbl -> findInlineFramesByVA(This,parent,va,ppResult) ) + +#define IDiaSession_findInlineeLines(This,parent,ppResult) \ + ( (This)->lpVtbl -> findInlineeLines(This,parent,ppResult) ) + +#define IDiaSession_findInlineeLinesByAddr(This,parent,isect,offset,length,ppResult) \ + ( (This)->lpVtbl -> findInlineeLinesByAddr(This,parent,isect,offset,length,ppResult) ) + +#define IDiaSession_findInlineeLinesByRVA(This,parent,rva,length,ppResult) \ + ( (This)->lpVtbl -> findInlineeLinesByRVA(This,parent,rva,length,ppResult) ) + +#define IDiaSession_findInlineeLinesByVA(This,parent,va,length,ppResult) \ + ( (This)->lpVtbl -> findInlineeLinesByVA(This,parent,va,length,ppResult) ) + +#define IDiaSession_findInlineeLinesByLinenum(This,compiland,file,linenum,column,ppResult) \ + ( (This)->lpVtbl -> findInlineeLinesByLinenum(This,compiland,file,linenum,column,ppResult) ) + +#define IDiaSession_findInlineesByName(This,name,option,ppResult) \ + ( (This)->lpVtbl -> findInlineesByName(This,name,option,ppResult) ) + +#define IDiaSession_findAcceleratorInlineeLinesByLinenum(This,parent,file,linenum,column,ppResult) \ + ( (This)->lpVtbl -> findAcceleratorInlineeLinesByLinenum(This,parent,file,linenum,column,ppResult) ) + +#define IDiaSession_findSymbolsForAcceleratorPointerTag(This,parent,tagValue,ppResult) \ + ( (This)->lpVtbl -> findSymbolsForAcceleratorPointerTag(This,parent,tagValue,ppResult) ) + +#define IDiaSession_findSymbolsByRVAForAcceleratorPointerTag(This,parent,tagValue,rva,ppResult) \ + ( (This)->lpVtbl -> findSymbolsByRVAForAcceleratorPointerTag(This,parent,tagValue,rva,ppResult) ) + +#define IDiaSession_findAcceleratorInlineesByName(This,name,option,ppResult) \ + ( (This)->lpVtbl -> findAcceleratorInlineesByName(This,name,option,ppResult) ) + +#define IDiaSession_addressForVA(This,va,pISect,pOffset) \ + ( (This)->lpVtbl -> addressForVA(This,va,pISect,pOffset) ) + +#define IDiaSession_addressForRVA(This,rva,pISect,pOffset) \ + ( (This)->lpVtbl -> addressForRVA(This,rva,pISect,pOffset) ) + +#define IDiaSession_findILOffsetsByAddr(This,isect,offset,length,ppResult) \ + ( (This)->lpVtbl -> findILOffsetsByAddr(This,isect,offset,length,ppResult) ) + +#define IDiaSession_findILOffsetsByRVA(This,rva,length,ppResult) \ + ( (This)->lpVtbl -> findILOffsetsByRVA(This,rva,length,ppResult) ) + +#define IDiaSession_findILOffsetsByVA(This,va,length,ppResult) \ + ( (This)->lpVtbl -> findILOffsetsByVA(This,va,length,ppResult) ) + +#define IDiaSession_findInputAssemblyFiles(This,ppResult) \ + ( (This)->lpVtbl -> findInputAssemblyFiles(This,ppResult) ) + +#define IDiaSession_findInputAssembly(This,index,ppResult) \ + ( (This)->lpVtbl -> findInputAssembly(This,index,ppResult) ) + +#define IDiaSession_findInputAssemblyById(This,uniqueId,ppResult) \ + ( (This)->lpVtbl -> findInputAssemblyById(This,uniqueId,ppResult) ) + +#define IDiaSession_getFuncMDTokenMapSize(This,pcb) \ + ( (This)->lpVtbl -> getFuncMDTokenMapSize(This,pcb) ) + +#define IDiaSession_getFuncMDTokenMap(This,cb,pcb,pb) \ + ( (This)->lpVtbl -> getFuncMDTokenMap(This,cb,pcb,pb) ) + +#define IDiaSession_getTypeMDTokenMapSize(This,pcb) \ + ( (This)->lpVtbl -> getTypeMDTokenMapSize(This,pcb) ) + +#define IDiaSession_getTypeMDTokenMap(This,cb,pcb,pb) \ + ( (This)->lpVtbl -> getTypeMDTokenMap(This,cb,pcb,pb) ) + +#define IDiaSession_getNumberOfFunctionFragments_VA(This,vaFunc,cbFunc,pNumFragments) \ + ( (This)->lpVtbl -> getNumberOfFunctionFragments_VA(This,vaFunc,cbFunc,pNumFragments) ) + +#define IDiaSession_getNumberOfFunctionFragments_RVA(This,rvaFunc,cbFunc,pNumFragments) \ + ( (This)->lpVtbl -> getNumberOfFunctionFragments_RVA(This,rvaFunc,cbFunc,pNumFragments) ) + +#define IDiaSession_getFunctionFragments_VA(This,vaFunc,cbFunc,cFragments,pVaFragment,pLenFragment) \ + ( (This)->lpVtbl -> getFunctionFragments_VA(This,vaFunc,cbFunc,cFragments,pVaFragment,pLenFragment) ) + +#define IDiaSession_getFunctionFragments_RVA(This,rvaFunc,cbFunc,cFragments,pRvaFragment,pLenFragment) \ + ( (This)->lpVtbl -> getFunctionFragments_RVA(This,rvaFunc,cbFunc,cFragments,pRvaFragment,pLenFragment) ) + +#define IDiaSession_getExports(This,ppResult) \ + ( (This)->lpVtbl -> getExports(This,ppResult) ) + +#define IDiaSession_getHeapAllocationSites(This,ppResult) \ + ( (This)->lpVtbl -> getHeapAllocationSites(This,ppResult) ) + +#define IDiaSession_findInputAssemblyFile(This,pSymbol,ppResult) \ + ( (This)->lpVtbl -> findInputAssemblyFile(This,pSymbol,ppResult) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaSession_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaSymbol_INTERFACE_DEFINED__ +#define __IDiaSymbol_INTERFACE_DEFINED__ + +/* interface IDiaSymbol */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaSymbol; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("cb787b2f-bd6c-4635-ba52-933126bd2dcd") + IDiaSymbol : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_symIndexId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_symTag( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_name( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_lexicalParent( + /* [retval][out] */ IDiaSymbol **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_classParent( + /* [retval][out] */ IDiaSymbol **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_type( + /* [retval][out] */ IDiaSymbol **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_dataKind( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_locationType( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_addressSection( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_addressOffset( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_relativeVirtualAddress( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_virtualAddress( + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_registerId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_offset( + /* [retval][out] */ LONG *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_length( + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_slot( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_volatileType( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_constType( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_unalignedType( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_access( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_libraryName( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_platform( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_language( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_editAndContinueEnabled( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_frontEndMajor( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_frontEndMinor( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_frontEndBuild( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_backEndMajor( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_backEndMinor( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_backEndBuild( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_sourceFileName( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_unused( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_thunkOrdinal( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_thisAdjust( + /* [retval][out] */ LONG *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_virtualBaseOffset( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_virtual( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_intro( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_pure( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_callingConvention( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_value( + /* [retval][out] */ VARIANT *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_baseType( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_token( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_timeStamp( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_guid( + /* [retval][out] */ GUID *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_symbolsFileName( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_reference( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_count( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_bitPosition( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_arrayIndexType( + /* [retval][out] */ IDiaSymbol **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_packed( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_constructor( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_overloadedOperator( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_nested( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_hasNestedTypes( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_hasAssignmentOperator( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_hasCastOperator( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_scoped( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_virtualBaseClass( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_indirectVirtualBaseClass( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_virtualBasePointerOffset( + /* [retval][out] */ LONG *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_virtualTableShape( + /* [retval][out] */ IDiaSymbol **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_lexicalParentId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_classParentId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_typeId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_arrayIndexTypeId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_virtualTableShapeId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_code( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_function( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_managed( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_msil( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_virtualBaseDispIndex( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_undecoratedName( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_age( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_signature( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_compilerGenerated( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_addressTaken( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_rank( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_lowerBound( + /* [retval][out] */ IDiaSymbol **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_upperBound( + /* [retval][out] */ IDiaSymbol **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_lowerBoundId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_upperBoundId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE get_dataBytes( + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData) = 0; + + virtual HRESULT STDMETHODCALLTYPE findChildren( + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findChildrenEx( + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findChildrenExByAddr( + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findChildrenExByVA( + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [in] */ ULONGLONG va, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findChildrenExByRVA( + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [in] */ DWORD rva, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_targetSection( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_targetOffset( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_targetRelativeVirtualAddress( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_targetVirtualAddress( + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_machineType( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_oemId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_oemSymbolId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE get_types( + /* [in] */ DWORD cTypes, + /* [out] */ DWORD *pcTypes, + /* [size_is][size_is][out] */ IDiaSymbol **pTypes) = 0; + + virtual HRESULT STDMETHODCALLTYPE get_typeIds( + /* [in] */ DWORD cTypeIds, + /* [out] */ DWORD *pcTypeIds, + /* [size_is][out] */ DWORD *pdwTypeIds) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_objectPointerType( + /* [retval][out] */ IDiaSymbol **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_udtKind( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE get_undecoratedNameEx( + /* [in] */ DWORD undecorateOptions, + /* [out] */ BSTR *name) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_noReturn( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_customCallingConvention( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_noInline( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_optimizedCodeDebugInfo( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_notReached( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_interruptReturn( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_farReturn( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isStatic( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_hasDebugInfo( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isLTCG( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isDataAligned( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_hasSecurityChecks( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_compilerName( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_hasAlloca( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_hasSetJump( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_hasLongJump( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_hasInlAsm( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_hasEH( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_hasSEH( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_hasEHa( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isNaked( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isAggregated( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isSplitted( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_container( + /* [retval][out] */ IDiaSymbol **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_inlSpec( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_noStackOrdering( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_virtualBaseTableType( + /* [retval][out] */ IDiaSymbol **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_hasManagedCode( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isHotpatchable( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isCVTCIL( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isMSILNetmodule( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isCTypes( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isStripped( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_frontEndQFE( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_backEndQFE( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_wasInlined( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_strictGSCheck( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isCxxReturnUdt( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isConstructorVirtualBase( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_RValueReference( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_unmodifiedType( + /* [retval][out] */ IDiaSymbol **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_framePointerPresent( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isSafeBuffers( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_intrinsic( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_sealed( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_hfaFloat( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_hfaDouble( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_liveRangeStartAddressSection( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_liveRangeStartAddressOffset( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_liveRangeStartRelativeVirtualAddress( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_countLiveRanges( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_liveRangeLength( + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_offsetInUdt( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_paramBasePointerRegisterId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_localBasePointerRegisterId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isLocationControlFlowDependent( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_stride( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_numberOfRows( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_numberOfColumns( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isMatrixRowMajor( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE get_numericProperties( + /* [in] */ DWORD cnt, + /* [out] */ DWORD *pcnt, + /* [size_is][out] */ DWORD *pProperties) = 0; + + virtual HRESULT STDMETHODCALLTYPE get_modifierValues( + /* [in] */ DWORD cnt, + /* [out] */ DWORD *pcnt, + /* [size_is][out] */ WORD *pModifiers) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isReturnValue( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isOptimizedAway( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_builtInKind( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_registerType( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_baseDataSlot( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_baseDataOffset( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_textureSlot( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_samplerSlot( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_uavSlot( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_sizeInUdt( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_memorySpaceKind( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_unmodifiedTypeId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_subTypeId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_subType( + /* [retval][out] */ IDiaSymbol **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_numberOfModifiers( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_numberOfRegisterIndices( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isHLSLData( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isPointerToDataMember( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isPointerToMemberFunction( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isSingleInheritance( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isMultipleInheritance( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isVirtualInheritance( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_restrictedType( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isPointerBasedOnSymbolValue( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_baseSymbol( + /* [retval][out] */ IDiaSymbol **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_baseSymbolId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_objectFileName( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isAcceleratorGroupSharedLocal( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isAcceleratorPointerTagLiveRange( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isAcceleratorStubFunction( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_numberOfAcceleratorPointerTags( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isSdl( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isWinRTPointer( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isRefUdt( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isValueUdt( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isInterfaceUdt( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInlineFramesByAddr( + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInlineFramesByRVA( + /* [in] */ DWORD rva, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInlineFramesByVA( + /* [in] */ ULONGLONG va, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInlineeLines( + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInlineeLinesByAddr( + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInlineeLinesByRVA( + /* [in] */ DWORD rva, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInlineeLinesByVA( + /* [in] */ ULONGLONG va, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findSymbolsForAcceleratorPointerTag( + /* [in] */ DWORD tagValue, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE findSymbolsByRVAForAcceleratorPointerTag( + /* [in] */ DWORD tagValue, + /* [in] */ DWORD rva, + /* [out] */ IDiaEnumSymbols **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE get_acceleratorPointerTags( + /* [in] */ DWORD cnt, + /* [out] */ DWORD *pcnt, + /* [size_is][out] */ DWORD *pPointerTags) = 0; + + virtual HRESULT STDMETHODCALLTYPE getSrcLineOnTypeDefn( + /* [out] */ IDiaLineNumber **ppResult) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isPGO( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_hasValidPGOCounts( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_isOptimizedForSpeed( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PGOEntryCount( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PGOEdgeCount( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PGODynamicInstructionCount( + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_staticSize( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_finalLiveStaticSize( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_phaseName( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_hasControlFlowCheck( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_constantExport( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_dataExport( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_privateExport( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_noNameExport( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_exportHasExplicitlyAssignedOrdinal( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_exportIsForwarder( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ordinal( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_frameSize( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_exceptionHandlerAddressSection( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_exceptionHandlerAddressOffset( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_exceptionHandlerRelativeVirtualAddress( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_exceptionHandlerVirtualAddress( + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE findInputAssemblyFile( + /* [out] */ IDiaInputAssemblyFile **ppResult) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_characteristics( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_coffGroup( + /* [retval][out] */ IDiaSymbol **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_bindID( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_bindSpace( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_bindSlot( + /* [retval][out] */ DWORD *pRetVal) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaSymbolVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaSymbol * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaSymbol * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaSymbol * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_symIndexId )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_symTag )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_name )( + IDiaSymbol * This, + /* [retval][out] */ BSTR *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_lexicalParent )( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_classParent )( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_type )( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_dataKind )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_locationType )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_addressSection )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_addressOffset )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_relativeVirtualAddress )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_virtualAddress )( + IDiaSymbol * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_registerId )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_offset )( + IDiaSymbol * This, + /* [retval][out] */ LONG *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_length )( + IDiaSymbol * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_slot )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_volatileType )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_constType )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_unalignedType )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_access )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_libraryName )( + IDiaSymbol * This, + /* [retval][out] */ BSTR *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_platform )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_language )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_editAndContinueEnabled )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_frontEndMajor )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_frontEndMinor )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_frontEndBuild )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_backEndMajor )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_backEndMinor )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_backEndBuild )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_sourceFileName )( + IDiaSymbol * This, + /* [retval][out] */ BSTR *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_unused )( + IDiaSymbol * This, + /* [retval][out] */ BSTR *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_thunkOrdinal )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_thisAdjust )( + IDiaSymbol * This, + /* [retval][out] */ LONG *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_virtualBaseOffset )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_virtual )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_intro )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_pure )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_callingConvention )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_value )( + IDiaSymbol * This, + /* [retval][out] */ VARIANT *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_baseType )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_token )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_timeStamp )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_guid )( + IDiaSymbol * This, + /* [retval][out] */ GUID *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_symbolsFileName )( + IDiaSymbol * This, + /* [retval][out] */ BSTR *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_reference )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_count )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_bitPosition )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_arrayIndexType )( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_packed )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_constructor )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_overloadedOperator )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_nested )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_hasNestedTypes )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_hasAssignmentOperator )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_hasCastOperator )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_scoped )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_virtualBaseClass )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_indirectVirtualBaseClass )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_virtualBasePointerOffset )( + IDiaSymbol * This, + /* [retval][out] */ LONG *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_virtualTableShape )( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_lexicalParentId )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_classParentId )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_typeId )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_arrayIndexTypeId )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_virtualTableShapeId )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_code )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_function )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_managed )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_msil )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_virtualBaseDispIndex )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_undecoratedName )( + IDiaSymbol * This, + /* [retval][out] */ BSTR *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_age )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_signature )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_compilerGenerated )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_addressTaken )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_rank )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_lowerBound )( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_upperBound )( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_lowerBoundId )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_upperBoundId )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *get_dataBytes )( + IDiaSymbol * This, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData); + + HRESULT ( STDMETHODCALLTYPE *findChildren )( + IDiaSymbol * This, + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findChildrenEx )( + IDiaSymbol * This, + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findChildrenExByAddr )( + IDiaSymbol * This, + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findChildrenExByVA )( + IDiaSymbol * This, + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [in] */ ULONGLONG va, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findChildrenExByRVA )( + IDiaSymbol * This, + /* [in] */ enum SymTagEnum symtag, + /* [in] */ LPCOLESTR name, + /* [in] */ DWORD compareFlags, + /* [in] */ DWORD rva, + /* [out] */ IDiaEnumSymbols **ppResult); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_targetSection )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_targetOffset )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_targetRelativeVirtualAddress )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_targetVirtualAddress )( + IDiaSymbol * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_machineType )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_oemId )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_oemSymbolId )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *get_types )( + IDiaSymbol * This, + /* [in] */ DWORD cTypes, + /* [out] */ DWORD *pcTypes, + /* [size_is][size_is][out] */ IDiaSymbol **pTypes); + + HRESULT ( STDMETHODCALLTYPE *get_typeIds )( + IDiaSymbol * This, + /* [in] */ DWORD cTypeIds, + /* [out] */ DWORD *pcTypeIds, + /* [size_is][out] */ DWORD *pdwTypeIds); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_objectPointerType )( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_udtKind )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *get_undecoratedNameEx )( + IDiaSymbol * This, + /* [in] */ DWORD undecorateOptions, + /* [out] */ BSTR *name); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_noReturn )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_customCallingConvention )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_noInline )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_optimizedCodeDebugInfo )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_notReached )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_interruptReturn )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_farReturn )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isStatic )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_hasDebugInfo )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isLTCG )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isDataAligned )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_hasSecurityChecks )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_compilerName )( + IDiaSymbol * This, + /* [retval][out] */ BSTR *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_hasAlloca )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_hasSetJump )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_hasLongJump )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_hasInlAsm )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_hasEH )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_hasSEH )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_hasEHa )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isNaked )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isAggregated )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isSplitted )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_container )( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_inlSpec )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_noStackOrdering )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_virtualBaseTableType )( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_hasManagedCode )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isHotpatchable )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isCVTCIL )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isMSILNetmodule )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isCTypes )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isStripped )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_frontEndQFE )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_backEndQFE )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_wasInlined )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_strictGSCheck )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isCxxReturnUdt )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isConstructorVirtualBase )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_RValueReference )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_unmodifiedType )( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_framePointerPresent )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isSafeBuffers )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_intrinsic )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_sealed )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_hfaFloat )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_hfaDouble )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_liveRangeStartAddressSection )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_liveRangeStartAddressOffset )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_liveRangeStartRelativeVirtualAddress )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_countLiveRanges )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_liveRangeLength )( + IDiaSymbol * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_offsetInUdt )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_paramBasePointerRegisterId )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_localBasePointerRegisterId )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isLocationControlFlowDependent )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_stride )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_numberOfRows )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_numberOfColumns )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isMatrixRowMajor )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *get_numericProperties )( + IDiaSymbol * This, + /* [in] */ DWORD cnt, + /* [out] */ DWORD *pcnt, + /* [size_is][out] */ DWORD *pProperties); + + HRESULT ( STDMETHODCALLTYPE *get_modifierValues )( + IDiaSymbol * This, + /* [in] */ DWORD cnt, + /* [out] */ DWORD *pcnt, + /* [size_is][out] */ WORD *pModifiers); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isReturnValue )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isOptimizedAway )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_builtInKind )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_registerType )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_baseDataSlot )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_baseDataOffset )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_textureSlot )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_samplerSlot )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_uavSlot )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_sizeInUdt )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_memorySpaceKind )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_unmodifiedTypeId )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_subTypeId )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_subType )( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_numberOfModifiers )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_numberOfRegisterIndices )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isHLSLData )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isPointerToDataMember )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isPointerToMemberFunction )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isSingleInheritance )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isMultipleInheritance )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isVirtualInheritance )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_restrictedType )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isPointerBasedOnSymbolValue )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_baseSymbol )( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_baseSymbolId )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_objectFileName )( + IDiaSymbol * This, + /* [retval][out] */ BSTR *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isAcceleratorGroupSharedLocal )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isAcceleratorPointerTagLiveRange )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isAcceleratorStubFunction )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_numberOfAcceleratorPointerTags )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isSdl )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isWinRTPointer )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isRefUdt )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isValueUdt )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isInterfaceUdt )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *findInlineFramesByAddr )( + IDiaSymbol * This, + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInlineFramesByRVA )( + IDiaSymbol * This, + /* [in] */ DWORD rva, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInlineFramesByVA )( + IDiaSymbol * This, + /* [in] */ ULONGLONG va, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInlineeLines )( + IDiaSymbol * This, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInlineeLinesByAddr )( + IDiaSymbol * This, + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInlineeLinesByRVA )( + IDiaSymbol * This, + /* [in] */ DWORD rva, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findInlineeLinesByVA )( + IDiaSymbol * This, + /* [in] */ ULONGLONG va, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findSymbolsForAcceleratorPointerTag )( + IDiaSymbol * This, + /* [in] */ DWORD tagValue, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *findSymbolsByRVAForAcceleratorPointerTag )( + IDiaSymbol * This, + /* [in] */ DWORD tagValue, + /* [in] */ DWORD rva, + /* [out] */ IDiaEnumSymbols **ppResult); + + HRESULT ( STDMETHODCALLTYPE *get_acceleratorPointerTags )( + IDiaSymbol * This, + /* [in] */ DWORD cnt, + /* [out] */ DWORD *pcnt, + /* [size_is][out] */ DWORD *pPointerTags); + + HRESULT ( STDMETHODCALLTYPE *getSrcLineOnTypeDefn )( + IDiaSymbol * This, + /* [out] */ IDiaLineNumber **ppResult); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isPGO )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_hasValidPGOCounts )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_isOptimizedForSpeed )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PGOEntryCount )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PGOEdgeCount )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PGODynamicInstructionCount )( + IDiaSymbol * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_staticSize )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_finalLiveStaticSize )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_phaseName )( + IDiaSymbol * This, + /* [retval][out] */ BSTR *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_hasControlFlowCheck )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_constantExport )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_dataExport )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_privateExport )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_noNameExport )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_exportHasExplicitlyAssignedOrdinal )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_exportIsForwarder )( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ordinal )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_frameSize )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_exceptionHandlerAddressSection )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_exceptionHandlerAddressOffset )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_exceptionHandlerRelativeVirtualAddress )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_exceptionHandlerVirtualAddress )( + IDiaSymbol * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *findInputAssemblyFile )( + IDiaSymbol * This, + /* [out] */ IDiaInputAssemblyFile **ppResult); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_characteristics )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_coffGroup )( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_bindID )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_bindSpace )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_bindSlot )( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + END_INTERFACE + } IDiaSymbolVtbl; + + interface IDiaSymbol + { + CONST_VTBL struct IDiaSymbolVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaSymbol_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaSymbol_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaSymbol_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaSymbol_get_symIndexId(This,pRetVal) \ + ( (This)->lpVtbl -> get_symIndexId(This,pRetVal) ) + +#define IDiaSymbol_get_symTag(This,pRetVal) \ + ( (This)->lpVtbl -> get_symTag(This,pRetVal) ) + +#define IDiaSymbol_get_name(This,pRetVal) \ + ( (This)->lpVtbl -> get_name(This,pRetVal) ) + +#define IDiaSymbol_get_lexicalParent(This,pRetVal) \ + ( (This)->lpVtbl -> get_lexicalParent(This,pRetVal) ) + +#define IDiaSymbol_get_classParent(This,pRetVal) \ + ( (This)->lpVtbl -> get_classParent(This,pRetVal) ) + +#define IDiaSymbol_get_type(This,pRetVal) \ + ( (This)->lpVtbl -> get_type(This,pRetVal) ) + +#define IDiaSymbol_get_dataKind(This,pRetVal) \ + ( (This)->lpVtbl -> get_dataKind(This,pRetVal) ) + +#define IDiaSymbol_get_locationType(This,pRetVal) \ + ( (This)->lpVtbl -> get_locationType(This,pRetVal) ) + +#define IDiaSymbol_get_addressSection(This,pRetVal) \ + ( (This)->lpVtbl -> get_addressSection(This,pRetVal) ) + +#define IDiaSymbol_get_addressOffset(This,pRetVal) \ + ( (This)->lpVtbl -> get_addressOffset(This,pRetVal) ) + +#define IDiaSymbol_get_relativeVirtualAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_relativeVirtualAddress(This,pRetVal) ) + +#define IDiaSymbol_get_virtualAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_virtualAddress(This,pRetVal) ) + +#define IDiaSymbol_get_registerId(This,pRetVal) \ + ( (This)->lpVtbl -> get_registerId(This,pRetVal) ) + +#define IDiaSymbol_get_offset(This,pRetVal) \ + ( (This)->lpVtbl -> get_offset(This,pRetVal) ) + +#define IDiaSymbol_get_length(This,pRetVal) \ + ( (This)->lpVtbl -> get_length(This,pRetVal) ) + +#define IDiaSymbol_get_slot(This,pRetVal) \ + ( (This)->lpVtbl -> get_slot(This,pRetVal) ) + +#define IDiaSymbol_get_volatileType(This,pRetVal) \ + ( (This)->lpVtbl -> get_volatileType(This,pRetVal) ) + +#define IDiaSymbol_get_constType(This,pRetVal) \ + ( (This)->lpVtbl -> get_constType(This,pRetVal) ) + +#define IDiaSymbol_get_unalignedType(This,pRetVal) \ + ( (This)->lpVtbl -> get_unalignedType(This,pRetVal) ) + +#define IDiaSymbol_get_access(This,pRetVal) \ + ( (This)->lpVtbl -> get_access(This,pRetVal) ) + +#define IDiaSymbol_get_libraryName(This,pRetVal) \ + ( (This)->lpVtbl -> get_libraryName(This,pRetVal) ) + +#define IDiaSymbol_get_platform(This,pRetVal) \ + ( (This)->lpVtbl -> get_platform(This,pRetVal) ) + +#define IDiaSymbol_get_language(This,pRetVal) \ + ( (This)->lpVtbl -> get_language(This,pRetVal) ) + +#define IDiaSymbol_get_editAndContinueEnabled(This,pRetVal) \ + ( (This)->lpVtbl -> get_editAndContinueEnabled(This,pRetVal) ) + +#define IDiaSymbol_get_frontEndMajor(This,pRetVal) \ + ( (This)->lpVtbl -> get_frontEndMajor(This,pRetVal) ) + +#define IDiaSymbol_get_frontEndMinor(This,pRetVal) \ + ( (This)->lpVtbl -> get_frontEndMinor(This,pRetVal) ) + +#define IDiaSymbol_get_frontEndBuild(This,pRetVal) \ + ( (This)->lpVtbl -> get_frontEndBuild(This,pRetVal) ) + +#define IDiaSymbol_get_backEndMajor(This,pRetVal) \ + ( (This)->lpVtbl -> get_backEndMajor(This,pRetVal) ) + +#define IDiaSymbol_get_backEndMinor(This,pRetVal) \ + ( (This)->lpVtbl -> get_backEndMinor(This,pRetVal) ) + +#define IDiaSymbol_get_backEndBuild(This,pRetVal) \ + ( (This)->lpVtbl -> get_backEndBuild(This,pRetVal) ) + +#define IDiaSymbol_get_sourceFileName(This,pRetVal) \ + ( (This)->lpVtbl -> get_sourceFileName(This,pRetVal) ) + +#define IDiaSymbol_get_unused(This,pRetVal) \ + ( (This)->lpVtbl -> get_unused(This,pRetVal) ) + +#define IDiaSymbol_get_thunkOrdinal(This,pRetVal) \ + ( (This)->lpVtbl -> get_thunkOrdinal(This,pRetVal) ) + +#define IDiaSymbol_get_thisAdjust(This,pRetVal) \ + ( (This)->lpVtbl -> get_thisAdjust(This,pRetVal) ) + +#define IDiaSymbol_get_virtualBaseOffset(This,pRetVal) \ + ( (This)->lpVtbl -> get_virtualBaseOffset(This,pRetVal) ) + +#define IDiaSymbol_get_virtual(This,pRetVal) \ + ( (This)->lpVtbl -> get_virtual(This,pRetVal) ) + +#define IDiaSymbol_get_intro(This,pRetVal) \ + ( (This)->lpVtbl -> get_intro(This,pRetVal) ) + +#define IDiaSymbol_get_pure(This,pRetVal) \ + ( (This)->lpVtbl -> get_pure(This,pRetVal) ) + +#define IDiaSymbol_get_callingConvention(This,pRetVal) \ + ( (This)->lpVtbl -> get_callingConvention(This,pRetVal) ) + +#define IDiaSymbol_get_value(This,pRetVal) \ + ( (This)->lpVtbl -> get_value(This,pRetVal) ) + +#define IDiaSymbol_get_baseType(This,pRetVal) \ + ( (This)->lpVtbl -> get_baseType(This,pRetVal) ) + +#define IDiaSymbol_get_token(This,pRetVal) \ + ( (This)->lpVtbl -> get_token(This,pRetVal) ) + +#define IDiaSymbol_get_timeStamp(This,pRetVal) \ + ( (This)->lpVtbl -> get_timeStamp(This,pRetVal) ) + +#define IDiaSymbol_get_guid(This,pRetVal) \ + ( (This)->lpVtbl -> get_guid(This,pRetVal) ) + +#define IDiaSymbol_get_symbolsFileName(This,pRetVal) \ + ( (This)->lpVtbl -> get_symbolsFileName(This,pRetVal) ) + +#define IDiaSymbol_get_reference(This,pRetVal) \ + ( (This)->lpVtbl -> get_reference(This,pRetVal) ) + +#define IDiaSymbol_get_count(This,pRetVal) \ + ( (This)->lpVtbl -> get_count(This,pRetVal) ) + +#define IDiaSymbol_get_bitPosition(This,pRetVal) \ + ( (This)->lpVtbl -> get_bitPosition(This,pRetVal) ) + +#define IDiaSymbol_get_arrayIndexType(This,pRetVal) \ + ( (This)->lpVtbl -> get_arrayIndexType(This,pRetVal) ) + +#define IDiaSymbol_get_packed(This,pRetVal) \ + ( (This)->lpVtbl -> get_packed(This,pRetVal) ) + +#define IDiaSymbol_get_constructor(This,pRetVal) \ + ( (This)->lpVtbl -> get_constructor(This,pRetVal) ) + +#define IDiaSymbol_get_overloadedOperator(This,pRetVal) \ + ( (This)->lpVtbl -> get_overloadedOperator(This,pRetVal) ) + +#define IDiaSymbol_get_nested(This,pRetVal) \ + ( (This)->lpVtbl -> get_nested(This,pRetVal) ) + +#define IDiaSymbol_get_hasNestedTypes(This,pRetVal) \ + ( (This)->lpVtbl -> get_hasNestedTypes(This,pRetVal) ) + +#define IDiaSymbol_get_hasAssignmentOperator(This,pRetVal) \ + ( (This)->lpVtbl -> get_hasAssignmentOperator(This,pRetVal) ) + +#define IDiaSymbol_get_hasCastOperator(This,pRetVal) \ + ( (This)->lpVtbl -> get_hasCastOperator(This,pRetVal) ) + +#define IDiaSymbol_get_scoped(This,pRetVal) \ + ( (This)->lpVtbl -> get_scoped(This,pRetVal) ) + +#define IDiaSymbol_get_virtualBaseClass(This,pRetVal) \ + ( (This)->lpVtbl -> get_virtualBaseClass(This,pRetVal) ) + +#define IDiaSymbol_get_indirectVirtualBaseClass(This,pRetVal) \ + ( (This)->lpVtbl -> get_indirectVirtualBaseClass(This,pRetVal) ) + +#define IDiaSymbol_get_virtualBasePointerOffset(This,pRetVal) \ + ( (This)->lpVtbl -> get_virtualBasePointerOffset(This,pRetVal) ) + +#define IDiaSymbol_get_virtualTableShape(This,pRetVal) \ + ( (This)->lpVtbl -> get_virtualTableShape(This,pRetVal) ) + +#define IDiaSymbol_get_lexicalParentId(This,pRetVal) \ + ( (This)->lpVtbl -> get_lexicalParentId(This,pRetVal) ) + +#define IDiaSymbol_get_classParentId(This,pRetVal) \ + ( (This)->lpVtbl -> get_classParentId(This,pRetVal) ) + +#define IDiaSymbol_get_typeId(This,pRetVal) \ + ( (This)->lpVtbl -> get_typeId(This,pRetVal) ) + +#define IDiaSymbol_get_arrayIndexTypeId(This,pRetVal) \ + ( (This)->lpVtbl -> get_arrayIndexTypeId(This,pRetVal) ) + +#define IDiaSymbol_get_virtualTableShapeId(This,pRetVal) \ + ( (This)->lpVtbl -> get_virtualTableShapeId(This,pRetVal) ) + +#define IDiaSymbol_get_code(This,pRetVal) \ + ( (This)->lpVtbl -> get_code(This,pRetVal) ) + +#define IDiaSymbol_get_function(This,pRetVal) \ + ( (This)->lpVtbl -> get_function(This,pRetVal) ) + +#define IDiaSymbol_get_managed(This,pRetVal) \ + ( (This)->lpVtbl -> get_managed(This,pRetVal) ) + +#define IDiaSymbol_get_msil(This,pRetVal) \ + ( (This)->lpVtbl -> get_msil(This,pRetVal) ) + +#define IDiaSymbol_get_virtualBaseDispIndex(This,pRetVal) \ + ( (This)->lpVtbl -> get_virtualBaseDispIndex(This,pRetVal) ) + +#define IDiaSymbol_get_undecoratedName(This,pRetVal) \ + ( (This)->lpVtbl -> get_undecoratedName(This,pRetVal) ) + +#define IDiaSymbol_get_age(This,pRetVal) \ + ( (This)->lpVtbl -> get_age(This,pRetVal) ) + +#define IDiaSymbol_get_signature(This,pRetVal) \ + ( (This)->lpVtbl -> get_signature(This,pRetVal) ) + +#define IDiaSymbol_get_compilerGenerated(This,pRetVal) \ + ( (This)->lpVtbl -> get_compilerGenerated(This,pRetVal) ) + +#define IDiaSymbol_get_addressTaken(This,pRetVal) \ + ( (This)->lpVtbl -> get_addressTaken(This,pRetVal) ) + +#define IDiaSymbol_get_rank(This,pRetVal) \ + ( (This)->lpVtbl -> get_rank(This,pRetVal) ) + +#define IDiaSymbol_get_lowerBound(This,pRetVal) \ + ( (This)->lpVtbl -> get_lowerBound(This,pRetVal) ) + +#define IDiaSymbol_get_upperBound(This,pRetVal) \ + ( (This)->lpVtbl -> get_upperBound(This,pRetVal) ) + +#define IDiaSymbol_get_lowerBoundId(This,pRetVal) \ + ( (This)->lpVtbl -> get_lowerBoundId(This,pRetVal) ) + +#define IDiaSymbol_get_upperBoundId(This,pRetVal) \ + ( (This)->lpVtbl -> get_upperBoundId(This,pRetVal) ) + +#define IDiaSymbol_get_dataBytes(This,cbData,pcbData,pbData) \ + ( (This)->lpVtbl -> get_dataBytes(This,cbData,pcbData,pbData) ) + +#define IDiaSymbol_findChildren(This,symtag,name,compareFlags,ppResult) \ + ( (This)->lpVtbl -> findChildren(This,symtag,name,compareFlags,ppResult) ) + +#define IDiaSymbol_findChildrenEx(This,symtag,name,compareFlags,ppResult) \ + ( (This)->lpVtbl -> findChildrenEx(This,symtag,name,compareFlags,ppResult) ) + +#define IDiaSymbol_findChildrenExByAddr(This,symtag,name,compareFlags,isect,offset,ppResult) \ + ( (This)->lpVtbl -> findChildrenExByAddr(This,symtag,name,compareFlags,isect,offset,ppResult) ) + +#define IDiaSymbol_findChildrenExByVA(This,symtag,name,compareFlags,va,ppResult) \ + ( (This)->lpVtbl -> findChildrenExByVA(This,symtag,name,compareFlags,va,ppResult) ) + +#define IDiaSymbol_findChildrenExByRVA(This,symtag,name,compareFlags,rva,ppResult) \ + ( (This)->lpVtbl -> findChildrenExByRVA(This,symtag,name,compareFlags,rva,ppResult) ) + +#define IDiaSymbol_get_targetSection(This,pRetVal) \ + ( (This)->lpVtbl -> get_targetSection(This,pRetVal) ) + +#define IDiaSymbol_get_targetOffset(This,pRetVal) \ + ( (This)->lpVtbl -> get_targetOffset(This,pRetVal) ) + +#define IDiaSymbol_get_targetRelativeVirtualAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_targetRelativeVirtualAddress(This,pRetVal) ) + +#define IDiaSymbol_get_targetVirtualAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_targetVirtualAddress(This,pRetVal) ) + +#define IDiaSymbol_get_machineType(This,pRetVal) \ + ( (This)->lpVtbl -> get_machineType(This,pRetVal) ) + +#define IDiaSymbol_get_oemId(This,pRetVal) \ + ( (This)->lpVtbl -> get_oemId(This,pRetVal) ) + +#define IDiaSymbol_get_oemSymbolId(This,pRetVal) \ + ( (This)->lpVtbl -> get_oemSymbolId(This,pRetVal) ) + +#define IDiaSymbol_get_types(This,cTypes,pcTypes,pTypes) \ + ( (This)->lpVtbl -> get_types(This,cTypes,pcTypes,pTypes) ) + +#define IDiaSymbol_get_typeIds(This,cTypeIds,pcTypeIds,pdwTypeIds) \ + ( (This)->lpVtbl -> get_typeIds(This,cTypeIds,pcTypeIds,pdwTypeIds) ) + +#define IDiaSymbol_get_objectPointerType(This,pRetVal) \ + ( (This)->lpVtbl -> get_objectPointerType(This,pRetVal) ) + +#define IDiaSymbol_get_udtKind(This,pRetVal) \ + ( (This)->lpVtbl -> get_udtKind(This,pRetVal) ) + +#define IDiaSymbol_get_undecoratedNameEx(This,undecorateOptions,name) \ + ( (This)->lpVtbl -> get_undecoratedNameEx(This,undecorateOptions,name) ) + +#define IDiaSymbol_get_noReturn(This,pRetVal) \ + ( (This)->lpVtbl -> get_noReturn(This,pRetVal) ) + +#define IDiaSymbol_get_customCallingConvention(This,pRetVal) \ + ( (This)->lpVtbl -> get_customCallingConvention(This,pRetVal) ) + +#define IDiaSymbol_get_noInline(This,pRetVal) \ + ( (This)->lpVtbl -> get_noInline(This,pRetVal) ) + +#define IDiaSymbol_get_optimizedCodeDebugInfo(This,pRetVal) \ + ( (This)->lpVtbl -> get_optimizedCodeDebugInfo(This,pRetVal) ) + +#define IDiaSymbol_get_notReached(This,pRetVal) \ + ( (This)->lpVtbl -> get_notReached(This,pRetVal) ) + +#define IDiaSymbol_get_interruptReturn(This,pRetVal) \ + ( (This)->lpVtbl -> get_interruptReturn(This,pRetVal) ) + +#define IDiaSymbol_get_farReturn(This,pRetVal) \ + ( (This)->lpVtbl -> get_farReturn(This,pRetVal) ) + +#define IDiaSymbol_get_isStatic(This,pRetVal) \ + ( (This)->lpVtbl -> get_isStatic(This,pRetVal) ) + +#define IDiaSymbol_get_hasDebugInfo(This,pRetVal) \ + ( (This)->lpVtbl -> get_hasDebugInfo(This,pRetVal) ) + +#define IDiaSymbol_get_isLTCG(This,pRetVal) \ + ( (This)->lpVtbl -> get_isLTCG(This,pRetVal) ) + +#define IDiaSymbol_get_isDataAligned(This,pRetVal) \ + ( (This)->lpVtbl -> get_isDataAligned(This,pRetVal) ) + +#define IDiaSymbol_get_hasSecurityChecks(This,pRetVal) \ + ( (This)->lpVtbl -> get_hasSecurityChecks(This,pRetVal) ) + +#define IDiaSymbol_get_compilerName(This,pRetVal) \ + ( (This)->lpVtbl -> get_compilerName(This,pRetVal) ) + +#define IDiaSymbol_get_hasAlloca(This,pRetVal) \ + ( (This)->lpVtbl -> get_hasAlloca(This,pRetVal) ) + +#define IDiaSymbol_get_hasSetJump(This,pRetVal) \ + ( (This)->lpVtbl -> get_hasSetJump(This,pRetVal) ) + +#define IDiaSymbol_get_hasLongJump(This,pRetVal) \ + ( (This)->lpVtbl -> get_hasLongJump(This,pRetVal) ) + +#define IDiaSymbol_get_hasInlAsm(This,pRetVal) \ + ( (This)->lpVtbl -> get_hasInlAsm(This,pRetVal) ) + +#define IDiaSymbol_get_hasEH(This,pRetVal) \ + ( (This)->lpVtbl -> get_hasEH(This,pRetVal) ) + +#define IDiaSymbol_get_hasSEH(This,pRetVal) \ + ( (This)->lpVtbl -> get_hasSEH(This,pRetVal) ) + +#define IDiaSymbol_get_hasEHa(This,pRetVal) \ + ( (This)->lpVtbl -> get_hasEHa(This,pRetVal) ) + +#define IDiaSymbol_get_isNaked(This,pRetVal) \ + ( (This)->lpVtbl -> get_isNaked(This,pRetVal) ) + +#define IDiaSymbol_get_isAggregated(This,pRetVal) \ + ( (This)->lpVtbl -> get_isAggregated(This,pRetVal) ) + +#define IDiaSymbol_get_isSplitted(This,pRetVal) \ + ( (This)->lpVtbl -> get_isSplitted(This,pRetVal) ) + +#define IDiaSymbol_get_container(This,pRetVal) \ + ( (This)->lpVtbl -> get_container(This,pRetVal) ) + +#define IDiaSymbol_get_inlSpec(This,pRetVal) \ + ( (This)->lpVtbl -> get_inlSpec(This,pRetVal) ) + +#define IDiaSymbol_get_noStackOrdering(This,pRetVal) \ + ( (This)->lpVtbl -> get_noStackOrdering(This,pRetVal) ) + +#define IDiaSymbol_get_virtualBaseTableType(This,pRetVal) \ + ( (This)->lpVtbl -> get_virtualBaseTableType(This,pRetVal) ) + +#define IDiaSymbol_get_hasManagedCode(This,pRetVal) \ + ( (This)->lpVtbl -> get_hasManagedCode(This,pRetVal) ) + +#define IDiaSymbol_get_isHotpatchable(This,pRetVal) \ + ( (This)->lpVtbl -> get_isHotpatchable(This,pRetVal) ) + +#define IDiaSymbol_get_isCVTCIL(This,pRetVal) \ + ( (This)->lpVtbl -> get_isCVTCIL(This,pRetVal) ) + +#define IDiaSymbol_get_isMSILNetmodule(This,pRetVal) \ + ( (This)->lpVtbl -> get_isMSILNetmodule(This,pRetVal) ) + +#define IDiaSymbol_get_isCTypes(This,pRetVal) \ + ( (This)->lpVtbl -> get_isCTypes(This,pRetVal) ) + +#define IDiaSymbol_get_isStripped(This,pRetVal) \ + ( (This)->lpVtbl -> get_isStripped(This,pRetVal) ) + +#define IDiaSymbol_get_frontEndQFE(This,pRetVal) \ + ( (This)->lpVtbl -> get_frontEndQFE(This,pRetVal) ) + +#define IDiaSymbol_get_backEndQFE(This,pRetVal) \ + ( (This)->lpVtbl -> get_backEndQFE(This,pRetVal) ) + +#define IDiaSymbol_get_wasInlined(This,pRetVal) \ + ( (This)->lpVtbl -> get_wasInlined(This,pRetVal) ) + +#define IDiaSymbol_get_strictGSCheck(This,pRetVal) \ + ( (This)->lpVtbl -> get_strictGSCheck(This,pRetVal) ) + +#define IDiaSymbol_get_isCxxReturnUdt(This,pRetVal) \ + ( (This)->lpVtbl -> get_isCxxReturnUdt(This,pRetVal) ) + +#define IDiaSymbol_get_isConstructorVirtualBase(This,pRetVal) \ + ( (This)->lpVtbl -> get_isConstructorVirtualBase(This,pRetVal) ) + +#define IDiaSymbol_get_RValueReference(This,pRetVal) \ + ( (This)->lpVtbl -> get_RValueReference(This,pRetVal) ) + +#define IDiaSymbol_get_unmodifiedType(This,pRetVal) \ + ( (This)->lpVtbl -> get_unmodifiedType(This,pRetVal) ) + +#define IDiaSymbol_get_framePointerPresent(This,pRetVal) \ + ( (This)->lpVtbl -> get_framePointerPresent(This,pRetVal) ) + +#define IDiaSymbol_get_isSafeBuffers(This,pRetVal) \ + ( (This)->lpVtbl -> get_isSafeBuffers(This,pRetVal) ) + +#define IDiaSymbol_get_intrinsic(This,pRetVal) \ + ( (This)->lpVtbl -> get_intrinsic(This,pRetVal) ) + +#define IDiaSymbol_get_sealed(This,pRetVal) \ + ( (This)->lpVtbl -> get_sealed(This,pRetVal) ) + +#define IDiaSymbol_get_hfaFloat(This,pRetVal) \ + ( (This)->lpVtbl -> get_hfaFloat(This,pRetVal) ) + +#define IDiaSymbol_get_hfaDouble(This,pRetVal) \ + ( (This)->lpVtbl -> get_hfaDouble(This,pRetVal) ) + +#define IDiaSymbol_get_liveRangeStartAddressSection(This,pRetVal) \ + ( (This)->lpVtbl -> get_liveRangeStartAddressSection(This,pRetVal) ) + +#define IDiaSymbol_get_liveRangeStartAddressOffset(This,pRetVal) \ + ( (This)->lpVtbl -> get_liveRangeStartAddressOffset(This,pRetVal) ) + +#define IDiaSymbol_get_liveRangeStartRelativeVirtualAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_liveRangeStartRelativeVirtualAddress(This,pRetVal) ) + +#define IDiaSymbol_get_countLiveRanges(This,pRetVal) \ + ( (This)->lpVtbl -> get_countLiveRanges(This,pRetVal) ) + +#define IDiaSymbol_get_liveRangeLength(This,pRetVal) \ + ( (This)->lpVtbl -> get_liveRangeLength(This,pRetVal) ) + +#define IDiaSymbol_get_offsetInUdt(This,pRetVal) \ + ( (This)->lpVtbl -> get_offsetInUdt(This,pRetVal) ) + +#define IDiaSymbol_get_paramBasePointerRegisterId(This,pRetVal) \ + ( (This)->lpVtbl -> get_paramBasePointerRegisterId(This,pRetVal) ) + +#define IDiaSymbol_get_localBasePointerRegisterId(This,pRetVal) \ + ( (This)->lpVtbl -> get_localBasePointerRegisterId(This,pRetVal) ) + +#define IDiaSymbol_get_isLocationControlFlowDependent(This,pRetVal) \ + ( (This)->lpVtbl -> get_isLocationControlFlowDependent(This,pRetVal) ) + +#define IDiaSymbol_get_stride(This,pRetVal) \ + ( (This)->lpVtbl -> get_stride(This,pRetVal) ) + +#define IDiaSymbol_get_numberOfRows(This,pRetVal) \ + ( (This)->lpVtbl -> get_numberOfRows(This,pRetVal) ) + +#define IDiaSymbol_get_numberOfColumns(This,pRetVal) \ + ( (This)->lpVtbl -> get_numberOfColumns(This,pRetVal) ) + +#define IDiaSymbol_get_isMatrixRowMajor(This,pRetVal) \ + ( (This)->lpVtbl -> get_isMatrixRowMajor(This,pRetVal) ) + +#define IDiaSymbol_get_numericProperties(This,cnt,pcnt,pProperties) \ + ( (This)->lpVtbl -> get_numericProperties(This,cnt,pcnt,pProperties) ) + +#define IDiaSymbol_get_modifierValues(This,cnt,pcnt,pModifiers) \ + ( (This)->lpVtbl -> get_modifierValues(This,cnt,pcnt,pModifiers) ) + +#define IDiaSymbol_get_isReturnValue(This,pRetVal) \ + ( (This)->lpVtbl -> get_isReturnValue(This,pRetVal) ) + +#define IDiaSymbol_get_isOptimizedAway(This,pRetVal) \ + ( (This)->lpVtbl -> get_isOptimizedAway(This,pRetVal) ) + +#define IDiaSymbol_get_builtInKind(This,pRetVal) \ + ( (This)->lpVtbl -> get_builtInKind(This,pRetVal) ) + +#define IDiaSymbol_get_registerType(This,pRetVal) \ + ( (This)->lpVtbl -> get_registerType(This,pRetVal) ) + +#define IDiaSymbol_get_baseDataSlot(This,pRetVal) \ + ( (This)->lpVtbl -> get_baseDataSlot(This,pRetVal) ) + +#define IDiaSymbol_get_baseDataOffset(This,pRetVal) \ + ( (This)->lpVtbl -> get_baseDataOffset(This,pRetVal) ) + +#define IDiaSymbol_get_textureSlot(This,pRetVal) \ + ( (This)->lpVtbl -> get_textureSlot(This,pRetVal) ) + +#define IDiaSymbol_get_samplerSlot(This,pRetVal) \ + ( (This)->lpVtbl -> get_samplerSlot(This,pRetVal) ) + +#define IDiaSymbol_get_uavSlot(This,pRetVal) \ + ( (This)->lpVtbl -> get_uavSlot(This,pRetVal) ) + +#define IDiaSymbol_get_sizeInUdt(This,pRetVal) \ + ( (This)->lpVtbl -> get_sizeInUdt(This,pRetVal) ) + +#define IDiaSymbol_get_memorySpaceKind(This,pRetVal) \ + ( (This)->lpVtbl -> get_memorySpaceKind(This,pRetVal) ) + +#define IDiaSymbol_get_unmodifiedTypeId(This,pRetVal) \ + ( (This)->lpVtbl -> get_unmodifiedTypeId(This,pRetVal) ) + +#define IDiaSymbol_get_subTypeId(This,pRetVal) \ + ( (This)->lpVtbl -> get_subTypeId(This,pRetVal) ) + +#define IDiaSymbol_get_subType(This,pRetVal) \ + ( (This)->lpVtbl -> get_subType(This,pRetVal) ) + +#define IDiaSymbol_get_numberOfModifiers(This,pRetVal) \ + ( (This)->lpVtbl -> get_numberOfModifiers(This,pRetVal) ) + +#define IDiaSymbol_get_numberOfRegisterIndices(This,pRetVal) \ + ( (This)->lpVtbl -> get_numberOfRegisterIndices(This,pRetVal) ) + +#define IDiaSymbol_get_isHLSLData(This,pRetVal) \ + ( (This)->lpVtbl -> get_isHLSLData(This,pRetVal) ) + +#define IDiaSymbol_get_isPointerToDataMember(This,pRetVal) \ + ( (This)->lpVtbl -> get_isPointerToDataMember(This,pRetVal) ) + +#define IDiaSymbol_get_isPointerToMemberFunction(This,pRetVal) \ + ( (This)->lpVtbl -> get_isPointerToMemberFunction(This,pRetVal) ) + +#define IDiaSymbol_get_isSingleInheritance(This,pRetVal) \ + ( (This)->lpVtbl -> get_isSingleInheritance(This,pRetVal) ) + +#define IDiaSymbol_get_isMultipleInheritance(This,pRetVal) \ + ( (This)->lpVtbl -> get_isMultipleInheritance(This,pRetVal) ) + +#define IDiaSymbol_get_isVirtualInheritance(This,pRetVal) \ + ( (This)->lpVtbl -> get_isVirtualInheritance(This,pRetVal) ) + +#define IDiaSymbol_get_restrictedType(This,pRetVal) \ + ( (This)->lpVtbl -> get_restrictedType(This,pRetVal) ) + +#define IDiaSymbol_get_isPointerBasedOnSymbolValue(This,pRetVal) \ + ( (This)->lpVtbl -> get_isPointerBasedOnSymbolValue(This,pRetVal) ) + +#define IDiaSymbol_get_baseSymbol(This,pRetVal) \ + ( (This)->lpVtbl -> get_baseSymbol(This,pRetVal) ) + +#define IDiaSymbol_get_baseSymbolId(This,pRetVal) \ + ( (This)->lpVtbl -> get_baseSymbolId(This,pRetVal) ) + +#define IDiaSymbol_get_objectFileName(This,pRetVal) \ + ( (This)->lpVtbl -> get_objectFileName(This,pRetVal) ) + +#define IDiaSymbol_get_isAcceleratorGroupSharedLocal(This,pRetVal) \ + ( (This)->lpVtbl -> get_isAcceleratorGroupSharedLocal(This,pRetVal) ) + +#define IDiaSymbol_get_isAcceleratorPointerTagLiveRange(This,pRetVal) \ + ( (This)->lpVtbl -> get_isAcceleratorPointerTagLiveRange(This,pRetVal) ) + +#define IDiaSymbol_get_isAcceleratorStubFunction(This,pRetVal) \ + ( (This)->lpVtbl -> get_isAcceleratorStubFunction(This,pRetVal) ) + +#define IDiaSymbol_get_numberOfAcceleratorPointerTags(This,pRetVal) \ + ( (This)->lpVtbl -> get_numberOfAcceleratorPointerTags(This,pRetVal) ) + +#define IDiaSymbol_get_isSdl(This,pRetVal) \ + ( (This)->lpVtbl -> get_isSdl(This,pRetVal) ) + +#define IDiaSymbol_get_isWinRTPointer(This,pRetVal) \ + ( (This)->lpVtbl -> get_isWinRTPointer(This,pRetVal) ) + +#define IDiaSymbol_get_isRefUdt(This,pRetVal) \ + ( (This)->lpVtbl -> get_isRefUdt(This,pRetVal) ) + +#define IDiaSymbol_get_isValueUdt(This,pRetVal) \ + ( (This)->lpVtbl -> get_isValueUdt(This,pRetVal) ) + +#define IDiaSymbol_get_isInterfaceUdt(This,pRetVal) \ + ( (This)->lpVtbl -> get_isInterfaceUdt(This,pRetVal) ) + +#define IDiaSymbol_findInlineFramesByAddr(This,isect,offset,ppResult) \ + ( (This)->lpVtbl -> findInlineFramesByAddr(This,isect,offset,ppResult) ) + +#define IDiaSymbol_findInlineFramesByRVA(This,rva,ppResult) \ + ( (This)->lpVtbl -> findInlineFramesByRVA(This,rva,ppResult) ) + +#define IDiaSymbol_findInlineFramesByVA(This,va,ppResult) \ + ( (This)->lpVtbl -> findInlineFramesByVA(This,va,ppResult) ) + +#define IDiaSymbol_findInlineeLines(This,ppResult) \ + ( (This)->lpVtbl -> findInlineeLines(This,ppResult) ) + +#define IDiaSymbol_findInlineeLinesByAddr(This,isect,offset,length,ppResult) \ + ( (This)->lpVtbl -> findInlineeLinesByAddr(This,isect,offset,length,ppResult) ) + +#define IDiaSymbol_findInlineeLinesByRVA(This,rva,length,ppResult) \ + ( (This)->lpVtbl -> findInlineeLinesByRVA(This,rva,length,ppResult) ) + +#define IDiaSymbol_findInlineeLinesByVA(This,va,length,ppResult) \ + ( (This)->lpVtbl -> findInlineeLinesByVA(This,va,length,ppResult) ) + +#define IDiaSymbol_findSymbolsForAcceleratorPointerTag(This,tagValue,ppResult) \ + ( (This)->lpVtbl -> findSymbolsForAcceleratorPointerTag(This,tagValue,ppResult) ) + +#define IDiaSymbol_findSymbolsByRVAForAcceleratorPointerTag(This,tagValue,rva,ppResult) \ + ( (This)->lpVtbl -> findSymbolsByRVAForAcceleratorPointerTag(This,tagValue,rva,ppResult) ) + +#define IDiaSymbol_get_acceleratorPointerTags(This,cnt,pcnt,pPointerTags) \ + ( (This)->lpVtbl -> get_acceleratorPointerTags(This,cnt,pcnt,pPointerTags) ) + +#define IDiaSymbol_getSrcLineOnTypeDefn(This,ppResult) \ + ( (This)->lpVtbl -> getSrcLineOnTypeDefn(This,ppResult) ) + +#define IDiaSymbol_get_isPGO(This,pRetVal) \ + ( (This)->lpVtbl -> get_isPGO(This,pRetVal) ) + +#define IDiaSymbol_get_hasValidPGOCounts(This,pRetVal) \ + ( (This)->lpVtbl -> get_hasValidPGOCounts(This,pRetVal) ) + +#define IDiaSymbol_get_isOptimizedForSpeed(This,pRetVal) \ + ( (This)->lpVtbl -> get_isOptimizedForSpeed(This,pRetVal) ) + +#define IDiaSymbol_get_PGOEntryCount(This,pRetVal) \ + ( (This)->lpVtbl -> get_PGOEntryCount(This,pRetVal) ) + +#define IDiaSymbol_get_PGOEdgeCount(This,pRetVal) \ + ( (This)->lpVtbl -> get_PGOEdgeCount(This,pRetVal) ) + +#define IDiaSymbol_get_PGODynamicInstructionCount(This,pRetVal) \ + ( (This)->lpVtbl -> get_PGODynamicInstructionCount(This,pRetVal) ) + +#define IDiaSymbol_get_staticSize(This,pRetVal) \ + ( (This)->lpVtbl -> get_staticSize(This,pRetVal) ) + +#define IDiaSymbol_get_finalLiveStaticSize(This,pRetVal) \ + ( (This)->lpVtbl -> get_finalLiveStaticSize(This,pRetVal) ) + +#define IDiaSymbol_get_phaseName(This,pRetVal) \ + ( (This)->lpVtbl -> get_phaseName(This,pRetVal) ) + +#define IDiaSymbol_get_hasControlFlowCheck(This,pRetVal) \ + ( (This)->lpVtbl -> get_hasControlFlowCheck(This,pRetVal) ) + +#define IDiaSymbol_get_constantExport(This,pRetVal) \ + ( (This)->lpVtbl -> get_constantExport(This,pRetVal) ) + +#define IDiaSymbol_get_dataExport(This,pRetVal) \ + ( (This)->lpVtbl -> get_dataExport(This,pRetVal) ) + +#define IDiaSymbol_get_privateExport(This,pRetVal) \ + ( (This)->lpVtbl -> get_privateExport(This,pRetVal) ) + +#define IDiaSymbol_get_noNameExport(This,pRetVal) \ + ( (This)->lpVtbl -> get_noNameExport(This,pRetVal) ) + +#define IDiaSymbol_get_exportHasExplicitlyAssignedOrdinal(This,pRetVal) \ + ( (This)->lpVtbl -> get_exportHasExplicitlyAssignedOrdinal(This,pRetVal) ) + +#define IDiaSymbol_get_exportIsForwarder(This,pRetVal) \ + ( (This)->lpVtbl -> get_exportIsForwarder(This,pRetVal) ) + +#define IDiaSymbol_get_ordinal(This,pRetVal) \ + ( (This)->lpVtbl -> get_ordinal(This,pRetVal) ) + +#define IDiaSymbol_get_frameSize(This,pRetVal) \ + ( (This)->lpVtbl -> get_frameSize(This,pRetVal) ) + +#define IDiaSymbol_get_exceptionHandlerAddressSection(This,pRetVal) \ + ( (This)->lpVtbl -> get_exceptionHandlerAddressSection(This,pRetVal) ) + +#define IDiaSymbol_get_exceptionHandlerAddressOffset(This,pRetVal) \ + ( (This)->lpVtbl -> get_exceptionHandlerAddressOffset(This,pRetVal) ) + +#define IDiaSymbol_get_exceptionHandlerRelativeVirtualAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_exceptionHandlerRelativeVirtualAddress(This,pRetVal) ) + +#define IDiaSymbol_get_exceptionHandlerVirtualAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_exceptionHandlerVirtualAddress(This,pRetVal) ) + +#define IDiaSymbol_findInputAssemblyFile(This,ppResult) \ + ( (This)->lpVtbl -> findInputAssemblyFile(This,ppResult) ) + +#define IDiaSymbol_get_characteristics(This,pRetVal) \ + ( (This)->lpVtbl -> get_characteristics(This,pRetVal) ) + +#define IDiaSymbol_get_coffGroup(This,pRetVal) \ + ( (This)->lpVtbl -> get_coffGroup(This,pRetVal) ) + +#define IDiaSymbol_get_bindID(This,pRetVal) \ + ( (This)->lpVtbl -> get_bindID(This,pRetVal) ) + +#define IDiaSymbol_get_bindSpace(This,pRetVal) \ + ( (This)->lpVtbl -> get_bindSpace(This,pRetVal) ) + +#define IDiaSymbol_get_bindSlot(This,pRetVal) \ + ( (This)->lpVtbl -> get_bindSlot(This,pRetVal) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_virtualBaseTableType_Proxy( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + +void __RPC_STUB IDiaSymbol_get_virtualBaseTableType_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_hasManagedCode_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_hasManagedCode_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isHotpatchable_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isHotpatchable_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isCVTCIL_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isCVTCIL_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isMSILNetmodule_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isMSILNetmodule_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isCTypes_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isCTypes_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isStripped_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isStripped_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_frontEndQFE_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_frontEndQFE_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_backEndQFE_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_backEndQFE_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_wasInlined_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_wasInlined_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_strictGSCheck_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_strictGSCheck_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isCxxReturnUdt_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isCxxReturnUdt_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isConstructorVirtualBase_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isConstructorVirtualBase_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_RValueReference_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_RValueReference_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_unmodifiedType_Proxy( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + +void __RPC_STUB IDiaSymbol_get_unmodifiedType_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_framePointerPresent_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_framePointerPresent_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isSafeBuffers_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isSafeBuffers_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_intrinsic_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_intrinsic_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_sealed_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_sealed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_hfaFloat_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_hfaFloat_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_hfaDouble_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_hfaDouble_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_liveRangeStartAddressSection_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_liveRangeStartAddressSection_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_liveRangeStartAddressOffset_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_liveRangeStartAddressOffset_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_liveRangeStartRelativeVirtualAddress_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_liveRangeStartRelativeVirtualAddress_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_countLiveRanges_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_countLiveRanges_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_liveRangeLength_Proxy( + IDiaSymbol * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_liveRangeLength_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_offsetInUdt_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_offsetInUdt_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_paramBasePointerRegisterId_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_paramBasePointerRegisterId_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_localBasePointerRegisterId_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_localBasePointerRegisterId_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isLocationControlFlowDependent_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isLocationControlFlowDependent_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_stride_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_stride_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_numberOfRows_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_numberOfRows_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_numberOfColumns_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_numberOfColumns_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isMatrixRowMajor_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isMatrixRowMajor_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDiaSymbol_get_numericProperties_Proxy( + IDiaSymbol * This, + /* [in] */ DWORD cnt, + /* [out] */ DWORD *pcnt, + /* [size_is][out] */ DWORD *pProperties); + + +void __RPC_STUB IDiaSymbol_get_numericProperties_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDiaSymbol_get_modifierValues_Proxy( + IDiaSymbol * This, + /* [in] */ DWORD cnt, + /* [out] */ DWORD *pcnt, + /* [size_is][out] */ WORD *pModifiers); + + +void __RPC_STUB IDiaSymbol_get_modifierValues_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isReturnValue_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isReturnValue_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isOptimizedAway_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isOptimizedAway_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_builtInKind_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_builtInKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_registerType_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_registerType_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_baseDataSlot_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_baseDataSlot_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_baseDataOffset_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_baseDataOffset_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_textureSlot_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_textureSlot_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_samplerSlot_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_samplerSlot_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_uavSlot_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_uavSlot_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_sizeInUdt_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_sizeInUdt_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_memorySpaceKind_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_memorySpaceKind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_unmodifiedTypeId_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_unmodifiedTypeId_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_subTypeId_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_subTypeId_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_subType_Proxy( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + +void __RPC_STUB IDiaSymbol_get_subType_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_numberOfModifiers_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_numberOfModifiers_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_numberOfRegisterIndices_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_numberOfRegisterIndices_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isHLSLData_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isHLSLData_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isPointerToDataMember_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isPointerToDataMember_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isPointerToMemberFunction_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isPointerToMemberFunction_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isSingleInheritance_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isSingleInheritance_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isMultipleInheritance_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isMultipleInheritance_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isVirtualInheritance_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isVirtualInheritance_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_restrictedType_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_restrictedType_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isPointerBasedOnSymbolValue_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isPointerBasedOnSymbolValue_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_baseSymbol_Proxy( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + +void __RPC_STUB IDiaSymbol_get_baseSymbol_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_baseSymbolId_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_baseSymbolId_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_objectFileName_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BSTR *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_objectFileName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isAcceleratorGroupSharedLocal_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isAcceleratorGroupSharedLocal_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isAcceleratorPointerTagLiveRange_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isAcceleratorPointerTagLiveRange_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isAcceleratorStubFunction_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isAcceleratorStubFunction_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_numberOfAcceleratorPointerTags_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_numberOfAcceleratorPointerTags_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isSdl_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isSdl_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isWinRTPointer_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isWinRTPointer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isRefUdt_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isRefUdt_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isValueUdt_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isValueUdt_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isInterfaceUdt_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isInterfaceUdt_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDiaSymbol_findInlineFramesByAddr_Proxy( + IDiaSymbol * This, + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [out] */ IDiaEnumSymbols **ppResult); + + +void __RPC_STUB IDiaSymbol_findInlineFramesByAddr_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDiaSymbol_findInlineFramesByRVA_Proxy( + IDiaSymbol * This, + /* [in] */ DWORD rva, + /* [out] */ IDiaEnumSymbols **ppResult); + + +void __RPC_STUB IDiaSymbol_findInlineFramesByRVA_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDiaSymbol_findInlineFramesByVA_Proxy( + IDiaSymbol * This, + /* [in] */ ULONGLONG va, + /* [out] */ IDiaEnumSymbols **ppResult); + + +void __RPC_STUB IDiaSymbol_findInlineFramesByVA_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDiaSymbol_findInlineeLines_Proxy( + IDiaSymbol * This, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + +void __RPC_STUB IDiaSymbol_findInlineeLines_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDiaSymbol_findInlineeLinesByAddr_Proxy( + IDiaSymbol * This, + /* [in] */ DWORD isect, + /* [in] */ DWORD offset, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + +void __RPC_STUB IDiaSymbol_findInlineeLinesByAddr_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDiaSymbol_findInlineeLinesByRVA_Proxy( + IDiaSymbol * This, + /* [in] */ DWORD rva, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + +void __RPC_STUB IDiaSymbol_findInlineeLinesByRVA_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDiaSymbol_findInlineeLinesByVA_Proxy( + IDiaSymbol * This, + /* [in] */ ULONGLONG va, + /* [in] */ DWORD length, + /* [out] */ IDiaEnumLineNumbers **ppResult); + + +void __RPC_STUB IDiaSymbol_findInlineeLinesByVA_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDiaSymbol_findSymbolsForAcceleratorPointerTag_Proxy( + IDiaSymbol * This, + /* [in] */ DWORD tagValue, + /* [out] */ IDiaEnumSymbols **ppResult); + + +void __RPC_STUB IDiaSymbol_findSymbolsForAcceleratorPointerTag_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDiaSymbol_findSymbolsByRVAForAcceleratorPointerTag_Proxy( + IDiaSymbol * This, + /* [in] */ DWORD tagValue, + /* [in] */ DWORD rva, + /* [out] */ IDiaEnumSymbols **ppResult); + + +void __RPC_STUB IDiaSymbol_findSymbolsByRVAForAcceleratorPointerTag_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDiaSymbol_get_acceleratorPointerTags_Proxy( + IDiaSymbol * This, + /* [in] */ DWORD cnt, + /* [out] */ DWORD *pcnt, + /* [size_is][out] */ DWORD *pPointerTags); + + +void __RPC_STUB IDiaSymbol_get_acceleratorPointerTags_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDiaSymbol_getSrcLineOnTypeDefn_Proxy( + IDiaSymbol * This, + /* [out] */ IDiaLineNumber **ppResult); + + +void __RPC_STUB IDiaSymbol_getSrcLineOnTypeDefn_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isPGO_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isPGO_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_hasValidPGOCounts_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_hasValidPGOCounts_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_isOptimizedForSpeed_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_isOptimizedForSpeed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_PGOEntryCount_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_PGOEntryCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_PGOEdgeCount_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_PGOEdgeCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_PGODynamicInstructionCount_Proxy( + IDiaSymbol * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_PGODynamicInstructionCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_staticSize_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_staticSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_finalLiveStaticSize_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_finalLiveStaticSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_phaseName_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BSTR *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_phaseName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_hasControlFlowCheck_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_hasControlFlowCheck_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_constantExport_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_constantExport_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_dataExport_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_dataExport_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_privateExport_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_privateExport_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_noNameExport_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_noNameExport_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_exportHasExplicitlyAssignedOrdinal_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_exportHasExplicitlyAssignedOrdinal_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_exportIsForwarder_Proxy( + IDiaSymbol * This, + /* [retval][out] */ BOOL *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_exportIsForwarder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_ordinal_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_ordinal_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_frameSize_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_frameSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_exceptionHandlerAddressSection_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_exceptionHandlerAddressSection_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_exceptionHandlerAddressOffset_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_exceptionHandlerAddressOffset_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_exceptionHandlerRelativeVirtualAddress_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_exceptionHandlerRelativeVirtualAddress_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_exceptionHandlerVirtualAddress_Proxy( + IDiaSymbol * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_exceptionHandlerVirtualAddress_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDiaSymbol_findInputAssemblyFile_Proxy( + IDiaSymbol * This, + /* [out] */ IDiaInputAssemblyFile **ppResult); + + +void __RPC_STUB IDiaSymbol_findInputAssemblyFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_characteristics_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_characteristics_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_coffGroup_Proxy( + IDiaSymbol * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + +void __RPC_STUB IDiaSymbol_get_coffGroup_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_bindID_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_bindID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_bindSpace_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_bindSpace_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IDiaSymbol_get_bindSlot_Proxy( + IDiaSymbol * This, + /* [retval][out] */ DWORD *pRetVal); + + +void __RPC_STUB IDiaSymbol_get_bindSlot_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IDiaSymbol_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaSourceFile_INTERFACE_DEFINED__ +#define __IDiaSourceFile_INTERFACE_DEFINED__ + +/* interface IDiaSourceFile */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaSourceFile; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("A2EF5353-F5A8-4eb3-90D2-CB526ACB3CDD") + IDiaSourceFile : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_uniqueId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_fileName( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_checksumType( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_compilands( + /* [retval][out] */ IDiaEnumSymbols **pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE get_checksum( + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaSourceFileVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaSourceFile * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaSourceFile * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaSourceFile * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_uniqueId )( + IDiaSourceFile * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_fileName )( + IDiaSourceFile * This, + /* [retval][out] */ BSTR *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_checksumType )( + IDiaSourceFile * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_compilands )( + IDiaSourceFile * This, + /* [retval][out] */ IDiaEnumSymbols **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *get_checksum )( + IDiaSourceFile * This, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData); + + END_INTERFACE + } IDiaSourceFileVtbl; + + interface IDiaSourceFile + { + CONST_VTBL struct IDiaSourceFileVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaSourceFile_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaSourceFile_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaSourceFile_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaSourceFile_get_uniqueId(This,pRetVal) \ + ( (This)->lpVtbl -> get_uniqueId(This,pRetVal) ) + +#define IDiaSourceFile_get_fileName(This,pRetVal) \ + ( (This)->lpVtbl -> get_fileName(This,pRetVal) ) + +#define IDiaSourceFile_get_checksumType(This,pRetVal) \ + ( (This)->lpVtbl -> get_checksumType(This,pRetVal) ) + +#define IDiaSourceFile_get_compilands(This,pRetVal) \ + ( (This)->lpVtbl -> get_compilands(This,pRetVal) ) + +#define IDiaSourceFile_get_checksum(This,cbData,pcbData,pbData) \ + ( (This)->lpVtbl -> get_checksum(This,cbData,pcbData,pbData) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaSourceFile_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaInputAssemblyFile_INTERFACE_DEFINED__ +#define __IDiaInputAssemblyFile_INTERFACE_DEFINED__ + +/* interface IDiaInputAssemblyFile */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaInputAssemblyFile; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3BFE56B0-390C-4863-9430-1F3D083B7684") + IDiaInputAssemblyFile : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_uniqueId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_index( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_timestamp( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_pdbAvailableAtILMerge( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_fileName( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE get_version( + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaInputAssemblyFileVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaInputAssemblyFile * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaInputAssemblyFile * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaInputAssemblyFile * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_uniqueId )( + IDiaInputAssemblyFile * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_index )( + IDiaInputAssemblyFile * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_timestamp )( + IDiaInputAssemblyFile * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_pdbAvailableAtILMerge )( + IDiaInputAssemblyFile * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_fileName )( + IDiaInputAssemblyFile * This, + /* [retval][out] */ BSTR *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *get_version )( + IDiaInputAssemblyFile * This, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData); + + END_INTERFACE + } IDiaInputAssemblyFileVtbl; + + interface IDiaInputAssemblyFile + { + CONST_VTBL struct IDiaInputAssemblyFileVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaInputAssemblyFile_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaInputAssemblyFile_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaInputAssemblyFile_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaInputAssemblyFile_get_uniqueId(This,pRetVal) \ + ( (This)->lpVtbl -> get_uniqueId(This,pRetVal) ) + +#define IDiaInputAssemblyFile_get_index(This,pRetVal) \ + ( (This)->lpVtbl -> get_index(This,pRetVal) ) + +#define IDiaInputAssemblyFile_get_timestamp(This,pRetVal) \ + ( (This)->lpVtbl -> get_timestamp(This,pRetVal) ) + +#define IDiaInputAssemblyFile_get_pdbAvailableAtILMerge(This,pRetVal) \ + ( (This)->lpVtbl -> get_pdbAvailableAtILMerge(This,pRetVal) ) + +#define IDiaInputAssemblyFile_get_fileName(This,pRetVal) \ + ( (This)->lpVtbl -> get_fileName(This,pRetVal) ) + +#define IDiaInputAssemblyFile_get_version(This,cbData,pcbData,pbData) \ + ( (This)->lpVtbl -> get_version(This,cbData,pcbData,pbData) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaInputAssemblyFile_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaLineNumber_INTERFACE_DEFINED__ +#define __IDiaLineNumber_INTERFACE_DEFINED__ + +/* interface IDiaLineNumber */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaLineNumber; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B388EB14-BE4D-421d-A8A1-6CF7AB057086") + IDiaLineNumber : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_compiland( + /* [retval][out] */ IDiaSymbol **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_sourceFile( + /* [retval][out] */ IDiaSourceFile **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_lineNumber( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_lineNumberEnd( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_columnNumber( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_columnNumberEnd( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_addressSection( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_addressOffset( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_relativeVirtualAddress( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_virtualAddress( + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_length( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_sourceFileId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_statement( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_compilandId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaLineNumberVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaLineNumber * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaLineNumber * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaLineNumber * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_compiland )( + IDiaLineNumber * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_sourceFile )( + IDiaLineNumber * This, + /* [retval][out] */ IDiaSourceFile **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_lineNumber )( + IDiaLineNumber * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_lineNumberEnd )( + IDiaLineNumber * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_columnNumber )( + IDiaLineNumber * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_columnNumberEnd )( + IDiaLineNumber * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_addressSection )( + IDiaLineNumber * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_addressOffset )( + IDiaLineNumber * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_relativeVirtualAddress )( + IDiaLineNumber * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_virtualAddress )( + IDiaLineNumber * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_length )( + IDiaLineNumber * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_sourceFileId )( + IDiaLineNumber * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_statement )( + IDiaLineNumber * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_compilandId )( + IDiaLineNumber * This, + /* [retval][out] */ DWORD *pRetVal); + + END_INTERFACE + } IDiaLineNumberVtbl; + + interface IDiaLineNumber + { + CONST_VTBL struct IDiaLineNumberVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaLineNumber_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaLineNumber_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaLineNumber_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaLineNumber_get_compiland(This,pRetVal) \ + ( (This)->lpVtbl -> get_compiland(This,pRetVal) ) + +#define IDiaLineNumber_get_sourceFile(This,pRetVal) \ + ( (This)->lpVtbl -> get_sourceFile(This,pRetVal) ) + +#define IDiaLineNumber_get_lineNumber(This,pRetVal) \ + ( (This)->lpVtbl -> get_lineNumber(This,pRetVal) ) + +#define IDiaLineNumber_get_lineNumberEnd(This,pRetVal) \ + ( (This)->lpVtbl -> get_lineNumberEnd(This,pRetVal) ) + +#define IDiaLineNumber_get_columnNumber(This,pRetVal) \ + ( (This)->lpVtbl -> get_columnNumber(This,pRetVal) ) + +#define IDiaLineNumber_get_columnNumberEnd(This,pRetVal) \ + ( (This)->lpVtbl -> get_columnNumberEnd(This,pRetVal) ) + +#define IDiaLineNumber_get_addressSection(This,pRetVal) \ + ( (This)->lpVtbl -> get_addressSection(This,pRetVal) ) + +#define IDiaLineNumber_get_addressOffset(This,pRetVal) \ + ( (This)->lpVtbl -> get_addressOffset(This,pRetVal) ) + +#define IDiaLineNumber_get_relativeVirtualAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_relativeVirtualAddress(This,pRetVal) ) + +#define IDiaLineNumber_get_virtualAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_virtualAddress(This,pRetVal) ) + +#define IDiaLineNumber_get_length(This,pRetVal) \ + ( (This)->lpVtbl -> get_length(This,pRetVal) ) + +#define IDiaLineNumber_get_sourceFileId(This,pRetVal) \ + ( (This)->lpVtbl -> get_sourceFileId(This,pRetVal) ) + +#define IDiaLineNumber_get_statement(This,pRetVal) \ + ( (This)->lpVtbl -> get_statement(This,pRetVal) ) + +#define IDiaLineNumber_get_compilandId(This,pRetVal) \ + ( (This)->lpVtbl -> get_compilandId(This,pRetVal) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaLineNumber_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaSectionContrib_INTERFACE_DEFINED__ +#define __IDiaSectionContrib_INTERFACE_DEFINED__ + +/* interface IDiaSectionContrib */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaSectionContrib; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("0CF4B60E-35B1-4c6c-BDD8-854B9C8E3857") + IDiaSectionContrib : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_compiland( + /* [retval][out] */ IDiaSymbol **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_addressSection( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_addressOffset( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_relativeVirtualAddress( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_virtualAddress( + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_length( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_notPaged( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_code( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_initializedData( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_uninitializedData( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_remove( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_comdat( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_discardable( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_notCached( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_share( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_execute( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_read( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_write( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_dataCrc( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_relocationsCrc( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_compilandId( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_code16bit( + /* [retval][out] */ BOOL *pRetVal) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaSectionContribVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaSectionContrib * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaSectionContrib * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaSectionContrib * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_compiland )( + IDiaSectionContrib * This, + /* [retval][out] */ IDiaSymbol **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_addressSection )( + IDiaSectionContrib * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_addressOffset )( + IDiaSectionContrib * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_relativeVirtualAddress )( + IDiaSectionContrib * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_virtualAddress )( + IDiaSectionContrib * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_length )( + IDiaSectionContrib * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_notPaged )( + IDiaSectionContrib * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_code )( + IDiaSectionContrib * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_initializedData )( + IDiaSectionContrib * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_uninitializedData )( + IDiaSectionContrib * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_remove )( + IDiaSectionContrib * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_comdat )( + IDiaSectionContrib * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_discardable )( + IDiaSectionContrib * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_notCached )( + IDiaSectionContrib * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_share )( + IDiaSectionContrib * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_execute )( + IDiaSectionContrib * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_read )( + IDiaSectionContrib * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_write )( + IDiaSectionContrib * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_dataCrc )( + IDiaSectionContrib * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_relocationsCrc )( + IDiaSectionContrib * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_compilandId )( + IDiaSectionContrib * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_code16bit )( + IDiaSectionContrib * This, + /* [retval][out] */ BOOL *pRetVal); + + END_INTERFACE + } IDiaSectionContribVtbl; + + interface IDiaSectionContrib + { + CONST_VTBL struct IDiaSectionContribVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaSectionContrib_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaSectionContrib_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaSectionContrib_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaSectionContrib_get_compiland(This,pRetVal) \ + ( (This)->lpVtbl -> get_compiland(This,pRetVal) ) + +#define IDiaSectionContrib_get_addressSection(This,pRetVal) \ + ( (This)->lpVtbl -> get_addressSection(This,pRetVal) ) + +#define IDiaSectionContrib_get_addressOffset(This,pRetVal) \ + ( (This)->lpVtbl -> get_addressOffset(This,pRetVal) ) + +#define IDiaSectionContrib_get_relativeVirtualAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_relativeVirtualAddress(This,pRetVal) ) + +#define IDiaSectionContrib_get_virtualAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_virtualAddress(This,pRetVal) ) + +#define IDiaSectionContrib_get_length(This,pRetVal) \ + ( (This)->lpVtbl -> get_length(This,pRetVal) ) + +#define IDiaSectionContrib_get_notPaged(This,pRetVal) \ + ( (This)->lpVtbl -> get_notPaged(This,pRetVal) ) + +#define IDiaSectionContrib_get_code(This,pRetVal) \ + ( (This)->lpVtbl -> get_code(This,pRetVal) ) + +#define IDiaSectionContrib_get_initializedData(This,pRetVal) \ + ( (This)->lpVtbl -> get_initializedData(This,pRetVal) ) + +#define IDiaSectionContrib_get_uninitializedData(This,pRetVal) \ + ( (This)->lpVtbl -> get_uninitializedData(This,pRetVal) ) + +#define IDiaSectionContrib_get_remove(This,pRetVal) \ + ( (This)->lpVtbl -> get_remove(This,pRetVal) ) + +#define IDiaSectionContrib_get_comdat(This,pRetVal) \ + ( (This)->lpVtbl -> get_comdat(This,pRetVal) ) + +#define IDiaSectionContrib_get_discardable(This,pRetVal) \ + ( (This)->lpVtbl -> get_discardable(This,pRetVal) ) + +#define IDiaSectionContrib_get_notCached(This,pRetVal) \ + ( (This)->lpVtbl -> get_notCached(This,pRetVal) ) + +#define IDiaSectionContrib_get_share(This,pRetVal) \ + ( (This)->lpVtbl -> get_share(This,pRetVal) ) + +#define IDiaSectionContrib_get_execute(This,pRetVal) \ + ( (This)->lpVtbl -> get_execute(This,pRetVal) ) + +#define IDiaSectionContrib_get_read(This,pRetVal) \ + ( (This)->lpVtbl -> get_read(This,pRetVal) ) + +#define IDiaSectionContrib_get_write(This,pRetVal) \ + ( (This)->lpVtbl -> get_write(This,pRetVal) ) + +#define IDiaSectionContrib_get_dataCrc(This,pRetVal) \ + ( (This)->lpVtbl -> get_dataCrc(This,pRetVal) ) + +#define IDiaSectionContrib_get_relocationsCrc(This,pRetVal) \ + ( (This)->lpVtbl -> get_relocationsCrc(This,pRetVal) ) + +#define IDiaSectionContrib_get_compilandId(This,pRetVal) \ + ( (This)->lpVtbl -> get_compilandId(This,pRetVal) ) + +#define IDiaSectionContrib_get_code16bit(This,pRetVal) \ + ( (This)->lpVtbl -> get_code16bit(This,pRetVal) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaSectionContrib_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaSegment_INTERFACE_DEFINED__ +#define __IDiaSegment_INTERFACE_DEFINED__ + +/* interface IDiaSegment */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaSegment; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("0775B784-C75B-4449-848B-B7BD3159545B") + IDiaSegment : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_frame( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_offset( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_length( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_read( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_write( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_execute( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_addressSection( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_relativeVirtualAddress( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_virtualAddress( + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaSegmentVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaSegment * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaSegment * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaSegment * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_frame )( + IDiaSegment * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_offset )( + IDiaSegment * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_length )( + IDiaSegment * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_read )( + IDiaSegment * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_write )( + IDiaSegment * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_execute )( + IDiaSegment * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_addressSection )( + IDiaSegment * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_relativeVirtualAddress )( + IDiaSegment * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_virtualAddress )( + IDiaSegment * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + END_INTERFACE + } IDiaSegmentVtbl; + + interface IDiaSegment + { + CONST_VTBL struct IDiaSegmentVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaSegment_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaSegment_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaSegment_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaSegment_get_frame(This,pRetVal) \ + ( (This)->lpVtbl -> get_frame(This,pRetVal) ) + +#define IDiaSegment_get_offset(This,pRetVal) \ + ( (This)->lpVtbl -> get_offset(This,pRetVal) ) + +#define IDiaSegment_get_length(This,pRetVal) \ + ( (This)->lpVtbl -> get_length(This,pRetVal) ) + +#define IDiaSegment_get_read(This,pRetVal) \ + ( (This)->lpVtbl -> get_read(This,pRetVal) ) + +#define IDiaSegment_get_write(This,pRetVal) \ + ( (This)->lpVtbl -> get_write(This,pRetVal) ) + +#define IDiaSegment_get_execute(This,pRetVal) \ + ( (This)->lpVtbl -> get_execute(This,pRetVal) ) + +#define IDiaSegment_get_addressSection(This,pRetVal) \ + ( (This)->lpVtbl -> get_addressSection(This,pRetVal) ) + +#define IDiaSegment_get_relativeVirtualAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_relativeVirtualAddress(This,pRetVal) ) + +#define IDiaSegment_get_virtualAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_virtualAddress(This,pRetVal) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaSegment_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaInjectedSource_INTERFACE_DEFINED__ +#define __IDiaInjectedSource_INTERFACE_DEFINED__ + +/* interface IDiaInjectedSource */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaInjectedSource; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("AE605CDC-8105-4a23-B710-3259F1E26112") + IDiaInjectedSource : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_crc( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_length( + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_filename( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_objectFilename( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_virtualFilename( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_sourceCompression( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE get_source( + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaInjectedSourceVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaInjectedSource * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaInjectedSource * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaInjectedSource * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_crc )( + IDiaInjectedSource * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_length )( + IDiaInjectedSource * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_filename )( + IDiaInjectedSource * This, + /* [retval][out] */ BSTR *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_objectFilename )( + IDiaInjectedSource * This, + /* [retval][out] */ BSTR *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_virtualFilename )( + IDiaInjectedSource * This, + /* [retval][out] */ BSTR *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_sourceCompression )( + IDiaInjectedSource * This, + /* [retval][out] */ DWORD *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *get_source )( + IDiaInjectedSource * This, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData); + + END_INTERFACE + } IDiaInjectedSourceVtbl; + + interface IDiaInjectedSource + { + CONST_VTBL struct IDiaInjectedSourceVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaInjectedSource_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaInjectedSource_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaInjectedSource_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaInjectedSource_get_crc(This,pRetVal) \ + ( (This)->lpVtbl -> get_crc(This,pRetVal) ) + +#define IDiaInjectedSource_get_length(This,pRetVal) \ + ( (This)->lpVtbl -> get_length(This,pRetVal) ) + +#define IDiaInjectedSource_get_filename(This,pRetVal) \ + ( (This)->lpVtbl -> get_filename(This,pRetVal) ) + +#define IDiaInjectedSource_get_objectFilename(This,pRetVal) \ + ( (This)->lpVtbl -> get_objectFilename(This,pRetVal) ) + +#define IDiaInjectedSource_get_virtualFilename(This,pRetVal) \ + ( (This)->lpVtbl -> get_virtualFilename(This,pRetVal) ) + +#define IDiaInjectedSource_get_sourceCompression(This,pRetVal) \ + ( (This)->lpVtbl -> get_sourceCompression(This,pRetVal) ) + +#define IDiaInjectedSource_get_source(This,cbData,pcbData,pbData) \ + ( (This)->lpVtbl -> get_source(This,cbData,pcbData,pbData) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaInjectedSource_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_dia2_0000_0025 */ +/* [local] */ + + +enum __MIDL___MIDL_itf_dia2_0000_0025_0001 + { + E_DIA_INPROLOG = ( HRESULT )(( ( ( ( unsigned long )1 << 31 ) | ( ( unsigned long )( LONG )0x6d << 16 ) ) | ( unsigned long )100 ) ), + E_DIA_SYNTAX = ( E_DIA_INPROLOG + 1 ) , + E_DIA_FRAME_ACCESS = ( E_DIA_SYNTAX + 1 ) , + E_DIA_VALUE = ( E_DIA_FRAME_ACCESS + 1 ) + } ; + + +extern RPC_IF_HANDLE __MIDL_itf_dia2_0000_0025_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_dia2_0000_0025_v0_0_s_ifspec; + +#ifndef __IDiaStackWalkFrame_INTERFACE_DEFINED__ +#define __IDiaStackWalkFrame_INTERFACE_DEFINED__ + +/* interface IDiaStackWalkFrame */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaStackWalkFrame; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("07C590C1-438D-4F47-BDCD-4397BC81AD75") + IDiaStackWalkFrame : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_registerValue( + /* [in] */ DWORD index, + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_registerValue( + /* [in] */ DWORD index, + /* [in] */ ULONGLONG NewVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE readMemory( + /* [in] */ enum MemoryTypeEnum type, + /* [in] */ ULONGLONG va, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData) = 0; + + virtual HRESULT STDMETHODCALLTYPE searchForReturnAddress( + /* [in] */ IDiaFrameData *frame, + /* [out] */ ULONGLONG *returnAddress) = 0; + + virtual HRESULT STDMETHODCALLTYPE searchForReturnAddressStart( + /* [in] */ IDiaFrameData *frame, + /* [in] */ ULONGLONG startAddress, + /* [out] */ ULONGLONG *returnAddress) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaStackWalkFrameVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaStackWalkFrame * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaStackWalkFrame * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaStackWalkFrame * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_registerValue )( + IDiaStackWalkFrame * This, + /* [in] */ DWORD index, + /* [retval][out] */ ULONGLONG *pRetVal); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_registerValue )( + IDiaStackWalkFrame * This, + /* [in] */ DWORD index, + /* [in] */ ULONGLONG NewVal); + + HRESULT ( STDMETHODCALLTYPE *readMemory )( + IDiaStackWalkFrame * This, + /* [in] */ enum MemoryTypeEnum type, + /* [in] */ ULONGLONG va, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData); + + HRESULT ( STDMETHODCALLTYPE *searchForReturnAddress )( + IDiaStackWalkFrame * This, + /* [in] */ IDiaFrameData *frame, + /* [out] */ ULONGLONG *returnAddress); + + HRESULT ( STDMETHODCALLTYPE *searchForReturnAddressStart )( + IDiaStackWalkFrame * This, + /* [in] */ IDiaFrameData *frame, + /* [in] */ ULONGLONG startAddress, + /* [out] */ ULONGLONG *returnAddress); + + END_INTERFACE + } IDiaStackWalkFrameVtbl; + + interface IDiaStackWalkFrame + { + CONST_VTBL struct IDiaStackWalkFrameVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaStackWalkFrame_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaStackWalkFrame_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaStackWalkFrame_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaStackWalkFrame_get_registerValue(This,index,pRetVal) \ + ( (This)->lpVtbl -> get_registerValue(This,index,pRetVal) ) + +#define IDiaStackWalkFrame_put_registerValue(This,index,NewVal) \ + ( (This)->lpVtbl -> put_registerValue(This,index,NewVal) ) + +#define IDiaStackWalkFrame_readMemory(This,type,va,cbData,pcbData,pbData) \ + ( (This)->lpVtbl -> readMemory(This,type,va,cbData,pcbData,pbData) ) + +#define IDiaStackWalkFrame_searchForReturnAddress(This,frame,returnAddress) \ + ( (This)->lpVtbl -> searchForReturnAddress(This,frame,returnAddress) ) + +#define IDiaStackWalkFrame_searchForReturnAddressStart(This,frame,startAddress,returnAddress) \ + ( (This)->lpVtbl -> searchForReturnAddressStart(This,frame,startAddress,returnAddress) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaStackWalkFrame_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaFrameData_INTERFACE_DEFINED__ +#define __IDiaFrameData_INTERFACE_DEFINED__ + +/* interface IDiaFrameData */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaFrameData; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("A39184B7-6A36-42de-8EEC-7DF9F3F59F33") + IDiaFrameData : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_addressSection( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_addressOffset( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_relativeVirtualAddress( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_virtualAddress( + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_lengthBlock( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_lengthLocals( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_lengthParams( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_maxStack( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_lengthProlog( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_lengthSavedRegisters( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_program( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_systemExceptionHandling( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_cplusplusExceptionHandling( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_functionStart( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_allocatesBasePointer( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_type( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_functionParent( + /* [retval][out] */ IDiaFrameData **pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE execute( + IDiaStackWalkFrame *frame) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaFrameDataVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaFrameData * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaFrameData * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaFrameData * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_addressSection )( + IDiaFrameData * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_addressOffset )( + IDiaFrameData * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_relativeVirtualAddress )( + IDiaFrameData * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_virtualAddress )( + IDiaFrameData * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_lengthBlock )( + IDiaFrameData * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_lengthLocals )( + IDiaFrameData * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_lengthParams )( + IDiaFrameData * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_maxStack )( + IDiaFrameData * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_lengthProlog )( + IDiaFrameData * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_lengthSavedRegisters )( + IDiaFrameData * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_program )( + IDiaFrameData * This, + /* [retval][out] */ BSTR *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_systemExceptionHandling )( + IDiaFrameData * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_cplusplusExceptionHandling )( + IDiaFrameData * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_functionStart )( + IDiaFrameData * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_allocatesBasePointer )( + IDiaFrameData * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_type )( + IDiaFrameData * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_functionParent )( + IDiaFrameData * This, + /* [retval][out] */ IDiaFrameData **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *execute )( + IDiaFrameData * This, + IDiaStackWalkFrame *frame); + + END_INTERFACE + } IDiaFrameDataVtbl; + + interface IDiaFrameData + { + CONST_VTBL struct IDiaFrameDataVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaFrameData_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaFrameData_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaFrameData_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaFrameData_get_addressSection(This,pRetVal) \ + ( (This)->lpVtbl -> get_addressSection(This,pRetVal) ) + +#define IDiaFrameData_get_addressOffset(This,pRetVal) \ + ( (This)->lpVtbl -> get_addressOffset(This,pRetVal) ) + +#define IDiaFrameData_get_relativeVirtualAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_relativeVirtualAddress(This,pRetVal) ) + +#define IDiaFrameData_get_virtualAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_virtualAddress(This,pRetVal) ) + +#define IDiaFrameData_get_lengthBlock(This,pRetVal) \ + ( (This)->lpVtbl -> get_lengthBlock(This,pRetVal) ) + +#define IDiaFrameData_get_lengthLocals(This,pRetVal) \ + ( (This)->lpVtbl -> get_lengthLocals(This,pRetVal) ) + +#define IDiaFrameData_get_lengthParams(This,pRetVal) \ + ( (This)->lpVtbl -> get_lengthParams(This,pRetVal) ) + +#define IDiaFrameData_get_maxStack(This,pRetVal) \ + ( (This)->lpVtbl -> get_maxStack(This,pRetVal) ) + +#define IDiaFrameData_get_lengthProlog(This,pRetVal) \ + ( (This)->lpVtbl -> get_lengthProlog(This,pRetVal) ) + +#define IDiaFrameData_get_lengthSavedRegisters(This,pRetVal) \ + ( (This)->lpVtbl -> get_lengthSavedRegisters(This,pRetVal) ) + +#define IDiaFrameData_get_program(This,pRetVal) \ + ( (This)->lpVtbl -> get_program(This,pRetVal) ) + +#define IDiaFrameData_get_systemExceptionHandling(This,pRetVal) \ + ( (This)->lpVtbl -> get_systemExceptionHandling(This,pRetVal) ) + +#define IDiaFrameData_get_cplusplusExceptionHandling(This,pRetVal) \ + ( (This)->lpVtbl -> get_cplusplusExceptionHandling(This,pRetVal) ) + +#define IDiaFrameData_get_functionStart(This,pRetVal) \ + ( (This)->lpVtbl -> get_functionStart(This,pRetVal) ) + +#define IDiaFrameData_get_allocatesBasePointer(This,pRetVal) \ + ( (This)->lpVtbl -> get_allocatesBasePointer(This,pRetVal) ) + +#define IDiaFrameData_get_type(This,pRetVal) \ + ( (This)->lpVtbl -> get_type(This,pRetVal) ) + +#define IDiaFrameData_get_functionParent(This,pRetVal) \ + ( (This)->lpVtbl -> get_functionParent(This,pRetVal) ) + +#define IDiaFrameData_execute(This,frame) \ + ( (This)->lpVtbl -> execute(This,frame) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaFrameData_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaImageData_INTERFACE_DEFINED__ +#define __IDiaImageData_INTERFACE_DEFINED__ + +/* interface IDiaImageData */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaImageData; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("C8E40ED2-A1D9-4221-8692-3CE661184B44") + IDiaImageData : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_relativeVirtualAddress( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_virtualAddress( + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_imageBase( + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaImageDataVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaImageData * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaImageData * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaImageData * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_relativeVirtualAddress )( + IDiaImageData * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_virtualAddress )( + IDiaImageData * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_imageBase )( + IDiaImageData * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + END_INTERFACE + } IDiaImageDataVtbl; + + interface IDiaImageData + { + CONST_VTBL struct IDiaImageDataVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaImageData_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaImageData_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaImageData_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaImageData_get_relativeVirtualAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_relativeVirtualAddress(This,pRetVal) ) + +#define IDiaImageData_get_virtualAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_virtualAddress(This,pRetVal) ) + +#define IDiaImageData_get_imageBase(This,pRetVal) \ + ( (This)->lpVtbl -> get_imageBase(This,pRetVal) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaImageData_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaTable_INTERFACE_DEFINED__ +#define __IDiaTable_INTERFACE_DEFINED__ + +/* interface IDiaTable */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaTable; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("4A59FB77-ABAC-469b-A30B-9ECC85BFEF14") + IDiaTable : public IEnumUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_name( + /* [retval][out] */ BSTR *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ LONG *pRetVal) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Item( + /* [in] */ DWORD index, + /* [retval][out] */ IUnknown **element) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaTableVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaTable * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaTable * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaTable * This); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Next )( + IDiaTable * This, + /* [annotation][in] */ + _In_ ULONG celt, + /* [annotation][out] */ + _Out_writes_to_(celt,*pceltFetched) IUnknown **rgelt, + /* [annotation][out] */ + _Out_opt_ ULONG *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + IDiaTable * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + IDiaTable * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + IDiaTable * This, + /* [out] */ IEnumUnknown **ppenum); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IDiaTable * This, + /* [retval][out] */ IUnknown **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_name )( + IDiaTable * This, + /* [retval][out] */ BSTR *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IDiaTable * This, + /* [retval][out] */ LONG *pRetVal); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Item )( + IDiaTable * This, + /* [in] */ DWORD index, + /* [retval][out] */ IUnknown **element); + + END_INTERFACE + } IDiaTableVtbl; + + interface IDiaTable + { + CONST_VTBL struct IDiaTableVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaTable_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaTable_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaTable_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaTable_Next(This,celt,rgelt,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched) ) + +#define IDiaTable_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define IDiaTable_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define IDiaTable_Clone(This,ppenum) \ + ( (This)->lpVtbl -> Clone(This,ppenum) ) + + +#define IDiaTable_get__NewEnum(This,pRetVal) \ + ( (This)->lpVtbl -> get__NewEnum(This,pRetVal) ) + +#define IDiaTable_get_name(This,pRetVal) \ + ( (This)->lpVtbl -> get_name(This,pRetVal) ) + +#define IDiaTable_get_Count(This,pRetVal) \ + ( (This)->lpVtbl -> get_Count(This,pRetVal) ) + +#define IDiaTable_Item(This,index,element) \ + ( (This)->lpVtbl -> Item(This,index,element) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaTable_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaEnumTables_INTERFACE_DEFINED__ +#define __IDiaEnumTables_INTERFACE_DEFINED__ + +/* interface IDiaEnumTables */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaEnumTables; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("C65C2B0A-1150-4d7a-AFCC-E05BF3DEE81E") + IDiaEnumTables : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum( + /* [retval][out] */ IUnknown **pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count( + /* [retval][out] */ LONG *pRetVal) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Item( + /* [in] */ VARIANT index, + /* [retval][out] */ IDiaTable **table) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + ULONG celt, + IDiaTable **rgelt, + ULONG *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ IDiaEnumTables **ppenum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaEnumTablesVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaEnumTables * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaEnumTables * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaEnumTables * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get__NewEnum )( + IDiaEnumTables * This, + /* [retval][out] */ IUnknown **pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Count )( + IDiaEnumTables * This, + /* [retval][out] */ LONG *pRetVal); + + /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Item )( + IDiaEnumTables * This, + /* [in] */ VARIANT index, + /* [retval][out] */ IDiaTable **table); + + HRESULT ( STDMETHODCALLTYPE *Next )( + IDiaEnumTables * This, + ULONG celt, + IDiaTable **rgelt, + ULONG *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + IDiaEnumTables * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + IDiaEnumTables * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + IDiaEnumTables * This, + /* [out] */ IDiaEnumTables **ppenum); + + END_INTERFACE + } IDiaEnumTablesVtbl; + + interface IDiaEnumTables + { + CONST_VTBL struct IDiaEnumTablesVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaEnumTables_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaEnumTables_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaEnumTables_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaEnumTables_get__NewEnum(This,pRetVal) \ + ( (This)->lpVtbl -> get__NewEnum(This,pRetVal) ) + +#define IDiaEnumTables_get_Count(This,pRetVal) \ + ( (This)->lpVtbl -> get_Count(This,pRetVal) ) + +#define IDiaEnumTables_Item(This,index,table) \ + ( (This)->lpVtbl -> Item(This,index,table) ) + +#define IDiaEnumTables_Next(This,celt,rgelt,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched) ) + +#define IDiaEnumTables_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define IDiaEnumTables_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define IDiaEnumTables_Clone(This,ppenum) \ + ( (This)->lpVtbl -> Clone(This,ppenum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaEnumTables_INTERFACE_DEFINED__ */ + + + +#ifndef __Dia2Lib_LIBRARY_DEFINED__ +#define __Dia2Lib_LIBRARY_DEFINED__ + +/* library Dia2Lib */ +/* [helpstring][version][uuid] */ + + +EXTERN_C const IID LIBID_Dia2Lib; + +EXTERN_C const CLSID CLSID_DiaSource; + +#ifdef __cplusplus + +class DECLSPEC_UUID("e6756135-1e65-4d17-8576-610761398c3c") +DiaSource; +#endif + +EXTERN_C const CLSID CLSID_DiaSourceAlt; + +#ifdef __cplusplus + +class DECLSPEC_UUID("91904831-49ca-4766-b95c-25397e2dd6dc") +DiaSourceAlt; +#endif + +EXTERN_C const CLSID CLSID_DiaStackWalker; + +#ifdef __cplusplus + +class DECLSPEC_UUID("ce4a85db-5768-475b-a4e1-c0bca2112a6b") +DiaStackWalker; +#endif +#endif /* __Dia2Lib_LIBRARY_DEFINED__ */ + +/* interface __MIDL_itf_dia2_0000_0031 */ +/* [local] */ + +#define DiaTable_Symbols ( L"Symbols" ) + +#define DiaTable_Sections ( L"Sections" ) + +#define DiaTable_SrcFiles ( L"SourceFiles" ) + +#define DiaTable_LineNums ( L"LineNumbers" ) + +#define DiaTable_SegMap ( L"SegmentMap" ) + +#define DiaTable_Dbg ( L"Dbg" ) + +#define DiaTable_InjSrc ( L"InjectedSource" ) + +#define DiaTable_FrameData ( L"FrameData" ) + +#define DiaTable_InputAssemblyFiles ( L"InputAssemblyFiles" ) + + + +extern RPC_IF_HANDLE __MIDL_itf_dia2_0000_0031_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_dia2_0000_0031_v0_0_s_ifspec; + +#ifndef __IDiaPropertyStorage_INTERFACE_DEFINED__ +#define __IDiaPropertyStorage_INTERFACE_DEFINED__ + +/* interface IDiaPropertyStorage */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaPropertyStorage; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9d416f9c-e184-45b2-a4f0-ce517f719e9b") + IDiaPropertyStorage : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE ReadMultiple( + /* [in] */ ULONG cpspec, + /* [size_is][in] */ const PROPSPEC *rgpspec, + /* [size_is][out] */ PROPVARIANT *rgvar) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReadPropertyNames( + /* [in] */ ULONG cpropid, + /* [size_is][in] */ const PROPID *rgpropid, + /* [size_is][out][in] */ BSTR *rglpwstrName) = 0; + + virtual HRESULT STDMETHODCALLTYPE Enum( + /* [out] */ IEnumSTATPROPSTG **ppenum) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReadDWORD( + /* [in] */ PROPID id, + /* [out] */ DWORD *pValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReadLONG( + /* [in] */ PROPID id, + /* [out] */ LONG *pValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReadBOOL( + /* [in] */ PROPID id, + /* [out] */ BOOL *pValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReadULONGLONG( + /* [in] */ PROPID id, + /* [out] */ ULONGLONG *pValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReadBSTR( + /* [in] */ PROPID id, + /* [out] */ BSTR *pValue) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaPropertyStorageVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaPropertyStorage * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaPropertyStorage * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaPropertyStorage * This); + + HRESULT ( STDMETHODCALLTYPE *ReadMultiple )( + IDiaPropertyStorage * This, + /* [in] */ ULONG cpspec, + /* [size_is][in] */ const PROPSPEC *rgpspec, + /* [size_is][out] */ PROPVARIANT *rgvar); + + HRESULT ( STDMETHODCALLTYPE *ReadPropertyNames )( + IDiaPropertyStorage * This, + /* [in] */ ULONG cpropid, + /* [size_is][in] */ const PROPID *rgpropid, + /* [size_is][out][in] */ BSTR *rglpwstrName); + + HRESULT ( STDMETHODCALLTYPE *Enum )( + IDiaPropertyStorage * This, + /* [out] */ IEnumSTATPROPSTG **ppenum); + + HRESULT ( STDMETHODCALLTYPE *ReadDWORD )( + IDiaPropertyStorage * This, + /* [in] */ PROPID id, + /* [out] */ DWORD *pValue); + + HRESULT ( STDMETHODCALLTYPE *ReadLONG )( + IDiaPropertyStorage * This, + /* [in] */ PROPID id, + /* [out] */ LONG *pValue); + + HRESULT ( STDMETHODCALLTYPE *ReadBOOL )( + IDiaPropertyStorage * This, + /* [in] */ PROPID id, + /* [out] */ BOOL *pValue); + + HRESULT ( STDMETHODCALLTYPE *ReadULONGLONG )( + IDiaPropertyStorage * This, + /* [in] */ PROPID id, + /* [out] */ ULONGLONG *pValue); + + HRESULT ( STDMETHODCALLTYPE *ReadBSTR )( + IDiaPropertyStorage * This, + /* [in] */ PROPID id, + /* [out] */ BSTR *pValue); + + END_INTERFACE + } IDiaPropertyStorageVtbl; + + interface IDiaPropertyStorage + { + CONST_VTBL struct IDiaPropertyStorageVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaPropertyStorage_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaPropertyStorage_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaPropertyStorage_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaPropertyStorage_ReadMultiple(This,cpspec,rgpspec,rgvar) \ + ( (This)->lpVtbl -> ReadMultiple(This,cpspec,rgpspec,rgvar) ) + +#define IDiaPropertyStorage_ReadPropertyNames(This,cpropid,rgpropid,rglpwstrName) \ + ( (This)->lpVtbl -> ReadPropertyNames(This,cpropid,rgpropid,rglpwstrName) ) + +#define IDiaPropertyStorage_Enum(This,ppenum) \ + ( (This)->lpVtbl -> Enum(This,ppenum) ) + +#define IDiaPropertyStorage_ReadDWORD(This,id,pValue) \ + ( (This)->lpVtbl -> ReadDWORD(This,id,pValue) ) + +#define IDiaPropertyStorage_ReadLONG(This,id,pValue) \ + ( (This)->lpVtbl -> ReadLONG(This,id,pValue) ) + +#define IDiaPropertyStorage_ReadBOOL(This,id,pValue) \ + ( (This)->lpVtbl -> ReadBOOL(This,id,pValue) ) + +#define IDiaPropertyStorage_ReadULONGLONG(This,id,pValue) \ + ( (This)->lpVtbl -> ReadULONGLONG(This,id,pValue) ) + +#define IDiaPropertyStorage_ReadBSTR(This,id,pValue) \ + ( (This)->lpVtbl -> ReadBSTR(This,id,pValue) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaPropertyStorage_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaStackFrame_INTERFACE_DEFINED__ +#define __IDiaStackFrame_INTERFACE_DEFINED__ + +/* interface IDiaStackFrame */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaStackFrame; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5edbc96d-cdd6-4792-afbe-cc89007d9610") + IDiaStackFrame : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_type( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_base( + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_size( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_returnAddress( + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_localsBase( + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_lengthLocals( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_lengthParams( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_lengthProlog( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_lengthSavedRegisters( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_systemExceptionHandling( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_cplusplusExceptionHandling( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_functionStart( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_allocatesBasePointer( + /* [retval][out] */ BOOL *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_maxStack( + /* [retval][out] */ DWORD *pRetVal) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_registerValue( + /* [in] */ DWORD index, + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaStackFrameVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaStackFrame * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaStackFrame * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaStackFrame * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_type )( + IDiaStackFrame * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_base )( + IDiaStackFrame * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_size )( + IDiaStackFrame * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_returnAddress )( + IDiaStackFrame * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_localsBase )( + IDiaStackFrame * This, + /* [retval][out] */ ULONGLONG *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_lengthLocals )( + IDiaStackFrame * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_lengthParams )( + IDiaStackFrame * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_lengthProlog )( + IDiaStackFrame * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_lengthSavedRegisters )( + IDiaStackFrame * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_systemExceptionHandling )( + IDiaStackFrame * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_cplusplusExceptionHandling )( + IDiaStackFrame * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_functionStart )( + IDiaStackFrame * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_allocatesBasePointer )( + IDiaStackFrame * This, + /* [retval][out] */ BOOL *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_maxStack )( + IDiaStackFrame * This, + /* [retval][out] */ DWORD *pRetVal); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_registerValue )( + IDiaStackFrame * This, + /* [in] */ DWORD index, + /* [retval][out] */ ULONGLONG *pRetVal); + + END_INTERFACE + } IDiaStackFrameVtbl; + + interface IDiaStackFrame + { + CONST_VTBL struct IDiaStackFrameVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaStackFrame_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaStackFrame_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaStackFrame_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaStackFrame_get_type(This,pRetVal) \ + ( (This)->lpVtbl -> get_type(This,pRetVal) ) + +#define IDiaStackFrame_get_base(This,pRetVal) \ + ( (This)->lpVtbl -> get_base(This,pRetVal) ) + +#define IDiaStackFrame_get_size(This,pRetVal) \ + ( (This)->lpVtbl -> get_size(This,pRetVal) ) + +#define IDiaStackFrame_get_returnAddress(This,pRetVal) \ + ( (This)->lpVtbl -> get_returnAddress(This,pRetVal) ) + +#define IDiaStackFrame_get_localsBase(This,pRetVal) \ + ( (This)->lpVtbl -> get_localsBase(This,pRetVal) ) + +#define IDiaStackFrame_get_lengthLocals(This,pRetVal) \ + ( (This)->lpVtbl -> get_lengthLocals(This,pRetVal) ) + +#define IDiaStackFrame_get_lengthParams(This,pRetVal) \ + ( (This)->lpVtbl -> get_lengthParams(This,pRetVal) ) + +#define IDiaStackFrame_get_lengthProlog(This,pRetVal) \ + ( (This)->lpVtbl -> get_lengthProlog(This,pRetVal) ) + +#define IDiaStackFrame_get_lengthSavedRegisters(This,pRetVal) \ + ( (This)->lpVtbl -> get_lengthSavedRegisters(This,pRetVal) ) + +#define IDiaStackFrame_get_systemExceptionHandling(This,pRetVal) \ + ( (This)->lpVtbl -> get_systemExceptionHandling(This,pRetVal) ) + +#define IDiaStackFrame_get_cplusplusExceptionHandling(This,pRetVal) \ + ( (This)->lpVtbl -> get_cplusplusExceptionHandling(This,pRetVal) ) + +#define IDiaStackFrame_get_functionStart(This,pRetVal) \ + ( (This)->lpVtbl -> get_functionStart(This,pRetVal) ) + +#define IDiaStackFrame_get_allocatesBasePointer(This,pRetVal) \ + ( (This)->lpVtbl -> get_allocatesBasePointer(This,pRetVal) ) + +#define IDiaStackFrame_get_maxStack(This,pRetVal) \ + ( (This)->lpVtbl -> get_maxStack(This,pRetVal) ) + +#define IDiaStackFrame_get_registerValue(This,index,pRetVal) \ + ( (This)->lpVtbl -> get_registerValue(This,index,pRetVal) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaStackFrame_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaEnumStackFrames_INTERFACE_DEFINED__ +#define __IDiaEnumStackFrames_INTERFACE_DEFINED__ + +/* interface IDiaEnumStackFrames */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaEnumStackFrames; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("ec9d461d-ce74-4711-a020-7d8f9a1dd255") + IDiaEnumStackFrames : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [out] */ IDiaStackFrame **rgelt, + /* [out] */ ULONG *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaEnumStackFramesVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaEnumStackFrames * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaEnumStackFrames * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaEnumStackFrames * This); + + HRESULT ( STDMETHODCALLTYPE *Next )( + IDiaEnumStackFrames * This, + /* [in] */ ULONG celt, + /* [out] */ IDiaStackFrame **rgelt, + /* [out] */ ULONG *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + IDiaEnumStackFrames * This); + + END_INTERFACE + } IDiaEnumStackFramesVtbl; + + interface IDiaEnumStackFrames + { + CONST_VTBL struct IDiaEnumStackFramesVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaEnumStackFrames_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaEnumStackFrames_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaEnumStackFrames_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaEnumStackFrames_Next(This,celt,rgelt,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched) ) + +#define IDiaEnumStackFrames_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaEnumStackFrames_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_dia2_0000_0034 */ +/* [local] */ + +typedef /* [public] */ struct __MIDL___MIDL_itf_dia2_0000_0034_0001 + { + DWORD ulOffStart; + DWORD cbProcSize; + DWORD cdwLocals; + WORD cdwParams; + WORD cdwFlags; + } FPODATA; + + + +extern RPC_IF_HANDLE __MIDL_itf_dia2_0000_0034_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_dia2_0000_0034_v0_0_s_ifspec; + +#ifndef __IDiaStackWalkHelper_INTERFACE_DEFINED__ +#define __IDiaStackWalkHelper_INTERFACE_DEFINED__ + +/* interface IDiaStackWalkHelper */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaStackWalkHelper; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("21F81B1B-C5BB-42A3-BC4F-CCBAA75B9F19") + IDiaStackWalkHelper : public IUnknown + { + public: + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_registerValue( + /* [in] */ DWORD index, + /* [retval][out] */ ULONGLONG *pRetVal) = 0; + + virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_registerValue( + /* [in] */ DWORD index, + /* [in] */ ULONGLONG NewVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE readMemory( + /* [in] */ enum MemoryTypeEnum type, + /* [in] */ ULONGLONG va, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData) = 0; + + virtual HRESULT STDMETHODCALLTYPE searchForReturnAddress( + /* [in] */ IDiaFrameData *frame, + /* [out] */ ULONGLONG *returnAddress) = 0; + + virtual HRESULT STDMETHODCALLTYPE searchForReturnAddressStart( + /* [in] */ IDiaFrameData *frame, + /* [in] */ ULONGLONG startAddress, + /* [out] */ ULONGLONG *returnAddress) = 0; + + virtual HRESULT STDMETHODCALLTYPE frameForVA( + /* [in] */ ULONGLONG va, + /* [out] */ IDiaFrameData **ppFrame) = 0; + + virtual HRESULT STDMETHODCALLTYPE symbolForVA( + /* [in] */ ULONGLONG va, + /* [out] */ IDiaSymbol **ppSymbol) = 0; + + virtual HRESULT STDMETHODCALLTYPE pdataForVA( + /* [in] */ ULONGLONG va, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData) = 0; + + virtual HRESULT STDMETHODCALLTYPE imageForVA( + /* [in] */ ULONGLONG vaContext, + /* [out] */ ULONGLONG *pvaImageStart) = 0; + + virtual HRESULT STDMETHODCALLTYPE addressForVA( + /* [in] */ ULONGLONG va, + /* [out] */ DWORD *pISect, + /* [out] */ DWORD *pOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE numberOfFunctionFragmentsForVA( + /* [in] */ ULONGLONG vaFunc, + /* [in] */ DWORD cbFunc, + /* [out] */ DWORD *pNumFragments) = 0; + + virtual HRESULT STDMETHODCALLTYPE functionFragmentsForVA( + /* [in] */ ULONGLONG vaFunc, + /* [in] */ DWORD cbFunc, + /* [in] */ DWORD cFragments, + /* [out] */ ULONGLONG *pVaFragment, + /* [out] */ DWORD *pLenFragment) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaStackWalkHelperVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaStackWalkHelper * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaStackWalkHelper * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaStackWalkHelper * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_registerValue )( + IDiaStackWalkHelper * This, + /* [in] */ DWORD index, + /* [retval][out] */ ULONGLONG *pRetVal); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_registerValue )( + IDiaStackWalkHelper * This, + /* [in] */ DWORD index, + /* [in] */ ULONGLONG NewVal); + + HRESULT ( STDMETHODCALLTYPE *readMemory )( + IDiaStackWalkHelper * This, + /* [in] */ enum MemoryTypeEnum type, + /* [in] */ ULONGLONG va, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData); + + HRESULT ( STDMETHODCALLTYPE *searchForReturnAddress )( + IDiaStackWalkHelper * This, + /* [in] */ IDiaFrameData *frame, + /* [out] */ ULONGLONG *returnAddress); + + HRESULT ( STDMETHODCALLTYPE *searchForReturnAddressStart )( + IDiaStackWalkHelper * This, + /* [in] */ IDiaFrameData *frame, + /* [in] */ ULONGLONG startAddress, + /* [out] */ ULONGLONG *returnAddress); + + HRESULT ( STDMETHODCALLTYPE *frameForVA )( + IDiaStackWalkHelper * This, + /* [in] */ ULONGLONG va, + /* [out] */ IDiaFrameData **ppFrame); + + HRESULT ( STDMETHODCALLTYPE *symbolForVA )( + IDiaStackWalkHelper * This, + /* [in] */ ULONGLONG va, + /* [out] */ IDiaSymbol **ppSymbol); + + HRESULT ( STDMETHODCALLTYPE *pdataForVA )( + IDiaStackWalkHelper * This, + /* [in] */ ULONGLONG va, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData); + + HRESULT ( STDMETHODCALLTYPE *imageForVA )( + IDiaStackWalkHelper * This, + /* [in] */ ULONGLONG vaContext, + /* [out] */ ULONGLONG *pvaImageStart); + + HRESULT ( STDMETHODCALLTYPE *addressForVA )( + IDiaStackWalkHelper * This, + /* [in] */ ULONGLONG va, + /* [out] */ DWORD *pISect, + /* [out] */ DWORD *pOffset); + + HRESULT ( STDMETHODCALLTYPE *numberOfFunctionFragmentsForVA )( + IDiaStackWalkHelper * This, + /* [in] */ ULONGLONG vaFunc, + /* [in] */ DWORD cbFunc, + /* [out] */ DWORD *pNumFragments); + + HRESULT ( STDMETHODCALLTYPE *functionFragmentsForVA )( + IDiaStackWalkHelper * This, + /* [in] */ ULONGLONG vaFunc, + /* [in] */ DWORD cbFunc, + /* [in] */ DWORD cFragments, + /* [out] */ ULONGLONG *pVaFragment, + /* [out] */ DWORD *pLenFragment); + + END_INTERFACE + } IDiaStackWalkHelperVtbl; + + interface IDiaStackWalkHelper + { + CONST_VTBL struct IDiaStackWalkHelperVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaStackWalkHelper_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaStackWalkHelper_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaStackWalkHelper_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaStackWalkHelper_get_registerValue(This,index,pRetVal) \ + ( (This)->lpVtbl -> get_registerValue(This,index,pRetVal) ) + +#define IDiaStackWalkHelper_put_registerValue(This,index,NewVal) \ + ( (This)->lpVtbl -> put_registerValue(This,index,NewVal) ) + +#define IDiaStackWalkHelper_readMemory(This,type,va,cbData,pcbData,pbData) \ + ( (This)->lpVtbl -> readMemory(This,type,va,cbData,pcbData,pbData) ) + +#define IDiaStackWalkHelper_searchForReturnAddress(This,frame,returnAddress) \ + ( (This)->lpVtbl -> searchForReturnAddress(This,frame,returnAddress) ) + +#define IDiaStackWalkHelper_searchForReturnAddressStart(This,frame,startAddress,returnAddress) \ + ( (This)->lpVtbl -> searchForReturnAddressStart(This,frame,startAddress,returnAddress) ) + +#define IDiaStackWalkHelper_frameForVA(This,va,ppFrame) \ + ( (This)->lpVtbl -> frameForVA(This,va,ppFrame) ) + +#define IDiaStackWalkHelper_symbolForVA(This,va,ppSymbol) \ + ( (This)->lpVtbl -> symbolForVA(This,va,ppSymbol) ) + +#define IDiaStackWalkHelper_pdataForVA(This,va,cbData,pcbData,pbData) \ + ( (This)->lpVtbl -> pdataForVA(This,va,cbData,pcbData,pbData) ) + +#define IDiaStackWalkHelper_imageForVA(This,vaContext,pvaImageStart) \ + ( (This)->lpVtbl -> imageForVA(This,vaContext,pvaImageStart) ) + +#define IDiaStackWalkHelper_addressForVA(This,va,pISect,pOffset) \ + ( (This)->lpVtbl -> addressForVA(This,va,pISect,pOffset) ) + +#define IDiaStackWalkHelper_numberOfFunctionFragmentsForVA(This,vaFunc,cbFunc,pNumFragments) \ + ( (This)->lpVtbl -> numberOfFunctionFragmentsForVA(This,vaFunc,cbFunc,pNumFragments) ) + +#define IDiaStackWalkHelper_functionFragmentsForVA(This,vaFunc,cbFunc,cFragments,pVaFragment,pLenFragment) \ + ( (This)->lpVtbl -> functionFragmentsForVA(This,vaFunc,cbFunc,cFragments,pVaFragment,pLenFragment) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaStackWalkHelper_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaStackWalker_INTERFACE_DEFINED__ +#define __IDiaStackWalker_INTERFACE_DEFINED__ + +/* interface IDiaStackWalker */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaStackWalker; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5485216b-a54c-469f-9670-52b24d5229bb") + IDiaStackWalker : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE getEnumFrames( + /* [in] */ IDiaStackWalkHelper *pHelper, + /* [out] */ IDiaEnumStackFrames **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE getEnumFrames2( + /* [in] */ enum CV_CPU_TYPE_e cpuid, + /* [in] */ IDiaStackWalkHelper *pHelper, + /* [out] */ IDiaEnumStackFrames **ppEnum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDiaStackWalkerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaStackWalker * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaStackWalker * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaStackWalker * This); + + HRESULT ( STDMETHODCALLTYPE *getEnumFrames )( + IDiaStackWalker * This, + /* [in] */ IDiaStackWalkHelper *pHelper, + /* [out] */ IDiaEnumStackFrames **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *getEnumFrames2 )( + IDiaStackWalker * This, + /* [in] */ enum CV_CPU_TYPE_e cpuid, + /* [in] */ IDiaStackWalkHelper *pHelper, + /* [out] */ IDiaEnumStackFrames **ppEnum); + + END_INTERFACE + } IDiaStackWalkerVtbl; + + interface IDiaStackWalker + { + CONST_VTBL struct IDiaStackWalkerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaStackWalker_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaStackWalker_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaStackWalker_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaStackWalker_getEnumFrames(This,pHelper,ppEnum) \ + ( (This)->lpVtbl -> getEnumFrames(This,pHelper,ppEnum) ) + +#define IDiaStackWalker_getEnumFrames2(This,cpuid,pHelper,ppEnum) \ + ( (This)->lpVtbl -> getEnumFrames2(This,cpuid,pHelper,ppEnum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaStackWalker_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaStackWalkHelper2_INTERFACE_DEFINED__ +#define __IDiaStackWalkHelper2_INTERFACE_DEFINED__ + +/* interface IDiaStackWalkHelper2 */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaStackWalkHelper2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("8222c490-507b-4bef-b3bd-41dca7b5934c") + IDiaStackWalkHelper2 : public IDiaStackWalkHelper + { + public: + }; + + +#else /* C style interface */ + + typedef struct IDiaStackWalkHelper2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaStackWalkHelper2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaStackWalkHelper2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaStackWalkHelper2 * This); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_registerValue )( + IDiaStackWalkHelper2 * This, + /* [in] */ DWORD index, + /* [retval][out] */ ULONGLONG *pRetVal); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_registerValue )( + IDiaStackWalkHelper2 * This, + /* [in] */ DWORD index, + /* [in] */ ULONGLONG NewVal); + + HRESULT ( STDMETHODCALLTYPE *readMemory )( + IDiaStackWalkHelper2 * This, + /* [in] */ enum MemoryTypeEnum type, + /* [in] */ ULONGLONG va, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData); + + HRESULT ( STDMETHODCALLTYPE *searchForReturnAddress )( + IDiaStackWalkHelper2 * This, + /* [in] */ IDiaFrameData *frame, + /* [out] */ ULONGLONG *returnAddress); + + HRESULT ( STDMETHODCALLTYPE *searchForReturnAddressStart )( + IDiaStackWalkHelper2 * This, + /* [in] */ IDiaFrameData *frame, + /* [in] */ ULONGLONG startAddress, + /* [out] */ ULONGLONG *returnAddress); + + HRESULT ( STDMETHODCALLTYPE *frameForVA )( + IDiaStackWalkHelper2 * This, + /* [in] */ ULONGLONG va, + /* [out] */ IDiaFrameData **ppFrame); + + HRESULT ( STDMETHODCALLTYPE *symbolForVA )( + IDiaStackWalkHelper2 * This, + /* [in] */ ULONGLONG va, + /* [out] */ IDiaSymbol **ppSymbol); + + HRESULT ( STDMETHODCALLTYPE *pdataForVA )( + IDiaStackWalkHelper2 * This, + /* [in] */ ULONGLONG va, + /* [in] */ DWORD cbData, + /* [out] */ DWORD *pcbData, + /* [size_is][out] */ BYTE *pbData); + + HRESULT ( STDMETHODCALLTYPE *imageForVA )( + IDiaStackWalkHelper2 * This, + /* [in] */ ULONGLONG vaContext, + /* [out] */ ULONGLONG *pvaImageStart); + + HRESULT ( STDMETHODCALLTYPE *addressForVA )( + IDiaStackWalkHelper2 * This, + /* [in] */ ULONGLONG va, + /* [out] */ DWORD *pISect, + /* [out] */ DWORD *pOffset); + + HRESULT ( STDMETHODCALLTYPE *numberOfFunctionFragmentsForVA )( + IDiaStackWalkHelper2 * This, + /* [in] */ ULONGLONG vaFunc, + /* [in] */ DWORD cbFunc, + /* [out] */ DWORD *pNumFragments); + + HRESULT ( STDMETHODCALLTYPE *functionFragmentsForVA )( + IDiaStackWalkHelper2 * This, + /* [in] */ ULONGLONG vaFunc, + /* [in] */ DWORD cbFunc, + /* [in] */ DWORD cFragments, + /* [out] */ ULONGLONG *pVaFragment, + /* [out] */ DWORD *pLenFragment); + + END_INTERFACE + } IDiaStackWalkHelper2Vtbl; + + interface IDiaStackWalkHelper2 + { + CONST_VTBL struct IDiaStackWalkHelper2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaStackWalkHelper2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaStackWalkHelper2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaStackWalkHelper2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaStackWalkHelper2_get_registerValue(This,index,pRetVal) \ + ( (This)->lpVtbl -> get_registerValue(This,index,pRetVal) ) + +#define IDiaStackWalkHelper2_put_registerValue(This,index,NewVal) \ + ( (This)->lpVtbl -> put_registerValue(This,index,NewVal) ) + +#define IDiaStackWalkHelper2_readMemory(This,type,va,cbData,pcbData,pbData) \ + ( (This)->lpVtbl -> readMemory(This,type,va,cbData,pcbData,pbData) ) + +#define IDiaStackWalkHelper2_searchForReturnAddress(This,frame,returnAddress) \ + ( (This)->lpVtbl -> searchForReturnAddress(This,frame,returnAddress) ) + +#define IDiaStackWalkHelper2_searchForReturnAddressStart(This,frame,startAddress,returnAddress) \ + ( (This)->lpVtbl -> searchForReturnAddressStart(This,frame,startAddress,returnAddress) ) + +#define IDiaStackWalkHelper2_frameForVA(This,va,ppFrame) \ + ( (This)->lpVtbl -> frameForVA(This,va,ppFrame) ) + +#define IDiaStackWalkHelper2_symbolForVA(This,va,ppSymbol) \ + ( (This)->lpVtbl -> symbolForVA(This,va,ppSymbol) ) + +#define IDiaStackWalkHelper2_pdataForVA(This,va,cbData,pcbData,pbData) \ + ( (This)->lpVtbl -> pdataForVA(This,va,cbData,pcbData,pbData) ) + +#define IDiaStackWalkHelper2_imageForVA(This,vaContext,pvaImageStart) \ + ( (This)->lpVtbl -> imageForVA(This,vaContext,pvaImageStart) ) + +#define IDiaStackWalkHelper2_addressForVA(This,va,pISect,pOffset) \ + ( (This)->lpVtbl -> addressForVA(This,va,pISect,pOffset) ) + +#define IDiaStackWalkHelper2_numberOfFunctionFragmentsForVA(This,vaFunc,cbFunc,pNumFragments) \ + ( (This)->lpVtbl -> numberOfFunctionFragmentsForVA(This,vaFunc,cbFunc,pNumFragments) ) + +#define IDiaStackWalkHelper2_functionFragmentsForVA(This,vaFunc,cbFunc,cFragments,pVaFragment,pLenFragment) \ + ( (This)->lpVtbl -> functionFragmentsForVA(This,vaFunc,cbFunc,cFragments,pVaFragment,pLenFragment) ) + + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaStackWalkHelper2_INTERFACE_DEFINED__ */ + + +#ifndef __IDiaStackWalker2_INTERFACE_DEFINED__ +#define __IDiaStackWalker2_INTERFACE_DEFINED__ + +/* interface IDiaStackWalker2 */ +/* [unique][helpstring][local][uuid][object] */ + + +EXTERN_C const IID IID_IDiaStackWalker2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("7c185885-a015-4cac-9411-0f4fb39b1f3a") + IDiaStackWalker2 : public IDiaStackWalker + { + public: + }; + + +#else /* C style interface */ + + typedef struct IDiaStackWalker2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDiaStackWalker2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDiaStackWalker2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDiaStackWalker2 * This); + + HRESULT ( STDMETHODCALLTYPE *getEnumFrames )( + IDiaStackWalker2 * This, + /* [in] */ IDiaStackWalkHelper *pHelper, + /* [out] */ IDiaEnumStackFrames **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *getEnumFrames2 )( + IDiaStackWalker2 * This, + /* [in] */ enum CV_CPU_TYPE_e cpuid, + /* [in] */ IDiaStackWalkHelper *pHelper, + /* [out] */ IDiaEnumStackFrames **ppEnum); + + END_INTERFACE + } IDiaStackWalker2Vtbl; + + interface IDiaStackWalker2 + { + CONST_VTBL struct IDiaStackWalker2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDiaStackWalker2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDiaStackWalker2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDiaStackWalker2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDiaStackWalker2_getEnumFrames(This,pHelper,ppEnum) \ + ( (This)->lpVtbl -> getEnumFrames(This,pHelper,ppEnum) ) + +#define IDiaStackWalker2_getEnumFrames2(This,cpuid,pHelper,ppEnum) \ + ( (This)->lpVtbl -> getEnumFrames2(This,cpuid,pHelper,ppEnum) ) + + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDiaStackWalker2_INTERFACE_DEFINED__ */ + + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/third/Blackbone/src/3rd_party/DIA/diacreate.h b/third/Blackbone/src/3rd_party/DIA/diacreate.h new file mode 100644 index 0000000000000000000000000000000000000000..fac6668752db977d9917b674667edc5e8f2ee28e --- /dev/null +++ b/third/Blackbone/src/3rd_party/DIA/diacreate.h @@ -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 diff --git a/third/Blackbone/src/3rd_party/VersionApi.h b/third/Blackbone/src/3rd_party/VersionApi.h new file mode 100644 index 0000000000000000000000000000000000000000..4d931e3ee2aaa9358a944316e8c31d4f626c34ee --- /dev/null +++ b/third/Blackbone/src/3rd_party/VersionApi.h @@ -0,0 +1,284 @@ +#pragma once +#include + +#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_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 +}; + +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(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_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 +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 ); +} + diff --git a/third/Blackbone/src/3rd_party/cor.h b/third/Blackbone/src/3rd_party/cor.h new file mode 100644 index 0000000000000000000000000000000000000000..a0590ac9a172f5898efbab8601a577a38c7420f5 --- /dev/null +++ b/third/Blackbone/src/3rd_party/cor.h @@ -0,0 +1,2628 @@ +// ==++== +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// ==--== +/***************************************************************************** + ** ** + ** Cor.h - general header for the Runtime. ** + ** ** + *****************************************************************************/ + + +#ifndef _COR_H_ +#define _COR_H_ + +//***************************************************************************** +// Required includes +#include // Definitions of OLE types. +#include +#include "corerror.h" + +//***************************************************************************** + +#ifdef __cplusplus +extern "C" { +#endif + +// {BED7F4EA-1A96-11d2-8F08-00A0C9A6186D} +EXTERN_GUID(LIBID_ComPlusRuntime, 0xbed7f4ea, 0x1a96, 0x11d2, 0x8f, 0x8, 0x0, 0xa0, 0xc9, 0xa6, 0x18, 0x6d); + +// {90883F05-3D28-11D2-8F17-00A0C9A6186D} +EXTERN_GUID(GUID_ExportedFromComPlus, 0x90883f05, 0x3d28, 0x11d2, 0x8f, 0x17, 0x0, 0xa0, 0xc9, 0xa6, 0x18, 0x6d); + +// {0F21F359-AB84-41e8-9A78-36D110E6D2F9} +EXTERN_GUID(GUID_ManagedName, 0xf21f359, 0xab84, 0x41e8, 0x9a, 0x78, 0x36, 0xd1, 0x10, 0xe6, 0xd2, 0xf9); + +// {54FC8F55-38DE-4703-9C4E-250351302B1C} +EXTERN_GUID(GUID_Function2Getter, 0x54fc8f55, 0x38de, 0x4703, 0x9c, 0x4e, 0x25, 0x3, 0x51, 0x30, 0x2b, 0x1c); + +// CLSID_CorMetaDataDispenserRuntime: {1EC2DE53-75CC-11d2-9775-00A0C9B4D50C} +// Dispenser coclass for version 1.5 and 2.0 meta data. To get the "latest" bind +// to CLSID_MetaDataDispenser. +EXTERN_GUID(CLSID_CorMetaDataDispenserRuntime, 0x1ec2de53, 0x75cc, 0x11d2, 0x97, 0x75, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc); + +// {CD2BC5C9-F452-4326-B714-F9C539D4DA58} +EXTERN_GUID(GUID_DispIdOverride, 0xcd2bc5c9, 0xf452, 0x4326, 0xb7, 0x14, 0xf9, 0xc5, 0x39, 0xd4, 0xda, 0x58); + +// {B64784EB-D8D4-4d9b-9ACD-0E30806426F7} +EXTERN_GUID(GUID_ForceIEnumerable, 0xb64784eb, 0xd8d4, 0x4d9b, 0x9a, 0xcd, 0x0e, 0x30, 0x80, 0x64, 0x26, 0xf7); + +// {2941FF83-88D8-4F73-B6A9-BDF8712D000D} +EXTERN_GUID(GUID_PropGetCA, 0x2941ff83, 0x88d8, 0x4f73, 0xb6, 0xa9, 0xbd, 0xf8, 0x71, 0x2d, 0x00, 0x0d); + +// {29533527-3683-4364-ABC0-DB1ADD822FA2} +EXTERN_GUID(GUID_PropPutCA, 0x29533527, 0x3683, 0x4364, 0xab, 0xc0, 0xdb, 0x1a, 0xdd, 0x82, 0x2f, 0xa2); + +// CLSID_CLR_v1_MetaData: {005023CA-72B1-11D3-9FC4-00C04F79A0A3} +// Used to generate v1 metadata (for v1.0 and v1.1 CLR compatibility). +EXTERN_GUID(CLSID_CLR_v1_MetaData, 0x005023ca, 0x72b1, 0x11d3, 0x9f, 0xc4, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); + +// CLSID_CLR_v2_MetaData: {EFEA471A-44FD-4862-9292-0C58D46E1F3A} +// Used to generate v1 metadata (for v1.0 and v1.1 CLR compatibility). +EXTERN_GUID(CLSID_CLR_v2_MetaData, 0xefea471a, 0x44fd, 0x4862, 0x92, 0x92, 0xc, 0x58, 0xd4, 0x6e, 0x1f, 0x3a); + + +// CLSID_CorMetaDataRuntime: +// This will can always be used to generate the "latest" metadata available. +#define CLSID_CorMetaDataRuntime CLSID_CLR_v2_MetaData + + +// {30FE7BE8-D7D9-11D2-9F80-00C04F79A0A3} +EXTERN_GUID(MetaDataCheckDuplicatesFor, 0x30fe7be8, 0xd7d9, 0x11d2, 0x9f, 0x80, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); + +// {DE3856F8-D7D9-11D2-9F80-00C04F79A0A3} +EXTERN_GUID(MetaDataRefToDefCheck, 0xde3856f8, 0xd7d9, 0x11d2, 0x9f, 0x80, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); + +// {E5D71A4C-D7DA-11D2-9F80-00C04F79A0A3} +EXTERN_GUID(MetaDataNotificationForTokenMovement, 0xe5d71a4c, 0xd7da, 0x11d2, 0x9f, 0x80, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); + +// {2eee315c-d7db-11d2-9f80-00c04f79a0a3} +EXTERN_GUID(MetaDataSetUpdate, 0x2eee315c, 0xd7db, 0x11d2, 0x9f, 0x80, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); +#define MetaDataSetENC MetaDataSetUpdate + +// Use this guid in SetOption to indicate if the import enumerator should skip over +// delete items or not. The default is yes. +// +// {79700F36-4AAC-11d3-84C3-009027868CB1} +EXTERN_GUID(MetaDataImportOption, 0x79700f36, 0x4aac, 0x11d3, 0x84, 0xc3, 0x0, 0x90, 0x27, 0x86, 0x8c, 0xb1); + +// Use this guid in the SetOption if compiler wants to have MetaData API to take reader/writer lock +// +// {F7559806-F266-42ea-8C63-0ADB45E8B234} +EXTERN_GUID(MetaDataThreadSafetyOptions, 0xf7559806, 0xf266, 0x42ea, 0x8c, 0x63, 0xa, 0xdb, 0x45, 0xe8, 0xb2, 0x34); + +// Use this guid in the SetOption if compiler wants error when some tokens are emitted out of order +// {1547872D-DC03-11d2-9420-0000F8083460} +EXTERN_GUID(MetaDataErrorIfEmitOutOfOrder, 0x1547872d, 0xdc03, 0x11d2, 0x94, 0x20, 0x0, 0x0, 0xf8, 0x8, 0x34, 0x60); + +// Use this guid in the SetOption to indicate if the tlbimporter should generate the +// TCE adapters for COM connection point containers. +// {DCC9DE90-4151-11d3-88D6-00902754C43A} +EXTERN_GUID(MetaDataGenerateTCEAdapters, 0xdcc9de90, 0x4151, 0x11d3, 0x88, 0xd6, 0x0, 0x90, 0x27, 0x54, 0xc4, 0x3a); + +// Use this guid in the SetOption to specifiy a non-default namespace for typelib import. +// {F17FF889-5A63-11d3-9FF2-00C04FF7431A} +EXTERN_GUID(MetaDataTypeLibImportNamespace, 0xf17ff889, 0x5a63, 0x11d3, 0x9f, 0xf2, 0x0, 0xc0, 0x4f, 0xf7, 0x43, 0x1a); + +// Use this guid in the SetOption to specify the behavior of UnmarkAll. See CorLinkerOptions. +// {47E099B6-AE7C-4797-8317-B48AA645B8F9} +EXTERN_GUID(MetaDataLinkerOptions, 0x47e099b6, 0xae7c, 0x4797, 0x83, 0x17, 0xb4, 0x8a, 0xa6, 0x45, 0xb8, 0xf9); + +// Use this guid in the SetOption to specify the runtime version stored in the CLR metadata. +// {47E099B7-AE7C-4797-8317-B48AA645B8F9} +EXTERN_GUID(MetaDataRuntimeVersion, 0x47e099b7, 0xae7c, 0x4797, 0x83, 0x17, 0xb4, 0x8a, 0xa6, 0x45, 0xb8, 0xf9); + +// Use this guid in the SetOption to specify the behavior of the merger. +// {132D3A6E-B35D-464e-951A-42EFB9FB6601} +EXTERN_GUID(MetaDataMergerOptions, 0x132d3a6e, 0xb35d, 0x464e, 0x95, 0x1a, 0x42, 0xef, 0xb9, 0xfb, 0x66, 0x1); + + +interface IMetaDataImport; +interface IMetaDataAssemblyEmit; +interface IMetaDataAssemblyImport; +interface IMetaDataEmit; +interface ICeeGen; + + +typedef UNALIGNED void const *UVCP_CONSTANT; + + +// Constant for connection id and task id +#define INVALID_CONNECTION_ID 0x0 +#define INVALID_TASK_ID 0x0 +#define MAX_CONNECTION_NAME MAX_PATH + +//***************************************************************************** +//***************************************************************************** +// +// D L L P U B L I C E N T R Y P O I N T D E C L A R A T I O N S +// +//***************************************************************************** +//***************************************************************************** + +BOOL STDMETHODCALLTYPE _CorDllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved); +__int32 STDMETHODCALLTYPE _CorExeMain(); +__int32 STDMETHODCALLTYPE _CorExeMain2( // Executable exit code. + PBYTE pUnmappedPE, // -> memory mapped code + DWORD cUnmappedPE, // Size of memory mapped code + _In_ LPWSTR pImageNameIn, // -> Executable Name + _In_ LPWSTR pLoadersFileName, // -> Loaders Name + _In_ LPWSTR pCmdLine); // -> Command Line + +STDAPI _CorValidateImage(PVOID *ImageBase, LPCWSTR FileName); +STDAPI_(VOID) _CorImageUnloading(PVOID ImageBase); + +STDAPI CoInitializeEE(DWORD fFlags); +STDAPI_(void) CoUninitializeEE(BOOL fFlags); +STDAPI_(void) CoEEShutDownCOM(void); + +#ifndef FEATURE_PAL + +#define MSCOREE_SHIM_W L"mscoree.dll" +#define MSCOREE_SHIM_A "mscoree.dll" + +#else // !FEATURE_PAL + +#define MSCOREE_SHIM_W MAKEDLLNAME_W(L"sscoree") +#define MSCOREE_SHIM_A MAKEDLLNAME_A("sscoree") + +#endif // !FEATURE_PAL + +#define SWITCHOUT_HANDLE_VALUE ((HANDLE)(LONG_PTR)-2) + + +// +// CoInitializeCor flags. +// +typedef enum tagCOINITCOR +{ + COINITCOR_DEFAULT = 0x0 // Default initialization mode. +} COINITICOR; + +// +// CoInitializeEE flags. +// +typedef enum tagCOINITEE +{ + COINITEE_DEFAULT = 0x0, // Default initialization mode. + COINITEE_DLL = 0x1, // Initialization mode for loading DLL. + COINITEE_MAIN = 0x2 // Initialize prior to entering the main routine +} COINITIEE; + +// +// CoInitializeEE flags. +// +typedef enum tagCOUNINITEE +{ + COUNINITEE_DEFAULT = 0x0, // Default uninitialization mode. + COUNINITEE_DLL = 0x1 // Uninitialization mode for unloading DLL. +} COUNINITIEE; + +//***************************************************************************** +//***************************************************************************** +// +// I L & F I L E F O R M A T D E C L A R A T I O N S +// +//***************************************************************************** +//***************************************************************************** + + +// The following definitions will get moved into by RTM but are +// kept here for the Alpha's and Beta's. +#ifndef _WINDOWS_UPDATES_ +#include +#endif // updates + +//***************************************************************************** +//***************************************************************************** +// +// D L L P U B L I C E N T R Y P O I N T D E C L A R A T I O N S +// +//***************************************************************************** +//***************************************************************************** + +STDAPI CoInitializeCor(DWORD fFlags); +STDAPI_(void) CoUninitializeCor(void); + +typedef void (* TDestructorCallback)(EXCEPTION_RECORD*); +STDAPI_(void) AddDestructorCallback(int code, TDestructorCallback callback); + +// +//***************************************************************************** +//***************************************************************************** + +// CLSID_Cor: {bee00000-ee77-11d0-a015-00c04fbbb884} +EXTERN_GUID(CLSID_Cor, 0xbee00010, 0xee77, 0x11d0, 0xa0, 0x15, 0x00, 0xc0, 0x4f, 0xbb, 0xb8, 0x84); + +// CLSID_CorMetaDataDispenser: {E5CB7A31-7512-11d2-89CE-0080C792E5D8} +// This is the "Master Dispenser", always guaranteed to be the most recent +// dispenser on the machine. +EXTERN_GUID(CLSID_CorMetaDataDispenser, 0xe5cb7a31, 0x7512, 0x11d2, 0x89, 0xce, 0x0, 0x80, 0xc7, 0x92, 0xe5, 0xd8); + + +// CLSID_CorMetaDataDispenserReg: {435755FF-7397-11d2-9771-00A0C9B4D50C} +// Dispenser coclass for version 1.0 meta data. To get the "latest" bind +// to CLSID_CorMetaDataDispenser. +EXTERN_GUID(CLSID_CorMetaDataDispenserReg, 0x435755ff, 0x7397, 0x11d2, 0x97, 0x71, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc); + + +// CLSID_CorMetaDataReg: {87F3A1F5-7397-11d2-9771-00A0C9B4D50C} +// For COM+ Meta Data, Data Driven Registration +EXTERN_GUID(CLSID_CorMetaDataReg, 0x87f3a1f5, 0x7397, 0x11d2, 0x97, 0x71, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc); + +// IID_IMetaDataInternal {39EE28B3-0181-4d48-B53C-2FFAFFD5FEC1} +EXTERN_GUID(IID_IMetaDataInternal, 0x39ee28b3, 0x181, 0x4d48, 0xb5, 0x3c, 0x2f, 0xfa, 0xff, 0xd5, 0xfe, 0xc1); + + +interface IMetaDataDispenser; + +//------------------------------------- +//--- IMetaDataError +//------------------------------------- +// {B81FF171-20F3-11d2-8DCC-00A0C9B09C19} +EXTERN_GUID(IID_IMetaDataError, 0xb81ff171, 0x20f3, 0x11d2, 0x8d, 0xcc, 0x0, 0xa0, 0xc9, 0xb0, 0x9c, 0x19); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataError +DECLARE_INTERFACE_(IMetaDataError, IUnknown) +{ + STDMETHOD(OnError)(HRESULT hrError, mdToken token) PURE; +}; + +//------------------------------------- +//--- IMapToken +//------------------------------------- +// IID_IMapToken: {06A3EA8B-0225-11d1-BF72-00C04FC31E12} +EXTERN_GUID(IID_IMapToken, 0x6a3ea8b, 0x225, 0x11d1, 0xbf, 0x72, 0x0, 0xc0, 0x4f, 0xc3, 0x1e, 0x12); + +//--- +#undef INTERFACE +#define INTERFACE IMapToken +DECLARE_INTERFACE_(IMapToken, IUnknown) +{ + STDMETHOD(Map)(mdToken tkImp, mdToken tkEmit) PURE; +}; + +//------------------------------------- +//--- IMetaDataDispenser +//------------------------------------- +// {B81FF171-20F3-11d2-8DCC-00A0C9B09C19} +EXTERN_GUID(IID_IMetaDataDispenser, 0x809c652e, 0x7396, 0x11d2, 0x97, 0x71, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataDispenser +DECLARE_INTERFACE_(IMetaDataDispenser, IUnknown) +{ + STDMETHOD(DefineScope)( // Return code. + REFCLSID rclsid, // [in] What version to create. + DWORD dwCreateFlags, // [in] Flags on the create. + REFIID riid, // [in] The interface desired. + IUnknown **ppIUnk) PURE; // [out] Return interface on success. + + STDMETHOD(OpenScope)( // Return code. + LPCWSTR szScope, // [in] The scope to open. + DWORD dwOpenFlags, // [in] Open mode flags. + REFIID riid, // [in] The interface desired. + IUnknown **ppIUnk) PURE; // [out] Return interface on success. + + STDMETHOD(OpenScopeOnMemory)( // Return code. + LPCVOID pData, // [in] Location of scope data. + ULONG cbData, // [in] Size of the data pointed to by pData. + DWORD dwOpenFlags, // [in] Open mode flags. + REFIID riid, // [in] The interface desired. + IUnknown **ppIUnk) PURE; // [out] Return interface on success. +}; + +//------------------------------------- +//--- IMetaDataEmit +//------------------------------------- +// {BA3FEE4C-ECB9-4e41-83B7-183FA41CD859} +EXTERN_GUID(IID_IMetaDataEmit, 0xba3fee4c, 0xecb9, 0x4e41, 0x83, 0xb7, 0x18, 0x3f, 0xa4, 0x1c, 0xd8, 0x59); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataEmit +DECLARE_INTERFACE_(IMetaDataEmit, IUnknown) +{ + STDMETHOD(SetModuleProps)( // S_OK or error. + LPCWSTR szName) PURE; // [IN] If not NULL, the name of the module to set. + + STDMETHOD(Save)( // S_OK or error. + LPCWSTR szFile, // [IN] The filename to save to. + DWORD dwSaveFlags) PURE; // [IN] Flags for the save. + + STDMETHOD(SaveToStream)( // S_OK or error. + IStream *pIStream, // [IN] A writable stream to save to. + DWORD dwSaveFlags) PURE; // [IN] Flags for the save. + + STDMETHOD(GetSaveSize)( // S_OK or error. + CorSaveSize fSave, // [IN] cssAccurate or cssQuick. + DWORD *pdwSaveSize) PURE; // [OUT] Put the size here. + + STDMETHOD(DefineTypeDef)( // S_OK or error. + LPCWSTR szTypeDef, // [IN] Name of TypeDef + DWORD dwTypeDefFlags, // [IN] CustomAttribute flags + mdToken tkExtends, // [IN] extends this TypeDef or typeref + mdToken rtkImplements[], // [IN] Implements interfaces + mdTypeDef *ptd) PURE; // [OUT] Put TypeDef token here + + STDMETHOD(DefineNestedType)( // S_OK or error. + LPCWSTR szTypeDef, // [IN] Name of TypeDef + DWORD dwTypeDefFlags, // [IN] CustomAttribute flags + mdToken tkExtends, // [IN] extends this TypeDef or typeref + mdToken rtkImplements[], // [IN] Implements interfaces + mdTypeDef tdEncloser, // [IN] TypeDef token of the enclosing type. + mdTypeDef *ptd) PURE; // [OUT] Put TypeDef token here + + STDMETHOD(SetHandler)( // S_OK. + IUnknown *pUnk) PURE; // [IN] The new error handler. + + STDMETHOD(DefineMethod)( // S_OK or error. + mdTypeDef td, // Parent TypeDef + LPCWSTR szName, // Name of member + DWORD dwMethodFlags, // Member attributes + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + ULONG ulCodeRVA, + DWORD dwImplFlags, + mdMethodDef *pmd) PURE; // Put member token here + + STDMETHOD(DefineMethodImpl)( // S_OK or error. + mdTypeDef td, // [IN] The class implementing the method + mdToken tkBody, // [IN] Method body - MethodDef or MethodRef + mdToken tkDecl) PURE; // [IN] Method declaration - MethodDef or MethodRef + + STDMETHOD(DefineTypeRefByName)( // S_OK or error. + mdToken tkResolutionScope, // [IN] ModuleRef, AssemblyRef or TypeRef. + LPCWSTR szName, // [IN] Name of the TypeRef. + mdTypeRef *ptr) PURE; // [OUT] Put TypeRef token here. + + STDMETHOD(DefineImportType)( // S_OK or error. + IMetaDataAssemblyImport *pAssemImport, // [IN] Assembly containing the TypeDef. + const void *pbHashValue, // [IN] Hash Blob for Assembly. + ULONG cbHashValue, // [IN] Count of bytes. + IMetaDataImport *pImport, // [IN] Scope containing the TypeDef. + mdTypeDef tdImport, // [IN] The imported TypeDef. + IMetaDataAssemblyEmit *pAssemEmit, // [IN] Assembly into which the TypeDef is imported. + mdTypeRef *ptr) PURE; // [OUT] Put TypeRef token here. + + STDMETHOD(DefineMemberRef)( // S_OK or error + mdToken tkImport, // [IN] ClassRef or ClassDef importing a member. + LPCWSTR szName, // [IN] member's name + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + mdMemberRef *pmr) PURE; // [OUT] memberref token + + STDMETHOD(DefineImportMember)( // S_OK or error. + IMetaDataAssemblyImport *pAssemImport, // [IN] Assembly containing the Member. + const void *pbHashValue, // [IN] Hash Blob for Assembly. + ULONG cbHashValue, // [IN] Count of bytes. + IMetaDataImport *pImport, // [IN] Import scope, with member. + mdToken mbMember, // [IN] Member in import scope. + IMetaDataAssemblyEmit *pAssemEmit, // [IN] Assembly into which the Member is imported. + mdToken tkParent, // [IN] Classref or classdef in emit scope. + mdMemberRef *pmr) PURE; // [OUT] Put member ref here. + + STDMETHOD(DefineEvent) ( + mdTypeDef td, // [IN] the class/interface on which the event is being defined + LPCWSTR szEvent, // [IN] Name of the event + DWORD dwEventFlags, // [IN] CorEventAttr + mdToken tkEventType, // [IN] a reference (mdTypeRef or mdTypeRef) to the Event class + mdMethodDef mdAddOn, // [IN] required add method + mdMethodDef mdRemoveOn, // [IN] required remove method + mdMethodDef mdFire, // [IN] optional fire method + mdMethodDef rmdOtherMethods[], // [IN] optional array of other methods associate with the event + mdEvent *pmdEvent) PURE; // [OUT] output event token + + STDMETHOD(SetClassLayout) ( + mdTypeDef td, // [IN] typedef + DWORD dwPackSize, // [IN] packing size specified as 1, 2, 4, 8, or 16 + COR_FIELD_OFFSET rFieldOffsets[], // [IN] array of layout specification + ULONG ulClassSize) PURE; // [IN] size of the class + + STDMETHOD(DeleteClassLayout) ( + mdTypeDef td) PURE; // [IN] typedef whose layout is to be deleted. + + STDMETHOD(SetFieldMarshal) ( + mdToken tk, // [IN] given a fieldDef or paramDef token + PCCOR_SIGNATURE pvNativeType, // [IN] native type specification + ULONG cbNativeType) PURE; // [IN] count of bytes of pvNativeType + + STDMETHOD(DeleteFieldMarshal) ( + mdToken tk) PURE; // [IN] given a fieldDef or paramDef token + + STDMETHOD(DefinePermissionSet) ( + mdToken tk, // [IN] the object to be decorated. + DWORD dwAction, // [IN] CorDeclSecurity. + void const *pvPermission, // [IN] permission blob. + ULONG cbPermission, // [IN] count of bytes of pvPermission. + mdPermission *ppm) PURE; // [OUT] returned permission token. + + STDMETHOD(SetRVA)( // S_OK or error. + mdMethodDef md, // [IN] Method for which to set offset + ULONG ulRVA) PURE; // [IN] The offset + + STDMETHOD(GetTokenFromSig)( // S_OK or error. + PCCOR_SIGNATURE pvSig, // [IN] Signature to define. + ULONG cbSig, // [IN] Size of signature data. + mdSignature *pmsig) PURE; // [OUT] returned signature token. + + STDMETHOD(DefineModuleRef)( // S_OK or error. + LPCWSTR szName, // [IN] DLL name + mdModuleRef *pmur) PURE; // [OUT] returned + + // @FUTURE: This should go away once everyone starts using SetMemberRefProps. + STDMETHOD(SetParent)( // S_OK or error. + mdMemberRef mr, // [IN] Token for the ref to be fixed up. + mdToken tk) PURE; // [IN] The ref parent. + + STDMETHOD(GetTokenFromTypeSpec)( // S_OK or error. + PCCOR_SIGNATURE pvSig, // [IN] TypeSpec Signature to define. + ULONG cbSig, // [IN] Size of signature data. + mdTypeSpec *ptypespec) PURE; // [OUT] returned TypeSpec token. + + STDMETHOD(SaveToMemory)( // S_OK or error. + void *pbData, // [OUT] Location to write data. + ULONG cbData) PURE; // [IN] Max size of data buffer. + + STDMETHOD(DefineUserString)( // Return code. + LPCWSTR szString, // [IN] User literal string. + ULONG cchString, // [IN] Length of string. + mdString *pstk) PURE; // [OUT] String token. + + STDMETHOD(DeleteToken)( // Return code. + mdToken tkObj) PURE; // [IN] The token to be deleted + + STDMETHOD(SetMethodProps)( // S_OK or error. + mdMethodDef md, // [IN] The MethodDef. + DWORD dwMethodFlags, // [IN] Method attributes. + ULONG ulCodeRVA, // [IN] Code RVA. + DWORD dwImplFlags) PURE; // [IN] Impl flags. + + STDMETHOD(SetTypeDefProps)( // S_OK or error. + mdTypeDef td, // [IN] The TypeDef. + DWORD dwTypeDefFlags, // [IN] TypeDef flags. + mdToken tkExtends, // [IN] Base TypeDef or TypeRef. + mdToken rtkImplements[]) PURE; // [IN] Implemented interfaces. + + STDMETHOD(SetEventProps)( // S_OK or error. + mdEvent ev, // [IN] The event token. + DWORD dwEventFlags, // [IN] CorEventAttr. + mdToken tkEventType, // [IN] A reference (mdTypeRef or mdTypeRef) to the Event class. + mdMethodDef mdAddOn, // [IN] Add method. + mdMethodDef mdRemoveOn, // [IN] Remove method. + mdMethodDef mdFire, // [IN] Fire method. + mdMethodDef rmdOtherMethods[]) PURE;// [IN] Array of other methods associate with the event. + + STDMETHOD(SetPermissionSetProps)( // S_OK or error. + mdToken tk, // [IN] The object to be decorated. + DWORD dwAction, // [IN] CorDeclSecurity. + void const *pvPermission, // [IN] Permission blob. + ULONG cbPermission, // [IN] Count of bytes of pvPermission. + mdPermission *ppm) PURE; // [OUT] Permission token. + + STDMETHOD(DefinePinvokeMap)( // Return code. + mdToken tk, // [IN] FieldDef or MethodDef. + DWORD dwMappingFlags, // [IN] Flags used for mapping. + LPCWSTR szImportName, // [IN] Import name. + mdModuleRef mrImportDLL) PURE; // [IN] ModuleRef token for the target DLL. + + STDMETHOD(SetPinvokeMap)( // Return code. + mdToken tk, // [IN] FieldDef or MethodDef. + DWORD dwMappingFlags, // [IN] Flags used for mapping. + LPCWSTR szImportName, // [IN] Import name. + mdModuleRef mrImportDLL) PURE; // [IN] ModuleRef token for the target DLL. + + STDMETHOD(DeletePinvokeMap)( // Return code. + mdToken tk) PURE; // [IN] FieldDef or MethodDef. + + // New CustomAttribute functions. + STDMETHOD(DefineCustomAttribute)( // Return code. + mdToken tkObj, // [IN] The object to put the value on. + mdToken tkType, // [IN] Type of the CustomAttribute (TypeRef/TypeDef). + void const *pCustomAttribute, // [IN] The custom value data. + ULONG cbCustomAttribute, // [IN] The custom value data length. + mdCustomAttribute *pcv) PURE; // [OUT] The custom value token value on return. + + STDMETHOD(SetCustomAttributeValue)( // Return code. + mdCustomAttribute pcv, // [IN] The custom value token whose value to replace. + void const *pCustomAttribute, // [IN] The custom value data. + ULONG cbCustomAttribute) PURE;// [IN] The custom value data length. + + STDMETHOD(DefineField)( // S_OK or error. + mdTypeDef td, // Parent TypeDef + LPCWSTR szName, // Name of member + DWORD dwFieldFlags, // Member attributes + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + DWORD dwCPlusTypeFlag, // [IN] flag for value type. selected ELEMENT_TYPE_* + void const *pValue, // [IN] constant value + ULONG cchValue, // [IN] size of constant value (string, in wide chars). + mdFieldDef *pmd) PURE; // [OUT] Put member token here + + STDMETHOD(DefineProperty)( + mdTypeDef td, // [IN] the class/interface on which the property is being defined + LPCWSTR szProperty, // [IN] Name of the property + DWORD dwPropFlags, // [IN] CorPropertyAttr + PCCOR_SIGNATURE pvSig, // [IN] the required type signature + ULONG cbSig, // [IN] the size of the type signature blob + DWORD dwCPlusTypeFlag, // [IN] flag for value type. selected ELEMENT_TYPE_* + void const *pValue, // [IN] constant value + ULONG cchValue, // [IN] size of constant value (string, in wide chars). + mdMethodDef mdSetter, // [IN] optional setter of the property + mdMethodDef mdGetter, // [IN] optional getter of the property + mdMethodDef rmdOtherMethods[], // [IN] an optional array of other methods + mdProperty *pmdProp) PURE; // [OUT] output property token + + STDMETHOD(DefineParam)( + mdMethodDef md, // [IN] Owning method + ULONG ulParamSeq, // [IN] Which param + LPCWSTR szName, // [IN] Optional param name + DWORD dwParamFlags, // [IN] Optional param flags + DWORD dwCPlusTypeFlag, // [IN] flag for value type. selected ELEMENT_TYPE_* + void const *pValue, // [IN] constant value + ULONG cchValue, // [IN] size of constant value (string, in wide chars). + mdParamDef *ppd) PURE; // [OUT] Put param token here + + STDMETHOD(SetFieldProps)( // S_OK or error. + mdFieldDef fd, // [IN] The FieldDef. + DWORD dwFieldFlags, // [IN] Field attributes. + DWORD dwCPlusTypeFlag, // [IN] Flag for the value type, selected ELEMENT_TYPE_* + void const *pValue, // [IN] Constant value. + ULONG cchValue) PURE; // [IN] size of constant value (string, in wide chars). + + STDMETHOD(SetPropertyProps)( // S_OK or error. + mdProperty pr, // [IN] Property token. + DWORD dwPropFlags, // [IN] CorPropertyAttr. + DWORD dwCPlusTypeFlag, // [IN] Flag for value type, selected ELEMENT_TYPE_* + void const *pValue, // [IN] Constant value. + ULONG cchValue, // [IN] size of constant value (string, in wide chars). + mdMethodDef mdSetter, // [IN] Setter of the property. + mdMethodDef mdGetter, // [IN] Getter of the property. + mdMethodDef rmdOtherMethods[]) PURE;// [IN] Array of other methods. + + STDMETHOD(SetParamProps)( // Return code. + mdParamDef pd, // [IN] Param token. + LPCWSTR szName, // [IN] Param name. + DWORD dwParamFlags, // [IN] Param flags. + DWORD dwCPlusTypeFlag, // [IN] Flag for value type. selected ELEMENT_TYPE_*. + void const *pValue, // [OUT] Constant value. + ULONG cchValue) PURE; // [IN] size of constant value (string, in wide chars). + + // Specialized Custom Attributes for security. + STDMETHOD(DefineSecurityAttributeSet)( // Return code. + mdToken tkObj, // [IN] Class or method requiring security attributes. + COR_SECATTR rSecAttrs[], // [IN] Array of security attribute descriptions. + ULONG cSecAttrs, // [IN] Count of elements in above array. + ULONG *pulErrorAttr) PURE; // [OUT] On error, index of attribute causing problem. + + STDMETHOD(ApplyEditAndContinue)( // S_OK or error. + IUnknown *pImport) PURE; // [IN] Metadata from the delta PE. + + STDMETHOD(TranslateSigWithScope)( + IMetaDataAssemblyImport *pAssemImport, // [IN] importing assembly interface + const void *pbHashValue, // [IN] Hash Blob for Assembly. + ULONG cbHashValue, // [IN] Count of bytes. + IMetaDataImport *import, // [IN] importing interface + PCCOR_SIGNATURE pbSigBlob, // [IN] signature in the importing scope + ULONG cbSigBlob, // [IN] count of bytes of signature + IMetaDataAssemblyEmit *pAssemEmit, // [IN] emit assembly interface + IMetaDataEmit *emit, // [IN] emit interface + PCOR_SIGNATURE pvTranslatedSig, // [OUT] buffer to hold translated signature + ULONG cbTranslatedSigMax, + ULONG *pcbTranslatedSig) PURE;// [OUT] count of bytes in the translated signature + + STDMETHOD(SetMethodImplFlags)( // [IN] S_OK or error. + mdMethodDef md, // [IN] Method for which to set ImplFlags + DWORD dwImplFlags) PURE; + + STDMETHOD(SetFieldRVA)( // [IN] S_OK or error. + mdFieldDef fd, // [IN] Field for which to set offset + ULONG ulRVA) PURE; // [IN] The offset + + STDMETHOD(Merge)( // S_OK or error. + IMetaDataImport *pImport, // [IN] The scope to be merged. + IMapToken *pHostMapToken, // [IN] Host IMapToken interface to receive token remap notification + IUnknown *pHandler) PURE; // [IN] An object to receive to receive error notification. + + STDMETHOD(MergeEnd)() PURE; // S_OK or error. + + // This interface is sealed. Do not change, add, or remove anything. Instead, derive a new iterface. + +}; // IMetaDataEmit + +//------------------------------------- +//--- IMetaDataEmit2 +//------------------------------------- +// {F5DD9950-F693-42e6-830E-7B833E8146A9} +EXTERN_GUID(IID_IMetaDataEmit2, 0xf5dd9950, 0xf693, 0x42e6, 0x83, 0xe, 0x7b, 0x83, 0x3e, 0x81, 0x46, 0xa9); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataEmit2 +DECLARE_INTERFACE_(IMetaDataEmit2, IMetaDataEmit) +{ + STDMETHOD(DefineMethodSpec)( + mdToken tkParent, // [IN] MethodDef or MemberRef + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + mdMethodSpec *pmi) PURE; // [OUT] method instantiation token + + STDMETHOD(GetDeltaSaveSize)( // S_OK or error. + CorSaveSize fSave, // [IN] cssAccurate or cssQuick. + DWORD *pdwSaveSize) PURE; // [OUT] Put the size here. + + STDMETHOD(SaveDelta)( // S_OK or error. + LPCWSTR szFile, // [IN] The filename to save to. + DWORD dwSaveFlags) PURE; // [IN] Flags for the save. + + STDMETHOD(SaveDeltaToStream)( // S_OK or error. + IStream *pIStream, // [IN] A writable stream to save to. + DWORD dwSaveFlags) PURE; // [IN] Flags for the save. + + STDMETHOD(SaveDeltaToMemory)( // S_OK or error. + void *pbData, // [OUT] Location to write data. + ULONG cbData) PURE; // [IN] Max size of data buffer. + + STDMETHOD(DefineGenericParam)( // S_OK or error. + mdToken tk, // [IN] TypeDef or MethodDef + ULONG ulParamSeq, // [IN] Index of the type parameter + DWORD dwParamFlags, // [IN] Flags, for future use (e.g. variance) + LPCWSTR szname, // [IN] Name + DWORD reserved, // [IN] For future use (e.g. non-type parameters) + mdToken rtkConstraints[], // [IN] Array of type constraints (TypeDef,TypeRef,TypeSpec) + mdGenericParam *pgp) PURE; // [OUT] Put GenericParam token here + + STDMETHOD(SetGenericParamProps)( // S_OK or error. + mdGenericParam gp, // [IN] GenericParam + DWORD dwParamFlags, // [IN] Flags, for future use (e.g. variance) + LPCWSTR szName, // [IN] Optional name + DWORD reserved, // [IN] For future use (e.g. non-type parameters) + mdToken rtkConstraints[]) PURE;// [IN] Array of type constraints (TypeDef,TypeRef,TypeSpec) + + STDMETHOD(ResetENCLog)() PURE; // S_OK or error. + +}; + +//------------------------------------- +//--- IMetaDataImport +//------------------------------------- +// {7DAC8207-D3AE-4c75-9B67-92801A497D44} +EXTERN_GUID(IID_IMetaDataImport, 0x7dac8207, 0xd3ae, 0x4c75, 0x9b, 0x67, 0x92, 0x80, 0x1a, 0x49, 0x7d, 0x44); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataImport +DECLARE_INTERFACE_(IMetaDataImport, IUnknown) +{ + STDMETHOD_(void, CloseEnum)(HCORENUM hEnum) PURE; + STDMETHOD(CountEnum)(HCORENUM hEnum, ULONG *pulCount) PURE; + STDMETHOD(ResetEnum)(HCORENUM hEnum, ULONG ulPos) PURE; + STDMETHOD(EnumTypeDefs)(HCORENUM *phEnum, mdTypeDef rTypeDefs[], + ULONG cMax, ULONG *pcTypeDefs) PURE; + STDMETHOD(EnumInterfaceImpls)(HCORENUM *phEnum, mdTypeDef td, + mdInterfaceImpl rImpls[], ULONG cMax, + ULONG* pcImpls) PURE; + STDMETHOD(EnumTypeRefs)(HCORENUM *phEnum, mdTypeRef rTypeRefs[], + ULONG cMax, ULONG* pcTypeRefs) PURE; + + STDMETHOD(FindTypeDefByName)( // S_OK or error. + LPCWSTR szTypeDef, // [IN] Name of the Type. + mdToken tkEnclosingClass, // [IN] TypeDef/TypeRef for Enclosing class. + mdTypeDef *ptd) PURE; // [OUT] Put the TypeDef token here. + + STDMETHOD(GetScopeProps)( // S_OK or error. + _Out_writes_to_opt_(cchName, *pchName) + LPWSTR szName, // [OUT] Put the name here. + ULONG cchName, // [IN] Size of name buffer in wide chars. + ULONG *pchName, // [OUT] Put size of name (wide chars) here. + GUID *pmvid) PURE; // [OUT, OPTIONAL] Put MVID here. + + STDMETHOD(GetModuleFromScope)( // S_OK. + mdModule *pmd) PURE; // [OUT] Put mdModule token here. + + STDMETHOD(GetTypeDefProps)( // S_OK or error. + mdTypeDef td, // [IN] TypeDef token for inquiry. + _Out_writes_to_opt_(cchTypeDef, *pchTypeDef) + LPWSTR szTypeDef, // [OUT] Put name here. + ULONG cchTypeDef, // [IN] size of name buffer in wide chars. + ULONG *pchTypeDef, // [OUT] put size of name (wide chars) here. + DWORD *pdwTypeDefFlags, // [OUT] Put flags here. + mdToken *ptkExtends) PURE; // [OUT] Put base class TypeDef/TypeRef here. + + STDMETHOD(GetInterfaceImplProps)( // S_OK or error. + mdInterfaceImpl iiImpl, // [IN] InterfaceImpl token. + mdTypeDef *pClass, // [OUT] Put implementing class token here. + mdToken *ptkIface) PURE; // [OUT] Put implemented interface token here. + + STDMETHOD(GetTypeRefProps)( // S_OK or error. + mdTypeRef tr, // [IN] TypeRef token. + mdToken *ptkResolutionScope, // [OUT] Resolution scope, ModuleRef or AssemblyRef. + _Out_writes_to_opt_(cchName, *pchName) + LPWSTR szName, // [OUT] Name of the TypeRef. + ULONG cchName, // [IN] Size of buffer. + ULONG *pchName) PURE; // [OUT] Size of Name. + + STDMETHOD(ResolveTypeRef)(mdTypeRef tr, REFIID riid, IUnknown **ppIScope, mdTypeDef *ptd) PURE; + + STDMETHOD(EnumMembers)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef cl, // [IN] TypeDef to scope the enumeration. + mdToken rMembers[], // [OUT] Put MemberDefs here. + ULONG cMax, // [IN] Max MemberDefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumMembersWithName)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef cl, // [IN] TypeDef to scope the enumeration. + LPCWSTR szName, // [IN] Limit results to those with this name. + mdToken rMembers[], // [OUT] Put MemberDefs here. + ULONG cMax, // [IN] Max MemberDefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumMethods)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef cl, // [IN] TypeDef to scope the enumeration. + mdMethodDef rMethods[], // [OUT] Put MethodDefs here. + ULONG cMax, // [IN] Max MethodDefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumMethodsWithName)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef cl, // [IN] TypeDef to scope the enumeration. + LPCWSTR szName, // [IN] Limit results to those with this name. + mdMethodDef rMethods[], // [OU] Put MethodDefs here. + ULONG cMax, // [IN] Max MethodDefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumFields)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef cl, // [IN] TypeDef to scope the enumeration. + mdFieldDef rFields[], // [OUT] Put FieldDefs here. + ULONG cMax, // [IN] Max FieldDefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumFieldsWithName)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef cl, // [IN] TypeDef to scope the enumeration. + LPCWSTR szName, // [IN] Limit results to those with this name. + mdFieldDef rFields[], // [OUT] Put MemberDefs here. + ULONG cMax, // [IN] Max MemberDefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + + STDMETHOD(EnumParams)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdMethodDef mb, // [IN] MethodDef to scope the enumeration. + mdParamDef rParams[], // [OUT] Put ParamDefs here. + ULONG cMax, // [IN] Max ParamDefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumMemberRefs)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdToken tkParent, // [IN] Parent token to scope the enumeration. + mdMemberRef rMemberRefs[], // [OUT] Put MemberRefs here. + ULONG cMax, // [IN] Max MemberRefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumMethodImpls)( // S_OK, S_FALSE, or error + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef td, // [IN] TypeDef to scope the enumeration. + mdToken rMethodBody[], // [OUT] Put Method Body tokens here. + mdToken rMethodDecl[], // [OUT] Put Method Declaration tokens here. + ULONG cMax, // [IN] Max tokens to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumPermissionSets)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdToken tk, // [IN] if !NIL, token to scope the enumeration. + DWORD dwActions, // [IN] if !0, return only these actions. + mdPermission rPermission[], // [OUT] Put Permissions here. + ULONG cMax, // [IN] Max Permissions to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(FindMember)( + mdTypeDef td, // [IN] given typedef + LPCWSTR szName, // [IN] member name + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + mdToken *pmb) PURE; // [OUT] matching memberdef + + STDMETHOD(FindMethod)( + mdTypeDef td, // [IN] given typedef + LPCWSTR szName, // [IN] member name + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + mdMethodDef *pmb) PURE; // [OUT] matching memberdef + + STDMETHOD(FindField)( + mdTypeDef td, // [IN] given typedef + LPCWSTR szName, // [IN] member name + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + mdFieldDef *pmb) PURE; // [OUT] matching memberdef + + STDMETHOD(FindMemberRef)( + mdTypeRef td, // [IN] given typeRef + LPCWSTR szName, // [IN] member name + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + mdMemberRef *pmr) PURE; // [OUT] matching memberref + + STDMETHOD (GetMethodProps)( + mdMethodDef mb, // The method for which to get props. + mdTypeDef *pClass, // Put method's class here. + _Out_writes_to_opt_(cchMethod, *pchMethod) + LPWSTR szMethod, // Put method's name here. + ULONG cchMethod, // Size of szMethod buffer in wide chars. + ULONG *pchMethod, // Put actual size here + DWORD *pdwAttr, // Put flags here. + PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data + ULONG *pcbSigBlob, // [OUT] actual size of signature blob + ULONG *pulCodeRVA, // [OUT] codeRVA + DWORD *pdwImplFlags) PURE; // [OUT] Impl. Flags + + STDMETHOD(GetMemberRefProps)( // S_OK or error. + mdMemberRef mr, // [IN] given memberref + mdToken *ptk, // [OUT] Put classref or classdef here. + _Out_writes_to_opt_(cchMember, *pchMember) + LPWSTR szMember, // [OUT] buffer to fill for member's name + ULONG cchMember, // [IN] the count of char of szMember + ULONG *pchMember, // [OUT] actual count of char in member name + PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to meta data blob value + ULONG *pbSig) PURE; // [OUT] actual size of signature blob + + STDMETHOD(EnumProperties)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef td, // [IN] TypeDef to scope the enumeration. + mdProperty rProperties[], // [OUT] Put Properties here. + ULONG cMax, // [IN] Max properties to put. + ULONG *pcProperties) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumEvents)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef td, // [IN] TypeDef to scope the enumeration. + mdEvent rEvents[], // [OUT] Put events here. + ULONG cMax, // [IN] Max events to put. + ULONG *pcEvents) PURE; // [OUT] Put # put here. + + STDMETHOD(GetEventProps)( // S_OK, S_FALSE, or error. + mdEvent ev, // [IN] event token + mdTypeDef *pClass, // [OUT] typedef containing the event declarion. + LPCWSTR szEvent, // [OUT] Event name + ULONG cchEvent, // [IN] the count of wchar of szEvent + ULONG *pchEvent, // [OUT] actual count of wchar for event's name + DWORD *pdwEventFlags, // [OUT] Event flags. + mdToken *ptkEventType, // [OUT] EventType class + mdMethodDef *pmdAddOn, // [OUT] AddOn method of the event + mdMethodDef *pmdRemoveOn, // [OUT] RemoveOn method of the event + mdMethodDef *pmdFire, // [OUT] Fire method of the event + mdMethodDef rmdOtherMethod[], // [OUT] other method of the event + ULONG cMax, // [IN] size of rmdOtherMethod + ULONG *pcOtherMethod) PURE; // [OUT] total number of other method of this event + + STDMETHOD(EnumMethodSemantics)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdMethodDef mb, // [IN] MethodDef to scope the enumeration. + mdToken rEventProp[], // [OUT] Put Event/Property here. + ULONG cMax, // [IN] Max properties to put. + ULONG *pcEventProp) PURE; // [OUT] Put # put here. + + STDMETHOD(GetMethodSemantics)( // S_OK, S_FALSE, or error. + mdMethodDef mb, // [IN] method token + mdToken tkEventProp, // [IN] event/property token. + DWORD *pdwSemanticsFlags) PURE; // [OUT] the role flags for the method/propevent pair + + STDMETHOD(GetClassLayout) ( + mdTypeDef td, // [IN] give typedef + DWORD *pdwPackSize, // [OUT] 1, 2, 4, 8, or 16 + COR_FIELD_OFFSET rFieldOffset[], // [OUT] field offset array + ULONG cMax, // [IN] size of the array + ULONG *pcFieldOffset, // [OUT] needed array size + ULONG *pulClassSize) PURE; // [OUT] the size of the class + + STDMETHOD(GetFieldMarshal) ( + mdToken tk, // [IN] given a field's memberdef + PCCOR_SIGNATURE *ppvNativeType, // [OUT] native type of this field + ULONG *pcbNativeType) PURE; // [OUT] the count of bytes of *ppvNativeType + + STDMETHOD(GetRVA)( // S_OK or error. + mdToken tk, // Member for which to set offset + ULONG *pulCodeRVA, // The offset + DWORD *pdwImplFlags) PURE; // the implementation flags + + STDMETHOD(GetPermissionSetProps) ( + mdPermission pm, // [IN] the permission token. + DWORD *pdwAction, // [OUT] CorDeclSecurity. + void const **ppvPermission, // [OUT] permission blob. + ULONG *pcbPermission) PURE; // [OUT] count of bytes of pvPermission. + + STDMETHOD(GetSigFromToken)( // S_OK or error. + mdSignature mdSig, // [IN] Signature token. + PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to token. + ULONG *pcbSig) PURE; // [OUT] return size of signature. + + STDMETHOD(GetModuleRefProps)( // S_OK or error. + mdModuleRef mur, // [IN] moduleref token. + _Out_writes_to_opt_(cchName, *pchName) + LPWSTR szName, // [OUT] buffer to fill with the moduleref name. + ULONG cchName, // [IN] size of szName in wide characters. + ULONG *pchName) PURE; // [OUT] actual count of characters in the name. + + STDMETHOD(EnumModuleRefs)( // S_OK or error. + HCORENUM *phEnum, // [IN|OUT] pointer to the enum. + mdModuleRef rModuleRefs[], // [OUT] put modulerefs here. + ULONG cmax, // [IN] max memberrefs to put. + ULONG *pcModuleRefs) PURE; // [OUT] put # put here. + + STDMETHOD(GetTypeSpecFromToken)( // S_OK or error. + mdTypeSpec typespec, // [IN] TypeSpec token. + PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to TypeSpec signature + ULONG *pcbSig) PURE; // [OUT] return size of signature. + + STDMETHOD(GetNameFromToken)( // Not Recommended! May be removed! + mdToken tk, // [IN] Token to get name from. Must have a name. + MDUTF8CSTR *pszUtf8NamePtr) PURE; // [OUT] Return pointer to UTF8 name in heap. + + STDMETHOD(EnumUnresolvedMethods)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdToken rMethods[], // [OUT] Put MemberDefs here. + ULONG cMax, // [IN] Max MemberDefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(GetUserString)( // S_OK or error. + mdString stk, // [IN] String token. + _Out_writes_to_opt_(cchString, *pchString) + LPWSTR szString, // [OUT] Copy of string. + ULONG cchString, // [IN] Max chars of room in szString. + ULONG *pchString) PURE; // [OUT] How many chars in actual string. + + STDMETHOD(GetPinvokeMap)( // S_OK or error. + mdToken tk, // [IN] FieldDef or MethodDef. + DWORD *pdwMappingFlags, // [OUT] Flags used for mapping. + _Out_writes_to_opt_(cchImportName, *pchImportName) + LPWSTR szImportName, // [OUT] Import name. + ULONG cchImportName, // [IN] Size of the name buffer. + ULONG *pchImportName, // [OUT] Actual number of characters stored. + mdModuleRef *pmrImportDLL) PURE; // [OUT] ModuleRef token for the target DLL. + + STDMETHOD(EnumSignatures)( // S_OK or error. + HCORENUM *phEnum, // [IN|OUT] pointer to the enum. + mdSignature rSignatures[], // [OUT] put signatures here. + ULONG cmax, // [IN] max signatures to put. + ULONG *pcSignatures) PURE; // [OUT] put # put here. + + STDMETHOD(EnumTypeSpecs)( // S_OK or error. + HCORENUM *phEnum, // [IN|OUT] pointer to the enum. + mdTypeSpec rTypeSpecs[], // [OUT] put TypeSpecs here. + ULONG cmax, // [IN] max TypeSpecs to put. + ULONG *pcTypeSpecs) PURE; // [OUT] put # put here. + + STDMETHOD(EnumUserStrings)( // S_OK or error. + HCORENUM *phEnum, // [IN/OUT] pointer to the enum. + mdString rStrings[], // [OUT] put Strings here. + ULONG cmax, // [IN] max Strings to put. + ULONG *pcStrings) PURE; // [OUT] put # put here. + + STDMETHOD(GetParamForMethodIndex)( // S_OK or error. + mdMethodDef md, // [IN] Method token. + ULONG ulParamSeq, // [IN] Parameter sequence. + mdParamDef *ppd) PURE; // [IN] Put Param token here. + + STDMETHOD(EnumCustomAttributes)( // S_OK or error. + HCORENUM *phEnum, // [IN, OUT] COR enumerator. + mdToken tk, // [IN] Token to scope the enumeration, 0 for all. + mdToken tkType, // [IN] Type of interest, 0 for all. + mdCustomAttribute rCustomAttributes[], // [OUT] Put custom attribute tokens here. + ULONG cMax, // [IN] Size of rCustomAttributes. + ULONG *pcCustomAttributes) PURE; // [OUT, OPTIONAL] Put count of token values here. + + STDMETHOD(GetCustomAttributeProps)( // S_OK or error. + mdCustomAttribute cv, // [IN] CustomAttribute token. + mdToken *ptkObj, // [OUT, OPTIONAL] Put object token here. + mdToken *ptkType, // [OUT, OPTIONAL] Put AttrType token here. + void const **ppBlob, // [OUT, OPTIONAL] Put pointer to data here. + ULONG *pcbSize) PURE; // [OUT, OPTIONAL] Put size of date here. + + STDMETHOD(FindTypeRef)( + mdToken tkResolutionScope, // [IN] ModuleRef, AssemblyRef or TypeRef. + LPCWSTR szName, // [IN] TypeRef Name. + mdTypeRef *ptr) PURE; // [OUT] matching TypeRef. + + STDMETHOD(GetMemberProps)( + mdToken mb, // The member for which to get props. + mdTypeDef *pClass, // Put member's class here. + _Out_writes_to_opt_(cchMember, *pchMember) + LPWSTR szMember, // Put member's name here. + ULONG cchMember, // Size of szMember buffer in wide chars. + ULONG *pchMember, // Put actual size here + DWORD *pdwAttr, // Put flags here. + PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data + ULONG *pcbSigBlob, // [OUT] actual size of signature blob + ULONG *pulCodeRVA, // [OUT] codeRVA + DWORD *pdwImplFlags, // [OUT] Impl. Flags + DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* + UVCP_CONSTANT *ppValue, // [OUT] constant value + ULONG *pcchValue) PURE; // [OUT] size of constant string in chars, 0 for non-strings. + + STDMETHOD(GetFieldProps)( + mdFieldDef mb, // The field for which to get props. + mdTypeDef *pClass, // Put field's class here. + _Out_writes_to_opt_(cchField, *pchField) + LPWSTR szField, // Put field's name here. + ULONG cchField, // Size of szField buffer in wide chars. + ULONG *pchField, // Put actual size here + DWORD *pdwAttr, // Put flags here. + PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data + ULONG *pcbSigBlob, // [OUT] actual size of signature blob + DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* + UVCP_CONSTANT *ppValue, // [OUT] constant value + ULONG *pcchValue) PURE; // [OUT] size of constant string in chars, 0 for non-strings. + + STDMETHOD(GetPropertyProps)( // S_OK, S_FALSE, or error. + mdProperty prop, // [IN] property token + mdTypeDef *pClass, // [OUT] typedef containing the property declarion. + LPCWSTR szProperty, // [OUT] Property name + ULONG cchProperty, // [IN] the count of wchar of szProperty + ULONG *pchProperty, // [OUT] actual count of wchar for property name + DWORD *pdwPropFlags, // [OUT] property flags. + PCCOR_SIGNATURE *ppvSig, // [OUT] property type. pointing to meta data internal blob + ULONG *pbSig, // [OUT] count of bytes in *ppvSig + DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* + UVCP_CONSTANT *ppDefaultValue, // [OUT] constant value + ULONG *pcchDefaultValue, // [OUT] size of constant string in chars, 0 for non-strings. + mdMethodDef *pmdSetter, // [OUT] setter method of the property + mdMethodDef *pmdGetter, // [OUT] getter method of the property + mdMethodDef rmdOtherMethod[], // [OUT] other method of the property + ULONG cMax, // [IN] size of rmdOtherMethod + ULONG *pcOtherMethod) PURE; // [OUT] total number of other method of this property + + STDMETHOD(GetParamProps)( // S_OK or error. + mdParamDef tk, // [IN]The Parameter. + mdMethodDef *pmd, // [OUT] Parent Method token. + ULONG *pulSequence, // [OUT] Parameter sequence. + _Out_writes_to_opt_(cchName, *pchName) + LPWSTR szName, // [OUT] Put name here. + ULONG cchName, // [OUT] Size of name buffer. + ULONG *pchName, // [OUT] Put actual size of name here. + DWORD *pdwAttr, // [OUT] Put flags here. + DWORD *pdwCPlusTypeFlag, // [OUT] Flag for value type. selected ELEMENT_TYPE_*. + UVCP_CONSTANT *ppValue, // [OUT] Constant value. + ULONG *pcchValue) PURE; // [OUT] size of constant string in chars, 0 for non-strings. + + STDMETHOD(GetCustomAttributeByName)( // S_OK or error. + mdToken tkObj, // [IN] Object with Custom Attribute. + LPCWSTR szName, // [IN] Name of desired Custom Attribute. + const void **ppData, // [OUT] Put pointer to data here. + ULONG *pcbData) PURE; // [OUT] Put size of data here. + + STDMETHOD_(BOOL, IsValidToken)( // True or False. + mdToken tk) PURE; // [IN] Given token. + + STDMETHOD(GetNestedClassProps)( // S_OK or error. + mdTypeDef tdNestedClass, // [IN] NestedClass token. + mdTypeDef *ptdEnclosingClass) PURE; // [OUT] EnclosingClass token. + + STDMETHOD(GetNativeCallConvFromSig)( // S_OK or error. + void const *pvSig, // [IN] Pointer to signature. + ULONG cbSig, // [IN] Count of signature bytes. + ULONG *pCallConv) PURE; // [OUT] Put calling conv here (see CorPinvokemap). + + STDMETHOD(IsGlobal)( // S_OK or error. + mdToken pd, // [IN] Type, Field, or Method token. + int *pbGlobal) PURE; // [OUT] Put 1 if global, 0 otherwise. + + // This interface is sealed. Do not change, add, or remove anything. Instead, derive a new iterface. + +}; // IMetaDataImport + +//------------------------------------- +//--- IMetaDataImport2 +//------------------------------------- +// {FCE5EFA0-8BBA-4f8e-A036-8F2022B08466} +EXTERN_GUID(IID_IMetaDataImport2, 0xfce5efa0, 0x8bba, 0x4f8e, 0xa0, 0x36, 0x8f, 0x20, 0x22, 0xb0, 0x84, 0x66); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataImport2 +DECLARE_INTERFACE_(IMetaDataImport2, IMetaDataImport) +{ + STDMETHOD(EnumGenericParams)( + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdToken tk, // [IN] TypeDef or MethodDef whose generic parameters are requested + mdGenericParam rGenericParams[], // [OUT] Put GenericParams here. + ULONG cMax, // [IN] Max GenericParams to put. + ULONG *pcGenericParams) PURE; // [OUT] Put # put here. + + STDMETHOD(GetGenericParamProps)( // S_OK or error. + mdGenericParam gp, // [IN] GenericParam + ULONG *pulParamSeq, // [OUT] Index of the type parameter + DWORD *pdwParamFlags, // [OUT] Flags, for future use (e.g. variance) + mdToken *ptOwner, // [OUT] Owner (TypeDef or MethodDef) + DWORD *reserved, // [OUT] For future use (e.g. non-type parameters) + _Out_writes_to_opt_(cchName, *pchName) + LPWSTR wzname, // [OUT] Put name here + ULONG cchName, // [IN] Size of buffer + ULONG *pchName) PURE; // [OUT] Put size of name (wide chars) here. + + STDMETHOD(GetMethodSpecProps)( + mdMethodSpec mi, // [IN] The method instantiation + mdToken *tkParent, // [OUT] MethodDef or MemberRef + PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data + ULONG *pcbSigBlob) PURE; // [OUT] actual size of signature blob + + STDMETHOD(EnumGenericParamConstraints)( + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdGenericParam tk, // [IN] GenericParam whose constraints are requested + mdGenericParamConstraint rGenericParamConstraints[], // [OUT] Put GenericParamConstraints here. + ULONG cMax, // [IN] Max GenericParamConstraints to put. + ULONG *pcGenericParamConstraints) PURE; // [OUT] Put # put here. + + STDMETHOD(GetGenericParamConstraintProps)( // S_OK or error. + mdGenericParamConstraint gpc, // [IN] GenericParamConstraint + mdGenericParam *ptGenericParam, // [OUT] GenericParam that is constrained + mdToken *ptkConstraintType) PURE; // [OUT] TypeDef/Ref/Spec constraint + + STDMETHOD(GetPEKind)( // S_OK or error. + DWORD* pdwPEKind, // [OUT] The kind of PE (0 - not a PE) + DWORD* pdwMAchine) PURE; // [OUT] Machine as defined in NT header + + STDMETHOD(GetVersionString)( // S_OK or error. + _Out_writes_to_opt_(cchBufSize, *pccBufSize) + LPWSTR pwzBuf, // [OUT[ Put version string here. + DWORD cchBufSize, // [IN] size of the buffer, in wide chars + DWORD *pccBufSize) PURE; // [OUT] Size of the version string, wide chars, including terminating nul. + + STDMETHOD(EnumMethodSpecs)( + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdToken tk, // [IN] MethodDef or MemberRef whose MethodSpecs are requested + mdMethodSpec rMethodSpecs[], // [OUT] Put MethodSpecs here. + ULONG cMax, // [IN] Max tokens to put. + ULONG *pcMethodSpecs) PURE; // [OUT] Put actual count here. + +}; // IMetaDataImport2 + +//------------------------------------- +//--- IMetaDataFilter +//------------------------------------- +// {D0E80DD1-12D4-11d3-B39D-00C04FF81795} +EXTERN_GUID(IID_IMetaDataFilter, 0xd0e80dd1, 0x12d4, 0x11d3, 0xb3, 0x9d, 0x0, 0xc0, 0x4f, 0xf8, 0x17, 0x95); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataFilter +DECLARE_INTERFACE_(IMetaDataFilter, IUnknown) +{ + STDMETHOD(UnmarkAll)() PURE; + STDMETHOD(MarkToken)(mdToken tk) PURE; + STDMETHOD(IsTokenMarked)(mdToken tk, BOOL *pIsMarked) PURE; +}; + + + +//------------------------------------- +//--- IHostFilter +//------------------------------------- +// {D0E80DD3-12D4-11d3-B39D-00C04FF81795} +EXTERN_GUID(IID_IHostFilter, 0xd0e80dd3, 0x12d4, 0x11d3, 0xb3, 0x9d, 0x0, 0xc0, 0x4f, 0xf8, 0x17, 0x95); + +//--- +#undef INTERFACE +#define INTERFACE IHostFilter +DECLARE_INTERFACE_(IHostFilter, IUnknown) +{ + STDMETHOD(MarkToken)(mdToken tk) PURE; +}; + + +//-------------------------------------- +//--- IMetaDataConverter +//-------------------------------------- +// {D9DEBD79-2992-11d3-8BC1-0000F8083A57} +EXTERN_GUID(IID_IMetaDataConverter, 0xd9debd79, 0x2992, 0x11d3, 0x8b, 0xc1, 0x0, 0x0, 0xf8, 0x8, 0x3a, 0x57); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataConverter +DECLARE_INTERFACE_(IMetaDataConverter, IUnknown) +{ + STDMETHOD(GetMetaDataFromTypeInfo)( + ITypeInfo* pITI, // [in] Type info + IMetaDataImport** ppMDI) PURE; // [out] return IMetaDataImport on success + + STDMETHOD(GetMetaDataFromTypeLib)( + ITypeLib* pITL, // [in] Type library + IMetaDataImport** ppMDI) PURE; // [out] return IMetaDataImport on success + + STDMETHOD(GetTypeLibFromMetaData)( + BSTR strModule, // [in] Module name + BSTR strTlbName, // [in] Type library name + ITypeLib** ppITL) PURE; // [out] return ITypeLib on success +}; + + +//***************************************************************************** +// Assembly Declarations +//***************************************************************************** + +typedef struct +{ + DWORD dwOSPlatformId; // Operating system platform. + DWORD dwOSMajorVersion; // OS Major version. + DWORD dwOSMinorVersion; // OS Minor version. +} OSINFO; + + +typedef struct +{ + USHORT usMajorVersion; // Major Version. + USHORT usMinorVersion; // Minor Version. + USHORT usBuildNumber; // Build Number. + USHORT usRevisionNumber; // Revision Number. + LPWSTR szLocale; // Locale. + ULONG cbLocale; // [IN/OUT] Size of the buffer in wide chars/Actual size. + DWORD *rProcessor; // Processor ID array. + ULONG ulProcessor; // [IN/OUT] Size of the Processor ID array/Actual # of entries filled in. + OSINFO *rOS; // OSINFO array. + ULONG ulOS; // [IN/OUT]Size of the OSINFO array/Actual # of entries filled in. +} ASSEMBLYMETADATA; + + +// {211EF15B-5317-4438-B196-DEC87B887693} +EXTERN_GUID(IID_IMetaDataAssemblyEmit, 0x211ef15b, 0x5317, 0x4438, 0xb1, 0x96, 0xde, 0xc8, 0x7b, 0x88, 0x76, 0x93); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataAssemblyEmit +DECLARE_INTERFACE_(IMetaDataAssemblyEmit, IUnknown) +{ + STDMETHOD(DefineAssembly)( // S_OK or error. + const void *pbPublicKey, // [IN] Public key of the assembly. + ULONG cbPublicKey, // [IN] Count of bytes in the public key. + ULONG ulHashAlgId, // [IN] Hash algorithm used to hash the files. + LPCWSTR szName, // [IN] Name of the assembly. + const ASSEMBLYMETADATA *pMetaData, // [IN] Assembly MetaData. + DWORD dwAssemblyFlags, // [IN] Flags. + mdAssembly *pma) PURE; // [OUT] Returned Assembly token. + + STDMETHOD(DefineAssemblyRef)( // S_OK or error. + const void *pbPublicKeyOrToken, // [IN] Public key or token of the assembly. + ULONG cbPublicKeyOrToken, // [IN] Count of bytes in the public key or token. + LPCWSTR szName, // [IN] Name of the assembly being referenced. + const ASSEMBLYMETADATA *pMetaData, // [IN] Assembly MetaData. + const void *pbHashValue, // [IN] Hash Blob. + ULONG cbHashValue, // [IN] Count of bytes in the Hash Blob. + DWORD dwAssemblyRefFlags, // [IN] Flags. + mdAssemblyRef *pmdar) PURE; // [OUT] Returned AssemblyRef token. + + STDMETHOD(DefineFile)( // S_OK or error. + LPCWSTR szName, // [IN] Name of the file. + const void *pbHashValue, // [IN] Hash Blob. + ULONG cbHashValue, // [IN] Count of bytes in the Hash Blob. + DWORD dwFileFlags, // [IN] Flags. + mdFile *pmdf) PURE; // [OUT] Returned File token. + + STDMETHOD(DefineExportedType)( // S_OK or error. + LPCWSTR szName, // [IN] Name of the Com Type. + mdToken tkImplementation, // [IN] mdFile or mdAssemblyRef or mdExportedType + mdTypeDef tkTypeDef, // [IN] TypeDef token within the file. + DWORD dwExportedTypeFlags, // [IN] Flags. + mdExportedType *pmdct) PURE; // [OUT] Returned ExportedType token. + + STDMETHOD(DefineManifestResource)( // S_OK or error. + LPCWSTR szName, // [IN] Name of the resource. + mdToken tkImplementation, // [IN] mdFile or mdAssemblyRef that provides the resource. + DWORD dwOffset, // [IN] Offset to the beginning of the resource within the file. + DWORD dwResourceFlags, // [IN] Flags. + mdManifestResource *pmdmr) PURE; // [OUT] Returned ManifestResource token. + + STDMETHOD(SetAssemblyProps)( // S_OK or error. + mdAssembly pma, // [IN] Assembly token. + const void *pbPublicKey, // [IN] Public key of the assembly. + ULONG cbPublicKey, // [IN] Count of bytes in the public key. + ULONG ulHashAlgId, // [IN] Hash algorithm used to hash the files. + LPCWSTR szName, // [IN] Name of the assembly. + const ASSEMBLYMETADATA *pMetaData, // [IN] Assembly MetaData. + DWORD dwAssemblyFlags) PURE; // [IN] Flags. + + STDMETHOD(SetAssemblyRefProps)( // S_OK or error. + mdAssemblyRef ar, // [IN] AssemblyRefToken. + const void *pbPublicKeyOrToken, // [IN] Public key or token of the assembly. + ULONG cbPublicKeyOrToken, // [IN] Count of bytes in the public key or token. + LPCWSTR szName, // [IN] Name of the assembly being referenced. + const ASSEMBLYMETADATA *pMetaData, // [IN] Assembly MetaData. + const void *pbHashValue, // [IN] Hash Blob. + ULONG cbHashValue, // [IN] Count of bytes in the Hash Blob. + DWORD dwAssemblyRefFlags) PURE; // [IN] Token for Execution Location. + + STDMETHOD(SetFileProps)( // S_OK or error. + mdFile file, // [IN] File token. + const void *pbHashValue, // [IN] Hash Blob. + ULONG cbHashValue, // [IN] Count of bytes in the Hash Blob. + DWORD dwFileFlags) PURE; // [IN] Flags. + + STDMETHOD(SetExportedTypeProps)( // S_OK or error. + mdExportedType ct, // [IN] ExportedType token. + mdToken tkImplementation, // [IN] mdFile or mdAssemblyRef or mdExportedType. + mdTypeDef tkTypeDef, // [IN] TypeDef token within the file. + DWORD dwExportedTypeFlags) PURE; // [IN] Flags. + + STDMETHOD(SetManifestResourceProps)( // S_OK or error. + mdManifestResource mr, // [IN] ManifestResource token. + mdToken tkImplementation, // [IN] mdFile or mdAssemblyRef that provides the resource. + DWORD dwOffset, // [IN] Offset to the beginning of the resource within the file. + DWORD dwResourceFlags) PURE; // [IN] Flags. + +}; // IMetaDataAssemblyEmit + + +// {EE62470B-E94B-424e-9B7C-2F00C9249F93} +EXTERN_GUID(IID_IMetaDataAssemblyImport, 0xee62470b, 0xe94b, 0x424e, 0x9b, 0x7c, 0x2f, 0x0, 0xc9, 0x24, 0x9f, 0x93); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataAssemblyImport +DECLARE_INTERFACE_(IMetaDataAssemblyImport, IUnknown) +{ + STDMETHOD(GetAssemblyProps)( // S_OK or error. + mdAssembly mda, // [IN] The Assembly for which to get the properties. + const void **ppbPublicKey, // [OUT] Pointer to the public key. + ULONG *pcbPublicKey, // [OUT] Count of bytes in the public key. + ULONG *pulHashAlgId, // [OUT] Hash Algorithm. + _Out_writes_to_opt_(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with assembly's simply name. + ULONG cchName, // [IN] Size of buffer in wide chars. + ULONG *pchName, // [OUT] Actual # of wide chars in name. + ASSEMBLYMETADATA *pMetaData, // [OUT] Assembly MetaData. + DWORD *pdwAssemblyFlags) PURE; // [OUT] Flags. + + STDMETHOD(GetAssemblyRefProps)( // S_OK or error. + mdAssemblyRef mdar, // [IN] The AssemblyRef for which to get the properties. + const void **ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token. + ULONG *pcbPublicKeyOrToken, // [OUT] Count of bytes in the public key or token. + _Out_writes_to_opt_(cchName, *pchName)LPWSTR szName, // [OUT] Buffer to fill with name. + ULONG cchName, // [IN] Size of buffer in wide chars. + ULONG *pchName, // [OUT] Actual # of wide chars in name. + ASSEMBLYMETADATA *pMetaData, // [OUT] Assembly MetaData. + const void **ppbHashValue, // [OUT] Hash blob. + ULONG *pcbHashValue, // [OUT] Count of bytes in the hash blob. + DWORD *pdwAssemblyRefFlags) PURE; // [OUT] Flags. + + STDMETHOD(GetFileProps)( // S_OK or error. + mdFile mdf, // [IN] The File for which to get the properties. + _Out_writes_to_opt_(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with name. + ULONG cchName, // [IN] Size of buffer in wide chars. + ULONG *pchName, // [OUT] Actual # of wide chars in name. + const void **ppbHashValue, // [OUT] Pointer to the Hash Value Blob. + ULONG *pcbHashValue, // [OUT] Count of bytes in the Hash Value Blob. + DWORD *pdwFileFlags) PURE; // [OUT] Flags. + + STDMETHOD(GetExportedTypeProps)( // S_OK or error. + mdExportedType mdct, // [IN] The ExportedType for which to get the properties. + _Out_writes_to_opt_(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with name. + ULONG cchName, // [IN] Size of buffer in wide chars. + ULONG *pchName, // [OUT] Actual # of wide chars in name. + mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef or mdExportedType. + mdTypeDef *ptkTypeDef, // [OUT] TypeDef token within the file. + DWORD *pdwExportedTypeFlags) PURE; // [OUT] Flags. + + STDMETHOD(GetManifestResourceProps)( // S_OK or error. + mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties. + _Out_writes_to_opt_(cchName, *pchName)LPWSTR szName, // [OUT] Buffer to fill with name. + ULONG cchName, // [IN] Size of buffer in wide chars. + ULONG *pchName, // [OUT] Actual # of wide chars in name. + mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ManifestResource. + DWORD *pdwOffset, // [OUT] Offset to the beginning of the resource within the file. + DWORD *pdwResourceFlags) PURE;// [OUT] Flags. + + STDMETHOD(EnumAssemblyRefs)( // S_OK or error + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdAssemblyRef rAssemblyRefs[], // [OUT] Put AssemblyRefs here. + ULONG cMax, // [IN] Max AssemblyRefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumFiles)( // S_OK or error + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdFile rFiles[], // [OUT] Put Files here. + ULONG cMax, // [IN] Max Files to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumExportedTypes)( // S_OK or error + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdExportedType rExportedTypes[], // [OUT] Put ExportedTypes here. + ULONG cMax, // [IN] Max ExportedTypes to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumManifestResources)( // S_OK or error + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdManifestResource rManifestResources[], // [OUT] Put ManifestResources here. + ULONG cMax, // [IN] Max Resources to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(GetAssemblyFromScope)( // S_OK or error + mdAssembly *ptkAssembly) PURE; // [OUT] Put token here. + + STDMETHOD(FindExportedTypeByName)( // S_OK or error + LPCWSTR szName, // [IN] Name of the ExportedType. + mdToken mdtExportedType, // [IN] ExportedType for the enclosing class. + mdExportedType *ptkExportedType) PURE; // [OUT] Put the ExportedType token here. + + STDMETHOD(FindManifestResourceByName)( // S_OK or error + LPCWSTR szName, // [IN] Name of the ManifestResource. + mdManifestResource *ptkManifestResource) PURE; // [OUT] Put the ManifestResource token here. + + STDMETHOD_(void, CloseEnum)( + HCORENUM hEnum) PURE; // Enum to be closed. + + STDMETHOD(FindAssembliesByName)( // S_OK or error + LPCWSTR szAppBase, // [IN] optional - can be NULL + LPCWSTR szPrivateBin, // [IN] optional - can be NULL + LPCWSTR szAssemblyName, // [IN] required - this is the assembly you are requesting + IUnknown *ppIUnk[], // [OUT] put IMetaDataAssemblyImport pointers here + ULONG cMax, // [IN] The max number to put + ULONG *pcAssemblies) PURE; // [OUT] The number of assemblies returned. +}; // IMetaDataAssemblyImport + + +//***************************************************************************** +// End Assembly Declarations +//***************************************************************************** + +//***************************************************************************** +// MetaData Validator Declarations +//***************************************************************************** + +// Specifies the type of the module, PE file vs. .obj file. +typedef enum +{ + ValidatorModuleTypeInvalid = 0x0, + ValidatorModuleTypeMin = 0x00000001, + ValidatorModuleTypePE = 0x00000001, + ValidatorModuleTypeObj = 0x00000002, + ValidatorModuleTypeEnc = 0x00000003, + ValidatorModuleTypeIncr = 0x00000004, + ValidatorModuleTypeMax = 0x00000004, +} CorValidatorModuleType; + + +// {4709C9C6-81FF-11D3-9FC7-00C04F79A0A3} +EXTERN_GUID(IID_IMetaDataValidate, 0x4709c9c6, 0x81ff, 0x11d3, 0x9f, 0xc7, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataValidate +DECLARE_INTERFACE_(IMetaDataValidate, IUnknown) +{ + STDMETHOD(ValidatorInit)( // S_OK or error. + DWORD dwModuleType, // [IN] Specifies the type of the module. + IUnknown *pUnk) PURE; // [IN] Validation error handler. + + STDMETHOD(ValidateMetaData)( // S_OK or error. + ) PURE; +}; // IMetaDataValidate + +//***************************************************************************** +// End MetaData Validator Declarations +//***************************************************************************** + +//***************************************************************************** +// IMetaDataDispenserEx declarations. +//***************************************************************************** + +// {31BCFCE2-DAFB-11D2-9F81-00C04F79A0A3} +EXTERN_GUID(IID_IMetaDataDispenserEx, 0x31bcfce2, 0xdafb, 0x11d2, 0x9f, 0x81, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); + +#undef INTERFACE +#define INTERFACE IMetaDataDispenserEx +DECLARE_INTERFACE_(IMetaDataDispenserEx, IMetaDataDispenser) +{ + STDMETHOD(SetOption)( // Return code. + REFGUID optionid, // [in] GUID for the option to be set. + const VARIANT *value) PURE; // [in] Value to which the option is to be set. + + STDMETHOD(GetOption)( // Return code. + REFGUID optionid, // [in] GUID for the option to be set. + VARIANT *pvalue) PURE; // [out] Value to which the option is currently set. + + STDMETHOD(OpenScopeOnITypeInfo)( // Return code. + ITypeInfo *pITI, // [in] ITypeInfo to open. + DWORD dwOpenFlags, // [in] Open mode flags. + REFIID riid, // [in] The interface desired. + IUnknown **ppIUnk) PURE; // [out] Return interface on success. + + STDMETHOD(GetCORSystemDirectory)( // Return code. + _Out_writes_to_opt_(cchBuffer, *pchBuffer) + LPWSTR szBuffer, // [out] Buffer for the directory name + DWORD cchBuffer, // [in] Size of the buffer + DWORD* pchBuffer) PURE; // [OUT] Number of characters returned + + STDMETHOD(FindAssembly)( // S_OK or error + LPCWSTR szAppBase, // [IN] optional - can be NULL + LPCWSTR szPrivateBin, // [IN] optional - can be NULL + LPCWSTR szGlobalBin, // [IN] optional - can be NULL + LPCWSTR szAssemblyName, // [IN] required - this is the assembly you are requesting + LPCWSTR szName, // [OUT] buffer - to hold name + ULONG cchName, // [IN] the name buffer's size + ULONG *pcName) PURE; // [OUT] the number of characters returend in the buffer + + STDMETHOD(FindAssemblyModule)( // S_OK or error + LPCWSTR szAppBase, // [IN] optional - can be NULL + LPCWSTR szPrivateBin, // [IN] optional - can be NULL + LPCWSTR szGlobalBin, // [IN] optional - can be NULL + LPCWSTR szAssemblyName, // [IN] required - this is the assembly you are requesting + LPCWSTR szModuleName, // [IN] required - the name of the module + _Out_writes_to_opt_(cchName, *pcName) + LPWSTR szName, // [OUT] buffer - to hold name + ULONG cchName, // [IN] the name buffer's size + ULONG *pcName) PURE; // [OUT] the number of characters returend in the buffer + +}; + +//***************************************************************************** +//***************************************************************************** +// +// Registration declarations. Will be replace by Services' Registration +// implementation. +// +//***************************************************************************** +//***************************************************************************** +// Various flags for use in installing a module or a composite +typedef enum +{ + regNoCopy = 0x00000001, // Don't copy files into destination + regConfig = 0x00000002, // Is a configuration + regHasRefs = 0x00000004 // Has class references +} CorRegFlags; + +typedef GUID CVID; + +typedef struct { + short Major; + short Minor; + short Sub; + short Build; +} CVStruct; + + +//***************************************************************************** +//***************************************************************************** +// +// CeeGen interfaces for generating in-memory Common Language Runtime files +// +//***************************************************************************** +//***************************************************************************** + +typedef void *HCEESECTION; + +typedef enum { + sdNone = 0, + sdReadOnly = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA, + sdReadWrite = sdReadOnly | IMAGE_SCN_MEM_WRITE, + sdExecute = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE +} CeeSectionAttr; + +// +// Relocation types. +// + +typedef enum { + // generate only a section-relative reloc, nothing into .reloc section + srRelocAbsolute, + + // generate a .reloc for a pointer sized location, + // This is transformed into BASED_HIGHLOW or BASED_DIR64 based on the platform + srRelocHighLow = 3, + + // generate a .reloc for the top 16-bits of a 32 bit number, where the + // bottom 16 bits are included in the next word in the .reloc table + srRelocHighAdj, // Never Used + + // generate a token map relocation, nothing into .reloc section + srRelocMapToken, + + // relative address fixup + srRelocRelative, + + // Generate only a section-relative reloc, nothing into .reloc + // section. This reloc is relative to the file position of the + // section, not the section's virtual address. + srRelocFilePos, + + // code relative address fixup + srRelocCodeRelative, + + // generate a .reloc for a 64 bit address in an ia64 movl instruction + srRelocIA64Imm64, + + // generate a .reloc for a 64 bit address + srRelocDir64, + + // generate a .reloc for a 25-bit PC relative address in an ia64 br.call instruction + srRelocIA64PcRel25, + + // generate a .reloc for a 64-bit PC relative address in an ia64 brl.call instruction + srRelocIA64PcRel64, + + // generate a 30-bit section-relative reloc, used for tagged pointer values + srRelocAbsoluteTagged, + + + // A sentinel value to help ensure any additions to this enum are reflected + // in PEWriter.cpp's RelocName array. + srRelocSentinel, + + // Flags that can be used with the above reloc types + + // do not emit base reloc + srNoBaseReloc = 0x4000, + + // pre-fixup contents of memory are ptr rather than a section offset + srRelocPtr = 0x8000, + + // legal enums which include the Ptr flag + srRelocAbsolutePtr = srRelocPtr + srRelocAbsolute, + srRelocHighLowPtr = srRelocPtr + srRelocHighLow, + srRelocRelativePtr = srRelocPtr + srRelocRelative, + srRelocIA64Imm64Ptr = srRelocPtr + srRelocIA64Imm64, + srRelocDir64Ptr = srRelocPtr + srRelocDir64, + +} CeeSectionRelocType; + +#define IMAGE_REL_BASED_REL32 7 +#define IMAGE_REL_BASED_IA64_PCREL21 11 +#define IMAGE_REL_BASED_IA64_PCREL60 12 + +typedef union { + USHORT highAdj; +} CeeSectionRelocExtra; + +//------------------------------------- +//--- ICeeGen +//------------------------------------- +// {7ED1BDFF-8E36-11d2-9C56-00A0C9B7CC45} +EXTERN_GUID(IID_ICeeGen, 0x7ed1bdff, 0x8e36, 0x11d2, 0x9c, 0x56, 0x0, 0xa0, 0xc9, 0xb7, 0xcc, 0x45); + +DECLARE_INTERFACE_(ICeeGen, IUnknown) +{ + STDMETHOD (EmitString) ( + _In_ + LPWSTR lpString, // [IN] String to emit + ULONG *RVA) PURE; // [OUT] RVA for string emitted string + + STDMETHOD (GetString) ( + ULONG RVA, // [IN] RVA for string to return + _Out_opt_ + LPWSTR *lpString) PURE; // [OUT] Returned string + + STDMETHOD (AllocateMethodBuffer) ( + ULONG cchBuffer, // [IN] Length of buffer to create + UCHAR **lpBuffer, // [OUT] Returned buffer + ULONG *RVA) PURE; // [OUT] RVA for method + + STDMETHOD (GetMethodBuffer) ( + ULONG RVA, // [IN] RVA for method to return + UCHAR **lpBuffer) PURE; // [OUT] Returned buffer + + STDMETHOD (GetIMapTokenIface) ( + IUnknown **pIMapToken) PURE; + + STDMETHOD (GenerateCeeFile) () PURE; + + STDMETHOD (GetIlSection) ( + HCEESECTION *section) PURE; + + STDMETHOD (GetStringSection) ( + HCEESECTION *section) PURE; + + STDMETHOD (AddSectionReloc) ( + HCEESECTION section, + ULONG offset, + HCEESECTION relativeTo, + CeeSectionRelocType relocType) PURE; + + // use these only if you have special section requirements not handled + // by other APIs + STDMETHOD (GetSectionCreate) ( + const char *name, + DWORD flags, + HCEESECTION *section) PURE; + + STDMETHOD (GetSectionDataLen) ( + HCEESECTION section, + ULONG *dataLen) PURE; + + STDMETHOD (GetSectionBlock) ( + HCEESECTION section, + ULONG len, + ULONG align=1, + void **ppBytes=0) PURE; + + STDMETHOD (TruncateSection) ( + HCEESECTION section, + ULONG len) PURE; + + STDMETHOD (GenerateCeeMemoryImage) ( + void **ppImage) PURE; + + STDMETHOD (ComputePointer) ( + HCEESECTION section, + ULONG RVA, // [IN] RVA for method to return + UCHAR **lpBuffer) PURE; // [OUT] Returned buffer + +}; + +//***************************************************************************** +//***************************************************************************** +// +// End of CeeGen declarations. +// +//***************************************************************************** + +//***************************************************************************** +//***************************************************************************** +// +// CorModule interfaces for generating in-memory modules +// +//***************************************************************************** +//***************************************************************************** + +typedef enum { + CORMODULE_MATCH = 0x00, // find an existing module that matches interfaces supported + CORMODULE_NEW = 0x01, // always create a new module and interfaces +} ICorModuleInitializeFlags; + +//------------------------------------- +//--- ICorModule +//------------------------------------- +// {2629F8E1-95E5-11d2-9C56-00A0C9B7CC45} +EXTERN_GUID(IID_ICorModule, 0x2629f8e1, 0x95e5, 0x11d2, 0x9c, 0x56, 0x0, 0xa0, 0xc9, 0xb7, 0xcc, 0x45); + +DECLARE_INTERFACE_(ICorModule, IUnknown) +{ + STDMETHOD (Initialize) ( + DWORD flags, // [IN] flags to control emitter returned + REFIID riidCeeGen, // [IN] type of cee generator to initialize with + REFIID riidEmitter) PURE; // [IN] type of emitter to initialize with + + STDMETHOD (GetCeeGen) ( + ICeeGen **pCeeGen) PURE; // [OUT] cee generator + + STDMETHOD (GetMetaDataEmit) ( + IMetaDataEmit **pEmitter) PURE; // [OUT] emitter +}; + +//***************************************************************************** +//***************************************************************************** +// +// End of CorModule declarations. +// +//***************************************************************************** + +//********************************************************************** +//********************************************************************** +//--- IMetaDataTables +//------------------------------------- +// This API isn't big endian friendly since it indexes directly into the memory that +// is stored in little endian format. +// {D8F579AB-402D-4b8e-82D9-5D63B1065C68} +EXTERN_GUID(IID_IMetaDataTables, 0xd8f579ab, 0x402d, 0x4b8e, 0x82, 0xd9, 0x5d, 0x63, 0xb1, 0x6, 0x5c, 0x68); + +DECLARE_INTERFACE_(IMetaDataTables, IUnknown) +{ + STDMETHOD (GetStringHeapSize) ( + ULONG *pcbStrings) PURE; // [OUT] Size of the string heap. + + STDMETHOD (GetBlobHeapSize) ( + ULONG *pcbBlobs) PURE; // [OUT] Size of the Blob heap. + + STDMETHOD (GetGuidHeapSize) ( + ULONG *pcbGuids) PURE; // [OUT] Size of the Guid heap. + + STDMETHOD (GetUserStringHeapSize) ( + ULONG *pcbBlobs) PURE; // [OUT] Size of the User String heap. + + STDMETHOD (GetNumTables) ( + ULONG *pcTables) PURE; // [OUT] Count of tables. + + STDMETHOD (GetTableIndex) ( + ULONG token, // [IN] Token for which to get table index. + ULONG *pixTbl) PURE; // [OUT] Put table index here. + + STDMETHOD (GetTableInfo) ( + ULONG ixTbl, // [IN] Which table. + ULONG *pcbRow, // [OUT] Size of a row, bytes. + ULONG *pcRows, // [OUT] Number of rows. + ULONG *pcCols, // [OUT] Number of columns in each row. + ULONG *piKey, // [OUT] Key column, or -1 if none. + const char **ppName) PURE; // [OUT] Name of the table. + + STDMETHOD (GetColumnInfo) ( + ULONG ixTbl, // [IN] Which Table + ULONG ixCol, // [IN] Which Column in the table + ULONG *poCol, // [OUT] Offset of the column in the row. + ULONG *pcbCol, // [OUT] Size of a column, bytes. + ULONG *pType, // [OUT] Type of the column. + const char **ppName) PURE; // [OUT] Name of the Column. + + STDMETHOD (GetCodedTokenInfo) ( + ULONG ixCdTkn, // [IN] Which kind of coded token. + ULONG *pcTokens, // [OUT] Count of tokens. + ULONG **ppTokens, // [OUT] List of tokens. + const char **ppName) PURE; // [OUT] Name of the CodedToken. + + STDMETHOD (GetRow) ( + ULONG ixTbl, // [IN] Which table. + ULONG rid, // [IN] Which row. + void **ppRow) PURE; // [OUT] Put pointer to row here. + + STDMETHOD (GetColumn) ( + ULONG ixTbl, // [IN] Which table. + ULONG ixCol, // [IN] Which column. + ULONG rid, // [IN] Which row. + ULONG *pVal) PURE; // [OUT] Put the column contents here. + + STDMETHOD (GetString) ( + ULONG ixString, // [IN] Value from a string column. + const char **ppString) PURE; // [OUT] Put a pointer to the string here. + + STDMETHOD (GetBlob) ( + ULONG ixBlob, // [IN] Value from a blob column. + ULONG *pcbData, // [OUT] Put size of the blob here. + const void **ppData) PURE; // [OUT] Put a pointer to the blob here. + + STDMETHOD (GetGuid) ( + ULONG ixGuid, // [IN] Value from a guid column. + const GUID **ppGUID) PURE; // [OUT] Put a pointer to the GUID here. + + STDMETHOD (GetUserString) ( + ULONG ixUserString, // [IN] Value from a UserString column. + ULONG *pcbData, // [OUT] Put size of the UserString here. + const void **ppData) PURE; // [OUT] Put a pointer to the UserString here. + + STDMETHOD (GetNextString) ( + ULONG ixString, // [IN] Value from a string column. + ULONG *pNext) PURE; // [OUT] Put the index of the next string here. + + STDMETHOD (GetNextBlob) ( + ULONG ixBlob, // [IN] Value from a blob column. + ULONG *pNext) PURE; // [OUT] Put the index of the netxt blob here. + + STDMETHOD (GetNextGuid) ( + ULONG ixGuid, // [IN] Value from a guid column. + ULONG *pNext) PURE; // [OUT] Put the index of the next guid here. + + STDMETHOD (GetNextUserString) ( + ULONG ixUserString, // [IN] Value from a UserString column. + ULONG *pNext) PURE; // [OUT] Put the index of the next user string here. + + // Interface is sealed. + +}; +// This API isn't big endian friendly since it indexes directly into the memory that +// is stored in little endian format. +// {BADB5F70-58DA-43a9-A1C6-D74819F19B15} +EXTERN_GUID(IID_IMetaDataTables2, 0xbadb5f70, 0x58da, 0x43a9, 0xa1, 0xc6, 0xd7, 0x48, 0x19, 0xf1, 0x9b, 0x15); + +DECLARE_INTERFACE_(IMetaDataTables2, IMetaDataTables) +{ + STDMETHOD (GetMetaDataStorage) ( //@todo: name? + const void **ppvMd, // [OUT] put pointer to MD section here (aka, 'BSJB'). + ULONG *pcbMd) PURE; // [OUT] put size of the stream here. + + STDMETHOD (GetMetaDataStreamInfo) ( // Get info about the MD stream. + ULONG ix, // [IN] Stream ordinal desired. + const char **ppchName, // [OUT] put pointer to stream name here. + const void **ppv, // [OUT] put pointer to MD stream here. + ULONG *pcb) PURE; // [OUT] put size of the stream here. + +}; // IMetaDataTables2 + +#ifdef _DEFINE_META_DATA_META_CONSTANTS +#ifndef _META_DATA_META_CONSTANTS_DEFINED +#define _META_DATA_META_CONSTANTS_DEFINED +const unsigned int iRidMax = 63; +const unsigned int iCodedToken = 64; // base of coded tokens. +const unsigned int iCodedTokenMax = 95; +const unsigned int iSHORT = 96; // fixed types. +const unsigned int iUSHORT = 97; +const unsigned int iLONG = 98; +const unsigned int iULONG = 99; +const unsigned int iBYTE = 100; +const unsigned int iSTRING = 101; // pool types. +const unsigned int iGUID = 102; +const unsigned int iBLOB = 103; + +inline int IsRidType(ULONG ix) { return ix <= iRidMax; } +inline int IsCodedTokenType(ULONG ix) { return (ix >= iCodedToken) && (ix <= iCodedTokenMax); } +inline int IsRidOrToken(ULONG ix) { return ix <= iCodedTokenMax; } +inline int IsHeapType(ULONG ix) { return ix >= iSTRING; } +inline int IsFixedType(ULONG ix) { return (ix < iSTRING) && (ix > iCodedTokenMax); } +#endif +#endif + +//********************************************************************** +// End of IMetaDataTables. +//********************************************************************** +// Gets the dependancies of a native image. If these change, then +// the native image cannot be used. +// +// IMetaDataImport::GetAssemblyRefProps() can be used to obtain information about +// the mdAssemblyRefs. +//***************************************************************************** + +// {814C9E35-3F3F-4975-977A-371F0A878AC7} +EXTERN_GUID(IID_INativeImageDependency, 0x814c9e35, 0x3f3f, 0x4975, 0x97, 0x7a, 0x37, 0x1f, 0xa, 0x87, 0x8a, 0xc7); + +struct CORCOMPILE_ASSEMBLY_SIGNATURE; +typedef GUID CORCOMPILE_NGEN_SIGNATURE; + +DECLARE_INTERFACE_(INativeImageDependency, IUnknown) +{ + // Get the referenced assembly + STDMETHOD (GetILAssemblyRef) ( + mdAssemblyRef * pAssemblyRef // [OUT] + ) PURE; + + // Get the post-policy assembly actually used + STDMETHOD (GetILAssemblyDef) ( + mdAssemblyRef * ppAssemblyDef, // [OUT] + CORCOMPILE_ASSEMBLY_SIGNATURE * pSign // [OUT] + ) PURE; + + // Get the native image corresponding to GetILAssemblyDef() IF + // there is a hard-bound (directly-referenced) native dependancy + // + // We do not need the configStrig because configStrings have to + // be an exact part. Any partial matches are factored out into GetConfigMask() + STDMETHOD (GetNativeAssemblyDef) ( + CORCOMPILE_NGEN_SIGNATURE * pNativeSign // [OUT] INVALID_NGEN_SIGNATURE if there is no hard-bound dependancy + ) PURE; +}; + +//***************************************************************************** +// +// Fusion uses IFusionNativeImageInfo to obtain (and cache) informaton +// about a native image being installed into the native image cache. +// This allows Fusion to bind directly to native images +// without requiring (expensively) binding to the IL assembly first. +// +// IMetaDataAssemblyImport can be queried for this interface +// +//***************************************************************************** +// {0EA273D0-B4DA-4008-A60D-8D6EFFDD6E91} +EXTERN_GUID(IID_INativeImageInstallInfo, 0xea273d0, 0xb4da, 0x4008, 0xa6, 0xd, 0x8d, 0x6e, 0xff, 0xdd, 0x6e, 0x91); + +DECLARE_INTERFACE_(INativeImageInstallInfo, IUnknown) +{ + // Signature of the ngen image + // This matches the argument type of INativeImageDependency::GetNativeAssemblyDef + + STDMETHOD (GetSignature) ( + CORCOMPILE_NGEN_SIGNATURE * pNgenSign // [OUT] + ) PURE; + + // Signature of the source IL assembly. This can be used to + // verify that the IL image matches a candidate ngen image. + // This matches the argument type of IAssemblyRuntimeSignature::CheckSignature + // + + STDMETHOD (GetILSignature) ( + CORCOMPILE_ASSEMBLY_SIGNATURE * pILSign // [OUT] + ) PURE; + + // Returns the equivalent of ISNAssemblySignature::GetSNAssemblySignature, + // except for unsigned assemblies where the GetSNAssemblySignature will fail. + // This can be used for matching the IL assembly in the GAC when the + // native-image is generated/installed. + // + // Sets *pcbSig and returns ERROR_INSUFFICIENT_BUFFER for insufficient buffer. + // Returns CORSEC_E_MISSING_STRONGNAME if the IL assembly is not strongly-named + + STDMETHOD (GetILStrongSignature) ( + BYTE *pbSig, // [IN, OUT] Buffer to write signature + DWORD *pcbSig // [IN, OUT] Size of buffer, bytes written + ) PURE; + + // Information about the contents/dependancies/assumptions of NativeImage + // All of this information has to match for the current NativeImage to + // be valid + // Sets *pdwLength and returns ERROR_INSUFFICIENT_BUFFER for + // insufficient szConfigString + + STDMETHOD (GetConfigString) ( + _Out_writes_to_opt_ (*pdwLength, *pdwLength) LPWSTR szConfigString, // [OUT] + _Inout_ DWORD * pdwLength // [IN|OUT] - Number of WCHARs written including terminating NULL + ) PURE; + + // A partial match is allowed for the current NativeImage to be valid + + STDMETHOD (GetConfigMask) ( + DWORD * pConfigMask // [OUT] + ) PURE; + + // Cache data that the CLR will need to determine if the NativeImage + // can be used (after the GetConfigString checks are satisfied) + // Sets *pdwBufferSize and returns ERROR_INSUFFICIENT_BUFFER for insufficient ppbBuffer + + STDMETHOD (GetEvaluationDataToCache) ( + BYTE * ppbBuffer, // [OUT] + DWORD * pdwBufferSize // [IN|OUT] Total number of bytes written to *ppbBuffer + ) PURE; + + // + // Dependancy assemblies. The native image is only valid + // if the dependancies have not changed. + // + + STDMETHOD (EnumDependencies) ( + HCORENUM * phEnum, // [IN/OUT] - Pointer to the enum + INativeImageDependency *rDeps[], // [OUT] + ULONG cMax, // [IN] Max dependancies to enumerate in this iteration + DWORD * pdwCount // [OUT] - Number of dependancies actually enumerated + ) PURE; +}; + +//***************************************************************************** +// +// Runtime callback made by Fusion into the CLR to determine if the NativeAssembly +// can be used. The pUnkBindSink argument of CAssemblyName::BindToObject() can +// be queried for this interface +// +//***************************************************************************** +// {065AA013-9BDC-447c-922F-FEE929908447} +EXTERN_GUID(IID_INativeImageEvaluate, 0x65aa013, 0x9bdc, 0x447c, 0x92, 0x2f, 0xfe, 0xe9, 0x29, 0x90, 0x84, 0x47); + +interface IAssembly; + +DECLARE_INTERFACE_(INativeImageEvaluate, IUnknown) +{ + // This will be called before the assemblies are actually loaded. + // + // Returns S_FALSE if the native-image cannot be used. + + STDMETHOD (Evaluate) ( + IAssembly *pILAssembly, // [IN] IL assembly in question + IAssembly *pNativeAssembly, // [IN] NGen image we are trying to use for pILAssembly + BYTE * pbCachedData, // [IN] Data cached when the native-image was generated + DWORD dwDataSize // [IN] Size of the pbCachedData buffer + ) PURE; +}; + +//********************************************************************** + +//********************************************************************** +// +// Predefined CustomAttribute and structures for these custom value +// +//********************************************************************** + +// +// Native Link method custom value definitions. This is for N-direct support. +// + +#define COR_NATIVE_LINK_CUSTOM_VALUE L"COMPLUS_NativeLink" +#define COR_NATIVE_LINK_CUSTOM_VALUE_ANSI "COMPLUS_NativeLink" + +// count of chars for COR_NATIVE_LINK_CUSTOM_VALUE(_ANSI) +#define COR_NATIVE_LINK_CUSTOM_VALUE_CC 18 + +#include +typedef struct +{ + BYTE m_linkType; // see CorNativeLinkType below + BYTE m_flags; // see CorNativeLinkFlags below + mdMemberRef m_entryPoint; // member ref token giving entry point, format is lib:entrypoint +} COR_NATIVE_LINK; +#include + +typedef enum +{ + nltNone = 1, // none of the keywords are specified + nltAnsi = 2, // ansi keyword specified + nltUnicode = 3, // unicode keyword specified + nltAuto = 4, // auto keyword specified + nltOle = 5, // ole keyword specified + nltMaxValue = 7, // used so we can assert how many bits are required for this enum +} CorNativeLinkType; + +typedef enum +{ + nlfNone = 0x00, // no flags + nlfLastError = 0x01, // setLastError keyword specified + nlfNoMangle = 0x02, // nomangle keyword specified + nlfMaxValue = 0x03, // used so we can assert how many bits are required for this enum +} CorNativeLinkFlags; + + +#define COR_DUAL_CUSTOM_VALUE L"IsDual" +#define COR_DUAL_CUSTOM_VALUE_ANSI "IsDual" + +#define COR_DISPATCH_CUSTOM_VALUE L"DISPID" +#define COR_DISPATCH_CUSTOM_VALUE_ANSI "DISPID" + +// +// Security custom value definitions (these are all deprecated). +// + +#define COR_PERM_REQUEST_REQD_CUSTOM_VALUE L"SecPermReq_Reqd" +#define COR_PERM_REQUEST_REQD_CUSTOM_VALUE_ANSI "SecPermReq_Reqd" + +#define COR_PERM_REQUEST_OPT_CUSTOM_VALUE L"SecPermReq_Opt" +#define COR_PERM_REQUEST_OPT_CUSTOM_VALUE_ANSI "SecPermReq_Opt" + +#define COR_PERM_REQUEST_REFUSE_CUSTOM_VALUE L"SecPermReq_Refuse" +#define COR_PERM_REQUEST_REFUSE_CUSTOM_VALUE_ANSI "SecPermReq_Refuse" + +// +// Base class for security custom attributes. +// + +#define COR_BASE_SECURITY_ATTRIBUTE_CLASS L"System.Security.Permissions.SecurityAttribute" +#define COR_BASE_SECURITY_ATTRIBUTE_CLASS_ANSI "System.Security.Permissions.SecurityAttribute" + +// +// Name of custom attribute used to indicate that per-call security checks should +// be disabled for P/Invoke calls. +// + +#define COR_SUPPRESS_UNMANAGED_CODE_CHECK_ATTRIBUTE L"System.Security.SuppressUnmanagedCodeSecurityAttribute" +#define COR_SUPPRESS_UNMANAGED_CODE_CHECK_ATTRIBUTE_ANSI "System.Security.SuppressUnmanagedCodeSecurityAttribute" + +// +// Name of custom attribute tagged on module to indicate it contains +// unverifiable code. +// + +#define COR_UNVER_CODE_ATTRIBUTE L"System.Security.UnverifiableCodeAttribute" +#define COR_UNVER_CODE_ATTRIBUTE_ANSI "System.Security.UnverifiableCodeAttribute" + +// +// Name of custom attribute indicating that a method requires a security object +// slot on the caller's stack. +// + +#define COR_REQUIRES_SECOBJ_ATTRIBUTE L"System.Security.DynamicSecurityMethodAttribute" +#define COR_REQUIRES_SECOBJ_ATTRIBUTE_ANSI "System.Security.DynamicSecurityMethodAttribute" + +#define COR_COMPILERSERVICE_DISCARDABLEATTRIBUTE L"System.Runtime.CompilerServices.DiscardableAttribute" +#define COR_COMPILERSERVICE_DISCARDABLEATTRIBUTE_ASNI "System.Runtime.CompilerServices.DiscardableAttribute" + + +#ifdef __cplusplus +} + +//***************************************************************************** +//***************************************************************************** +// +// C O M + s i g n a t u r e s u p p o r t +// +//***************************************************************************** +//***************************************************************************** + +#ifndef FORCEINLINE + #if _MSC_VER < 1200 + #define FORCEINLINE inline + #else + #define FORCEINLINE __forceinline + #endif +#endif + +// return true if it is a primitive type, i.e. only need to store CorElementType +FORCEINLINE int CorIsPrimitiveType(CorElementType elementtype) +{ + return (elementtype < ELEMENT_TYPE_PTR || elementtype == ELEMENT_TYPE_I || elementtype == ELEMENT_TYPE_U); +} + + +// Return true if element type is a modifier, i.e. ELEMENT_TYPE_MODIFIER bits are +// turned on. For now, it is checking for ELEMENT_TYPE_PTR and ELEMENT_TYPE_BYREF +// as well. This will be removed when we turn on ELEMENT_TYPE_MODIFIER bits for +// these two enum members. +// +FORCEINLINE int CorIsModifierElementType(CorElementType elementtype) +{ + if (elementtype == ELEMENT_TYPE_PTR || elementtype == ELEMENT_TYPE_BYREF) + return 1; + return (elementtype & ELEMENT_TYPE_MODIFIER); +} + +// Given a compress byte (*pData), return the size of the uncompressed data. +inline ULONG CorSigUncompressedDataSize( + PCCOR_SIGNATURE pData) +{ + if ((*pData & 0x80) == 0) + return 1; + else if ((*pData & 0xC0) == 0x80) + return 2; + else + return 4; +} + +///////////////////////////////////////////////////////////////////////////////////////////// +// +// Given a compressed integer(*pData), expand the compressed int to *pDataOut. +// Return value is the number of bytes that the integer occupies in the compressed format +// It is caller's responsibility to ensure pDataOut has at least 4 bytes to be written to. +// +// This function returns -1 if pass in with an incorrectly compressed data, such as +// (*pBytes & 0xE0) == 0XE0. +///////////////////////////////////////////////////////////////////////////////////////////// +inline ULONG CorSigUncompressBigData( + PCCOR_SIGNATURE &pData) // [IN,OUT] compressed data +{ + ULONG res; + + // 1 byte data is handled in CorSigUncompressData + // _ASSERTE(*pData & 0x80); + + // Medium. + if ((*pData & 0xC0) == 0x80) // 10?? ???? + { + res = (ULONG)((*pData++ & 0x3f) << 8); + res |= *pData++; + } + else // 110? ???? + { + res = (*pData++ & 0x1f) << 24; + res |= *pData++ << 16; + res |= *pData++ << 8; + res |= *pData++; + } + return res; +} +FORCEINLINE ULONG CorSigUncompressData( + PCCOR_SIGNATURE &pData) // [IN,OUT] compressed data +{ + // Handle smallest data inline. + if ((*pData & 0x80) == 0x00) // 0??? ???? + return *pData++; + return CorSigUncompressBigData(pData); +} + +inline HRESULT CorSigUncompressData( // return S_OK or E_BADIMAGEFORMAT if the signature is bad + PCCOR_SIGNATURE pData, // [IN] compressed data + DWORD len, // [IN] length of the signature + ULONG *pDataOut, // [OUT] the expanded *pData + ULONG *pDataLen) // [OUT] length of the expanded *pData +{ + HRESULT hr = S_OK; + BYTE const *pBytes = reinterpret_cast(pData); + + // Smallest. + if ((*pBytes & 0x80) == 0x00) // 0??? ???? + { + if (len < 1) + hr = META_E_BAD_SIGNATURE; + else + { + *pDataOut = *pBytes; + *pDataLen = 1; + } + } + // Medium. + else if ((*pBytes & 0xC0) == 0x80) // 10?? ???? + { + if (len < 2) + hr = META_E_BAD_SIGNATURE; + else + { + *pDataOut = (ULONG)(((*pBytes & 0x3f) << 8 | *(pBytes+1))); + *pDataLen = 2; + } + } + else if ((*pBytes & 0xE0) == 0xC0) // 110? ???? + { + if (len < 4) + hr = META_E_BAD_SIGNATURE; + else + { + *pDataOut = (ULONG)(((*pBytes & 0x1f) << 24 | *(pBytes+1) << 16 | *(pBytes+2) << 8 | *(pBytes+3))); + *pDataLen = 4; + } + } + else // We don't recognize this encoding + hr = META_E_BAD_SIGNATURE; + + return hr; + +} + +inline ULONG CorSigUncompressData( // return number of bytes of that compressed data occupied in pData + PCCOR_SIGNATURE pData, // [IN] compressed data + ULONG *pDataOut) // [OUT] the expanded *pData +{ + + ULONG dwSizeOfData = 0; + + // We don't know how big the signature is, so we'll just say that it's big enough + if (FAILED(CorSigUncompressData(pData, 0xff, pDataOut, &dwSizeOfData))) + return (ULONG)-1; + + + return dwSizeOfData; +} + + + + +const static mdToken g_tkCorEncodeToken[4] ={mdtTypeDef, mdtTypeRef, mdtTypeSpec, mdtBaseType}; + +// uncompress a token +inline mdToken CorSigUncompressToken( // return the token. + PCCOR_SIGNATURE &pData) // [IN,OUT] compressed data +{ + mdToken tk; + mdToken tkType; + + tk = CorSigUncompressData(pData); + tkType = g_tkCorEncodeToken[tk & 0x3]; + tk = TokenFromRid(tk >> 2, tkType); + return tk; +} + + +inline ULONG CorSigUncompressToken( // return number of bytes of that compressed data occupied in pData + PCCOR_SIGNATURE pData, // [IN] compressed data + mdToken *pToken) // [OUT] the expanded *pData +{ + ULONG cb; + mdToken tk; + mdToken tkType; + + cb = CorSigUncompressData(pData, (ULONG *)&tk); + tkType = g_tkCorEncodeToken[tk & 0x3]; + tk = TokenFromRid(tk >> 2, tkType); + *pToken = tk; + return cb; +} + +inline HRESULT CorSigUncompressToken( + PCCOR_SIGNATURE pData, // [IN] compressed data + DWORD dwLen, // [IN] Remaining length of sigature + mdToken *pToken, // [OUT] the expanded *pData + DWORD *dwTokenLength) // [OUT] The length of the token in the sigature +{ + mdToken tk; + mdToken tkType; + + HRESULT hr = CorSigUncompressData(pData, dwLen, (ULONG *)&tk, dwTokenLength); + + if (SUCCEEDED(hr)) + { + tkType = g_tkCorEncodeToken[tk & 0x3]; + tk = TokenFromRid(tk >> 2, tkType); + *pToken = tk; + } + return hr; +} + + + +FORCEINLINE ULONG CorSigUncompressCallingConv( + PCCOR_SIGNATURE &pData) // [IN,OUT] compressed data +{ + return *pData++; +} + +FORCEINLINE HRESULT CorSigUncompressCallingConv( + PCCOR_SIGNATURE pData, // [IN] Signature + DWORD dwLen, // [IN] Length of signature + ULONG *data) // [OUT] compressed data +{ + if (dwLen > 0) + { + *data = *pData; + return S_OK; + } + else + return META_E_BAD_SIGNATURE; +} + + +enum { + SIGN_MASK_ONEBYTE = 0xffffffc0, // Mask the same size as the missing bits. + SIGN_MASK_TWOBYTE = 0xffffe000, // Mask the same size as the missing bits. + SIGN_MASK_FOURBYTE = 0xf0000000, // Mask the same size as the missing bits. +}; + +// uncompress a signed integer +inline ULONG CorSigUncompressSignedInt( // return number of bytes of that compressed data occupied in pData + PCCOR_SIGNATURE pData, // [IN] compressed data + int *pInt) // [OUT] the expanded *pInt +{ + ULONG cb; + ULONG ulSigned; + ULONG iData; + + cb = CorSigUncompressData(pData, &iData); + if (cb == (ULONG) -1) return cb; + ulSigned = iData & 0x1; + iData = iData >> 1; + if (ulSigned) + { + if (cb == 1) + { + iData |= SIGN_MASK_ONEBYTE; + } + else if (cb == 2) + { + iData |= SIGN_MASK_TWOBYTE; + } + else + { + iData |= SIGN_MASK_FOURBYTE; + } + } + *pInt = (int)iData; + return cb; +} + + +// uncompress encoded element type +FORCEINLINE CorElementType CorSigUncompressElementType(//Element type + PCCOR_SIGNATURE &pData) // [IN,OUT] compressed data +{ + return (CorElementType)*pData++; +} + +inline ULONG CorSigUncompressElementType(// return number of bytes of that compressed data occupied in pData + PCCOR_SIGNATURE pData, // [IN] compressed data + CorElementType *pElementType) // [OUT] the expanded *pData +{ + *pElementType = (CorElementType)(*pData & 0x7f); + return 1; +} + + +///////////////////////////////////////////////////////////////////////////////////////////// +// +// Given an uncompressed unsigned integer (iLen), Store it to pDataOut in a compressed format. +// Return value is the number of bytes that the integer occupies in the compressed format. +// It is caller's responsibilityt to ensure *pDataOut has at least 4 bytes to write to. +// +// Note that this function returns -1 if iLen is too big to be compressed. We currently can +// only represent to 0x1FFFFFFF. +// +///////////////////////////////////////////////////////////////////////////////////////////// +inline ULONG CorSigCompressData( // return number of bytes that compressed form of iLen will take + ULONG iLen, // [IN] given uncompressed data + void *pDataOut) // [OUT] buffer where iLen will be compressed and stored. +{ + BYTE *pBytes = reinterpret_cast(pDataOut); + + if (iLen <= 0x7F) + { + *pBytes = BYTE(iLen); + return 1; + } + + if (iLen <= 0x3FFF) + { + *pBytes = BYTE((iLen >> 8) | 0x80); + *(pBytes+1) = BYTE(iLen & 0xff); + return 2; + } + + if (iLen <= 0x1FFFFFFF) + { + *pBytes = BYTE((iLen >> 24) | 0xC0); + *(pBytes+1) = BYTE((iLen >> 16) & 0xff); + *(pBytes+2) = BYTE((iLen >> 8) & 0xff); + *(pBytes+3) = BYTE(iLen & 0xff); + return 4; + } + return (ULONG) -1; + +} + +// compress a token +// The least significant bit of the first compress byte will indicate the token type. +// +inline ULONG CorSigCompressToken( // return number of bytes that compressed form of iLen will take + mdToken tk, // [IN] given token + void *pDataOut) // [OUT] buffer where iLen will be compressed and stored. +{ + RID rid = RidFromToken(tk); + ULONG32 ulTyp = TypeFromToken(tk); + + if (rid > 0x3FFFFFF) + // token is too big to be compressed + return (ULONG) -1; + + rid = (rid << 2); + + // TypeDef is encoded with low bits 00 + // TypeRef is encoded with low bits 01 + // TypeSpec is encoded with low bits 10 + // BaseType is encoded with low bit 11 + // + if (ulTyp == g_tkCorEncodeToken[1]) + { + // make the last two bits 01 + rid |= 0x1; + } + else if (ulTyp == g_tkCorEncodeToken[2]) + { + // make last two bits 0 + rid |= 0x2; + } + else if (ulTyp == g_tkCorEncodeToken[3]) + { + rid |= 0x3; + } + return CorSigCompressData((ULONG)rid, pDataOut); +} + +// compress a signed integer +// The least significant bit of the first compress byte will be the signed bit. +// +inline ULONG CorSigCompressSignedInt( // return number of bytes that compressed form of iData will take + int iData, // [IN] given integer + void *pDataOut) // [OUT] buffer where iLen will be compressed and stored. +{ + ULONG isSigned = 0; + + if (iData < 0) + isSigned = 0x1; + + if ((iData & SIGN_MASK_ONEBYTE) == 0 || (iData & SIGN_MASK_ONEBYTE) == SIGN_MASK_ONEBYTE) + { + iData &= ~SIGN_MASK_ONEBYTE; + } + else if ((iData & SIGN_MASK_TWOBYTE) == 0 || (iData & SIGN_MASK_TWOBYTE) == SIGN_MASK_TWOBYTE) + { + iData &= ~SIGN_MASK_TWOBYTE; + } + + else if ((iData & SIGN_MASK_FOURBYTE) == 0 || (iData & SIGN_MASK_FOURBYTE) == SIGN_MASK_FOURBYTE) + { + iData &= ~SIGN_MASK_FOURBYTE; + } + else + { + // out of compressable range + return (ULONG) -1; + } + iData = (int) (iData << 1 | isSigned); + return CorSigCompressData((ULONG)iData, pDataOut); +} + + + +// uncompress encoded element type +inline ULONG CorSigCompressElementType(// return number of bytes of that compressed data occupied in pData + CorElementType et, // [OUT] the expanded *pData + void *pData) // [IN] compressed data +{ + BYTE *pBytes = (BYTE *)(pData); + + *pBytes = BYTE(et); + return 1; + +} + +// Compress a pointer (used for internal element types only, never for persisted +// signatures). +inline ULONG CorSigCompressPointer( // return number of bytes of that compressed data occupied + void *pvPointer, // [IN] given uncompressed data + void *pData) // [OUT] buffer where iLen will be compressed and stored. +{ + *((void* UNALIGNED *)pData) = pvPointer; + return sizeof(void*); +} + +// Uncompress a pointer (see above for comments). +inline ULONG CorSigUncompressPointer( // return number of bytes of that compressed data occupied + PCCOR_SIGNATURE pData, // [IN] compressed data + void **ppvPointer) // [OUT] the expanded *pData +{ + *ppvPointer = *(void* UNALIGNED *)pData; + return sizeof(void*); +} + +#endif // __cplusplus + +#endif // _COR_H_ +// EOF ======================================================================= diff --git a/third/Blackbone/src/3rd_party/corhdr.h b/third/Blackbone/src/3rd_party/corhdr.h new file mode 100644 index 0000000000000000000000000000000000000000..d366713fc923c146a80fc0b875563f7268d219ca --- /dev/null +++ b/third/Blackbone/src/3rd_party/corhdr.h @@ -0,0 +1,1795 @@ +// ==++== +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// ==--== +/***************************************************************************** + ** ** + ** CorHdr.h - contains definitions for the Runtime structures, ** + ** needed to work with metadata. ** + ** ** + *****************************************************************************/ + + +#ifndef __CORHDR_H__ +#define __CORHDR_H__ + +#define FRAMEWORK_REGISTRY_KEY "Software\\Microsoft\\.NETFramework" +#define FRAMEWORK_REGISTRY_KEY_W L"Software\\Microsoft\\.NETFramework" + +#ifdef _MSC_VER +#pragma warning(disable:4200) // nonstandard extension used : zero-sized array in struct/union. +#endif +typedef LPVOID mdScope; // Obsolete; not used in the runtime. +typedef ULONG32 mdToken; // Generic token + + +// Token definitions + + +typedef mdToken mdModule; // Module token (roughly, a scope) +typedef mdToken mdTypeRef; // TypeRef reference (this or other scope) +typedef mdToken mdTypeDef; // TypeDef in this scope +typedef mdToken mdFieldDef; // Field in this scope +typedef mdToken mdMethodDef; // Method in this scope +typedef mdToken mdParamDef; // param token +typedef mdToken mdInterfaceImpl; // interface implementation token + +typedef mdToken mdMemberRef; // MemberRef (this or other scope) +typedef mdToken mdCustomAttribute; // attribute token +typedef mdToken mdPermission; // DeclSecurity + +typedef mdToken mdSignature; // Signature object +typedef mdToken mdEvent; // event token +typedef mdToken mdProperty; // property token + +typedef mdToken mdModuleRef; // Module reference (for the imported modules) + +// Assembly tokens. +typedef mdToken mdAssembly; // Assembly token. +typedef mdToken mdAssemblyRef; // AssemblyRef token. +typedef mdToken mdFile; // File token. +typedef mdToken mdExportedType; // ExportedType token. +typedef mdToken mdManifestResource; // ManifestResource token. + +typedef mdToken mdTypeSpec; // TypeSpec object + +typedef mdToken mdGenericParam; // formal parameter to generic type or method +typedef mdToken mdMethodSpec; // instantiation of a generic method +typedef mdToken mdGenericParamConstraint; // constraint on a formal generic parameter + +// Application string. +typedef mdToken mdString; // User literal string token. + +typedef mdToken mdCPToken; // constantpool token + +#ifndef MACROS_NOT_SUPPORTED +typedef ULONG RID; +#else +typedef unsigned RID; +#endif // MACROS_NOT_SUPPORTED + +typedef enum ReplacesGeneralNumericDefines +{ +// Directory entry macro for CLR data. +#ifndef IMAGE_DIRECTORY_ENTRY_COMHEADER + IMAGE_DIRECTORY_ENTRY_COMHEADER =14, +#endif // IMAGE_DIRECTORY_ENTRY_COMHEADER + + _NEW_FLAGS_IMPLEMENTED =1, + __NEW_FLAGS_IMPLEMENTED =1, +} ReplacesGeneralNumericDefines; + + +#ifndef __IMAGE_COR20_HEADER_DEFINED__ +#define __IMAGE_COR20_HEADER_DEFINED__ + +typedef enum ReplacesCorHdrNumericDefines +{ +// COM+ Header entry point flags. + COMIMAGE_FLAGS_ILONLY =0x00000001, + COMIMAGE_FLAGS_32BITREQUIRED =0x00000002, + COMIMAGE_FLAGS_IL_LIBRARY =0x00000004, + COMIMAGE_FLAGS_STRONGNAMESIGNED =0x00000008, +// DDBLD - Added Next Line - Still verifying general usage + COMIMAGE_FLAGS_NATIVE_ENTRYPOINT =0x00000010, +// DDBLD - End of Add + COMIMAGE_FLAGS_TRACKDEBUGDATA =0x00010000, + +// Version flags for image. + COR_VERSION_MAJOR_V2 =2, + COR_VERSION_MAJOR =COR_VERSION_MAJOR_V2, + COR_VERSION_MINOR =5, + COR_DELETED_NAME_LENGTH =8, + COR_VTABLEGAP_NAME_LENGTH =8, + +// Maximum size of a NativeType descriptor. + NATIVE_TYPE_MAX_CB =1, + COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE=0xFF, + +// #defines for the MIH FLAGS + IMAGE_COR_MIH_METHODRVA =0x01, + IMAGE_COR_MIH_EHRVA =0x02, + IMAGE_COR_MIH_BASICBLOCK =0x08, + +// V-table constants + COR_VTABLE_32BIT =0x01, // V-table slots are 32-bits in size. + COR_VTABLE_64BIT =0x02, // V-table slots are 64-bits in size. + COR_VTABLE_FROM_UNMANAGED =0x04, // If set, transition from unmanaged. + COR_VTABLE_CALL_MOST_DERIVED =0x10, // Call most derived method described by + +// EATJ constants + IMAGE_COR_EATJ_THUNK_SIZE =32, // Size of a jump thunk reserved range. + +// Max name lengths + //@todo: Change to unlimited name lengths. + MAX_CLASS_NAME =1024, + MAX_PACKAGE_NAME =1024, +} ReplacesCorHdrNumericDefines; + +// COM+ 2.0 header structure. +typedef struct IMAGE_COR20_HEADER +{ + // Header versioning + DWORD cb; + WORD MajorRuntimeVersion; + WORD MinorRuntimeVersion; + + // Symbol table and startup information + IMAGE_DATA_DIRECTORY MetaData; + DWORD Flags; +// DDBLD - Added next section to replace following lin +// DDBLD - Still verifying, since not in NT SDK +// DWORD EntryPointToken; + + // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is not set, EntryPointToken represents a managed entrypoint. + // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is set, EntryPointRVA represents an RVA to a native entrypoint. + union { + DWORD EntryPointToken; + DWORD EntryPointRVA; + }; +// DDBLD - End of Added Area + + // Binding information + IMAGE_DATA_DIRECTORY Resources; + IMAGE_DATA_DIRECTORY StrongNameSignature; + + // Regular fixup and binding information + IMAGE_DATA_DIRECTORY CodeManagerTable; + IMAGE_DATA_DIRECTORY VTableFixups; + IMAGE_DATA_DIRECTORY ExportAddressTableJumps; + + // Precompiled image info (internal use only - set to zero) + IMAGE_DATA_DIRECTORY ManagedNativeHeader; + +} IMAGE_COR20_HEADER, *PIMAGE_COR20_HEADER; + +#else // !__IMAGE_COR20_HEADER_DEFINED__ + +// @TODO: This hack is required because we pull in the COM+ 2.0 PE header +// definition from winnt.h, and the constant below hasn't propogated yet. +#define COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN 0x08 + +#endif // __IMAGE_COR20_HEADER_DEFINED__ + +// The most recent version. + +#define COR_CTOR_METHOD_NAME ".ctor" +#define COR_CTOR_METHOD_NAME_W L".ctor" +#define COR_CCTOR_METHOD_NAME ".cctor" +#define COR_CCTOR_METHOD_NAME_W L".cctor" + +#define COR_ENUM_FIELD_NAME "value__" +#define COR_ENUM_FIELD_NAME_W L"value__" + +// The predefined name for deleting a typeDef,MethodDef, FieldDef, Property and Event +#define COR_DELETED_NAME_A "_Deleted" +#define COR_DELETED_NAME_W L"_Deleted" +#define COR_VTABLEGAP_NAME_A "_VtblGap" +#define COR_VTABLEGAP_NAME_W L"_VtblGap" + +// We intentionally use strncmp so that we will ignore any suffix +#define IsDeletedName(strName) (strncmp(strName, COR_DELETED_NAME_A, COR_DELETED_NAME_LENGTH) == 0) +#define IsVtblGapName(strName) (strncmp(strName, COR_VTABLEGAP_NAME_A, COR_VTABLEGAP_NAME_LENGTH) == 0) + +// TypeDef/ExportedType attr bits, used by DefineTypeDef. +typedef enum CorTypeAttr +{ + // Use this mask to retrieve the type visibility information. + tdVisibilityMask = 0x00000007, + tdNotPublic = 0x00000000, // Class is not public scope. + tdPublic = 0x00000001, // Class is public scope. + tdNestedPublic = 0x00000002, // Class is nested with public visibility. + tdNestedPrivate = 0x00000003, // Class is nested with private visibility. + tdNestedFamily = 0x00000004, // Class is nested with family visibility. + tdNestedAssembly = 0x00000005, // Class is nested with assembly visibility. + tdNestedFamANDAssem = 0x00000006, // Class is nested with family and assembly visibility. + tdNestedFamORAssem = 0x00000007, // Class is nested with family or assembly visibility. + + // Use this mask to retrieve class layout information + tdLayoutMask = 0x00000018, + tdAutoLayout = 0x00000000, // Class fields are auto-laid out + tdSequentialLayout = 0x00000008, // Class fields are laid out sequentially + tdExplicitLayout = 0x00000010, // Layout is supplied explicitly + // end layout mask + + // Use this mask to retrieve class semantics information. + tdClassSemanticsMask = 0x00000060, + tdClass = 0x00000000, // Type is a class. + tdInterface = 0x00000020, // Type is an interface. + // end semantics mask + + // Special semantics in addition to class semantics. + tdAbstract = 0x00000080, // Class is abstract + tdSealed = 0x00000100, // Class is concrete and may not be extended + tdSpecialName = 0x00000400, // Class name is special. Name describes how. + + // Implementation attributes. + tdImport = 0x00001000, // Class / interface is imported + tdSerializable = 0x00002000, // The class is Serializable. + + // Use tdStringFormatMask to retrieve string information for native interop + tdStringFormatMask = 0x00030000, + tdAnsiClass = 0x00000000, // LPTSTR is interpreted as ANSI in this class + tdUnicodeClass = 0x00010000, // LPTSTR is interpreted as UNICODE + tdAutoClass = 0x00020000, // LPTSTR is interpreted automatically + tdCustomFormatClass = 0x00030000, // A non-standard encoding specified by CustomFormatMask + tdCustomFormatMask = 0x00C00000, // Use this mask to retrieve non-standard encoding information for native interop. The meaning of the values of these 2 bits is unspecified. + + // end string format mask + + tdBeforeFieldInit = 0x00100000, // Initialize the class any time before first static field access. + tdForwarder = 0x00200000, // This ExportedType is a type forwarder. + + // Flags reserved for runtime use. + tdReservedMask = 0x00040800, + tdRTSpecialName = 0x00000800, // Runtime should check name encoding. + tdHasSecurity = 0x00040000, // Class has security associate with it. +} CorTypeAttr; + + +// Macros for accessing the members of the CorTypeAttr. +#define IsTdNotPublic(x) (((x) & tdVisibilityMask) == tdNotPublic) +#define IsTdPublic(x) (((x) & tdVisibilityMask) == tdPublic) +#define IsTdNestedPublic(x) (((x) & tdVisibilityMask) == tdNestedPublic) +#define IsTdNestedPrivate(x) (((x) & tdVisibilityMask) == tdNestedPrivate) +#define IsTdNestedFamily(x) (((x) & tdVisibilityMask) == tdNestedFamily) +#define IsTdNestedAssembly(x) (((x) & tdVisibilityMask) == tdNestedAssembly) +#define IsTdNestedFamANDAssem(x) (((x) & tdVisibilityMask) == tdNestedFamANDAssem) +#define IsTdNestedFamORAssem(x) (((x) & tdVisibilityMask) == tdNestedFamORAssem) +#define IsTdNested(x) (((x) & tdVisibilityMask) >= tdNestedPublic) + +#define IsTdAutoLayout(x) (((x) & tdLayoutMask) == tdAutoLayout) +#define IsTdSequentialLayout(x) (((x) & tdLayoutMask) == tdSequentialLayout) +#define IsTdExplicitLayout(x) (((x) & tdLayoutMask) == tdExplicitLayout) + +#define IsTdClass(x) (((x) & tdClassSemanticsMask) == tdClass) +#define IsTdInterface(x) (((x) & tdClassSemanticsMask) == tdInterface) + +#define IsTdAbstract(x) ((x) & tdAbstract) +#define IsTdSealed(x) ((x) & tdSealed) +#define IsTdSpecialName(x) ((x) & tdSpecialName) + +#define IsTdImport(x) ((x) & tdImport) +#define IsTdSerializable(x) ((x) & tdSerializable) + +#define IsTdAnsiClass(x) (((x) & tdStringFormatMask) == tdAnsiClass) +#define IsTdUnicodeClass(x) (((x) & tdStringFormatMask) == tdUnicodeClass) +#define IsTdAutoClass(x) (((x) & tdStringFormatMask) == tdAutoClass) +#define IsTdCustomFormatClass(x) (((x) & tdStringFormatMask) == tdCustomFormatClass) +#define IsTdBeforeFieldInit(x) ((x) & tdBeforeFieldInit) +#define IsTdForwarder(x) ((x) & tdForwarder) + +#define IsTdRTSpecialName(x) ((x) & tdRTSpecialName) +#define IsTdHasSecurity(x) ((x) & tdHasSecurity) + +// MethodDef attr bits, Used by DefineMethod. +typedef enum CorMethodAttr +{ + // member access mask - Use this mask to retrieve accessibility information. + mdMemberAccessMask = 0x0007, + mdPrivateScope = 0x0000, // Member not referenceable. + mdPrivate = 0x0001, // Accessible only by the parent type. + mdFamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly. + mdAssem = 0x0003, // Accessibly by anyone in the Assembly. + mdFamily = 0x0004, // Accessible only by type and sub-types. + mdFamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly. + mdPublic = 0x0006, // Accessibly by anyone who has visibility to this scope. + // end member access mask + + // method contract attributes. + mdStatic = 0x0010, // Defined on type, else per instance. + mdFinal = 0x0020, // Method may not be overridden. + mdVirtual = 0x0040, // Method virtual. + mdHideBySig = 0x0080, // Method hides by name+sig, else just by name. + + // vtable layout mask - Use this mask to retrieve vtable attributes. + mdVtableLayoutMask = 0x0100, + mdReuseSlot = 0x0000, // The default. + mdNewSlot = 0x0100, // Method always gets a new slot in the vtable. + // end vtable layout mask + + // method implementation attributes. + mdCheckAccessOnOverride = 0x0200, // Overridability is the same as the visibility. + mdAbstract = 0x0400, // Method does not provide an implementation. + mdSpecialName = 0x0800, // Method is special. Name describes how. + + // interop attributes + mdPinvokeImpl = 0x2000, // Implementation is forwarded through pinvoke. + mdUnmanagedExport = 0x0008, // Managed method exported via thunk to unmanaged code. + + // Reserved flags for runtime use only. + mdReservedMask = 0xd000, + mdRTSpecialName = 0x1000, // Runtime should check name encoding. + mdHasSecurity = 0x4000, // Method has security associate with it. + mdRequireSecObject = 0x8000, // Method calls another method containing security code. + +} CorMethodAttr; + +// Macros for accessing the members of CorMethodAttr. +#define IsMdPrivateScope(x) (((x) & mdMemberAccessMask) == mdPrivateScope) +#define IsMdPrivate(x) (((x) & mdMemberAccessMask) == mdPrivate) +#define IsMdFamANDAssem(x) (((x) & mdMemberAccessMask) == mdFamANDAssem) +#define IsMdAssem(x) (((x) & mdMemberAccessMask) == mdAssem) +#define IsMdFamily(x) (((x) & mdMemberAccessMask) == mdFamily) +#define IsMdFamORAssem(x) (((x) & mdMemberAccessMask) == mdFamORAssem) +#define IsMdPublic(x) (((x) & mdMemberAccessMask) == mdPublic) + +#define IsMdStatic(x) ((x) & mdStatic) +#define IsMdFinal(x) ((x) & mdFinal) +#define IsMdVirtual(x) ((x) & mdVirtual) +#define IsMdHideBySig(x) ((x) & mdHideBySig) + +#define IsMdReuseSlot(x) (((x) & mdVtableLayoutMask) == mdReuseSlot) +#define IsMdNewSlot(x) (((x) & mdVtableLayoutMask) == mdNewSlot) + +#define IsMdCheckAccessOnOverride(x) ((x) & mdCheckAccessOnOverride) +#define IsMdAbstract(x) ((x) & mdAbstract) +#define IsMdSpecialName(x) ((x) & mdSpecialName) + +#define IsMdPinvokeImpl(x) ((x) & mdPinvokeImpl) +#define IsMdUnmanagedExport(x) ((x) & mdUnmanagedExport) + +#define IsMdRTSpecialName(x) ((x) & mdRTSpecialName) +#define IsMdInstanceInitializer(x, str) (((x) & mdRTSpecialName) && !strcmp((str), COR_CTOR_METHOD_NAME)) +#define IsMdInstanceInitializerW(x, str) (((x) & mdRTSpecialName) && !wcscmp((str), COR_CTOR_METHOD_NAME_W)) +#define IsMdClassConstructor(x, str) (((x) & mdRTSpecialName) && !strcmp((str), COR_CCTOR_METHOD_NAME)) +#define IsMdClassConstructorW(x, str) (((x) & mdRTSpecialName) && !wcscmp((str), COR_CCTOR_METHOD_NAME_W)) +#define IsMdHasSecurity(x) ((x) & mdHasSecurity) +#define IsMdRequireSecObject(x) ((x) & mdRequireSecObject) + +// FieldDef attr bits, used by DefineField. +typedef enum CorFieldAttr +{ + // member access mask - Use this mask to retrieve accessibility information. + fdFieldAccessMask = 0x0007, + fdPrivateScope = 0x0000, // Member not referenceable. + fdPrivate = 0x0001, // Accessible only by the parent type. + fdFamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly. + fdAssembly = 0x0003, // Accessibly by anyone in the Assembly. + fdFamily = 0x0004, // Accessible only by type and sub-types. + fdFamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly. + fdPublic = 0x0006, // Accessibly by anyone who has visibility to this scope. + // end member access mask + + // field contract attributes. + fdStatic = 0x0010, // Defined on type, else per instance. + fdInitOnly = 0x0020, // Field may only be initialized, not written to after init. + fdLiteral = 0x0040, // Value is compile time constant. + fdNotSerialized = 0x0080, // Field does not have to be serialized when type is remoted. + + fdSpecialName = 0x0200, // field is special. Name describes how. + + // interop attributes + fdPinvokeImpl = 0x2000, // Implementation is forwarded through pinvoke. + + // Reserved flags for runtime use only. + fdReservedMask = 0x9500, + fdRTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding. + fdHasFieldMarshal = 0x1000, // Field has marshalling information. + fdHasDefault = 0x8000, // Field has default. + fdHasFieldRVA = 0x0100, // Field has RVA. +} CorFieldAttr; + +// Macros for accessing the members of CorFieldAttr. +#define IsFdPrivateScope(x) (((x) & fdFieldAccessMask) == fdPrivateScope) +#define IsFdPrivate(x) (((x) & fdFieldAccessMask) == fdPrivate) +#define IsFdFamANDAssem(x) (((x) & fdFieldAccessMask) == fdFamANDAssem) +#define IsFdAssembly(x) (((x) & fdFieldAccessMask) == fdAssembly) +#define IsFdFamily(x) (((x) & fdFieldAccessMask) == fdFamily) +#define IsFdFamORAssem(x) (((x) & fdFieldAccessMask) == fdFamORAssem) +#define IsFdPublic(x) (((x) & fdFieldAccessMask) == fdPublic) + +#define IsFdStatic(x) ((x) & fdStatic) +#define IsFdInitOnly(x) ((x) & fdInitOnly) +#define IsFdLiteral(x) ((x) & fdLiteral) +#define IsFdNotSerialized(x) ((x) & fdNotSerialized) + +#define IsFdPinvokeImpl(x) ((x) & fdPinvokeImpl) +#define IsFdSpecialName(x) ((x) & fdSpecialName) +#define IsFdHasFieldRVA(x) ((x) & fdHasFieldRVA) + +#define IsFdRTSpecialName(x) ((x) & fdRTSpecialName) +#define IsFdHasFieldMarshal(x) ((x) & fdHasFieldMarshal) +#define IsFdHasDefault(x) ((x) & fdHasDefault) + +// Param attr bits, used by DefineParam. +typedef enum CorParamAttr +{ + pdIn = 0x0001, // Param is [In] + pdOut = 0x0002, // Param is [out] + pdOptional = 0x0010, // Param is optional + + // Reserved flags for Runtime use only. + pdReservedMask = 0xf000, + pdHasDefault = 0x1000, // Param has default value. + pdHasFieldMarshal = 0x2000, // Param has FieldMarshal. + + pdUnused = 0xcfe0, +} CorParamAttr; + +// Macros for accessing the members of CorParamAttr. +#define IsPdIn(x) ((x) & pdIn) +#define IsPdOut(x) ((x) & pdOut) +#define IsPdOptional(x) ((x) & pdOptional) + +#define IsPdHasDefault(x) ((x) & pdHasDefault) +#define IsPdHasFieldMarshal(x) ((x) & pdHasFieldMarshal) + + +// Property attr bits, used by DefineProperty. +typedef enum CorPropertyAttr +{ + prSpecialName = 0x0200, // property is special. Name describes how. + + // Reserved flags for Runtime use only. + prReservedMask = 0xf400, + prRTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding. + prHasDefault = 0x1000, // Property has default + + prUnused = 0xe9ff, +} CorPropertyAttr; + +// Macros for accessing the members of CorPropertyAttr. +#define IsPrSpecialName(x) ((x) & prSpecialName) + +#define IsPrRTSpecialName(x) ((x) & prRTSpecialName) +#define IsPrHasDefault(x) ((x) & prHasDefault) + +// Event attr bits, used by DefineEvent. +typedef enum CorEventAttr +{ + evSpecialName = 0x0200, // event is special. Name describes how. + + // Reserved flags for Runtime use only. + evReservedMask = 0x0400, + evRTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding. +} CorEventAttr; + +// Macros for accessing the members of CorEventAttr. +#define IsEvSpecialName(x) ((x) & evSpecialName) + +#define IsEvRTSpecialName(x) ((x) & evRTSpecialName) + + +// MethodSemantic attr bits, used by DefineProperty, DefineEvent. +typedef enum CorMethodSemanticsAttr +{ + msSetter = 0x0001, // Setter for property + msGetter = 0x0002, // Getter for property + msOther = 0x0004, // other method for property or event + msAddOn = 0x0008, // AddOn method for event + msRemoveOn = 0x0010, // RemoveOn method for event + msFire = 0x0020, // Fire method for event +} CorMethodSemanticsAttr; + +// Macros for accessing the members of CorMethodSemanticsAttr. +#define IsMsSetter(x) ((x) & msSetter) +#define IsMsGetter(x) ((x) & msGetter) +#define IsMsOther(x) ((x) & msOther) +#define IsMsAddOn(x) ((x) & msAddOn) +#define IsMsRemoveOn(x) ((x) & msRemoveOn) +#define IsMsFire(x) ((x) & msFire) + + +// DeclSecurity attr bits, used by DefinePermissionSet. +typedef enum CorDeclSecurity +{ + dclActionMask = 0x001f, // Mask allows growth of enum. + dclActionNil = 0x0000, // + dclRequest = 0x0001, // + dclDemand = 0x0002, // + dclAssert = 0x0003, // + dclDeny = 0x0004, // + dclPermitOnly = 0x0005, // + dclLinktimeCheck = 0x0006, // + dclInheritanceCheck = 0x0007, // + dclRequestMinimum = 0x0008, // + dclRequestOptional = 0x0009, // + dclRequestRefuse = 0x000a, // + dclPrejitGrant = 0x000b, // Persisted grant set at prejit time + dclPrejitDenied = 0x000c, // Persisted denied set at prejit time + dclNonCasDemand = 0x000d, // + dclNonCasLinkDemand = 0x000e, // + dclNonCasInheritance = 0x000f, // + dclMaximumValue = 0x000f, // Maximum legal value +} CorDeclSecurity; + +// Macros for accessing the members of CorDeclSecurity. +#define IsDclActionNil(x) (((x) & dclActionMask) == dclActionNil) +// Is this a demand that can trigger a stackwalk? +#define IsDclActionAnyStackModifier(x) ((((x) & dclActionMask) == dclAssert) || \ + (((x) & dclActionMask) == dclDeny) || \ + (((x) & dclActionMask) == dclPermitOnly)) + +// MethodImpl attr bits, used by DefineMethodImpl. +typedef enum CorMethodImpl +{ + // code impl mask + miCodeTypeMask = 0x0003, // Flags about code type. + miIL = 0x0000, // Method impl is IL. + miNative = 0x0001, // Method impl is native. + miOPTIL = 0x0002, // Method impl is OPTIL + miRuntime = 0x0003, // Method impl is provided by the runtime. + // end code impl mask + + // managed mask + miManagedMask = 0x0004, // Flags specifying whether the code is managed or unmanaged. + miUnmanaged = 0x0004, // Method impl is unmanaged, otherwise managed. + miManaged = 0x0000, // Method impl is managed. + // end managed mask + + // implementation info and interop + miForwardRef = 0x0010, // Indicates method is defined; used primarily in merge scenarios. + miPreserveSig = 0x0080, // Indicates method sig is not to be mangled to do HRESULT conversion. + + miInternalCall = 0x1000, // Reserved for internal use. + + miSynchronized = 0x0020, // Method is single threaded through the body. + miNoInlining = 0x0008, // Method may not be inlined. + miMaxMethodImplVal = 0xffff, // Range check value +} CorMethodImpl; + +// Macros for accesing the members of CorMethodImpl. +#define IsMiIL(x) (((x) & miCodeTypeMask) == miIL) +#define IsMiNative(x) (((x) & miCodeTypeMask) == miNative) +#define IsMiOPTIL(x) (((x) & miCodeTypeMask) == miOPTIL) +#define IsMiRuntime(x) (((x) & miCodeTypeMask) == miRuntime) + +#define IsMiUnmanaged(x) (((x) & miManagedMask) == miUnmanaged) +#define IsMiManaged(x) (((x) & miManagedMask) == miManaged) + +#define IsMiForwardRef(x) ((x) & miForwardRef) +#define IsMiPreserveSig(x) ((x) & miPreserveSig) + +#define IsMiInternalCall(x) ((x) & miInternalCall) + +#define IsMiSynchronized(x) ((x) & miSynchronized) +#define IsMiNoInlining(x) ((x) & miNoInlining) + + +// PinvokeMap attr bits, used by DefinePinvokeMap. +typedef enum CorPinvokeMap +{ + pmNoMangle = 0x0001, // Pinvoke is to use the member name as specified. + + // Use this mask to retrieve the CharSet information. + pmCharSetMask = 0x0006, + pmCharSetNotSpec = 0x0000, + pmCharSetAnsi = 0x0002, + pmCharSetUnicode = 0x0004, + pmCharSetAuto = 0x0006, + + + pmBestFitUseAssem = 0x0000, + pmBestFitEnabled = 0x0010, + pmBestFitDisabled = 0x0020, + pmBestFitMask = 0x0030, + + pmThrowOnUnmappableCharUseAssem = 0x0000, + pmThrowOnUnmappableCharEnabled = 0x1000, + pmThrowOnUnmappableCharDisabled = 0x2000, + pmThrowOnUnmappableCharMask = 0x3000, + + pmSupportsLastError = 0x0040, // Information about target function. Not relevant for fields. + + // None of the calling convention flags is relevant for fields. + pmCallConvMask = 0x0700, + pmCallConvWinapi = 0x0100, // Pinvoke will use native callconv appropriate to target windows platform. + pmCallConvCdecl = 0x0200, + pmCallConvStdcall = 0x0300, + pmCallConvThiscall = 0x0400, // In M9, pinvoke will raise exception. + pmCallConvFastcall = 0x0500, + + pmMaxValue = 0xFFFF, +} CorPinvokeMap; + +// Macros for accessing the members of CorPinvokeMap +#define IsPmNoMangle(x) ((x) & pmNoMangle) + +#define IsPmCharSetNotSpec(x) (((x) & pmCharSetMask) == pmCharSetNotSpec) +#define IsPmCharSetAnsi(x) (((x) & pmCharSetMask) == pmCharSetAnsi) +#define IsPmCharSetUnicode(x) (((x) & pmCharSetMask) == pmCharSetUnicode) +#define IsPmCharSetAuto(x) (((x) & pmCharSetMask) == pmCharSetAuto) + +#define IsPmSupportsLastError(x) ((x) & pmSupportsLastError) + +#define IsPmCallConvWinapi(x) (((x) & pmCallConvMask) == pmCallConvWinapi) +#define IsPmCallConvCdecl(x) (((x) & pmCallConvMask) == pmCallConvCdecl) +#define IsPmCallConvStdcall(x) (((x) & pmCallConvMask) == pmCallConvStdcall) +#define IsPmCallConvThiscall(x) (((x) & pmCallConvMask) == pmCallConvThiscall) +#define IsPmCallConvFastcall(x) (((x) & pmCallConvMask) == pmCallConvFastcall) + +#define IsPmBestFitEnabled(x) (((x) & pmBestFitMask) == pmBestFitEnabled) +#define IsPmBestFitDisabled(x) (((x) & pmBestFitMask) == pmBestFitDisabled) +#define IsPmBestFitUseAssem(x) (((x) & pmBestFitMask) == pmBestFitUseAssem) + +#define IsPmThrowOnUnmappableCharEnabled(x) (((x) & pmThrowOnUnmappableCharMask) == pmThrowOnUnmappableCharEnabled) +#define IsPmThrowOnUnmappableCharDisabled(x) (((x) & pmThrowOnUnmappableCharMask) == pmThrowOnUnmappableCharDisabled) +#define IsPmThrowOnUnmappableCharUseAssem(x) (((x) & pmThrowOnUnmappableCharMask) == pmThrowOnUnmappableCharUseAssem) + +// Assembly attr bits, used by DefineAssembly. +typedef enum CorAssemblyFlags +{ + afPublicKey = 0x0001, // The assembly ref holds the full (unhashed) public key. + + afPA_None = 0x0000, // Processor Architecture unspecified + afPA_MSIL = 0x0010, // Processor Architecture: neutral (PE32) + afPA_x86 = 0x0020, // Processor Architecture: x86 (PE32) + afPA_IA64 = 0x0030, // Processor Architecture: Itanium (PE32+) + afPA_AMD64 = 0x0040, // Processor Architecture: AMD X64 (PE32+) + afPA_Specified = 0x0080, // Propagate PA flags to AssemblyRef record + afPA_Mask = 0x0070, // Bits describing the processor architecture + afPA_FullMask = 0x00F0, // Bits describing the PA incl. Specified + afPA_Shift = 0x0004, // NOT A FLAG, shift count in PA flags <--> index conversion + + afEnableJITcompileTracking = 0x8000, // From "DebuggableAttribute". + afDisableJITcompileOptimizer= 0x4000, // From "DebuggableAttribute". + + afRetargetable = 0x0100, // The assembly can be retargeted (at runtime) to an + // assembly from a different publisher. +} CorAssemblyFlags; + +// Macros for accessing the members of CorAssemblyFlags. +#define IsAfRetargetable(x) ((x) & afRetargetable) + +// Macros for accessing the Processor Architecture flags of CorAssemblyFlags. +#define IsAfPA_MSIL(x) (((x) & afPA_Mask) == afPA_MSIL) +#define IsAfPA_x86(x) (((x) & afPA_Mask) == afPA_x86) +#define IsAfPA_IA64(x) (((x) & afPA_Mask) == afPA_IA64) +#define IsAfPA_AMD64(x) (((x) & afPA_Mask) == afPA_AMD64) +#define IsAfPA_Specified(x) ((x) & afPA_Specified) +#define PAIndex(x) (((x) & afPA_Mask) >> afPA_Shift) +#define PAFlag(x) (((x) << afPA_Shift) & afPA_Mask) +#define PrepareForSaving(x) ((x) & (((x) & afPA_Specified) ? ~afPA_Specified : ~afPA_FullMask)) + +#define IsAfEnableJITcompileTracking(x) ((x) & afEnableJITcompileTracking) +#define IsAfDisableJITcompileOptimizer(x) ((x) & afDisableJITcompileOptimizer) + +// Macros for accessing the public key flags of CorAssemblyFlags. +#define IsAfPublicKey(x) ((x) & afPublicKey) +#define IsAfPublicKeyToken(x) (((x) & afPublicKey) == 0) + + +// ManifestResource attr bits, used by DefineManifestResource. +typedef enum CorManifestResourceFlags +{ + mrVisibilityMask = 0x0007, + mrPublic = 0x0001, // The Resource is exported from the Assembly. + mrPrivate = 0x0002, // The Resource is private to the Assembly. +} CorManifestResourceFlags; + +// Macros for accessing the members of CorManifestResourceFlags. +#define IsMrPublic(x) (((x) & mrVisibilityMask) == mrPublic) +#define IsMrPrivate(x) (((x) & mrVisibilityMask) == mrPrivate) + + +// File attr bits, used by DefineFile. +typedef enum CorFileFlags +{ + ffContainsMetaData = 0x0000, // This is not a resource file + ffContainsNoMetaData = 0x0001, // This is a resource file or other non-metadata-containing file +} CorFileFlags; + +// Macros for accessing the members of CorFileFlags. +#define IsFfContainsMetaData(x) (!((x) & ffContainsNoMetaData)) +#define IsFfContainsNoMetaData(x) ((x) & ffContainsNoMetaData) + +// PE file kind bits, returned by IMetaDataImport2::GetPEKind() +typedef enum CorPEKind +{ + peNot = 0x00000000, // not a PE file + peILonly = 0x00000001, // flag IL_ONLY is set in COR header + pe32BitRequired=0x00000002, // flag 32BIT_REQUIRED is set in COR header + pe32Plus = 0x00000004, // PE32+ file (64 bit) + pe32Unmanaged=0x00000008 // PE32 without COR header +} CorPEKind; + + +// GenericParam bits, used by DefineGenericParam. +typedef enum CorGenericParamAttr +{ + // Variance of type parameters, only applicable to generic parameters + // for generic interfaces and delegates + gpVarianceMask = 0x0003, + gpNonVariant = 0x0000, + gpCovariant = 0x0001, + gpContravariant = 0x0002, + + // Special constraints, applicable to any type parameters + gpSpecialConstraintMask = 0x001C, + gpNoSpecialConstraint = 0x0000, + gpReferenceTypeConstraint = 0x0004, // type argument must be a reference type + gpNotNullableValueTypeConstraint = 0x0008, // type argument must be a value type but not Nullable + gpDefaultConstructorConstraint = 0x0010, // type argument must have a public default constructor +} CorGenericParamAttr; + +// structures and enums moved from COR.H +typedef unsigned __int8 COR_SIGNATURE; + +typedef COR_SIGNATURE* PCOR_SIGNATURE; // pointer to a cor sig. Not void* so that + // the bytes can be incremented easily +typedef const COR_SIGNATURE* PCCOR_SIGNATURE; + + +typedef const char * MDUTF8CSTR; +typedef char * MDUTF8STR; + +//***************************************************************************** +// +// Element type for Cor signature +// +//***************************************************************************** + +typedef enum CorElementType +{ + ELEMENT_TYPE_END = 0x0, + ELEMENT_TYPE_VOID = 0x1, + ELEMENT_TYPE_BOOLEAN = 0x2, + ELEMENT_TYPE_CHAR = 0x3, + ELEMENT_TYPE_I1 = 0x4, + ELEMENT_TYPE_U1 = 0x5, + ELEMENT_TYPE_I2 = 0x6, + ELEMENT_TYPE_U2 = 0x7, + ELEMENT_TYPE_I4 = 0x8, + ELEMENT_TYPE_U4 = 0x9, + ELEMENT_TYPE_I8 = 0xa, + ELEMENT_TYPE_U8 = 0xb, + ELEMENT_TYPE_R4 = 0xc, + ELEMENT_TYPE_R8 = 0xd, + ELEMENT_TYPE_STRING = 0xe, + + // every type above PTR will be simple type + ELEMENT_TYPE_PTR = 0xf, // PTR + ELEMENT_TYPE_BYREF = 0x10, // BYREF + + // Please use ELEMENT_TYPE_VALUETYPE. ELEMENT_TYPE_VALUECLASS is deprecated. + ELEMENT_TYPE_VALUETYPE = 0x11, // VALUETYPE + ELEMENT_TYPE_CLASS = 0x12, // CLASS + ELEMENT_TYPE_VAR = 0x13, // a class type variable VAR + ELEMENT_TYPE_ARRAY = 0x14, // MDARRAY ... ... + ELEMENT_TYPE_GENERICINST = 0x15, // GENERICINST ... + ELEMENT_TYPE_TYPEDBYREF = 0x16, // TYPEDREF (it takes no args) a typed referece to some other type + + ELEMENT_TYPE_I = 0x18, // native integer size + ELEMENT_TYPE_U = 0x19, // native unsigned integer size + ELEMENT_TYPE_FNPTR = 0x1B, // FNPTR + ELEMENT_TYPE_OBJECT = 0x1C, // Shortcut for System.Object + ELEMENT_TYPE_SZARRAY = 0x1D, // Shortcut for single dimension zero lower bound array + // SZARRAY + ELEMENT_TYPE_MVAR = 0x1e, // a method type variable MVAR + + // This is only for binding + ELEMENT_TYPE_CMOD_REQD = 0x1F, // required C modifier : E_T_CMOD_REQD + ELEMENT_TYPE_CMOD_OPT = 0x20, // optional C modifier : E_T_CMOD_OPT + + // This is for signatures generated internally (which will not be persisted in any way). + ELEMENT_TYPE_INTERNAL = 0x21, // INTERNAL + + // Note that this is the max of base type excluding modifiers + ELEMENT_TYPE_MAX = 0x22, // first invalid element type + + + ELEMENT_TYPE_MODIFIER = 0x40, + ELEMENT_TYPE_SENTINEL = 0x01 | ELEMENT_TYPE_MODIFIER, // sentinel for varargs + ELEMENT_TYPE_PINNED = 0x05 | ELEMENT_TYPE_MODIFIER, + ELEMENT_TYPE_R4_HFA = 0x06 | ELEMENT_TYPE_MODIFIER, // used only internally for R4 HFA types + ELEMENT_TYPE_R8_HFA = 0x07 | ELEMENT_TYPE_MODIFIER, // used only internally for R8 HFA types + +} CorElementType; + + +//***************************************************************************** +// +// Serialization types for Custom attribute support +// +//***************************************************************************** + +typedef enum CorSerializationType +{ + SERIALIZATION_TYPE_UNDEFINED = 0, + SERIALIZATION_TYPE_BOOLEAN = ELEMENT_TYPE_BOOLEAN, + SERIALIZATION_TYPE_CHAR = ELEMENT_TYPE_CHAR, + SERIALIZATION_TYPE_I1 = ELEMENT_TYPE_I1, + SERIALIZATION_TYPE_U1 = ELEMENT_TYPE_U1, + SERIALIZATION_TYPE_I2 = ELEMENT_TYPE_I2, + SERIALIZATION_TYPE_U2 = ELEMENT_TYPE_U2, + SERIALIZATION_TYPE_I4 = ELEMENT_TYPE_I4, + SERIALIZATION_TYPE_U4 = ELEMENT_TYPE_U4, + SERIALIZATION_TYPE_I8 = ELEMENT_TYPE_I8, + SERIALIZATION_TYPE_U8 = ELEMENT_TYPE_U8, + SERIALIZATION_TYPE_R4 = ELEMENT_TYPE_R4, + SERIALIZATION_TYPE_R8 = ELEMENT_TYPE_R8, + SERIALIZATION_TYPE_STRING = ELEMENT_TYPE_STRING, + SERIALIZATION_TYPE_SZARRAY = ELEMENT_TYPE_SZARRAY, // Shortcut for single dimension zero lower bound array + SERIALIZATION_TYPE_TYPE = 0x50, + SERIALIZATION_TYPE_TAGGED_OBJECT= 0x51, + SERIALIZATION_TYPE_FIELD = 0x53, + SERIALIZATION_TYPE_PROPERTY = 0x54, + SERIALIZATION_TYPE_ENUM = 0x55 +} CorSerializationType; + +// +// Calling convention flags. +// + + +typedef enum CorCallingConvention +{ + IMAGE_CEE_CS_CALLCONV_DEFAULT = 0x0, + + IMAGE_CEE_CS_CALLCONV_VARARG = 0x5, + IMAGE_CEE_CS_CALLCONV_FIELD = 0x6, + IMAGE_CEE_CS_CALLCONV_LOCAL_SIG = 0x7, + IMAGE_CEE_CS_CALLCONV_PROPERTY = 0x8, + IMAGE_CEE_CS_CALLCONV_UNMGD = 0x9, + IMAGE_CEE_CS_CALLCONV_GENERICINST = 0xa, // generic method instantiation + IMAGE_CEE_CS_CALLCONV_NATIVEVARARG = 0xb, // used ONLY for 64bit vararg PInvoke calls + IMAGE_CEE_CS_CALLCONV_MAX = 0xc, // first invalid calling convention + + + // The high bits of the calling convention convey additional info + IMAGE_CEE_CS_CALLCONV_MASK = 0x0f, // Calling convention is bottom 4 bits + IMAGE_CEE_CS_CALLCONV_HASTHIS = 0x20, // Top bit indicates a 'this' parameter + IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS = 0x40, // This parameter is explicitly in the signature + IMAGE_CEE_CS_CALLCONV_GENERIC = 0x10, // Generic method sig with explicit number of type arguments (precedes ordinary parameter count) +} CorCallingConvention; + +#define IMAGE_CEE_CS_CALLCONV_INSTANTIATION IMAGE_CEE_CS_CALLCONV_GENERICINST + +typedef enum CorUnmanagedCallingConvention +{ + IMAGE_CEE_UNMANAGED_CALLCONV_C = 0x1, + IMAGE_CEE_UNMANAGED_CALLCONV_STDCALL = 0x2, + IMAGE_CEE_UNMANAGED_CALLCONV_THISCALL = 0x3, + IMAGE_CEE_UNMANAGED_CALLCONV_FASTCALL = 0x4, + + IMAGE_CEE_CS_CALLCONV_C = IMAGE_CEE_UNMANAGED_CALLCONV_C, + IMAGE_CEE_CS_CALLCONV_STDCALL = IMAGE_CEE_UNMANAGED_CALLCONV_STDCALL, + IMAGE_CEE_CS_CALLCONV_THISCALL = IMAGE_CEE_UNMANAGED_CALLCONV_THISCALL, + IMAGE_CEE_CS_CALLCONV_FASTCALL = IMAGE_CEE_UNMANAGED_CALLCONV_FASTCALL, + +} CorUnmanagedCallingConvention; + + +typedef enum CorArgType +{ + IMAGE_CEE_CS_END = 0x0, + IMAGE_CEE_CS_VOID = 0x1, + IMAGE_CEE_CS_I4 = 0x2, + IMAGE_CEE_CS_I8 = 0x3, + IMAGE_CEE_CS_R4 = 0x4, + IMAGE_CEE_CS_R8 = 0x5, + IMAGE_CEE_CS_PTR = 0x6, + IMAGE_CEE_CS_OBJECT = 0x7, + IMAGE_CEE_CS_STRUCT4 = 0x8, + IMAGE_CEE_CS_STRUCT32 = 0x9, + IMAGE_CEE_CS_BYVALUE = 0xA, +} CorArgType; + + +//***************************************************************************** +// +// Native type for N-Direct +// +//***************************************************************************** + +typedef enum CorNativeType +{ + NATIVE_TYPE_END = 0x0, //DEPRECATED + NATIVE_TYPE_VOID = 0x1, //DEPRECATED + NATIVE_TYPE_BOOLEAN = 0x2, // (4 byte boolean value: TRUE = non-zero, FALSE = 0) + NATIVE_TYPE_I1 = 0x3, + NATIVE_TYPE_U1 = 0x4, + NATIVE_TYPE_I2 = 0x5, + NATIVE_TYPE_U2 = 0x6, + NATIVE_TYPE_I4 = 0x7, + NATIVE_TYPE_U4 = 0x8, + NATIVE_TYPE_I8 = 0x9, + NATIVE_TYPE_U8 = 0xa, + NATIVE_TYPE_R4 = 0xb, + NATIVE_TYPE_R8 = 0xc, + NATIVE_TYPE_SYSCHAR = 0xd, //DEPRECATED + NATIVE_TYPE_VARIANT = 0xe, //DEPRECATED + NATIVE_TYPE_CURRENCY = 0xf, + NATIVE_TYPE_PTR = 0x10, //DEPRECATED + + NATIVE_TYPE_DECIMAL = 0x11, //DEPRECATED + NATIVE_TYPE_DATE = 0x12, //DEPRECATED + NATIVE_TYPE_BSTR = 0x13, //COMINTEROP + NATIVE_TYPE_LPSTR = 0x14, + NATIVE_TYPE_LPWSTR = 0x15, + NATIVE_TYPE_LPTSTR = 0x16, + NATIVE_TYPE_FIXEDSYSSTRING = 0x17, + NATIVE_TYPE_OBJECTREF = 0x18, //DEPRECATED + NATIVE_TYPE_IUNKNOWN = 0x19, //COMINTEROP + NATIVE_TYPE_IDISPATCH = 0x1a, //COMINTEROP + NATIVE_TYPE_STRUCT = 0x1b, + NATIVE_TYPE_INTF = 0x1c, //COMINTEROP + NATIVE_TYPE_SAFEARRAY = 0x1d, //COMINTEROP + NATIVE_TYPE_FIXEDARRAY = 0x1e, + NATIVE_TYPE_INT = 0x1f, + NATIVE_TYPE_UINT = 0x20, + + NATIVE_TYPE_NESTEDSTRUCT = 0x21, //DEPRECATED (use NATIVE_TYPE_STRUCT) + + NATIVE_TYPE_BYVALSTR = 0x22, //COMINTEROP + + NATIVE_TYPE_ANSIBSTR = 0x23, //COMINTEROP + + NATIVE_TYPE_TBSTR = 0x24, // select BSTR or ANSIBSTR depending on platform + //COMINTEROP + + NATIVE_TYPE_VARIANTBOOL = 0x25, // (2-byte boolean value: TRUE = -1, FALSE = 0) + //COMINTEROP + NATIVE_TYPE_FUNC = 0x26, + + NATIVE_TYPE_ASANY = 0x28, + + NATIVE_TYPE_ARRAY = 0x2a, + NATIVE_TYPE_LPSTRUCT = 0x2b, + + NATIVE_TYPE_CUSTOMMARSHALER = 0x2c, // Custom marshaler native type. This must be followed + // by a string of the following format: + // "Native type name/0Custom marshaler type name/0Optional cookie/0" + // Or + // "{Native type GUID}/0Custom marshaler type name/0Optional cookie/0" + + NATIVE_TYPE_ERROR = 0x2d, // This native type coupled with ELEMENT_TYPE_I4 will map to VT_HRESULT + //COMINTEROP + + NATIVE_TYPE_MAX = 0x50, // first invalid element type +} CorNativeType; + + +enum +{ + DESCR_GROUP_METHODDEF = 0, // DESCR group for MethodDefs + DESCR_GROUP_METHODIMPL, // DESCR group for MethodImpls +}; + +/***********************************************************************************/ +// a COR_ILMETHOD_SECT is a generic container for attributes that are private +// to a particular method. The COR_ILMETHOD structure points to one of these +// (see GetSect()). COR_ILMETHOD_SECT can decode the Kind of attribute (but not +// its internal data layout, and can skip past the current attibute to find the +// Next one. The overhead for COR_ILMETHOD_SECT is a minimum of 2 bytes. + +typedef enum CorILMethodSect // codes that identify attributes +{ + CorILMethod_Sect_Reserved = 0, + CorILMethod_Sect_EHTable = 1, + CorILMethod_Sect_OptILTable = 2, + + CorILMethod_Sect_KindMask = 0x3F, // The mask for decoding the type code + CorILMethod_Sect_FatFormat = 0x40, // fat format + CorILMethod_Sect_MoreSects = 0x80, // there is another attribute after this one +} CorILMethodSect; + +/************************************/ +/* NOTE this structure must be DWORD aligned!! */ + +typedef struct IMAGE_COR_ILMETHOD_SECT_SMALL +{ + BYTE Kind; + BYTE DataSize; + +} IMAGE_COR_ILMETHOD_SECT_SMALL; + + + +/************************************/ +/* NOTE this structure must be DWORD aligned!! */ +typedef struct IMAGE_COR_ILMETHOD_SECT_FAT +{ + unsigned Kind : 8; + unsigned DataSize : 24; + +} IMAGE_COR_ILMETHOD_SECT_FAT; + + + +/***********************************************************************************/ +/* If COR_ILMETHOD_SECT_HEADER::Kind() = CorILMethod_Sect_EHTable then the attribute + is a list of exception handling clauses. There are two formats, fat or small +*/ +typedef enum CorExceptionFlag // defintitions for the Flags field below (for both big and small) +{ + COR_ILEXCEPTION_CLAUSE_NONE, // This is a typed handler + COR_ILEXCEPTION_CLAUSE_OFFSETLEN = 0x0000, // Deprecated + COR_ILEXCEPTION_CLAUSE_DEPRECATED = 0x0000, // Deprecated + COR_ILEXCEPTION_CLAUSE_FILTER = 0x0001, // If this bit is on, then this EH entry is for a filter + COR_ILEXCEPTION_CLAUSE_FINALLY = 0x0002, // This clause is a finally clause + COR_ILEXCEPTION_CLAUSE_FAULT = 0x0004, // Fault clause (finally that is called on exception only) + COR_ILEXCEPTION_CLAUSE_DUPLICATED = 0x0008, // duplicated clase.. this clause was duplicated down to a funclet which was pulled out of line +} CorExceptionFlag; + +/***********************************/ +// NOTE !!! NOTE +// This structure should line up with EE_ILEXCEPTION_CLAUSE, +// otherwise you'll have to adjust code in Excep.cpp, re: EHRangeTree +// NOTE !!! NOTE + +typedef struct IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT +{ + CorExceptionFlag Flags; + DWORD TryOffset; + DWORD TryLength; // relative to start of try block + DWORD HandlerOffset; + DWORD HandlerLength; // relative to start of handler + union { + DWORD ClassToken; // use for type-based exception handlers + DWORD FilterOffset; // use for filter-based exception handlers (COR_ILEXCEPTION_FILTER is set) + }; +} IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT; + +typedef struct IMAGE_COR_ILMETHOD_SECT_EH_FAT +{ + IMAGE_COR_ILMETHOD_SECT_FAT SectFat; + IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT Clauses[1]; // actually variable size +} IMAGE_COR_ILMETHOD_SECT_EH_FAT; + +/***********************************/ +typedef struct IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL +{ +#ifdef _WIN64 + unsigned Flags : 16; +#else // !_WIN64 + CorExceptionFlag Flags : 16; +#endif + unsigned TryOffset : 16; + unsigned TryLength : 8; // relative to start of try block + unsigned HandlerOffset : 16; + unsigned HandlerLength : 8; // relative to start of handler + union { + DWORD ClassToken; + DWORD FilterOffset; + }; +} IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL; + +/***********************************/ +typedef struct IMAGE_COR_ILMETHOD_SECT_EH_SMALL +{ + IMAGE_COR_ILMETHOD_SECT_SMALL SectSmall; + WORD Reserved; + IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL Clauses[1]; // actually variable size +} IMAGE_COR_ILMETHOD_SECT_EH_SMALL; + + + +typedef union IMAGE_COR_ILMETHOD_SECT_EH +{ + IMAGE_COR_ILMETHOD_SECT_EH_SMALL Small; + IMAGE_COR_ILMETHOD_SECT_EH_FAT Fat; +} IMAGE_COR_ILMETHOD_SECT_EH; + + +/***********************************************************************************/ +typedef enum CorILMethodFlags +{ + CorILMethod_InitLocals = 0x0010, // call default constructor on all local vars + CorILMethod_MoreSects = 0x0008, // there is another attribute after this one + + CorILMethod_CompressedIL = 0x0040, // FIX Remove this and do it on a per Module basis + + // Indicates the format for the COR_ILMETHOD header + CorILMethod_FormatShift = 3, + CorILMethod_FormatMask = ((1 << CorILMethod_FormatShift) - 1), + CorILMethod_TinyFormat = 0x0002, // use this code if the code size is even + CorILMethod_SmallFormat = 0x0000, + CorILMethod_FatFormat = 0x0003, + CorILMethod_TinyFormat1 = 0x0006, // use this code if the code size is odd +} CorILMethodFlags; + +/***************************************************************************/ +/* Used when the method is tiny (< 64 bytes), and there are no local vars */ +typedef struct IMAGE_COR_ILMETHOD_TINY +{ + BYTE Flags_CodeSize; +} IMAGE_COR_ILMETHOD_TINY; + +/************************************/ +// This strucuture is the 'fat' layout, where no compression is attempted. +// Note that this structure can be added on at the end, thus making it extensible +typedef struct IMAGE_COR_ILMETHOD_FAT +{ + unsigned Flags : 12; // Flags + unsigned Size : 4; // size in DWords of this structure (currently 3) + unsigned MaxStack : 16; // maximum number of items (I4, I, I8, obj ...), on the operand stack + DWORD CodeSize; // size of the code + mdSignature LocalVarSigTok; // token that indicates the signature of the local vars (0 means none) + +} IMAGE_COR_ILMETHOD_FAT; + +typedef union IMAGE_COR_ILMETHOD +{ + IMAGE_COR_ILMETHOD_TINY Tiny; + IMAGE_COR_ILMETHOD_FAT Fat; +} IMAGE_COR_ILMETHOD; + +// +// Native method descriptor. +// + +typedef struct IMAGE_COR_NATIVE_DESCRIPTOR +{ + DWORD GCInfo; + DWORD EHInfo; +} IMAGE_COR_NATIVE_DESCRIPTOR; + + +typedef struct IMAGE_COR_X86_RUNTIME_FUNCTION_ENTRY +{ + ULONG BeginAddress; // RVA of start of function + ULONG EndAddress; // RVA of end of function + ULONG MIH; // Associated MIH +} IMAGE_COR_X86_RUNTIME_FUNCTION_ENTRY; + +typedef struct IMAGE_COR_MIH_ENTRY +{ + ULONG EHRVA; + ULONG MethodRVA; + mdToken Token; + BYTE Flags; + BYTE CodeManager; + BYTE MIHData[0]; +} IMAGE_COR_MIH_ENTRY; + +//***************************************************************************** +// Non VOS v-table entries. Define an array of these pointed to by +// IMAGE_COR20_HEADER.VTableFixups. Each entry describes a contiguous array of +// v-table slots. The slots start out initialized to the meta data token value +// for the method they need to call. At image load time, the CLR Loader will +// turn each entry into a pointer to machine code for the CPU and can be +// called directly. +//***************************************************************************** + +typedef struct IMAGE_COR_VTABLEFIXUP +{ + ULONG RVA; // Offset of v-table array in image. + USHORT Count; // How many entries at location. + USHORT Type; // COR_VTABLE_xxx type of entries. +} IMAGE_COR_VTABLEFIXUP; + + + + + +//***************************************************************************** +//***************************************************************************** +// +// M E T A - D A T A D E C L A R A T I O N S +// +//***************************************************************************** +//***************************************************************************** + +//***************************************************************************** +// +// Enums for SetOption API. +// +//***************************************************************************** + +// flags for MetaDataCheckDuplicatesFor +typedef enum CorCheckDuplicatesFor +{ + MDDupAll = 0xffffffff, + MDDupENC = MDDupAll, + MDNoDupChecks = 0x00000000, + MDDupTypeDef = 0x00000001, + MDDupInterfaceImpl = 0x00000002, + MDDupMethodDef = 0x00000004, + MDDupTypeRef = 0x00000008, + MDDupMemberRef = 0x00000010, + MDDupCustomAttribute = 0x00000020, + MDDupParamDef = 0x00000040, + MDDupPermission = 0x00000080, + MDDupProperty = 0x00000100, + MDDupEvent = 0x00000200, + MDDupFieldDef = 0x00000400, + MDDupSignature = 0x00000800, + MDDupModuleRef = 0x00001000, + MDDupTypeSpec = 0x00002000, + MDDupImplMap = 0x00004000, + MDDupAssemblyRef = 0x00008000, + MDDupFile = 0x00010000, + MDDupExportedType = 0x00020000, + MDDupManifestResource = 0x00040000, + MDDupGenericParam = 0x00080000, + MDDupMethodSpec = 0x00100000, + MDDupGenericParamConstraint = 0x00200000, + // gap for debug junk + MDDupAssembly = 0x10000000, + + // This is the default behavior on metadata. It will check duplicates for TypeRef, MemberRef, Signature, TypeSpec and MethodSpec. + MDDupDefault = MDNoDupChecks | MDDupTypeRef | MDDupMemberRef | MDDupSignature | MDDupTypeSpec | MDDupMethodSpec, +} CorCheckDuplicatesFor; + +// flags for MetaDataRefToDefCheck +typedef enum CorRefToDefCheck +{ + // default behavior is to always perform TypeRef to TypeDef and MemberRef to MethodDef/FieldDef optimization + MDRefToDefDefault = 0x00000003, + MDRefToDefAll = 0xffffffff, + MDRefToDefNone = 0x00000000, + MDTypeRefToDef = 0x00000001, + MDMemberRefToDef = 0x00000002 +} CorRefToDefCheck; + + +// MetaDataNotificationForTokenMovement +typedef enum CorNotificationForTokenMovement +{ + // default behavior is to notify TypeRef, MethodDef, MemberRef, and FieldDef token remaps + MDNotifyDefault = 0x0000000f, + MDNotifyAll = 0xffffffff, + MDNotifyNone = 0x00000000, + MDNotifyMethodDef = 0x00000001, + MDNotifyMemberRef = 0x00000002, + MDNotifyFieldDef = 0x00000004, + MDNotifyTypeRef = 0x00000008, + + MDNotifyTypeDef = 0x00000010, + MDNotifyParamDef = 0x00000020, + MDNotifyInterfaceImpl = 0x00000040, + MDNotifyProperty = 0x00000080, + MDNotifyEvent = 0x00000100, + MDNotifySignature = 0x00000200, + MDNotifyTypeSpec = 0x00000400, + MDNotifyCustomAttribute = 0x00000800, + MDNotifySecurityValue = 0x00001000, + MDNotifyPermission = 0x00002000, + MDNotifyModuleRef = 0x00004000, + + MDNotifyNameSpace = 0x00008000, + + MDNotifyAssemblyRef = 0x01000000, + MDNotifyFile = 0x02000000, + MDNotifyExportedType = 0x04000000, + MDNotifyResource = 0x08000000, +} CorNotificationForTokenMovement; + + +typedef enum CorSetENC +{ + MDSetENCOn = 0x00000001, // Deprecated name. + MDSetENCOff = 0x00000002, // Deprecated name. + + MDUpdateENC = 0x00000001, // ENC mode. Tokens don't move; can be updated. + MDUpdateFull = 0x00000002, // "Normal" update mode. + MDUpdateExtension = 0x00000003, // Extension mode. Tokens don't move, adds only. + MDUpdateIncremental = 0x00000004, // Incremental compilation + MDUpdateDelta = 0x00000005, // If ENC on, save only deltas. + MDUpdateMask = 0x00000007, + + +} CorSetENC; + +#define IsENCDelta(x) (((x) & MDUpdateMask) == MDUpdateDelta) + +// flags used in SetOption when pair with MetaDataErrorIfEmitOutOfOrder guid +typedef enum CorErrorIfEmitOutOfOrder +{ + MDErrorOutOfOrderDefault = 0x00000000, // default not to generate any error + MDErrorOutOfOrderNone = 0x00000000, // do not generate error for out of order emit + MDErrorOutOfOrderAll = 0xffffffff, // generate out of order emit for method, field, param, property, and event + MDMethodOutOfOrder = 0x00000001, // generate error when methods are emitted out of order + MDFieldOutOfOrder = 0x00000002, // generate error when fields are emitted out of order + MDParamOutOfOrder = 0x00000004, // generate error when params are emitted out of order + MDPropertyOutOfOrder = 0x00000008, // generate error when properties are emitted out of order + MDEventOutOfOrder = 0x00000010, // generate error when events are emitted out of order +} CorErrorIfEmitOutOfOrder; + + +// flags used in SetOption when pair with MetaDataImportOption guid +typedef enum CorImportOptions +{ + MDImportOptionDefault = 0x00000000, // default to skip over deleted records + MDImportOptionAll = 0xFFFFFFFF, // Enumerate everything + MDImportOptionAllTypeDefs = 0x00000001, // all of the typedefs including the deleted typedef + MDImportOptionAllMethodDefs = 0x00000002, // all of the methoddefs including the deleted ones + MDImportOptionAllFieldDefs = 0x00000004, // all of the fielddefs including the deleted ones + MDImportOptionAllProperties = 0x00000008, // all of the properties including the deleted ones + MDImportOptionAllEvents = 0x00000010, // all of the events including the deleted ones + MDImportOptionAllCustomAttributes = 0x00000020, // all of the custom attributes including the deleted ones + MDImportOptionAllExportedTypes = 0x00000040, // all of the ExportedTypes including the deleted ones + +} CorImportOptions; + + +// flags for MetaDataThreadSafetyOptions +typedef enum CorThreadSafetyOptions +{ + // default behavior is to have thread safety turn off. This means that MetaData APIs will not take reader/writer + // lock. Clients is responsible to make sure the properly thread synchornization when using MetaData APIs. + MDThreadSafetyDefault = 0x00000000, + MDThreadSafetyOff = 0x00000000, + MDThreadSafetyOn = 0x00000001, +} CorThreadSafetyOptions; + + +// flags for MetaDataLinkerOptions +typedef enum CorLinkerOptions +{ + // default behavior is not to keep private types + MDAssembly = 0x00000000, + MDNetModule = 0x00000001, +} CorLinkerOptions; + +// flags for MetaDataMergeOptions +typedef enum MergeFlags +{ + MergeFlagsNone = 0, + MergeManifest = 0x00000001, + DropMemberRefCAs = 0x00000002, + NoDupCheck = 0x00000004, + MergeExportedTypes = 0x00000008 +} MergeFlags; + + +// +// struct used to retrieve field offset +// used by GetClassLayout and SetClassLayout +// + +#ifndef _COR_FIELD_OFFSET_ +#define _COR_FIELD_OFFSET_ + +typedef struct COR_FIELD_OFFSET +{ + mdFieldDef ridOfField; + ULONG ulOffset; +} COR_FIELD_OFFSET; + +#endif + +typedef struct IMAGE_COR_FIXUPENTRY +{ + ULONG ulRVA; + ULONG Count; +} IMAGE_COR_FIXUPENTRY; + + +// +// Token tags. +// +typedef enum CorTokenType +{ + mdtModule = 0x00000000, // + mdtTypeRef = 0x01000000, // + mdtTypeDef = 0x02000000, // + mdtFieldDef = 0x04000000, // + mdtMethodDef = 0x06000000, // + mdtParamDef = 0x08000000, // + mdtInterfaceImpl = 0x09000000, // + mdtMemberRef = 0x0a000000, // + mdtCustomAttribute = 0x0c000000, // + mdtPermission = 0x0e000000, // + mdtSignature = 0x11000000, // + mdtEvent = 0x14000000, // + mdtProperty = 0x17000000, // + mdtModuleRef = 0x1a000000, // + mdtTypeSpec = 0x1b000000, // + mdtAssembly = 0x20000000, // + mdtAssemblyRef = 0x23000000, // + mdtFile = 0x26000000, // + mdtExportedType = 0x27000000, // + mdtManifestResource = 0x28000000, // + mdtGenericParam = 0x2a000000, // + mdtMethodSpec = 0x2b000000, // + mdtGenericParamConstraint = 0x2c000000, + + mdtString = 0x70000000, // + mdtName = 0x71000000, // + mdtBaseType = 0x72000000, // Leave this on the high end value. This does not correspond to metadata table +} CorTokenType; + +// +// Build / decompose tokens. +// +#define RidToToken(rid,tktype) ((rid) |= (tktype)) +#define TokenFromRid(rid,tktype) ((rid) | (tktype)) +#define RidFromToken(tk) ((RID) ((tk) & 0x00ffffff)) +#define TypeFromToken(tk) ((ULONG32)((tk) & 0xff000000)) +#define IsNilToken(tk) ((RidFromToken(tk)) == 0) + +// +// Nil tokens +// +#define mdTokenNil ((mdToken)0) +#define mdModuleNil ((mdModule)mdtModule) +#define mdTypeRefNil ((mdTypeRef)mdtTypeRef) +#define mdTypeDefNil ((mdTypeDef)mdtTypeDef) +#define mdFieldDefNil ((mdFieldDef)mdtFieldDef) +#define mdMethodDefNil ((mdMethodDef)mdtMethodDef) +#define mdParamDefNil ((mdParamDef)mdtParamDef) +#define mdInterfaceImplNil ((mdInterfaceImpl)mdtInterfaceImpl) +#define mdMemberRefNil ((mdMemberRef)mdtMemberRef) +#define mdCustomAttributeNil ((mdCustomAttribute)mdtCustomAttribute) +#define mdPermissionNil ((mdPermission)mdtPermission) +#define mdSignatureNil ((mdSignature)mdtSignature) +#define mdEventNil ((mdEvent)mdtEvent) +#define mdPropertyNil ((mdProperty)mdtProperty) +#define mdModuleRefNil ((mdModuleRef)mdtModuleRef) +#define mdTypeSpecNil ((mdTypeSpec)mdtTypeSpec) +#define mdAssemblyNil ((mdAssembly)mdtAssembly) +#define mdAssemblyRefNil ((mdAssemblyRef)mdtAssemblyRef) +#define mdFileNil ((mdFile)mdtFile) +#define mdExportedTypeNil ((mdExportedType)mdtExportedType) +#define mdManifestResourceNil ((mdManifestResource)mdtManifestResource) + +#define mdGenericParamNil ((mdGenericParam)mdtGenericParam) +#define mdGenericParamConstraintNil ((mdGenericParamConstraint)mdtGenericParamConstraint) +#define mdMethodSpecNil ((mdMethodSpec)mdtMethodSpec) + +#define mdStringNil ((mdString)mdtString) + +// +// Open bits. +// +typedef enum CorOpenFlags +{ + ofRead = 0x00000000, // Open scope for read + ofWrite = 0x00000001, // Open scope for write. + ofReadWriteMask = 0x00000001, // Mask for read/write bit. + + ofCopyMemory = 0x00000002, // Open scope with memory. Ask metadata to maintain its own copy of memory. + + ofManifestMetadata = 0x00000008, // Open scope on ngen image, return the manifest metadata instead of the IL metadata + ofReadOnly = 0x00000010, // Open scope for read. Will be unable to QI for a IMetadataEmit* interface + ofTakeOwnership = 0x00000020, // The memory was allocated with CoTaskMemAlloc and will be freed by the metadata + + // These are obsolete and are ignored. + ofCacheImage = 0x00000004, // EE maps but does not do relocations or verify image + ofNoTypeLib = 0x00000080, // Don't OpenScope on a typelib. + + // Internal bits + ofReserved1 = 0x00000100, // Reserved for internal use. + ofReserved2 = 0x00000200, // Reserved for internal use. + ofReserved = 0xffffff40 // All the reserved bits. + +} CorOpenFlags; + +#define IsOfRead(x) (((x) & ofReadWriteMask) == ofRead) +#define IsOfReadWrite(x) (((x) & ofReadWriteMask) == ofWrite) + +#define IsOfCopyMemory(x) ((x) & ofCopyMemory) +#define IsOfManifestMetadata(x) ((x) & ofManifestMetadata) + +#define IsOfReadOnly(x) ((x) & ofReadOnly) +#define IsOfTakeOwnership(x) ((x) & ofTakeOwnership) + +#define IsOfReserved(x) (((x) & ofReserved) != 0) + +typedef CorTypeAttr CorRegTypeAttr; + +// +// Opaque type for an enumeration handle. +// +typedef void *HCORENUM; + + +// Note that this must be kept in sync with System.AttributeTargets. +typedef enum CorAttributeTargets +{ + catAssembly = 0x0001, + catModule = 0x0002, + catClass = 0x0004, + catStruct = 0x0008, + catEnum = 0x0010, + catConstructor = 0x0020, + catMethod = 0x0040, + catProperty = 0x0080, + catField = 0x0100, + catEvent = 0x0200, + catInterface = 0x0400, + catParameter = 0x0800, + catDelegate = 0x1000, + catGenericParameter = 0x4000, + + catAll = catAssembly | catModule | catClass | catStruct | catEnum | catConstructor | + catMethod | catProperty | catField | catEvent | catInterface | catParameter | catDelegate | catGenericParameter, + catClassMembers = catClass | catStruct | catEnum | catConstructor | catMethod | catProperty | catField | catEvent | catDelegate | catInterface, + +} CorAttributeTargets; + +#ifndef MACROS_NOT_SUPPORTED +// +// Some well-known custom attributes +// +#ifndef IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS + #define IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS (IMAGE_CEE_CS_CALLCONV_DEFAULT | IMAGE_CEE_CS_CALLCONV_HASTHIS) +#endif + +#define INTEROP_DISPID_TYPE_W L"System.Runtime.InteropServices.DispIdAttribute" +#define INTEROP_DISPID_TYPE "System.Runtime.InteropServices.DispIdAttribute" +#define INTEROP_DISPID_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I4} + +#define INTEROP_INTERFACETYPE_TYPE_W L"System.Runtime.InteropServices.InterfaceTypeAttribute" +#define INTEROP_INTERFACETYPE_TYPE "System.Runtime.InteropServices.InterfaceTypeAttribute" +#define INTEROP_INTERFACETYPE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2} + +#define INTEROP_CLASSINTERFACE_TYPE_W L"System.Runtime.InteropServices.ClassInterfaceAttribute" +#define INTEROP_CLASSINTERFACE_TYPE "System.Runtime.InteropServices.ClassInterfaceAttribute" +#define INTEROP_CLASSINTERFACE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2} + +#define INTEROP_COMVISIBLE_TYPE_W L"System.Runtime.InteropServices.ComVisibleAttribute" +#define INTEROP_COMVISIBLE_TYPE "System.Runtime.InteropServices.ComVisibleAttribute" +#define INTEROP_COMVISIBLE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_BOOLEAN} + +#define INTEROP_COMREGISTERFUNCTION_TYPE_W L"System.Runtime.InteropServices.ComRegisterFunctionAttribute" +#define INTEROP_COMREGISTERFUNCTION_TYPE "System.Runtime.InteropServices.ComRegisterFunctionAttribute" +#define INTEROP_COMREGISTERFUNCTION_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_COMUNREGISTERFUNCTION_TYPE_W L"System.Runtime.InteropServices.ComUnregisterFunctionAttribute" +#define INTEROP_COMUNREGISTERFUNCTION_TYPE "System.Runtime.InteropServices.ComUnregisterFunctionAttribute" +#define INTEROP_COMUNREGISTERFUNCTION_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_IMPORTEDFROMTYPELIB_TYPE_W L"System.Runtime.InteropServices.ImportedFromTypeLibAttribute" +#define INTEROP_IMPORTEDFROMTYPELIB_TYPE "System.Runtime.InteropServices.ImportedFromTypeLibAttribute" +#define INTEROP_IMPORTEDFROMTYPELIB_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING} + +#define INTEROP_IDISPATCHIMPL_TYPE_W L"System.Runtime.InteropServices.IDispatchImplAttribute" +#define INTEROP_IDISPATCHIMPL_TYPE "System.Runtime.InteropServices.IDispatchImplAttribute" +#define INTEROP_IDISPATCHIMPL_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2} + +#define INTEROP_COMSOURCEINTERFACES_TYPE_W L"System.Runtime.InteropServices.ComSourceInterfacesAttribute" +#define INTEROP_COMSOURCEINTERFACES_TYPE "System.Runtime.InteropServices.ComSourceInterfacesAttribute" +#define INTEROP_COMSOURCEINTERFACES_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING} + +#define INTEROP_COMDEFAULTINTERFACE_TYPE_W L"System.Runtime.InteropServices.ComDefaultInterfaceAttribute" +#define INTEROP_COMDEFAULTINTERFACE_TYPE "System.Runtime.InteropServices.ComDefaultInterfaceAttribute" + +#define INTEROP_COMCONVERSIONLOSS_TYPE_W L"System.Runtime.InteropServices.ComConversionLossAttribute" +#define INTEROP_COMCONVERSIONLOSS_TYPE "System.Runtime.InteropServices.ComConversionLossAttribute" +#define INTEROP_COMCONVERSIONLOSS_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_BESTFITMAPPING_TYPE_W L"System.Runtime.InteropServices.BestFitMappingAttribute" +#define INTEROP_BESTFITMAPPING_TYPE "System.Runtime.InteropServices.BestFitMappingAttribute" +#define INTEROP_BESTFITMAPPING_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 2, ELEMENT_TYPE_VOID, ELEMENT_TYPE_BOOLEAN, ELEMENT_TYPE_BOOLEAN} + +#define INTEROP_TYPELIBTYPE_TYPE_W L"System.Runtime.InteropServices.TypeLibTypeAttribute" +#define INTEROP_TYPELIBTYPE_TYPE "System.Runtime.InteropServices.TypeLibTypeAttribute" +#define INTEROP_TYPELIBTYPE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2} + +#define INTEROP_TYPELIBFUNC_TYPE_W L"System.Runtime.InteropServices.TypeLibFuncAttribute" +#define INTEROP_TYPELIBFUNC_TYPE "System.Runtime.InteropServices.TypeLibFuncAttribute" +#define INTEROP_TYPELIBFUNC_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2} + +#define INTEROP_TYPELIBVAR_TYPE_W L"System.Runtime.InteropServices.TypeLibVarAttribute" +#define INTEROP_TYPELIBVAR_TYPE "System.Runtime.InteropServices.TypeLibVarAttribute" +#define INTEROP_TYPELIBVAR_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2} + +#define INTEROP_MARSHALAS_TYPE_W L"System.Runtime.InteropServices.MarshalAsAttribute" +#define INTEROP_MARSHALAS_TYPE "System.Runtime.InteropServices.MarshalAsAttribute" +#define INTEROP_MARSHALAS_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2} + +#define INTEROP_COMIMPORT_TYPE_W L"System.Runtime.InteropServices.ComImportAttribute" +#define INTEROP_COMIMPORT_TYPE "System.Runtime.InteropServices.ComImportAttribute" +#define INTEROP_COMIMPORT_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_GUID_TYPE_W L"System.Runtime.InteropServices.GuidAttribute" +#define INTEROP_GUID_TYPE "System.Runtime.InteropServices.GuidAttribute" +#define INTEROP_GUID_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING} + +#define INTEROP_DEFAULTMEMBER_TYPE_W L"System.Reflection.DefaultMemberAttribute" +#define INTEROP_DEFAULTMEMBER_TYPE "System.Reflection.DefaultMemberAttribute" +#define INTEROP_DEFAULTMEMBER_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING} + +#define INTEROP_COMEMULATE_TYPE_W L"System.Runtime.InteropServices.ComEmulateAttribute" +#define INTEROP_COMEMULATE_TYPE "System.Runtime.InteropServices.ComEmulateAttribute" +#define INTEROP_COMEMULATE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING} + +#define INTEROP_PRESERVESIG_TYPE_W L"System.Runtime.InteropServices.PreserveSigAttribure" +#define INTEROP_PRESERVESIG_TYPE "System.Runtime.InteropServices.PreserveSigAttribure" +#define INTEROP_PRESERVESIG_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_BOOLEAN} + +#define INTEROP_IN_TYPE_W L"System.Runtime.InteropServices.InAttribute" +#define INTEROP_IN_TYPE "System.Runtime.InteropServices.InAttribute" +#define INTEROP_IN_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_OUT_TYPE_W L"System.Runtime.InteropServices.OutAttribute" +#define INTEROP_OUT_TYPE "System.Runtime.InteropServices.OutAttribute" +#define INTEROP_OUT_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_COMALIASNAME_TYPE_W L"System.Runtime.InteropServices.ComAliasNameAttribute" +#define INTEROP_COMALIASNAME_TYPE "System.Runtime.InteropServices.ComAliasNameAttribute" +#define INTEROP_COMALIASNAME_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING} + +#define INTEROP_PARAMARRAY_TYPE_W L"System.ParamArrayAttribute" +#define INTEROP_PARAMARRAY_TYPE "System.ParamArrayAttribute" +#define INTEROP_PARAMARRAY_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_LCIDCONVERSION_TYPE_W L"System.Runtime.InteropServices.LCIDConversionAttribute" +#define INTEROP_LCIDCONVERSION_TYPE "System.Runtime.InteropServices.LCIDConversionAttribute" +#define INTEROP_LCIDCONVERSION_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I4} + +#define INTEROP_COMSUBSTITUTABLEINTERFACE_TYPE_W L"System.Runtime.InteropServices.ComSubstitutableInterfaceAttribute" +#define INTEROP_COMSUBSTITUTABLEINTERFACE_TYPE "System.Runtime.InteropServices.ComSubstitutableInterfaceAttribute" +#define INTEROP_COMSUBSTITUTABLEINTERFACE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_DECIMALVALUE_TYPE_W L"System.Runtime.CompilerServices.DecimalConstantAttribute" +#define INTEROP_DECIMALVALUE_TYPE "System.Runtime.CompilerServices.DecimalConstantAttribute" +#define INTEROP_DECIMALVALUE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 5, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U4, ELEMENT_TYPE_U4, ELEMENT_TYPE_U4} + +#define INTEROP_DATETIMEVALUE_TYPE_W L"System.Runtime.CompilerServices.DateTimeConstantAttribute" +#define INTEROP_DATETIMEVALUE_TYPE "System.Runtime.CompilerServices.DateTimeConstantAttribute" +#define INTEROP_DATETIMEVALUE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I8} + +#define INTEROP_IUNKNOWNVALUE_TYPE_W L"System.Runtime.CompilerServices.IUnknownConstantAttribute" +#define INTEROP_IUNKNOWNVALUE_TYPE "System.Runtime.CompilerServices.IUnknownConstantAttribute" +#define INTEROP_IUNKNOWNVALUE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_IDISPATCHVALUE_TYPE_W L"System.Runtime.CompilerServices.IDispatchConstantAttribute" +#define INTEROP_IDISPATCHVALUE_TYPE "System.Runtime.CompilerServices.IDispatchConstantAttribute" +#define INTEROP_IDISPATCHVALUE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_AUTOPROXY_TYPE_W L"System.Runtime.InteropServices.AutomationProxyAttribute" +#define INTEROP_AUTOPROXY_TYPE "System.Runtime.InteropServices.AutomationProxyAttribute" +#define INTEROP_AUTOPROXY_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_BOOLEAN} + +#define INTEROP_TYPELIBIMPORTCLASS_TYPE_W L"System.Runtime.InteropServices.TypeLibImportClassAttribute" +#define INTEROP_TYPELIBIMPORTCLASS_TYPE "System.Runtime.InteropServices.TypeLibImportClassAttribute" + + +#define INTEROP_TYPELIBVERSION_TYPE_W L"System.Runtime.InteropServices.TypeLibVersionAttribute" +#define INTEROP_TYPELIBVERSION_TYPE "System.Runtime.InteropServices.TypeLibVersionAttribute" +#define INTEROP_TYPELIBVERSION_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 2, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2, ELEMENT_TYPE_I2} + +#define INTEROP_COMCOMPATIBLEVERSION_TYPE_W L"System.Runtime.InteropServices.ComCompatibleVersionAttribute" +#define INTEROP_COMCOMPATIBLEVERSION_TYPE "System.Runtime.InteropServices.ComCompatibleVersionAttribute" +#define INTEROP_COMCOMPATIBLEVERSION_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 4, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2, ELEMENT_TYPE_I2, ELEMENT_TYPE_I2, ELEMENT_TYPE_I2} + +#define INTEROP_COMEVENTINTERFACE_TYPE_W L"System.Runtime.InteropServices.ComEventInterfaceAttribute" +#define INTEROP_COMEVENTINTERFACE_TYPE "System.Runtime.InteropServices.ComEventInterfaceAttribute" + +#define INTEROP_COCLASS_TYPE_W L"System.Runtime.InteropServices.CoClassAttribute" +#define INTEROP_COCLASS_TYPE "System.Runtime.InteropServices.CoClassAttribute" + +#define INTEROP_SERIALIZABLE_TYPE_W L"System.SerializableAttribute" +#define INTEROP_SERIALIZABLE_TYPE "System.SerializableAttribute" +#define INTEROP_SERIALIZABLE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_SETWIN32CONTEXTINIDISPATCHATTRIBUTE_TYPE_W L"System.Runtime.InteropServices.SetWin32ContextInIDispatchAttribute" +#define INTEROP_SETWIN32CONTEXTINIDISPATCHATTRIBUTE_TYPE "System.Runtime.InteropServices.SetWin32ContextInIDispatchAttribute" +#define INTEROP_SETWIN32CONTEXTINIDISPATCHATTRIBUTE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define FRIEND_ASSEMBLY_TYPE_W L"System.Runtime.CompilerServices.InternalsVisibleToAttribute" +#define FRIEND_ASSEMBLY_TYPE "System.Runtime.CompilerServices.InternalsVisibleToAttribute" +#define FRIEND_ASSEMBLY_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING} + +#define DEFAULTDOMAIN_STA_TYPE_W L"System.STAThreadAttribute" +#define DEFAULTDOMAIN_STA_TYPE "System.STAThreadAttribute" +#define DEFAULTDOMAIN_STA_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define DEFAULTDOMAIN_MTA_TYPE_W L"System.MTAThreadAttribute" +#define DEFAULTDOMAIN_MTA_TYPE "System.MTAThreadAttribute" +#define DEFAULTDOMAIN_MTA_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define DEFAULTDOMAIN_LOADEROPTIMIZATION_TYPE_W L"System.LoaderOptimizationAttribute" +#define DEFAULTDOMAIN_LOADEROPTIMIZATION_TYPE "System.LoaderOptimizationAttribute" +#define DEFAULTDOMAIN_LOADEROPTIMIZATION_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I1} + + +// Keep in sync with CompilationRelaxations.cs +typedef enum CompilationRelaxationsEnum +{ + CompilationRelaxations_NoStringInterning = 0x0008, + +} CompilationRelaxationEnum; + +#define COMPILATIONRELAXATIONS_TYPE_W L"System.Runtime.CompilerServices.CompilationRelaxationsAttribute" +#define COMPILATIONRELAXATIONS_TYPE "System.Runtime.CompilerServices.CompilationRelaxationsAttribute" + + +// Keep in sync with RuntimeCompatibilityAttribute.cs +#define RUNTIMECOMPATIBILITY_TYPE_W L"System.Runtime.CompilerServices.RuntimeCompatibilityAttribute" +#define RUNTIMECOMPATIBILITY_TYPE "System.Runtime.CompilerServices.RuntimeCompatibilityAttribute" + + +// Keep in sync with AssemblySettingAttributes.cs + +typedef enum NGenHintEnum +{ + NGenDefault = 0x0000, // No preference specified + + NGenEager = 0x0001, // NGen at install time + NGenLazy = 0x0002, // NGen after install time + NGenNever = 0x0003 // Assembly should not be ngened +} NGenHintEnum; + +typedef enum LoadHintEnum +{ + LoadDefault = 0x0000, // No preference specified + + LoadAlways = 0x0001, // Dependency is always loaded + LoadSometimes = 0x0002, // Dependency is sometimes loaded + LoadNever = 0x0003 // Dependency is never loaded +} LoadHintEnum; + +#define NGEN_TYPE_W L"System.Runtime.CompilerServices.NGenAttribute" +#define NGEN_TYPE "System.Runtime.CompilerServices.NGenAttribute" + +#define DEFAULTDEPENDENCY_TYPE_W L"System.Runtime.CompilerServices.DefaultDependencyAttribute" +#define DEFAULTDEPENDENCY_TYPE "System.Runtime.CompilerServices.DefaultDependencyAttribute" + +#define DEPENDENCY_TYPE_W L"System.Runtime.CompilerServices.DependencyAttribute" +#define DEPENDENCY_TYPE "System.Runtime.CompilerServices.DependencyAttribute" + + +#define CMOD_CALLCONV_NAMESPACE_OLD "System.Runtime.InteropServices" +#define CMOD_CALLCONV_NAMESPACE "System.Runtime.CompilerServices" +#define CMOD_CALLCONV_NAME_CDECL "CallConvCdecl" +#define CMOD_CALLCONV_NAME_STDCALL "CallConvStdcall" +#define CMOD_CALLCONV_NAME_THISCALL "CallConvThiscall" +#define CMOD_CALLCONV_NAME_FASTCALL "CallConvFastcall" + +#endif // MACROS_NOT_SUPPORTED + +// +// GetSaveSize accuracy +// +#ifndef _CORSAVESIZE_DEFINED_ +#define _CORSAVESIZE_DEFINED_ +typedef enum CorSaveSize +{ + cssAccurate = 0x0000, // Find exact save size, accurate but slower. + cssQuick = 0x0001, // Estimate save size, may pad estimate, but faster. + cssDiscardTransientCAs = 0x0002, // remove all of the CAs of discardable types +} CorSaveSize; +#endif + +#define COR_IS_METHOD_MANAGED_IL(flags) ((flags & 0xf) == (miIL | miManaged)) +#define COR_IS_METHOD_MANAGED_OPTIL(flags) ((flags & 0xf) == (miOPTIL | miManaged)) +#define COR_IS_METHOD_MANAGED_NATIVE(flags) ((flags & 0xf) == (miNative | miManaged)) +#define COR_IS_METHOD_UNMANAGED_NATIVE(flags) ((flags & 0xf) == (miNative | miUnmanaged)) + +// +// Enum used with NATIVE_TYPE_ARRAY. +// +typedef enum NativeTypeArrayFlags +{ + ntaSizeParamIndexSpecified = 0x0001, + ntaReserved = 0xfffe // All the reserved bits. +} NativeTypeArrayFlags; + +// +// Opaque types for security properties and values. +// +typedef void * PSECURITY_PROPS ; +typedef void * PSECURITY_VALUE ; +typedef void ** PPSECURITY_PROPS ; +typedef void ** PPSECURITY_VALUE ; + +//------------------------------------- +//--- Security data structures +//------------------------------------- + +// Descriptor for a single security custom attribute. +typedef struct COR_SECATTR { + mdMemberRef tkCtor; // Ref to constructor of security attribute. + const void *pCustomAttribute; // Blob describing ctor args and field/property values. + ULONG cbCustomAttribute; // Length of the above blob. +} COR_SECATTR; + +#endif // __CORHDR_H__ + diff --git a/third/Blackbone/src/3rd_party/gchost.h b/third/Blackbone/src/3rd_party/gchost.h new file mode 100644 index 0000000000000000000000000000000000000000..8b34b074d8f0a04dd3973511552b3bf2bc590f36 --- /dev/null +++ b/third/Blackbone/src/3rd_party/gchost.h @@ -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 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 +#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 + + diff --git a/third/Blackbone/src/3rd_party/ivalidator.h b/third/Blackbone/src/3rd_party/ivalidator.h new file mode 100644 index 0000000000000000000000000000000000000000..466eef7a11fdb76d64fce1ad182b09f0ac314665 --- /dev/null +++ b/third/Blackbone/src/3rd_party/ivalidator.h @@ -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 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 +#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 + + diff --git a/third/Blackbone/src/3rd_party/ivehandler.h b/third/Blackbone/src/3rd_party/ivehandler.h new file mode 100644 index 0000000000000000000000000000000000000000..50035a9e89275a6b93babae8e0365dbad40b728e --- /dev/null +++ b/third/Blackbone/src/3rd_party/ivehandler.h @@ -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 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 +#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 + + diff --git a/third/Blackbone/src/3rd_party/metahost.h b/third/Blackbone/src/3rd_party/metahost.h new file mode 100644 index 0000000000000000000000000000000000000000..70792b22278ea436edf69c541de31e64629f7b1c --- /dev/null +++ b/third/Blackbone/src/3rd_party/metahost.h @@ -0,0 +1,1634 @@ + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.00.0601 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCSAL_H_VERSION__ +#define __REQUIRED_RPCSAL_H_VERSION__ 100 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __metahost_h__ +#define __metahost_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __ICLRMetaHost_FWD_DEFINED__ +#define __ICLRMetaHost_FWD_DEFINED__ +typedef interface ICLRMetaHost ICLRMetaHost; + +#endif /* __ICLRMetaHost_FWD_DEFINED__ */ + + +#ifndef __ICLRMetaHostPolicy_FWD_DEFINED__ +#define __ICLRMetaHostPolicy_FWD_DEFINED__ +typedef interface ICLRMetaHostPolicy ICLRMetaHostPolicy; + +#endif /* __ICLRMetaHostPolicy_FWD_DEFINED__ */ + + +#ifndef __ICLRProfiling_FWD_DEFINED__ +#define __ICLRProfiling_FWD_DEFINED__ +typedef interface ICLRProfiling ICLRProfiling; + +#endif /* __ICLRProfiling_FWD_DEFINED__ */ + + +#ifndef __ICLRDebuggingLibraryProvider_FWD_DEFINED__ +#define __ICLRDebuggingLibraryProvider_FWD_DEFINED__ +typedef interface ICLRDebuggingLibraryProvider ICLRDebuggingLibraryProvider; + +#endif /* __ICLRDebuggingLibraryProvider_FWD_DEFINED__ */ + + +#ifndef __ICLRDebugging_FWD_DEFINED__ +#define __ICLRDebugging_FWD_DEFINED__ +typedef interface ICLRDebugging ICLRDebugging; + +#endif /* __ICLRDebugging_FWD_DEFINED__ */ + + +#ifndef __ICLRRuntimeInfo_FWD_DEFINED__ +#define __ICLRRuntimeInfo_FWD_DEFINED__ +typedef interface ICLRRuntimeInfo ICLRRuntimeInfo; + +#endif /* __ICLRRuntimeInfo_FWD_DEFINED__ */ + + +#ifndef __ICLRStrongName_FWD_DEFINED__ +#define __ICLRStrongName_FWD_DEFINED__ +typedef interface ICLRStrongName ICLRStrongName; + +#endif /* __ICLRStrongName_FWD_DEFINED__ */ + + +#ifndef __ICLRStrongName2_FWD_DEFINED__ +#define __ICLRStrongName2_FWD_DEFINED__ +typedef interface ICLRStrongName2 ICLRStrongName2; + +#endif /* __ICLRStrongName2_FWD_DEFINED__ */ + + +#ifndef __ICLRMetaHost_FWD_DEFINED__ +#define __ICLRMetaHost_FWD_DEFINED__ +typedef interface ICLRMetaHost ICLRMetaHost; + +#endif /* __ICLRMetaHost_FWD_DEFINED__ */ + + +#ifndef __ICLRMetaHostPolicy_FWD_DEFINED__ +#define __ICLRMetaHostPolicy_FWD_DEFINED__ +typedef interface ICLRMetaHostPolicy ICLRMetaHostPolicy; + +#endif /* __ICLRMetaHostPolicy_FWD_DEFINED__ */ + + +#ifndef __ICLRProfiling_FWD_DEFINED__ +#define __ICLRProfiling_FWD_DEFINED__ +typedef interface ICLRProfiling ICLRProfiling; + +#endif /* __ICLRProfiling_FWD_DEFINED__ */ + + +#ifndef __ICLRDebuggingLibraryProvider_FWD_DEFINED__ +#define __ICLRDebuggingLibraryProvider_FWD_DEFINED__ +typedef interface ICLRDebuggingLibraryProvider ICLRDebuggingLibraryProvider; + +#endif /* __ICLRDebuggingLibraryProvider_FWD_DEFINED__ */ + + +#ifndef __ICLRDebugging_FWD_DEFINED__ +#define __ICLRDebugging_FWD_DEFINED__ +typedef interface ICLRDebugging ICLRDebugging; + +#endif /* __ICLRDebugging_FWD_DEFINED__ */ + + +#ifndef __ICLRRuntimeInfo_FWD_DEFINED__ +#define __ICLRRuntimeInfo_FWD_DEFINED__ +typedef interface ICLRRuntimeInfo ICLRRuntimeInfo; + +#endif /* __ICLRRuntimeInfo_FWD_DEFINED__ */ + + +#ifndef __ICLRStrongName_FWD_DEFINED__ +#define __ICLRStrongName_FWD_DEFINED__ +typedef interface ICLRStrongName ICLRStrongName; + +#endif /* __ICLRStrongName_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "unknwn.h" +#include "oaidl.h" +#include "ocidl.h" +#include "mscoree.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_metahost_0000_0000 */ +/* [local] */ + +#include +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +STDAPI CLRCreateInstance(REFCLSID clsid, REFIID riid, /*iid_is(riid)*/ LPVOID *ppInterface); +EXTERN_GUID(CLSID_CLRStrongName, 0xB79B0ACD, 0xF5CD, 0x409b, 0xB5, 0xA5, 0xA1, 0x62, 0x44, 0x61, 0x0B, 0x92); +EXTERN_GUID(IID_ICLRMetaHost, 0xD332DB9E, 0xB9B3, 0x4125, 0x82, 0x07, 0xA1, 0x48, 0x84, 0xF5, 0x32, 0x16); +EXTERN_GUID(CLSID_CLRMetaHost, 0x9280188d, 0xe8e, 0x4867, 0xb3, 0xc, 0x7f, 0xa8, 0x38, 0x84, 0xe8, 0xde); +EXTERN_GUID(IID_ICLRMetaHostPolicy, 0xE2190695, 0x77B2, 0x492e, 0x8E, 0x14, 0xC4, 0xB3, 0xA7, 0xFD, 0xD5, 0x93); +EXTERN_GUID(CLSID_CLRMetaHostPolicy, 0x2ebcd49a, 0x1b47, 0x4a61, 0xb1, 0x3a, 0x4a, 0x3, 0x70, 0x1e, 0x59, 0x4b); +EXTERN_GUID(IID_ICLRDebugging, 0xd28f3c5a, 0x9634, 0x4206, 0xa5, 0x9, 0x47, 0x75, 0x52, 0xee, 0xfb, 0x10); +EXTERN_GUID(CLSID_CLRDebugging, 0xbacc578d, 0xfbdd, 0x48a4, 0x96, 0x9f, 0x2, 0xd9, 0x32, 0xb7, 0x46, 0x34); +EXTERN_GUID(IID_ICLRRuntimeInfo, 0xBD39D1D2, 0xBA2F, 0x486a, 0x89, 0xB0, 0xB4, 0xB0, 0xCB, 0x46, 0x68, 0x91); +EXTERN_GUID(IID_ICLRStrongName, 0x9FD93CCF, 0x3280, 0x4391, 0xB3, 0xA9, 0x96, 0xE1, 0xCD, 0xE7, 0x7C, 0x8D); +EXTERN_GUID(IID_ICLRStrongName2, 0xC22ED5C5, 0x4B59, 0x4975, 0x90, 0xEB, 0x85, 0xEA, 0x55, 0xC0, 0x06, 0x9B); +EXTERN_GUID(CLSID_CLRDebuggingLegacy, 0xDF8395B5, 0xA4BA, 0x450b, 0xA7, 0x7C, 0xA9, 0xA4, 0x77, 0x62, 0xC5, 0x20); +EXTERN_GUID(CLSID_CLRProfiling, 0xbd097ed8, 0x733e, 0x43fe, 0x8e, 0xd7, 0xa9, 0x5f, 0xf9, 0xa8, 0x44, 0x8c); +EXTERN_GUID(IID_ICLRProfiling, 0xb349abe3, 0xb56f, 0x4689, 0xbf, 0xcd, 0x76, 0xbf, 0x39, 0xd8, 0x88, 0xea); +EXTERN_GUID(IID_ICLRDebuggingLibraryProvider, 0x3151c08d, 0x4d09, 0x4f9b, 0x88, 0x38, 0x28, 0x80, 0xbf, 0x18, 0xfe, 0x51); +typedef HRESULT ( __stdcall *CLRCreateInstanceFnPtr )( + REFCLSID clsid, + REFIID riid, + LPVOID *ppInterface); + +typedef HRESULT ( __stdcall *CreateInterfaceFnPtr )( + REFCLSID clsid, + REFIID riid, + LPVOID *ppInterface); + + +typedef HRESULT ( __stdcall *CallbackThreadSetFnPtr )( void); + +typedef HRESULT ( __stdcall *CallbackThreadUnsetFnPtr )( void); + +typedef void ( __stdcall *RuntimeLoadedCallbackFnPtr )( + ICLRRuntimeInfo *pRuntimeInfo, + CallbackThreadSetFnPtr pfnCallbackThreadSet, + CallbackThreadUnsetFnPtr pfnCallbackThreadUnset); + + + +extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0000_v0_0_s_ifspec; + +#ifndef __ICLRMetaHost_INTERFACE_DEFINED__ +#define __ICLRMetaHost_INTERFACE_DEFINED__ + +/* interface ICLRMetaHost */ +/* [object][local][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRMetaHost; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("D332DB9E-B9B3-4125-8207-A14884F53216") + ICLRMetaHost : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetRuntime( + /* [in] */ LPCWSTR pwzVersion, + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppRuntime) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetVersionFromFile( + /* [in] */ LPCWSTR pwzFilePath, + /* [annotation][size_is][out] */ + _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateInstalledRuntimes( + /* [retval][out] */ IEnumUnknown **ppEnumerator) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateLoadedRuntimes( + /* [in] */ HANDLE hndProcess, + /* [retval][out] */ IEnumUnknown **ppEnumerator) = 0; + + virtual HRESULT STDMETHODCALLTYPE RequestRuntimeLoadedNotification( + /* [in] */ RuntimeLoadedCallbackFnPtr pCallbackFunction) = 0; + + virtual HRESULT STDMETHODCALLTYPE QueryLegacyV2RuntimeBinding( + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppUnk) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExitProcess( + /* [in] */ INT32 iExitCode) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRMetaHostVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRMetaHost * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRMetaHost * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRMetaHost * This); + + HRESULT ( STDMETHODCALLTYPE *GetRuntime )( + ICLRMetaHost * This, + /* [in] */ LPCWSTR pwzVersion, + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppRuntime); + + HRESULT ( STDMETHODCALLTYPE *GetVersionFromFile )( + ICLRMetaHost * This, + /* [in] */ LPCWSTR pwzFilePath, + /* [annotation][size_is][out] */ + _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBuffer); + + HRESULT ( STDMETHODCALLTYPE *EnumerateInstalledRuntimes )( + ICLRMetaHost * This, + /* [retval][out] */ IEnumUnknown **ppEnumerator); + + HRESULT ( STDMETHODCALLTYPE *EnumerateLoadedRuntimes )( + ICLRMetaHost * This, + /* [in] */ HANDLE hndProcess, + /* [retval][out] */ IEnumUnknown **ppEnumerator); + + HRESULT ( STDMETHODCALLTYPE *RequestRuntimeLoadedNotification )( + ICLRMetaHost * This, + /* [in] */ RuntimeLoadedCallbackFnPtr pCallbackFunction); + + HRESULT ( STDMETHODCALLTYPE *QueryLegacyV2RuntimeBinding )( + ICLRMetaHost * This, + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppUnk); + + HRESULT ( STDMETHODCALLTYPE *ExitProcess )( + ICLRMetaHost * This, + /* [in] */ INT32 iExitCode); + + END_INTERFACE + } ICLRMetaHostVtbl; + + interface ICLRMetaHost + { + CONST_VTBL struct ICLRMetaHostVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRMetaHost_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRMetaHost_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRMetaHost_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRMetaHost_GetRuntime(This,pwzVersion,riid,ppRuntime) \ + ( (This)->lpVtbl -> GetRuntime(This,pwzVersion,riid,ppRuntime) ) + +#define ICLRMetaHost_GetVersionFromFile(This,pwzFilePath,pwzBuffer,pcchBuffer) \ + ( (This)->lpVtbl -> GetVersionFromFile(This,pwzFilePath,pwzBuffer,pcchBuffer) ) + +#define ICLRMetaHost_EnumerateInstalledRuntimes(This,ppEnumerator) \ + ( (This)->lpVtbl -> EnumerateInstalledRuntimes(This,ppEnumerator) ) + +#define ICLRMetaHost_EnumerateLoadedRuntimes(This,hndProcess,ppEnumerator) \ + ( (This)->lpVtbl -> EnumerateLoadedRuntimes(This,hndProcess,ppEnumerator) ) + +#define ICLRMetaHost_RequestRuntimeLoadedNotification(This,pCallbackFunction) \ + ( (This)->lpVtbl -> RequestRuntimeLoadedNotification(This,pCallbackFunction) ) + +#define ICLRMetaHost_QueryLegacyV2RuntimeBinding(This,riid,ppUnk) \ + ( (This)->lpVtbl -> QueryLegacyV2RuntimeBinding(This,riid,ppUnk) ) + +#define ICLRMetaHost_ExitProcess(This,iExitCode) \ + ( (This)->lpVtbl -> ExitProcess(This,iExitCode) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRMetaHost_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_metahost_0000_0001 */ +/* [local] */ + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_metahost_0000_0001_0001 + { + METAHOST_POLICY_HIGHCOMPAT = 0, + METAHOST_POLICY_APPLY_UPGRADE_POLICY = 0x8, + METAHOST_POLICY_EMULATE_EXE_LAUNCH = 0x10, + METAHOST_POLICY_SHOW_ERROR_DIALOG = 0x20, + METAHOST_POLICY_USE_PROCESS_IMAGE_PATH = 0x40, + METAHOST_POLICY_ENSURE_SKU_SUPPORTED = 0x80, + METAHOST_POLICY_IGNORE_ERROR_MODE = 0x1000 + } METAHOST_POLICY_FLAGS; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_metahost_0000_0001_0002 + { + METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_UNSET = 0, + METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_TRUE = 0x1, + METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_FALSE = 0x2, + METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_MASK = 0x3 + } METAHOST_CONFIG_FLAGS; + + + +extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0001_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0001_v0_0_s_ifspec; + +#ifndef __ICLRMetaHostPolicy_INTERFACE_DEFINED__ +#define __ICLRMetaHostPolicy_INTERFACE_DEFINED__ + +/* interface ICLRMetaHostPolicy */ +/* [object][local][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRMetaHostPolicy; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("E2190695-77B2-492e-8E14-C4B3A7FDD593") + ICLRMetaHostPolicy : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetRequestedRuntime( + /* [in] */ METAHOST_POLICY_FLAGS dwPolicyFlags, + /* [in] */ LPCWSTR pwzBinary, + /* [in] */ IStream *pCfgStream, + /* [annotation][size_is][out][in] */ + _Inout_updates_all_opt_(*pcchVersion) LPWSTR pwzVersion, + /* [out][in] */ DWORD *pcchVersion, + /* [annotation][size_is][out] */ + _Out_writes_all_opt_(*pcchImageVersion) LPWSTR pwzImageVersion, + /* [out][in] */ DWORD *pcchImageVersion, + /* [out] */ DWORD *pdwConfigFlags, + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppRuntime) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRMetaHostPolicyVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRMetaHostPolicy * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRMetaHostPolicy * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRMetaHostPolicy * This); + + HRESULT ( STDMETHODCALLTYPE *GetRequestedRuntime )( + ICLRMetaHostPolicy * This, + /* [in] */ METAHOST_POLICY_FLAGS dwPolicyFlags, + /* [in] */ LPCWSTR pwzBinary, + /* [in] */ IStream *pCfgStream, + /* [annotation][size_is][out][in] */ + _Inout_updates_all_opt_(*pcchVersion) LPWSTR pwzVersion, + /* [out][in] */ DWORD *pcchVersion, + /* [annotation][size_is][out] */ + _Out_writes_all_opt_(*pcchImageVersion) LPWSTR pwzImageVersion, + /* [out][in] */ DWORD *pcchImageVersion, + /* [out] */ DWORD *pdwConfigFlags, + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppRuntime); + + END_INTERFACE + } ICLRMetaHostPolicyVtbl; + + interface ICLRMetaHostPolicy + { + CONST_VTBL struct ICLRMetaHostPolicyVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRMetaHostPolicy_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRMetaHostPolicy_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRMetaHostPolicy_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRMetaHostPolicy_GetRequestedRuntime(This,dwPolicyFlags,pwzBinary,pCfgStream,pwzVersion,pcchVersion,pwzImageVersion,pcchImageVersion,pdwConfigFlags,riid,ppRuntime) \ + ( (This)->lpVtbl -> GetRequestedRuntime(This,dwPolicyFlags,pwzBinary,pCfgStream,pwzVersion,pcchVersion,pwzImageVersion,pcchImageVersion,pdwConfigFlags,riid,ppRuntime) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRMetaHostPolicy_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRProfiling_INTERFACE_DEFINED__ +#define __ICLRProfiling_INTERFACE_DEFINED__ + +/* interface ICLRProfiling */ +/* [object][local][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRProfiling; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B349ABE3-B56F-4689-BFCD-76BF39D888EA") + ICLRProfiling : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE AttachProfiler( + /* [in] */ DWORD dwProfileeProcessID, + /* [in] */ DWORD dwMillisecondsMax, + /* [in] */ const CLSID *pClsidProfiler, + /* [in] */ LPCWSTR wszProfilerPath, + /* [size_is][in] */ void *pvClientData, + /* [in] */ UINT cbClientData) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRProfilingVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRProfiling * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRProfiling * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRProfiling * This); + + HRESULT ( STDMETHODCALLTYPE *AttachProfiler )( + ICLRProfiling * This, + /* [in] */ DWORD dwProfileeProcessID, + /* [in] */ DWORD dwMillisecondsMax, + /* [in] */ const CLSID *pClsidProfiler, + /* [in] */ LPCWSTR wszProfilerPath, + /* [size_is][in] */ void *pvClientData, + /* [in] */ UINT cbClientData); + + END_INTERFACE + } ICLRProfilingVtbl; + + interface ICLRProfiling + { + CONST_VTBL struct ICLRProfilingVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRProfiling_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRProfiling_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRProfiling_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRProfiling_AttachProfiler(This,dwProfileeProcessID,dwMillisecondsMax,pClsidProfiler,wszProfilerPath,pvClientData,cbClientData) \ + ( (This)->lpVtbl -> AttachProfiler(This,dwProfileeProcessID,dwMillisecondsMax,pClsidProfiler,wszProfilerPath,pvClientData,cbClientData) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRProfiling_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_metahost_0000_0003 */ +/* [local] */ + +typedef struct _CLR_DEBUGGING_VERSION + { + WORD wStructVersion; + WORD wMajor; + WORD wMinor; + WORD wBuild; + WORD wRevision; + } CLR_DEBUGGING_VERSION; + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_metahost_0000_0003_0001 + { + CLR_DEBUGGING_MANAGED_EVENT_PENDING = 1, + CLR_DEBUGGING_MANAGED_EVENT_DEBUGGER_LAUNCH = 2 + } CLR_DEBUGGING_PROCESS_FLAGS; + + + +extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0003_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0003_v0_0_s_ifspec; + +#ifndef __ICLRDebuggingLibraryProvider_INTERFACE_DEFINED__ +#define __ICLRDebuggingLibraryProvider_INTERFACE_DEFINED__ + +/* interface ICLRDebuggingLibraryProvider */ +/* [object][local][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRDebuggingLibraryProvider; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3151C08D-4D09-4f9b-8838-2880BF18FE51") + ICLRDebuggingLibraryProvider : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE ProvideLibrary( + /* [in] */ const WCHAR *pwszFileName, + /* [in] */ DWORD dwTimestamp, + /* [in] */ DWORD dwSizeOfImage, + /* [out] */ HMODULE *phModule) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRDebuggingLibraryProviderVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRDebuggingLibraryProvider * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRDebuggingLibraryProvider * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRDebuggingLibraryProvider * This); + + HRESULT ( STDMETHODCALLTYPE *ProvideLibrary )( + ICLRDebuggingLibraryProvider * This, + /* [in] */ const WCHAR *pwszFileName, + /* [in] */ DWORD dwTimestamp, + /* [in] */ DWORD dwSizeOfImage, + /* [out] */ HMODULE *phModule); + + END_INTERFACE + } ICLRDebuggingLibraryProviderVtbl; + + interface ICLRDebuggingLibraryProvider + { + CONST_VTBL struct ICLRDebuggingLibraryProviderVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRDebuggingLibraryProvider_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRDebuggingLibraryProvider_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRDebuggingLibraryProvider_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRDebuggingLibraryProvider_ProvideLibrary(This,pwszFileName,dwTimestamp,dwSizeOfImage,phModule) \ + ( (This)->lpVtbl -> ProvideLibrary(This,pwszFileName,dwTimestamp,dwSizeOfImage,phModule) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRDebuggingLibraryProvider_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRDebugging_INTERFACE_DEFINED__ +#define __ICLRDebugging_INTERFACE_DEFINED__ + +/* interface ICLRDebugging */ +/* [object][local][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRDebugging; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("D28F3C5A-9634-4206-A509-477552EEFB10") + ICLRDebugging : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE OpenVirtualProcess( + /* [in] */ ULONG64 moduleBaseAddress, + /* [in] */ IUnknown *pDataTarget, + /* [in] */ ICLRDebuggingLibraryProvider *pLibraryProvider, + /* [in] */ CLR_DEBUGGING_VERSION *pMaxDebuggerSupportedVersion, + /* [in] */ REFIID riidProcess, + /* [iid_is][out] */ IUnknown **ppProcess, + /* [out][in] */ CLR_DEBUGGING_VERSION *pVersion, + /* [out] */ CLR_DEBUGGING_PROCESS_FLAGS *pdwFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE CanUnloadNow( + HMODULE hModule) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRDebuggingVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRDebugging * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRDebugging * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRDebugging * This); + + HRESULT ( STDMETHODCALLTYPE *OpenVirtualProcess )( + ICLRDebugging * This, + /* [in] */ ULONG64 moduleBaseAddress, + /* [in] */ IUnknown *pDataTarget, + /* [in] */ ICLRDebuggingLibraryProvider *pLibraryProvider, + /* [in] */ CLR_DEBUGGING_VERSION *pMaxDebuggerSupportedVersion, + /* [in] */ REFIID riidProcess, + /* [iid_is][out] */ IUnknown **ppProcess, + /* [out][in] */ CLR_DEBUGGING_VERSION *pVersion, + /* [out] */ CLR_DEBUGGING_PROCESS_FLAGS *pdwFlags); + + HRESULT ( STDMETHODCALLTYPE *CanUnloadNow )( + ICLRDebugging * This, + HMODULE hModule); + + END_INTERFACE + } ICLRDebuggingVtbl; + + interface ICLRDebugging + { + CONST_VTBL struct ICLRDebuggingVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRDebugging_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRDebugging_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRDebugging_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRDebugging_OpenVirtualProcess(This,moduleBaseAddress,pDataTarget,pLibraryProvider,pMaxDebuggerSupportedVersion,riidProcess,ppProcess,pVersion,pdwFlags) \ + ( (This)->lpVtbl -> OpenVirtualProcess(This,moduleBaseAddress,pDataTarget,pLibraryProvider,pMaxDebuggerSupportedVersion,riidProcess,ppProcess,pVersion,pdwFlags) ) + +#define ICLRDebugging_CanUnloadNow(This,hModule) \ + ( (This)->lpVtbl -> CanUnloadNow(This,hModule) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRDebugging_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRRuntimeInfo_INTERFACE_DEFINED__ +#define __ICLRRuntimeInfo_INTERFACE_DEFINED__ + +/* interface ICLRRuntimeInfo */ +/* [object][local][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRRuntimeInfo; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("BD39D1D2-BA2F-486a-89B0-B4B0CB466891") + ICLRRuntimeInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetVersionString( + /* [annotation][size_is][out] */ + _Out_writes_all_opt_(*pcchBuffer) LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRuntimeDirectory( + /* [annotation][size_is][out] */ + _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsLoaded( + /* [in] */ HANDLE hndProcess, + /* [retval][out] */ BOOL *pbLoaded) = 0; + + virtual HRESULT STDMETHODCALLTYPE LoadErrorString( + /* [in] */ UINT iResourceID, + /* [annotation][size_is][out] */ + _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBuffer, + /* [lcid][in] */ LONG iLocaleID) = 0; + + virtual HRESULT STDMETHODCALLTYPE LoadLibrary( + /* [in] */ LPCWSTR pwzDllName, + /* [retval][out] */ HMODULE *phndModule) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetProcAddress( + /* [in] */ LPCSTR pszProcName, + /* [retval][out] */ LPVOID *ppProc) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetInterface( + /* [in] */ REFCLSID rclsid, + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppUnk) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsLoadable( + /* [retval][out] */ BOOL *pbLoadable) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetDefaultStartupFlags( + /* [in] */ DWORD dwStartupFlags, + /* [in] */ LPCWSTR pwzHostConfigFile) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDefaultStartupFlags( + /* [out] */ DWORD *pdwStartupFlags, + /* [annotation][size_is][out] */ + _Out_writes_all_opt_(*pcchHostConfigFile) LPWSTR pwzHostConfigFile, + /* [out][in] */ DWORD *pcchHostConfigFile) = 0; + + virtual HRESULT STDMETHODCALLTYPE BindAsLegacyV2Runtime( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsStarted( + /* [out] */ BOOL *pbStarted, + /* [out] */ DWORD *pdwStartupFlags) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRRuntimeInfoVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRRuntimeInfo * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRRuntimeInfo * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRRuntimeInfo * This); + + HRESULT ( STDMETHODCALLTYPE *GetVersionString )( + ICLRRuntimeInfo * This, + /* [annotation][size_is][out] */ + _Out_writes_all_opt_(*pcchBuffer) LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBuffer); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeDirectory )( + ICLRRuntimeInfo * This, + /* [annotation][size_is][out] */ + _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBuffer); + + HRESULT ( STDMETHODCALLTYPE *IsLoaded )( + ICLRRuntimeInfo * This, + /* [in] */ HANDLE hndProcess, + /* [retval][out] */ BOOL *pbLoaded); + + HRESULT ( STDMETHODCALLTYPE *LoadErrorString )( + ICLRRuntimeInfo * This, + /* [in] */ UINT iResourceID, + /* [annotation][size_is][out] */ + _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBuffer, + /* [lcid][in] */ LONG iLocaleID); + + HRESULT ( STDMETHODCALLTYPE *LoadLibrary )( + ICLRRuntimeInfo * This, + /* [in] */ LPCWSTR pwzDllName, + /* [retval][out] */ HMODULE *phndModule); + + HRESULT ( STDMETHODCALLTYPE *GetProcAddress )( + ICLRRuntimeInfo * This, + /* [in] */ LPCSTR pszProcName, + /* [retval][out] */ LPVOID *ppProc); + + HRESULT ( STDMETHODCALLTYPE *GetInterface )( + ICLRRuntimeInfo * This, + /* [in] */ REFCLSID rclsid, + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppUnk); + + HRESULT ( STDMETHODCALLTYPE *IsLoadable )( + ICLRRuntimeInfo * This, + /* [retval][out] */ BOOL *pbLoadable); + + HRESULT ( STDMETHODCALLTYPE *SetDefaultStartupFlags )( + ICLRRuntimeInfo * This, + /* [in] */ DWORD dwStartupFlags, + /* [in] */ LPCWSTR pwzHostConfigFile); + + HRESULT ( STDMETHODCALLTYPE *GetDefaultStartupFlags )( + ICLRRuntimeInfo * This, + /* [out] */ DWORD *pdwStartupFlags, + /* [annotation][size_is][out] */ + _Out_writes_all_opt_(*pcchHostConfigFile) LPWSTR pwzHostConfigFile, + /* [out][in] */ DWORD *pcchHostConfigFile); + + HRESULT ( STDMETHODCALLTYPE *BindAsLegacyV2Runtime )( + ICLRRuntimeInfo * This); + + HRESULT ( STDMETHODCALLTYPE *IsStarted )( + ICLRRuntimeInfo * This, + /* [out] */ BOOL *pbStarted, + /* [out] */ DWORD *pdwStartupFlags); + + END_INTERFACE + } ICLRRuntimeInfoVtbl; + + interface ICLRRuntimeInfo + { + CONST_VTBL struct ICLRRuntimeInfoVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRRuntimeInfo_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRRuntimeInfo_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRRuntimeInfo_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRRuntimeInfo_GetVersionString(This,pwzBuffer,pcchBuffer) \ + ( (This)->lpVtbl -> GetVersionString(This,pwzBuffer,pcchBuffer) ) + +#define ICLRRuntimeInfo_GetRuntimeDirectory(This,pwzBuffer,pcchBuffer) \ + ( (This)->lpVtbl -> GetRuntimeDirectory(This,pwzBuffer,pcchBuffer) ) + +#define ICLRRuntimeInfo_IsLoaded(This,hndProcess,pbLoaded) \ + ( (This)->lpVtbl -> IsLoaded(This,hndProcess,pbLoaded) ) + +#define ICLRRuntimeInfo_LoadErrorString(This,iResourceID,pwzBuffer,pcchBuffer,iLocaleID) \ + ( (This)->lpVtbl -> LoadErrorString(This,iResourceID,pwzBuffer,pcchBuffer,iLocaleID) ) + +#define ICLRRuntimeInfo_LoadLibrary(This,pwzDllName,phndModule) \ + ( (This)->lpVtbl -> LoadLibrary(This,pwzDllName,phndModule) ) + +#define ICLRRuntimeInfo_GetProcAddress(This,pszProcName,ppProc) \ + ( (This)->lpVtbl -> GetProcAddress(This,pszProcName,ppProc) ) + +#define ICLRRuntimeInfo_GetInterface(This,rclsid,riid,ppUnk) \ + ( (This)->lpVtbl -> GetInterface(This,rclsid,riid,ppUnk) ) + +#define ICLRRuntimeInfo_IsLoadable(This,pbLoadable) \ + ( (This)->lpVtbl -> IsLoadable(This,pbLoadable) ) + +#define ICLRRuntimeInfo_SetDefaultStartupFlags(This,dwStartupFlags,pwzHostConfigFile) \ + ( (This)->lpVtbl -> SetDefaultStartupFlags(This,dwStartupFlags,pwzHostConfigFile) ) + +#define ICLRRuntimeInfo_GetDefaultStartupFlags(This,pdwStartupFlags,pwzHostConfigFile,pcchHostConfigFile) \ + ( (This)->lpVtbl -> GetDefaultStartupFlags(This,pdwStartupFlags,pwzHostConfigFile,pcchHostConfigFile) ) + +#define ICLRRuntimeInfo_BindAsLegacyV2Runtime(This) \ + ( (This)->lpVtbl -> BindAsLegacyV2Runtime(This) ) + +#define ICLRRuntimeInfo_IsStarted(This,pbStarted,pdwStartupFlags) \ + ( (This)->lpVtbl -> IsStarted(This,pbStarted,pdwStartupFlags) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRRuntimeInfo_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRStrongName_INTERFACE_DEFINED__ +#define __ICLRStrongName_INTERFACE_DEFINED__ + +/* interface ICLRStrongName */ +/* [object][local][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRStrongName; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9FD93CCF-3280-4391-B3A9-96E1CDE77C8D") + ICLRStrongName : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetHashFromAssemblyFile( + /* [in] */ LPCSTR pszFilePath, + /* [out][in] */ unsigned int *piHashAlg, + /* [length_is][size_is][out] */ BYTE *pbHash, + /* [in] */ DWORD cchHash, + /* [out] */ DWORD *pchHash) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHashFromAssemblyFileW( + /* [in] */ LPCWSTR pwzFilePath, + /* [out][in] */ unsigned int *piHashAlg, + /* [length_is][size_is][out] */ BYTE *pbHash, + /* [in] */ DWORD cchHash, + /* [out] */ DWORD *pchHash) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHashFromBlob( + /* [in] */ BYTE *pbBlob, + /* [in] */ DWORD cchBlob, + /* [out][in] */ unsigned int *piHashAlg, + /* [length_is][size_is][out] */ BYTE *pbHash, + /* [in] */ DWORD cchHash, + /* [out] */ DWORD *pchHash) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHashFromFile( + /* [in] */ LPCSTR pszFilePath, + /* [out][in] */ unsigned int *piHashAlg, + /* [length_is][size_is][out] */ BYTE *pbHash, + /* [in] */ DWORD cchHash, + /* [out] */ DWORD *pchHash) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHashFromFileW( + /* [in] */ LPCWSTR pwzFilePath, + /* [out][in] */ unsigned int *piHashAlg, + /* [length_is][size_is][out] */ BYTE *pbHash, + /* [in] */ DWORD cchHash, + /* [out] */ DWORD *pchHash) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHashFromHandle( + /* [in] */ HANDLE hFile, + /* [out][in] */ unsigned int *piHashAlg, + /* [length_is][size_is][out] */ BYTE *pbHash, + /* [in] */ DWORD cchHash, + /* [out] */ DWORD *pchHash) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameCompareAssemblies( + /* [in] */ LPCWSTR pwzAssembly1, + /* [in] */ LPCWSTR pwzAssembly2, + /* [retval][out] */ DWORD *pdwResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameFreeBuffer( + /* [in] */ BYTE *pbMemory) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameGetBlob( + /* [in] */ LPCWSTR pwzFilePath, + /* [length_is][size_is][out][in] */ BYTE *pbBlob, + /* [out][in] */ DWORD *pcbBlob) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameGetBlobFromImage( + /* [size_is][in] */ BYTE *pbBase, + /* [in] */ DWORD dwLength, + /* [length_is][size_is][out] */ BYTE *pbBlob, + /* [out][in] */ DWORD *pcbBlob) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameGetPublicKey( + /* [in] */ LPCWSTR pwzKeyContainer, + /* [in] */ BYTE *pbKeyBlob, + /* [in] */ ULONG cbKeyBlob, + /* [out] */ BYTE **ppbPublicKeyBlob, + /* [out] */ ULONG *pcbPublicKeyBlob) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameHashSize( + /* [in] */ ULONG ulHashAlg, + /* [retval][out] */ DWORD *pcbSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameKeyDelete( + /* [in] */ LPCWSTR pwzKeyContainer) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameKeyGen( + /* [in] */ LPCWSTR pwzKeyContainer, + /* [in] */ DWORD dwFlags, + /* [out] */ BYTE **ppbKeyBlob, + /* [out] */ ULONG *pcbKeyBlob) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameKeyGenEx( + /* [in] */ LPCWSTR pwzKeyContainer, + /* [in] */ DWORD dwFlags, + /* [in] */ DWORD dwKeySize, + /* [out] */ BYTE **ppbKeyBlob, + /* [out] */ ULONG *pcbKeyBlob) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameKeyInstall( + /* [in] */ LPCWSTR pwzKeyContainer, + /* [in] */ BYTE *pbKeyBlob, + /* [in] */ ULONG cbKeyBlob) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameSignatureGeneration( + /* [in] */ LPCWSTR pwzFilePath, + /* [in] */ LPCWSTR pwzKeyContainer, + /* [in] */ BYTE *pbKeyBlob, + /* [in] */ ULONG cbKeyBlob, + /* [out] */ BYTE **ppbSignatureBlob, + /* [out] */ ULONG *pcbSignatureBlob) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameSignatureGenerationEx( + /* [in] */ LPCWSTR wszFilePath, + /* [in] */ LPCWSTR wszKeyContainer, + /* [in] */ BYTE *pbKeyBlob, + /* [in] */ ULONG cbKeyBlob, + /* [out] */ BYTE **ppbSignatureBlob, + /* [out] */ ULONG *pcbSignatureBlob, + /* [in] */ DWORD dwFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameSignatureSize( + /* [in] */ BYTE *pbPublicKeyBlob, + /* [in] */ ULONG cbPublicKeyBlob, + /* [in] */ DWORD *pcbSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameSignatureVerification( + /* [in] */ LPCWSTR pwzFilePath, + /* [in] */ DWORD dwInFlags, + /* [retval][out] */ DWORD *pdwOutFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameSignatureVerificationEx( + /* [in] */ LPCWSTR pwzFilePath, + /* [in] */ BOOLEAN fForceVerification, + /* [retval][out] */ BOOLEAN *pfWasVerified) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameSignatureVerificationFromImage( + /* [in] */ BYTE *pbBase, + /* [in] */ DWORD dwLength, + /* [in] */ DWORD dwInFlags, + /* [retval][out] */ DWORD *pdwOutFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameTokenFromAssembly( + /* [in] */ LPCWSTR pwzFilePath, + /* [out] */ BYTE **ppbStrongNameToken, + /* [out] */ ULONG *pcbStrongNameToken) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameTokenFromAssemblyEx( + /* [in] */ LPCWSTR pwzFilePath, + /* [out] */ BYTE **ppbStrongNameToken, + /* [out] */ ULONG *pcbStrongNameToken, + /* [out] */ BYTE **ppbPublicKeyBlob, + /* [out] */ ULONG *pcbPublicKeyBlob) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameTokenFromPublicKey( + /* [in] */ BYTE *pbPublicKeyBlob, + /* [in] */ ULONG cbPublicKeyBlob, + /* [out] */ BYTE **ppbStrongNameToken, + /* [out] */ ULONG *pcbStrongNameToken) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRStrongNameVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRStrongName * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRStrongName * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRStrongName * This); + + HRESULT ( STDMETHODCALLTYPE *GetHashFromAssemblyFile )( + ICLRStrongName * This, + /* [in] */ LPCSTR pszFilePath, + /* [out][in] */ unsigned int *piHashAlg, + /* [length_is][size_is][out] */ BYTE *pbHash, + /* [in] */ DWORD cchHash, + /* [out] */ DWORD *pchHash); + + HRESULT ( STDMETHODCALLTYPE *GetHashFromAssemblyFileW )( + ICLRStrongName * This, + /* [in] */ LPCWSTR pwzFilePath, + /* [out][in] */ unsigned int *piHashAlg, + /* [length_is][size_is][out] */ BYTE *pbHash, + /* [in] */ DWORD cchHash, + /* [out] */ DWORD *pchHash); + + HRESULT ( STDMETHODCALLTYPE *GetHashFromBlob )( + ICLRStrongName * This, + /* [in] */ BYTE *pbBlob, + /* [in] */ DWORD cchBlob, + /* [out][in] */ unsigned int *piHashAlg, + /* [length_is][size_is][out] */ BYTE *pbHash, + /* [in] */ DWORD cchHash, + /* [out] */ DWORD *pchHash); + + HRESULT ( STDMETHODCALLTYPE *GetHashFromFile )( + ICLRStrongName * This, + /* [in] */ LPCSTR pszFilePath, + /* [out][in] */ unsigned int *piHashAlg, + /* [length_is][size_is][out] */ BYTE *pbHash, + /* [in] */ DWORD cchHash, + /* [out] */ DWORD *pchHash); + + HRESULT ( STDMETHODCALLTYPE *GetHashFromFileW )( + ICLRStrongName * This, + /* [in] */ LPCWSTR pwzFilePath, + /* [out][in] */ unsigned int *piHashAlg, + /* [length_is][size_is][out] */ BYTE *pbHash, + /* [in] */ DWORD cchHash, + /* [out] */ DWORD *pchHash); + + HRESULT ( STDMETHODCALLTYPE *GetHashFromHandle )( + ICLRStrongName * This, + /* [in] */ HANDLE hFile, + /* [out][in] */ unsigned int *piHashAlg, + /* [length_is][size_is][out] */ BYTE *pbHash, + /* [in] */ DWORD cchHash, + /* [out] */ DWORD *pchHash); + + HRESULT ( STDMETHODCALLTYPE *StrongNameCompareAssemblies )( + ICLRStrongName * This, + /* [in] */ LPCWSTR pwzAssembly1, + /* [in] */ LPCWSTR pwzAssembly2, + /* [retval][out] */ DWORD *pdwResult); + + HRESULT ( STDMETHODCALLTYPE *StrongNameFreeBuffer )( + ICLRStrongName * This, + /* [in] */ BYTE *pbMemory); + + HRESULT ( STDMETHODCALLTYPE *StrongNameGetBlob )( + ICLRStrongName * This, + /* [in] */ LPCWSTR pwzFilePath, + /* [length_is][size_is][out][in] */ BYTE *pbBlob, + /* [out][in] */ DWORD *pcbBlob); + + HRESULT ( STDMETHODCALLTYPE *StrongNameGetBlobFromImage )( + ICLRStrongName * This, + /* [size_is][in] */ BYTE *pbBase, + /* [in] */ DWORD dwLength, + /* [length_is][size_is][out] */ BYTE *pbBlob, + /* [out][in] */ DWORD *pcbBlob); + + HRESULT ( STDMETHODCALLTYPE *StrongNameGetPublicKey )( + ICLRStrongName * This, + /* [in] */ LPCWSTR pwzKeyContainer, + /* [in] */ BYTE *pbKeyBlob, + /* [in] */ ULONG cbKeyBlob, + /* [out] */ BYTE **ppbPublicKeyBlob, + /* [out] */ ULONG *pcbPublicKeyBlob); + + HRESULT ( STDMETHODCALLTYPE *StrongNameHashSize )( + ICLRStrongName * This, + /* [in] */ ULONG ulHashAlg, + /* [retval][out] */ DWORD *pcbSize); + + HRESULT ( STDMETHODCALLTYPE *StrongNameKeyDelete )( + ICLRStrongName * This, + /* [in] */ LPCWSTR pwzKeyContainer); + + HRESULT ( STDMETHODCALLTYPE *StrongNameKeyGen )( + ICLRStrongName * This, + /* [in] */ LPCWSTR pwzKeyContainer, + /* [in] */ DWORD dwFlags, + /* [out] */ BYTE **ppbKeyBlob, + /* [out] */ ULONG *pcbKeyBlob); + + HRESULT ( STDMETHODCALLTYPE *StrongNameKeyGenEx )( + ICLRStrongName * This, + /* [in] */ LPCWSTR pwzKeyContainer, + /* [in] */ DWORD dwFlags, + /* [in] */ DWORD dwKeySize, + /* [out] */ BYTE **ppbKeyBlob, + /* [out] */ ULONG *pcbKeyBlob); + + HRESULT ( STDMETHODCALLTYPE *StrongNameKeyInstall )( + ICLRStrongName * This, + /* [in] */ LPCWSTR pwzKeyContainer, + /* [in] */ BYTE *pbKeyBlob, + /* [in] */ ULONG cbKeyBlob); + + HRESULT ( STDMETHODCALLTYPE *StrongNameSignatureGeneration )( + ICLRStrongName * This, + /* [in] */ LPCWSTR pwzFilePath, + /* [in] */ LPCWSTR pwzKeyContainer, + /* [in] */ BYTE *pbKeyBlob, + /* [in] */ ULONG cbKeyBlob, + /* [out] */ BYTE **ppbSignatureBlob, + /* [out] */ ULONG *pcbSignatureBlob); + + HRESULT ( STDMETHODCALLTYPE *StrongNameSignatureGenerationEx )( + ICLRStrongName * This, + /* [in] */ LPCWSTR wszFilePath, + /* [in] */ LPCWSTR wszKeyContainer, + /* [in] */ BYTE *pbKeyBlob, + /* [in] */ ULONG cbKeyBlob, + /* [out] */ BYTE **ppbSignatureBlob, + /* [out] */ ULONG *pcbSignatureBlob, + /* [in] */ DWORD dwFlags); + + HRESULT ( STDMETHODCALLTYPE *StrongNameSignatureSize )( + ICLRStrongName * This, + /* [in] */ BYTE *pbPublicKeyBlob, + /* [in] */ ULONG cbPublicKeyBlob, + /* [in] */ DWORD *pcbSize); + + HRESULT ( STDMETHODCALLTYPE *StrongNameSignatureVerification )( + ICLRStrongName * This, + /* [in] */ LPCWSTR pwzFilePath, + /* [in] */ DWORD dwInFlags, + /* [retval][out] */ DWORD *pdwOutFlags); + + HRESULT ( STDMETHODCALLTYPE *StrongNameSignatureVerificationEx )( + ICLRStrongName * This, + /* [in] */ LPCWSTR pwzFilePath, + /* [in] */ BOOLEAN fForceVerification, + /* [retval][out] */ BOOLEAN *pfWasVerified); + + HRESULT ( STDMETHODCALLTYPE *StrongNameSignatureVerificationFromImage )( + ICLRStrongName * This, + /* [in] */ BYTE *pbBase, + /* [in] */ DWORD dwLength, + /* [in] */ DWORD dwInFlags, + /* [retval][out] */ DWORD *pdwOutFlags); + + HRESULT ( STDMETHODCALLTYPE *StrongNameTokenFromAssembly )( + ICLRStrongName * This, + /* [in] */ LPCWSTR pwzFilePath, + /* [out] */ BYTE **ppbStrongNameToken, + /* [out] */ ULONG *pcbStrongNameToken); + + HRESULT ( STDMETHODCALLTYPE *StrongNameTokenFromAssemblyEx )( + ICLRStrongName * This, + /* [in] */ LPCWSTR pwzFilePath, + /* [out] */ BYTE **ppbStrongNameToken, + /* [out] */ ULONG *pcbStrongNameToken, + /* [out] */ BYTE **ppbPublicKeyBlob, + /* [out] */ ULONG *pcbPublicKeyBlob); + + HRESULT ( STDMETHODCALLTYPE *StrongNameTokenFromPublicKey )( + ICLRStrongName * This, + /* [in] */ BYTE *pbPublicKeyBlob, + /* [in] */ ULONG cbPublicKeyBlob, + /* [out] */ BYTE **ppbStrongNameToken, + /* [out] */ ULONG *pcbStrongNameToken); + + END_INTERFACE + } ICLRStrongNameVtbl; + + interface ICLRStrongName + { + CONST_VTBL struct ICLRStrongNameVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRStrongName_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRStrongName_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRStrongName_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRStrongName_GetHashFromAssemblyFile(This,pszFilePath,piHashAlg,pbHash,cchHash,pchHash) \ + ( (This)->lpVtbl -> GetHashFromAssemblyFile(This,pszFilePath,piHashAlg,pbHash,cchHash,pchHash) ) + +#define ICLRStrongName_GetHashFromAssemblyFileW(This,pwzFilePath,piHashAlg,pbHash,cchHash,pchHash) \ + ( (This)->lpVtbl -> GetHashFromAssemblyFileW(This,pwzFilePath,piHashAlg,pbHash,cchHash,pchHash) ) + +#define ICLRStrongName_GetHashFromBlob(This,pbBlob,cchBlob,piHashAlg,pbHash,cchHash,pchHash) \ + ( (This)->lpVtbl -> GetHashFromBlob(This,pbBlob,cchBlob,piHashAlg,pbHash,cchHash,pchHash) ) + +#define ICLRStrongName_GetHashFromFile(This,pszFilePath,piHashAlg,pbHash,cchHash,pchHash) \ + ( (This)->lpVtbl -> GetHashFromFile(This,pszFilePath,piHashAlg,pbHash,cchHash,pchHash) ) + +#define ICLRStrongName_GetHashFromFileW(This,pwzFilePath,piHashAlg,pbHash,cchHash,pchHash) \ + ( (This)->lpVtbl -> GetHashFromFileW(This,pwzFilePath,piHashAlg,pbHash,cchHash,pchHash) ) + +#define ICLRStrongName_GetHashFromHandle(This,hFile,piHashAlg,pbHash,cchHash,pchHash) \ + ( (This)->lpVtbl -> GetHashFromHandle(This,hFile,piHashAlg,pbHash,cchHash,pchHash) ) + +#define ICLRStrongName_StrongNameCompareAssemblies(This,pwzAssembly1,pwzAssembly2,pdwResult) \ + ( (This)->lpVtbl -> StrongNameCompareAssemblies(This,pwzAssembly1,pwzAssembly2,pdwResult) ) + +#define ICLRStrongName_StrongNameFreeBuffer(This,pbMemory) \ + ( (This)->lpVtbl -> StrongNameFreeBuffer(This,pbMemory) ) + +#define ICLRStrongName_StrongNameGetBlob(This,pwzFilePath,pbBlob,pcbBlob) \ + ( (This)->lpVtbl -> StrongNameGetBlob(This,pwzFilePath,pbBlob,pcbBlob) ) + +#define ICLRStrongName_StrongNameGetBlobFromImage(This,pbBase,dwLength,pbBlob,pcbBlob) \ + ( (This)->lpVtbl -> StrongNameGetBlobFromImage(This,pbBase,dwLength,pbBlob,pcbBlob) ) + +#define ICLRStrongName_StrongNameGetPublicKey(This,pwzKeyContainer,pbKeyBlob,cbKeyBlob,ppbPublicKeyBlob,pcbPublicKeyBlob) \ + ( (This)->lpVtbl -> StrongNameGetPublicKey(This,pwzKeyContainer,pbKeyBlob,cbKeyBlob,ppbPublicKeyBlob,pcbPublicKeyBlob) ) + +#define ICLRStrongName_StrongNameHashSize(This,ulHashAlg,pcbSize) \ + ( (This)->lpVtbl -> StrongNameHashSize(This,ulHashAlg,pcbSize) ) + +#define ICLRStrongName_StrongNameKeyDelete(This,pwzKeyContainer) \ + ( (This)->lpVtbl -> StrongNameKeyDelete(This,pwzKeyContainer) ) + +#define ICLRStrongName_StrongNameKeyGen(This,pwzKeyContainer,dwFlags,ppbKeyBlob,pcbKeyBlob) \ + ( (This)->lpVtbl -> StrongNameKeyGen(This,pwzKeyContainer,dwFlags,ppbKeyBlob,pcbKeyBlob) ) + +#define ICLRStrongName_StrongNameKeyGenEx(This,pwzKeyContainer,dwFlags,dwKeySize,ppbKeyBlob,pcbKeyBlob) \ + ( (This)->lpVtbl -> StrongNameKeyGenEx(This,pwzKeyContainer,dwFlags,dwKeySize,ppbKeyBlob,pcbKeyBlob) ) + +#define ICLRStrongName_StrongNameKeyInstall(This,pwzKeyContainer,pbKeyBlob,cbKeyBlob) \ + ( (This)->lpVtbl -> StrongNameKeyInstall(This,pwzKeyContainer,pbKeyBlob,cbKeyBlob) ) + +#define ICLRStrongName_StrongNameSignatureGeneration(This,pwzFilePath,pwzKeyContainer,pbKeyBlob,cbKeyBlob,ppbSignatureBlob,pcbSignatureBlob) \ + ( (This)->lpVtbl -> StrongNameSignatureGeneration(This,pwzFilePath,pwzKeyContainer,pbKeyBlob,cbKeyBlob,ppbSignatureBlob,pcbSignatureBlob) ) + +#define ICLRStrongName_StrongNameSignatureGenerationEx(This,wszFilePath,wszKeyContainer,pbKeyBlob,cbKeyBlob,ppbSignatureBlob,pcbSignatureBlob,dwFlags) \ + ( (This)->lpVtbl -> StrongNameSignatureGenerationEx(This,wszFilePath,wszKeyContainer,pbKeyBlob,cbKeyBlob,ppbSignatureBlob,pcbSignatureBlob,dwFlags) ) + +#define ICLRStrongName_StrongNameSignatureSize(This,pbPublicKeyBlob,cbPublicKeyBlob,pcbSize) \ + ( (This)->lpVtbl -> StrongNameSignatureSize(This,pbPublicKeyBlob,cbPublicKeyBlob,pcbSize) ) + +#define ICLRStrongName_StrongNameSignatureVerification(This,pwzFilePath,dwInFlags,pdwOutFlags) \ + ( (This)->lpVtbl -> StrongNameSignatureVerification(This,pwzFilePath,dwInFlags,pdwOutFlags) ) + +#define ICLRStrongName_StrongNameSignatureVerificationEx(This,pwzFilePath,fForceVerification,pfWasVerified) \ + ( (This)->lpVtbl -> StrongNameSignatureVerificationEx(This,pwzFilePath,fForceVerification,pfWasVerified) ) + +#define ICLRStrongName_StrongNameSignatureVerificationFromImage(This,pbBase,dwLength,dwInFlags,pdwOutFlags) \ + ( (This)->lpVtbl -> StrongNameSignatureVerificationFromImage(This,pbBase,dwLength,dwInFlags,pdwOutFlags) ) + +#define ICLRStrongName_StrongNameTokenFromAssembly(This,pwzFilePath,ppbStrongNameToken,pcbStrongNameToken) \ + ( (This)->lpVtbl -> StrongNameTokenFromAssembly(This,pwzFilePath,ppbStrongNameToken,pcbStrongNameToken) ) + +#define ICLRStrongName_StrongNameTokenFromAssemblyEx(This,pwzFilePath,ppbStrongNameToken,pcbStrongNameToken,ppbPublicKeyBlob,pcbPublicKeyBlob) \ + ( (This)->lpVtbl -> StrongNameTokenFromAssemblyEx(This,pwzFilePath,ppbStrongNameToken,pcbStrongNameToken,ppbPublicKeyBlob,pcbPublicKeyBlob) ) + +#define ICLRStrongName_StrongNameTokenFromPublicKey(This,pbPublicKeyBlob,cbPublicKeyBlob,ppbStrongNameToken,pcbStrongNameToken) \ + ( (This)->lpVtbl -> StrongNameTokenFromPublicKey(This,pbPublicKeyBlob,cbPublicKeyBlob,ppbStrongNameToken,pcbStrongNameToken) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRStrongName_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRStrongName2_INTERFACE_DEFINED__ +#define __ICLRStrongName2_INTERFACE_DEFINED__ + +/* interface ICLRStrongName2 */ +/* [object][local][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRStrongName2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("C22ED5C5-4B59-4975-90EB-85EA55C0069B") + ICLRStrongName2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE StrongNameGetPublicKeyEx( + /* [in] */ LPCWSTR pwzKeyContainer, + /* [in] */ BYTE *pbKeyBlob, + /* [in] */ ULONG cbKeyBlob, + /* [out] */ BYTE **ppbPublicKeyBlob, + /* [out] */ ULONG *pcbPublicKeyBlob, + /* [in] */ ULONG uHashAlgId, + /* [in] */ ULONG uReserved) = 0; + + virtual HRESULT STDMETHODCALLTYPE StrongNameSignatureVerificationEx2( + /* [in] */ LPCWSTR wszFilePath, + /* [in] */ BOOLEAN fForceVerification, + /* [in] */ BYTE *pbEcmaPublicKey, + /* [in] */ DWORD cbEcmaPublicKey, + /* [out] */ BOOLEAN *pfWasVerified) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRStrongName2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRStrongName2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRStrongName2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRStrongName2 * This); + + HRESULT ( STDMETHODCALLTYPE *StrongNameGetPublicKeyEx )( + ICLRStrongName2 * This, + /* [in] */ LPCWSTR pwzKeyContainer, + /* [in] */ BYTE *pbKeyBlob, + /* [in] */ ULONG cbKeyBlob, + /* [out] */ BYTE **ppbPublicKeyBlob, + /* [out] */ ULONG *pcbPublicKeyBlob, + /* [in] */ ULONG uHashAlgId, + /* [in] */ ULONG uReserved); + + HRESULT ( STDMETHODCALLTYPE *StrongNameSignatureVerificationEx2 )( + ICLRStrongName2 * This, + /* [in] */ LPCWSTR wszFilePath, + /* [in] */ BOOLEAN fForceVerification, + /* [in] */ BYTE *pbEcmaPublicKey, + /* [in] */ DWORD cbEcmaPublicKey, + /* [out] */ BOOLEAN *pfWasVerified); + + END_INTERFACE + } ICLRStrongName2Vtbl; + + interface ICLRStrongName2 + { + CONST_VTBL struct ICLRStrongName2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRStrongName2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRStrongName2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRStrongName2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRStrongName2_StrongNameGetPublicKeyEx(This,pwzKeyContainer,pbKeyBlob,cbKeyBlob,ppbPublicKeyBlob,pcbPublicKeyBlob,uHashAlgId,uReserved) \ + ( (This)->lpVtbl -> StrongNameGetPublicKeyEx(This,pwzKeyContainer,pbKeyBlob,cbKeyBlob,ppbPublicKeyBlob,pcbPublicKeyBlob,uHashAlgId,uReserved) ) + +#define ICLRStrongName2_StrongNameSignatureVerificationEx2(This,wszFilePath,fForceVerification,pbEcmaPublicKey,cbEcmaPublicKey,pfWasVerified) \ + ( (This)->lpVtbl -> StrongNameSignatureVerificationEx2(This,wszFilePath,fForceVerification,pbEcmaPublicKey,cbEcmaPublicKey,pfWasVerified) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRStrongName2_INTERFACE_DEFINED__ */ + + + +#ifndef __CLRMetaHost_LIBRARY_DEFINED__ +#define __CLRMetaHost_LIBRARY_DEFINED__ + +/* library CLRMetaHost */ +/* [version][uuid] */ + + + + + + + + + +EXTERN_C const IID LIBID_CLRMetaHost; +#endif /* __CLRMetaHost_LIBRARY_DEFINED__ */ + +/* interface __MIDL_itf_metahost_0000_0009 */ +/* [local] */ + +#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + + +extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0009_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0009_v0_0_s_ifspec; + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/third/Blackbone/src/3rd_party/mscoree.h b/third/Blackbone/src/3rd_party/mscoree.h new file mode 100644 index 0000000000000000000000000000000000000000..acbc4815dd5e95565f2e2a3ea22799a00db532d2 --- /dev/null +++ b/third/Blackbone/src/3rd_party/mscoree.h @@ -0,0 +1,10074 @@ +// +// 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 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 +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __mscoree_h__ +#define __mscoree_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __IObjectHandle_FWD_DEFINED__ +#define __IObjectHandle_FWD_DEFINED__ +typedef interface IObjectHandle IObjectHandle; +#endif /* __IObjectHandle_FWD_DEFINED__ */ + + +#ifndef __IAppDomainBinding_FWD_DEFINED__ +#define __IAppDomainBinding_FWD_DEFINED__ +typedef interface IAppDomainBinding IAppDomainBinding; +#endif /* __IAppDomainBinding_FWD_DEFINED__ */ + + +#ifndef __IGCThreadControl_FWD_DEFINED__ +#define __IGCThreadControl_FWD_DEFINED__ +typedef interface IGCThreadControl IGCThreadControl; +#endif /* __IGCThreadControl_FWD_DEFINED__ */ + + +#ifndef __IGCHostControl_FWD_DEFINED__ +#define __IGCHostControl_FWD_DEFINED__ +typedef interface IGCHostControl IGCHostControl; +#endif /* __IGCHostControl_FWD_DEFINED__ */ + + +#ifndef __ICorThreadpool_FWD_DEFINED__ +#define __ICorThreadpool_FWD_DEFINED__ +typedef interface ICorThreadpool ICorThreadpool; +#endif /* __ICorThreadpool_FWD_DEFINED__ */ + + +#ifndef __IDebuggerThreadControl_FWD_DEFINED__ +#define __IDebuggerThreadControl_FWD_DEFINED__ +typedef interface IDebuggerThreadControl IDebuggerThreadControl; +#endif /* __IDebuggerThreadControl_FWD_DEFINED__ */ + + +#ifndef __IDebuggerInfo_FWD_DEFINED__ +#define __IDebuggerInfo_FWD_DEFINED__ +typedef interface IDebuggerInfo IDebuggerInfo; +#endif /* __IDebuggerInfo_FWD_DEFINED__ */ + + +#ifndef __ICorConfiguration_FWD_DEFINED__ +#define __ICorConfiguration_FWD_DEFINED__ +typedef interface ICorConfiguration ICorConfiguration; +#endif /* __ICorConfiguration_FWD_DEFINED__ */ + + +#ifndef __ICorRuntimeHost_FWD_DEFINED__ +#define __ICorRuntimeHost_FWD_DEFINED__ +typedef interface ICorRuntimeHost ICorRuntimeHost; +#endif /* __ICorRuntimeHost_FWD_DEFINED__ */ + + +#ifndef __ICLRMemoryNotificationCallback_FWD_DEFINED__ +#define __ICLRMemoryNotificationCallback_FWD_DEFINED__ +typedef interface ICLRMemoryNotificationCallback ICLRMemoryNotificationCallback; +#endif /* __ICLRMemoryNotificationCallback_FWD_DEFINED__ */ + + +#ifndef __IHostMalloc_FWD_DEFINED__ +#define __IHostMalloc_FWD_DEFINED__ +typedef interface IHostMalloc IHostMalloc; +#endif /* __IHostMalloc_FWD_DEFINED__ */ + + +#ifndef __IHostMemoryManager_FWD_DEFINED__ +#define __IHostMemoryManager_FWD_DEFINED__ +typedef interface IHostMemoryManager IHostMemoryManager; +#endif /* __IHostMemoryManager_FWD_DEFINED__ */ + + +#ifndef __ICLRTask_FWD_DEFINED__ +#define __ICLRTask_FWD_DEFINED__ +typedef interface ICLRTask ICLRTask; +#endif /* __ICLRTask_FWD_DEFINED__ */ + + +#ifndef __IHostTask_FWD_DEFINED__ +#define __IHostTask_FWD_DEFINED__ +typedef interface IHostTask IHostTask; +#endif /* __IHostTask_FWD_DEFINED__ */ + + +#ifndef __ICLRTaskManager_FWD_DEFINED__ +#define __ICLRTaskManager_FWD_DEFINED__ +typedef interface ICLRTaskManager ICLRTaskManager; +#endif /* __ICLRTaskManager_FWD_DEFINED__ */ + + +#ifndef __IHostTaskManager_FWD_DEFINED__ +#define __IHostTaskManager_FWD_DEFINED__ +typedef interface IHostTaskManager IHostTaskManager; +#endif /* __IHostTaskManager_FWD_DEFINED__ */ + + +#ifndef __IHostThreadpoolManager_FWD_DEFINED__ +#define __IHostThreadpoolManager_FWD_DEFINED__ +typedef interface IHostThreadpoolManager IHostThreadpoolManager; +#endif /* __IHostThreadpoolManager_FWD_DEFINED__ */ + + +#ifndef __ICLRIoCompletionManager_FWD_DEFINED__ +#define __ICLRIoCompletionManager_FWD_DEFINED__ +typedef interface ICLRIoCompletionManager ICLRIoCompletionManager; +#endif /* __ICLRIoCompletionManager_FWD_DEFINED__ */ + + +#ifndef __IHostIoCompletionManager_FWD_DEFINED__ +#define __IHostIoCompletionManager_FWD_DEFINED__ +typedef interface IHostIoCompletionManager IHostIoCompletionManager; +#endif /* __IHostIoCompletionManager_FWD_DEFINED__ */ + + +#ifndef __ICLRDebugManager_FWD_DEFINED__ +#define __ICLRDebugManager_FWD_DEFINED__ +typedef interface ICLRDebugManager ICLRDebugManager; +#endif /* __ICLRDebugManager_FWD_DEFINED__ */ + + +#ifndef __ICLRErrorReportingManager_FWD_DEFINED__ +#define __ICLRErrorReportingManager_FWD_DEFINED__ +typedef interface ICLRErrorReportingManager ICLRErrorReportingManager; +#endif /* __ICLRErrorReportingManager_FWD_DEFINED__ */ + + +#ifndef __IHostCrst_FWD_DEFINED__ +#define __IHostCrst_FWD_DEFINED__ +typedef interface IHostCrst IHostCrst; +#endif /* __IHostCrst_FWD_DEFINED__ */ + + +#ifndef __IHostAutoEvent_FWD_DEFINED__ +#define __IHostAutoEvent_FWD_DEFINED__ +typedef interface IHostAutoEvent IHostAutoEvent; +#endif /* __IHostAutoEvent_FWD_DEFINED__ */ + + +#ifndef __IHostManualEvent_FWD_DEFINED__ +#define __IHostManualEvent_FWD_DEFINED__ +typedef interface IHostManualEvent IHostManualEvent; +#endif /* __IHostManualEvent_FWD_DEFINED__ */ + + +#ifndef __IHostSemaphore_FWD_DEFINED__ +#define __IHostSemaphore_FWD_DEFINED__ +typedef interface IHostSemaphore IHostSemaphore; +#endif /* __IHostSemaphore_FWD_DEFINED__ */ + + +#ifndef __ICLRSyncManager_FWD_DEFINED__ +#define __ICLRSyncManager_FWD_DEFINED__ +typedef interface ICLRSyncManager ICLRSyncManager; +#endif /* __ICLRSyncManager_FWD_DEFINED__ */ + + +#ifndef __IHostSyncManager_FWD_DEFINED__ +#define __IHostSyncManager_FWD_DEFINED__ +typedef interface IHostSyncManager IHostSyncManager; +#endif /* __IHostSyncManager_FWD_DEFINED__ */ + + +#ifndef __ICLRPolicyManager_FWD_DEFINED__ +#define __ICLRPolicyManager_FWD_DEFINED__ +typedef interface ICLRPolicyManager ICLRPolicyManager; +#endif /* __ICLRPolicyManager_FWD_DEFINED__ */ + + +#ifndef __IHostPolicyManager_FWD_DEFINED__ +#define __IHostPolicyManager_FWD_DEFINED__ +typedef interface IHostPolicyManager IHostPolicyManager; +#endif /* __IHostPolicyManager_FWD_DEFINED__ */ + + +#ifndef __IActionOnCLREvent_FWD_DEFINED__ +#define __IActionOnCLREvent_FWD_DEFINED__ +typedef interface IActionOnCLREvent IActionOnCLREvent; +#endif /* __IActionOnCLREvent_FWD_DEFINED__ */ + + +#ifndef __ICLROnEventManager_FWD_DEFINED__ +#define __ICLROnEventManager_FWD_DEFINED__ +typedef interface ICLROnEventManager ICLROnEventManager; +#endif /* __ICLROnEventManager_FWD_DEFINED__ */ + + +#ifndef __IHostGCManager_FWD_DEFINED__ +#define __IHostGCManager_FWD_DEFINED__ +typedef interface IHostGCManager IHostGCManager; +#endif /* __IHostGCManager_FWD_DEFINED__ */ + + +#ifndef __ICLRGCManager_FWD_DEFINED__ +#define __ICLRGCManager_FWD_DEFINED__ +typedef interface ICLRGCManager ICLRGCManager; +#endif /* __ICLRGCManager_FWD_DEFINED__ */ + + +#ifndef __ICLRAssemblyReferenceList_FWD_DEFINED__ +#define __ICLRAssemblyReferenceList_FWD_DEFINED__ +typedef interface ICLRAssemblyReferenceList ICLRAssemblyReferenceList; +#endif /* __ICLRAssemblyReferenceList_FWD_DEFINED__ */ + + +#ifndef __ICLRReferenceAssemblyEnum_FWD_DEFINED__ +#define __ICLRReferenceAssemblyEnum_FWD_DEFINED__ +typedef interface ICLRReferenceAssemblyEnum ICLRReferenceAssemblyEnum; +#endif /* __ICLRReferenceAssemblyEnum_FWD_DEFINED__ */ + + +#ifndef __ICLRProbingAssemblyEnum_FWD_DEFINED__ +#define __ICLRProbingAssemblyEnum_FWD_DEFINED__ +typedef interface ICLRProbingAssemblyEnum ICLRProbingAssemblyEnum; +#endif /* __ICLRProbingAssemblyEnum_FWD_DEFINED__ */ + + +#ifndef __ICLRAssemblyIdentityManager_FWD_DEFINED__ +#define __ICLRAssemblyIdentityManager_FWD_DEFINED__ +typedef interface ICLRAssemblyIdentityManager ICLRAssemblyIdentityManager; +#endif /* __ICLRAssemblyIdentityManager_FWD_DEFINED__ */ + + +#ifndef __ICLRHostBindingPolicyManager_FWD_DEFINED__ +#define __ICLRHostBindingPolicyManager_FWD_DEFINED__ +typedef interface ICLRHostBindingPolicyManager ICLRHostBindingPolicyManager; +#endif /* __ICLRHostBindingPolicyManager_FWD_DEFINED__ */ + + +#ifndef __IHostAssemblyStore_FWD_DEFINED__ +#define __IHostAssemblyStore_FWD_DEFINED__ +typedef interface IHostAssemblyStore IHostAssemblyStore; +#endif /* __IHostAssemblyStore_FWD_DEFINED__ */ + + +#ifndef __IHostAssemblyManager_FWD_DEFINED__ +#define __IHostAssemblyManager_FWD_DEFINED__ +typedef interface IHostAssemblyManager IHostAssemblyManager; +#endif /* __IHostAssemblyManager_FWD_DEFINED__ */ + + +#ifndef __IHostControl_FWD_DEFINED__ +#define __IHostControl_FWD_DEFINED__ +typedef interface IHostControl IHostControl; +#endif /* __IHostControl_FWD_DEFINED__ */ + + +#ifndef __ICLRControl_FWD_DEFINED__ +#define __ICLRControl_FWD_DEFINED__ +typedef interface ICLRControl ICLRControl; +#endif /* __ICLRControl_FWD_DEFINED__ */ + + +#ifndef __ICLRRuntimeHost_FWD_DEFINED__ +#define __ICLRRuntimeHost_FWD_DEFINED__ +typedef interface ICLRRuntimeHost ICLRRuntimeHost; +#endif /* __ICLRRuntimeHost_FWD_DEFINED__ */ + + +#ifndef __ICLRHostProtectionManager_FWD_DEFINED__ +#define __ICLRHostProtectionManager_FWD_DEFINED__ +typedef interface ICLRHostProtectionManager ICLRHostProtectionManager; +#endif /* __ICLRHostProtectionManager_FWD_DEFINED__ */ + + +#ifndef __ITypeName_FWD_DEFINED__ +#define __ITypeName_FWD_DEFINED__ +typedef interface ITypeName ITypeName; +#endif /* __ITypeName_FWD_DEFINED__ */ + + +#ifndef __ITypeNameBuilder_FWD_DEFINED__ +#define __ITypeNameBuilder_FWD_DEFINED__ +typedef interface ITypeNameBuilder ITypeNameBuilder; +#endif /* __ITypeNameBuilder_FWD_DEFINED__ */ + + +#ifndef __ITypeNameFactory_FWD_DEFINED__ +#define __ITypeNameFactory_FWD_DEFINED__ +typedef interface ITypeNameFactory ITypeNameFactory; +#endif /* __ITypeNameFactory_FWD_DEFINED__ */ + + +#ifndef __IApartmentCallback_FWD_DEFINED__ +#define __IApartmentCallback_FWD_DEFINED__ +typedef interface IApartmentCallback IApartmentCallback; +#endif /* __IApartmentCallback_FWD_DEFINED__ */ + + +#ifndef __IManagedObject_FWD_DEFINED__ +#define __IManagedObject_FWD_DEFINED__ +typedef interface IManagedObject IManagedObject; +#endif /* __IManagedObject_FWD_DEFINED__ */ + + +#ifndef __ICatalogServices_FWD_DEFINED__ +#define __ICatalogServices_FWD_DEFINED__ +typedef interface ICatalogServices ICatalogServices; +#endif /* __ICatalogServices_FWD_DEFINED__ */ + + +#ifndef __ComCallUnmarshal_FWD_DEFINED__ +#define __ComCallUnmarshal_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class ComCallUnmarshal ComCallUnmarshal; +#else +typedef struct ComCallUnmarshal ComCallUnmarshal; +#endif /* __cplusplus */ + +#endif /* __ComCallUnmarshal_FWD_DEFINED__ */ + + +#ifndef __CorRuntimeHost_FWD_DEFINED__ +#define __CorRuntimeHost_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class CorRuntimeHost CorRuntimeHost; +#else +typedef struct CorRuntimeHost CorRuntimeHost; +#endif /* __cplusplus */ + +#endif /* __CorRuntimeHost_FWD_DEFINED__ */ + + +#ifndef __CLRRuntimeHost_FWD_DEFINED__ +#define __CLRRuntimeHost_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class CLRRuntimeHost CLRRuntimeHost; +#else +typedef struct CLRRuntimeHost CLRRuntimeHost; +#endif /* __cplusplus */ + +#endif /* __CLRRuntimeHost_FWD_DEFINED__ */ + + +#ifndef __TypeNameFactory_FWD_DEFINED__ +#define __TypeNameFactory_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class TypeNameFactory TypeNameFactory; +#else +typedef struct TypeNameFactory TypeNameFactory; +#endif /* __cplusplus */ + +#endif /* __TypeNameFactory_FWD_DEFINED__ */ + + +#ifndef __IHostSecurityContext_FWD_DEFINED__ +#define __IHostSecurityContext_FWD_DEFINED__ +typedef interface IHostSecurityContext IHostSecurityContext; +#endif /* __IHostSecurityContext_FWD_DEFINED__ */ + + +#ifndef __IHostSecurityManager_FWD_DEFINED__ +#define __IHostSecurityManager_FWD_DEFINED__ +typedef interface IHostSecurityManager IHostSecurityManager; +#endif /* __IHostSecurityManager_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "unknwn.h" +#include "gchost.h" +#include "ivalidator.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +void * __RPC_USER MIDL_user_allocate(size_t); +void __RPC_USER MIDL_user_free( void * ); + +/* interface __MIDL_itf_mscoree_0000 */ +/* [local] */ + +#define CLR_MAJOR_VERSION ( 2 ) + +#define CLR_MINOR_VERSION ( 0 ) + +#define CLR_BUILD_VERSION ( 50727 ) + +#define CLR_ASSEMBLY_MAJOR_VERSION ( 2 ) + +#define CLR_ASSEMBLY_MINOR_VERSION ( 0 ) + +#define CLR_ASSEMBLY_BUILD_VERSION ( 0 ) + +EXTERN_GUID(LIBID_mscoree, 0x5477469e,0x83b1,0x11d2,0x8b,0x49,0x00,0xa0,0xc9,0xb7,0xc9,0xc4); +EXTERN_GUID(CLSID_CorRuntimeHost, 0xcb2f6723, 0xab3a, 0x11d2, 0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e); +EXTERN_GUID(CLSID_TypeNameFactory, 0xB81FF171, 0x20F3, 0x11d2, 0x8d, 0xcc, 0x00, 0xa0, 0xc9, 0xb0, 0x05, 0x25); +EXTERN_GUID(CLSID_CLRRuntimeHost, 0x90F1A06E, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02); +EXTERN_GUID(CLSID_ComCallUnmarshal, 0x3F281000,0xE95A,0x11d2,0x88,0x6B,0x00,0xC0,0x4F,0x86,0x9F,0x04); +EXTERN_GUID(IID_IObjectHandle, 0xc460e2b4, 0xe199, 0x412a, 0x84, 0x56, 0x84, 0xdc, 0x3e, 0x48, 0x38, 0xc3); +EXTERN_GUID(IID_IManagedObject, 0xc3fcc19e, 0xa970, 0x11d2, 0x8b, 0x5a, 0x00, 0xa0, 0xc9, 0xb7, 0xc9, 0xc4); +EXTERN_GUID(IID_IApartmentCallback, 0x178e5337, 0x1528, 0x4591, 0xb1, 0xc9, 0x1c, 0x6e, 0x48, 0x46, 0x86, 0xd8); +EXTERN_GUID(IID_ICatalogServices, 0x04c6be1e, 0x1db1, 0x4058, 0xab, 0x7a, 0x70, 0x0c, 0xcc, 0xfb, 0xf2, 0x54); +EXTERN_GUID(IID_ICorRuntimeHost, 0xcb2f6722, 0xab3a, 0x11d2, 0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e); +EXTERN_GUID(IID_ICorThreadpool, 0x84680D3A, 0xB2C1, 0x46e8, 0xAC, 0xC2, 0xDB, 0xC0, 0xA3, 0x59, 0x15, 0x9A); +EXTERN_GUID(IID_ICLRDebugManager, 0xdcaec6, 0x2ac0, 0x43a9, 0xac, 0xf9, 0x1e, 0x36, 0xc1, 0x39, 0xb1, 0xd); +EXTERN_GUID(IID_ICLRErrorReportingManager, 0x980d2f1a, 0xbf79, 0x4c08, 0x81, 0x2a, 0xbb, 0x97, 0x78, 0x92, 0x8f, 0x78); +EXTERN_GUID(IID_IHostMemoryNeededCallback, 0x47EB8E57, 0x0846, 0x4546, 0xAF, 0x76, 0x6F, 0x42, 0xFC, 0xFC, 0x26, 0x49); +EXTERN_GUID(IID_IHostMalloc, 0x1831991C, 0xCC53, 0x4A31, 0xB2, 0x18, 0x04, 0xE9, 0x10, 0x44, 0x64, 0x79); +EXTERN_GUID(IID_IHostMemoryManager, 0x7BC698D1, 0xF9E3, 0x4460, 0x9C, 0xDE, 0xD0, 0x42, 0x48, 0xE9, 0xFA, 0x25); +EXTERN_GUID(IID_ICLRTask, 0x28E66A4A, 0x9906, 0x4225, 0xB2, 0x31, 0x91, 0x87, 0xc3, 0xeb, 0x86, 0x11); +EXTERN_GUID(IID_IHostTask, 0xC2275828, 0xC4B1, 0x4B55, 0x82, 0xC9, 0x92, 0x13, 0x5F, 0x74, 0xDF, 0x1A); +EXTERN_GUID(IID_ICLRTaskManager, 0x4862efbe, 0x3ae5, 0x44f8, 0x8F, 0xEB, 0x34, 0x61, 0x90, 0xeE, 0x8A, 0x34); +EXTERN_GUID(IID_IHostTaskManager, 0x997FF24C, 0x43B7, 0x4352, 0x86, 0x67, 0x0D, 0xC0, 0x4F, 0xAF, 0xD3, 0x54); +EXTERN_GUID(IID_IHostThreadpoolManager, 0x983D50E2, 0xCB15, 0x466B, 0x80, 0xFC, 0x84, 0x5D, 0xC6, 0xE8, 0xC5, 0xFD); +EXTERN_GUID(IID_ICLRIoCompletionManager, 0x2D74CE86, 0xB8D6, 0x4C84, 0xB3, 0xA7, 0x97, 0x68, 0x93, 0x3B, 0x3C, 0x12); +EXTERN_GUID(IID_ICLRGCManager, 0x54D9007E, 0xA8E2, 0x4885, 0xB7, 0xBF, 0xF9, 0x98, 0xDE, 0xEE, 0x4F, 0x2A); +EXTERN_GUID(IID_IHostIoCompletionManager, 0x8BDE9D80, 0xEC06, 0x41D6, 0x83, 0xE6, 0x22, 0x58, 0x0E, 0xFF, 0xCC, 0x20); +EXTERN_GUID(IID_IHostSyncManager, 0x234330c7, 0x5f10, 0x4f20, 0x96, 0x15, 0x51, 0x22, 0xda, 0xb7, 0xa0, 0xac); +EXTERN_GUID(IID_IHostCrst, 0x6DF710A6, 0x26A4, 0x4a65, 0x8c, 0xd5, 0x72, 0x37, 0xb8, 0xbd, 0xa8, 0xdc); +EXTERN_GUID(IID_IHostAutoEvent, 0x50B0CFCE, 0x4063, 0x4278, 0x96, 0x73, 0xe5, 0xcb, 0x4e, 0xd0, 0xbd, 0xb8); +EXTERN_GUID(IID_IHostManualEvent, 0x1BF4EC38, 0xAFFE, 0x4fb9, 0x85, 0xa6, 0x52, 0x52, 0x68, 0xf1, 0x5b, 0x54); +EXTERN_GUID(IID_IHostSemaphore, 0x855efd47, 0xcc09, 0x463a, 0xa9, 0x7d, 0x16, 0xac, 0xab, 0x88, 0x26, 0x61); +EXTERN_GUID(IID_ICLRSyncManager, 0x55FF199D, 0xAD21, 0x48f9, 0xa1, 0x6c, 0xf2, 0x4e, 0xbb, 0xb8, 0x72, 0x7d); +EXTERN_GUID(IID_ICLRPolicyManager, 0x7D290010, 0xD781, 0x45da, 0xA6, 0xF8, 0xAA, 0x5D, 0x71, 0x1A, 0x73, 0x0E); +EXTERN_GUID(IID_IHostPolicyManager, 0x7AE49844, 0xB1E3, 0x4683, 0xBA, 0x7C, 0x1E, 0x82, 0x12, 0xEA, 0x3B, 0x79); +EXTERN_GUID(IID_IHostGCManager, 0x5D4EC34E, 0xF248, 0x457B, 0xB6, 0x03, 0x25, 0x5F, 0xAA, 0xBA, 0x0D, 0x21); +EXTERN_GUID(IID_IActionOnCLREvent, 0x607BE24B, 0xD91B, 0x4E28, 0xA2, 0x42, 0x61, 0x87, 0x1C, 0xE5, 0x6E, 0x35); +EXTERN_GUID(IID_ICLROnEventManager, 0x1D0E0132, 0xE64F, 0x493D, 0x92, 0x60, 0x02, 0x5C, 0x0E, 0x32, 0xC1, 0x75); +EXTERN_GUID(IID_ICLRRuntimeHost, 0x90F1A06C, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02); +EXTERN_GUID(IID_ICLRHostProtectionManager, 0x89f25f5c, 0xceef, 0x43e1, 0x9c, 0xfa, 0xa6, 0x8c, 0xe8, 0x63, 0xaa, 0xac); +EXTERN_GUID(IID_IHostAssemblyStore, 0x7b102a88, 0x3f7f, 0x496d, 0x8f, 0xa2, 0xc3, 0x53, 0x74, 0xe0, 0x1a, 0xf3); +EXTERN_GUID(IID_IHostAssemblyManager, 0x613dabd7, 0x62b2, 0x493e, 0x9e, 0x65, 0xc1, 0xe3, 0x2a, 0x1e, 0x0c, 0x5e); +EXTERN_GUID(IID_IHostSecurityManager, 0x75ad2468, 0xa349, 0x4d02, 0xa7, 0x64, 0x76, 0xa6, 0x8a, 0xee, 0x0c, 0x4f); +EXTERN_GUID(IID_IHostSecurityContext, 0x7e573ce4, 0x343, 0x4423, 0x98, 0xd7, 0x63, 0x18, 0x34, 0x8a, 0x1d, 0x3c); +EXTERN_GUID(IID_ICLRAssemblyIdentityManager, 0x15f0a9da, 0x3ff6, 0x4393, 0x9d, 0xa9, 0xfd, 0xfd, 0x28, 0x4e, 0x69, 0x72); +EXTERN_GUID(IID_ITypeName, 0xB81FF171, 0x20F3, 0x11d2, 0x8d, 0xcc, 0x00, 0xa0, 0xc9, 0xb0, 0x05, 0x22); +EXTERN_GUID(IID_ICLRAssemblyReferenceList, 0x1b2c9750, 0x2e66, 0x4bda, 0x8b, 0x44, 0x0a, 0x64, 0x2c, 0x5c, 0xd7, 0x33); +EXTERN_GUID(IID_ICLRReferenceAssemblyEnum, 0xd509cb5d, 0xcf32, 0x4876, 0xae, 0x61, 0x67, 0x77, 0x0c, 0xf9, 0x19, 0x73); +EXTERN_GUID(IID_ICLRProbingAssemblyEnum, 0xd0c5fb1f, 0x416b, 0x4f97, 0x81, 0xf4, 0x7a, 0xc7, 0xdc, 0x24, 0xdd, 0x5d); +EXTERN_GUID(IID_ICLRHostBindingPolicyManager, 0x4b3545e7, 0x1856, 0x48c9, 0xa8, 0xba, 0x24, 0xb2, 0x1a, 0x75, 0x3c, 0x09); +EXTERN_GUID(IID_ITypeNameBuilder, 0xB81FF171, 0x20F3, 0x11d2, 0x8d, 0xcc, 0x00, 0xa0, 0xc9, 0xb0, 0x05, 0x23); +EXTERN_GUID(IID_ITypeNameFactory, 0xB81FF171, 0x20F3, 0x11d2, 0x8d, 0xcc, 0x00, 0xa0, 0xc9, 0xb0, 0x05, 0x21); +STDAPI GetCORSystemDirectory(LPWSTR pbuffer, DWORD cchBuffer, DWORD* dwLength); +STDAPI GetCORVersion(LPWSTR pbBuffer, DWORD cchBuffer, DWORD* dwLength); +STDAPI GetFileVersion(LPCWSTR szFilename, LPWSTR szBuffer, DWORD cchBuffer, DWORD* dwLength); +STDAPI GetCORRequiredVersion(LPWSTR pbuffer, DWORD cchBuffer, DWORD* dwLength); +STDAPI GetRequestedRuntimeInfo(LPCWSTR pExe, LPCWSTR pwszVersion, LPCWSTR pConfigurationFile, DWORD startupFlags, DWORD runtimeInfoFlags, LPWSTR pDirectory, DWORD dwDirectory, DWORD *dwDirectoryLength, LPWSTR pVersion, DWORD cchBuffer, DWORD* dwlength); +STDAPI GetRequestedRuntimeVersion(LPWSTR pExe, LPWSTR pVersion, DWORD cchBuffer, DWORD* dwLength); +STDAPI CorBindToRuntimeHost(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, LPCWSTR pwszHostConfigFile, VOID* pReserved, DWORD startupFlags, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv); +STDAPI CorBindToRuntimeEx(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, DWORD startupFlags, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv); +STDAPI CorBindToRuntimeByCfg(IStream* pCfgStream, DWORD reserved, DWORD startupFlags, REFCLSID rclsid,REFIID riid, LPVOID FAR* ppv); +STDAPI CorBindToRuntime(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv); +STDAPI CorBindToCurrentRuntime(LPCWSTR pwszFileName, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv); +STDAPI ClrCreateManagedInstance(LPCWSTR pTypeName, REFIID riid, void **ppObject); +void STDMETHODCALLTYPE CorMarkThreadInThreadPool(); +STDAPI RunDll32ShimW(HWND hwnd, HINSTANCE hinst, LPCWSTR lpszCmdLine, int nCmdShow); +STDAPI LoadLibraryShim(LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE *phModDll); +STDAPI CallFunctionShim(LPCWSTR szDllName, LPCSTR szFunctionName, LPVOID lpvArgument1, LPVOID lpvArgument2, LPCWSTR szVersion, LPVOID pvReserved); +STDAPI GetRealProcAddress(LPCSTR pwszProcName, VOID** ppv); +void STDMETHODCALLTYPE CorExitProcess(int exitCode); +STDAPI LoadStringRC(UINT iResouceID, LPWSTR szBuffer, int iMax, int bQuiet); +STDAPI LoadStringRCEx(LCID lcid, UINT iResouceID, LPWSTR szBuffer, int iMax, int bQuiet, int *pcwchUsed); +typedef HRESULT (__stdcall *FLockClrVersionCallback) (); +STDAPI LockClrVersion(FLockClrVersionCallback hostCallback,FLockClrVersionCallback *pBeginHostSetup,FLockClrVersionCallback *pEndHostSetup); +STDAPI CreateDebuggingInterfaceFromVersion(int iDebuggerVersion, LPCWSTR szDebuggeeVersion, IUnknown ** ppCordb); +STDAPI GetVersionFromProcess(HANDLE hProcess, LPWSTR pVersion, DWORD cchBuffer, DWORD* dwLength); +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscoree_0000_0001 + { HOST_TYPE_DEFAULT = 0, + HOST_TYPE_APPLAUNCH = 0x1, + HOST_TYPE_CORFLAG = 0x2 + } HOST_TYPE; + +STDAPI CorLaunchApplication(HOST_TYPE dwClickOnceHost, LPCWSTR pwzAppFullName, DWORD dwManifestPaths, LPCWSTR* ppwzManifestPaths, DWORD dwActivationData, LPCWSTR* ppwzActivationData, LPPROCESS_INFORMATION lpProcessInformation); +typedef HRESULT ( __stdcall *FExecuteInAppDomainCallback )( + void *cookie); + +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscoree_0000_0002 + { STARTUP_CONCURRENT_GC = 0x1, + STARTUP_LOADER_OPTIMIZATION_MASK = 0x3 << 1, + STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN = 0x1 << 1, + STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN = 0x2 << 1, + STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN_HOST = 0x3 << 1, + STARTUP_LOADER_SAFEMODE = 0x10, + STARTUP_LOADER_SETPREFERENCE = 0x100, + STARTUP_SERVER_GC = 0x1000, + STARTUP_HOARD_GC_VM = 0x2000, + STARTUP_SINGLE_VERSION_HOSTING_INTERFACE = 0x4000, + STARTUP_LEGACY_IMPERSONATION = 0x10000, + STARTUP_DISABLE_COMMITTHREADSTACK = 0x20000, + STARTUP_ALWAYSFLOW_IMPERSONATION = 0x40000 + } STARTUP_FLAGS; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscoree_0000_0003 + { CLSID_RESOLUTION_DEFAULT = 0, + CLSID_RESOLUTION_REGISTERED = 0x1 + } CLSID_RESOLUTION_FLAGS; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscoree_0000_0004 + { RUNTIME_INFO_UPGRADE_VERSION = 0x1, + RUNTIME_INFO_REQUEST_IA64 = 0x2, + RUNTIME_INFO_REQUEST_AMD64 = 0x4, + RUNTIME_INFO_REQUEST_X86 = 0x8, + RUNTIME_INFO_DONT_RETURN_DIRECTORY = 0x10, + RUNTIME_INFO_DONT_RETURN_VERSION = 0x20, + RUNTIME_INFO_DONT_SHOW_ERROR_DIALOG = 0x40 + } RUNTIME_INFO_FLAGS; + +STDAPI GetRequestedRuntimeVersionForCLSID(REFCLSID rclsid, LPWSTR pVersion, DWORD cchBuffer, DWORD* dwLength, CLSID_RESOLUTION_FLAGS dwResolutionFlags); + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0000_v0_0_s_ifspec; + +#ifndef __IObjectHandle_INTERFACE_DEFINED__ +#define __IObjectHandle_INTERFACE_DEFINED__ + +/* interface IObjectHandle */ +/* [unique][helpstring][uuid][oleautomation][object] */ + + +EXTERN_C const IID IID_IObjectHandle; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("C460E2B4-E199-412a-8456-84DC3E4838C3") + IObjectHandle : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Unwrap( + /* [retval][out] */ VARIANT *ppv) = 0; + + }; + +#else /* C style interface */ + + typedef struct IObjectHandleVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IObjectHandle * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IObjectHandle * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IObjectHandle * This); + + HRESULT ( STDMETHODCALLTYPE *Unwrap )( + IObjectHandle * This, + /* [retval][out] */ VARIANT *ppv); + + END_INTERFACE + } IObjectHandleVtbl; + + interface IObjectHandle + { + CONST_VTBL struct IObjectHandleVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IObjectHandle_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IObjectHandle_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IObjectHandle_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IObjectHandle_Unwrap(This,ppv) \ + (This)->lpVtbl -> Unwrap(This,ppv) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IObjectHandle_Unwrap_Proxy( + IObjectHandle * This, + /* [retval][out] */ VARIANT *ppv); + + +void __RPC_STUB IObjectHandle_Unwrap_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IObjectHandle_INTERFACE_DEFINED__ */ + + +#ifndef __IAppDomainBinding_INTERFACE_DEFINED__ +#define __IAppDomainBinding_INTERFACE_DEFINED__ + +/* interface IAppDomainBinding */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IAppDomainBinding; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5C2B07A7-1E98-11d3-872F-00C04F79ED0D") + IAppDomainBinding : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE OnAppDomain( + /* [in] */ IUnknown *pAppdomain) = 0; + + }; + +#else /* C style interface */ + + typedef struct IAppDomainBindingVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IAppDomainBinding * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IAppDomainBinding * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IAppDomainBinding * This); + + HRESULT ( STDMETHODCALLTYPE *OnAppDomain )( + IAppDomainBinding * This, + /* [in] */ IUnknown *pAppdomain); + + END_INTERFACE + } IAppDomainBindingVtbl; + + interface IAppDomainBinding + { + CONST_VTBL struct IAppDomainBindingVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IAppDomainBinding_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IAppDomainBinding_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IAppDomainBinding_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IAppDomainBinding_OnAppDomain(This,pAppdomain) \ + (This)->lpVtbl -> OnAppDomain(This,pAppdomain) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IAppDomainBinding_OnAppDomain_Proxy( + IAppDomainBinding * This, + /* [in] */ IUnknown *pAppdomain); + + +void __RPC_STUB IAppDomainBinding_OnAppDomain_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IAppDomainBinding_INTERFACE_DEFINED__ */ + + +#ifndef __IGCThreadControl_INTERFACE_DEFINED__ +#define __IGCThreadControl_INTERFACE_DEFINED__ + +/* interface IGCThreadControl */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IGCThreadControl; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("F31D1788-C397-4725-87A5-6AF3472C2791") + IGCThreadControl : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE ThreadIsBlockingForSuspension( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SuspensionStarting( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SuspensionEnding( + DWORD Generation) = 0; + + }; + +#else /* C style interface */ + + typedef struct IGCThreadControlVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IGCThreadControl * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IGCThreadControl * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IGCThreadControl * This); + + HRESULT ( STDMETHODCALLTYPE *ThreadIsBlockingForSuspension )( + IGCThreadControl * This); + + HRESULT ( STDMETHODCALLTYPE *SuspensionStarting )( + IGCThreadControl * This); + + HRESULT ( STDMETHODCALLTYPE *SuspensionEnding )( + IGCThreadControl * This, + DWORD Generation); + + END_INTERFACE + } IGCThreadControlVtbl; + + interface IGCThreadControl + { + CONST_VTBL struct IGCThreadControlVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IGCThreadControl_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IGCThreadControl_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IGCThreadControl_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IGCThreadControl_ThreadIsBlockingForSuspension(This) \ + (This)->lpVtbl -> ThreadIsBlockingForSuspension(This) + +#define IGCThreadControl_SuspensionStarting(This) \ + (This)->lpVtbl -> SuspensionStarting(This) + +#define IGCThreadControl_SuspensionEnding(This,Generation) \ + (This)->lpVtbl -> SuspensionEnding(This,Generation) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IGCThreadControl_ThreadIsBlockingForSuspension_Proxy( + IGCThreadControl * This); + + +void __RPC_STUB IGCThreadControl_ThreadIsBlockingForSuspension_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IGCThreadControl_SuspensionStarting_Proxy( + IGCThreadControl * This); + + +void __RPC_STUB IGCThreadControl_SuspensionStarting_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IGCThreadControl_SuspensionEnding_Proxy( + IGCThreadControl * This, + DWORD Generation); + + +void __RPC_STUB IGCThreadControl_SuspensionEnding_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IGCThreadControl_INTERFACE_DEFINED__ */ + + +#ifndef __IGCHostControl_INTERFACE_DEFINED__ +#define __IGCHostControl_INTERFACE_DEFINED__ + +/* interface IGCHostControl */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IGCHostControl; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5513D564-8374-4cb9-AED9-0083F4160A1D") + IGCHostControl : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE RequestVirtualMemLimit( + /* [in] */ SIZE_T sztMaxVirtualMemMB, + /* [out][in] */ SIZE_T *psztNewMaxVirtualMemMB) = 0; + + }; + +#else /* C style interface */ + + typedef struct IGCHostControlVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IGCHostControl * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IGCHostControl * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IGCHostControl * This); + + HRESULT ( STDMETHODCALLTYPE *RequestVirtualMemLimit )( + IGCHostControl * This, + /* [in] */ SIZE_T sztMaxVirtualMemMB, + /* [out][in] */ SIZE_T *psztNewMaxVirtualMemMB); + + END_INTERFACE + } IGCHostControlVtbl; + + interface IGCHostControl + { + CONST_VTBL struct IGCHostControlVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IGCHostControl_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IGCHostControl_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IGCHostControl_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IGCHostControl_RequestVirtualMemLimit(This,sztMaxVirtualMemMB,psztNewMaxVirtualMemMB) \ + (This)->lpVtbl -> RequestVirtualMemLimit(This,sztMaxVirtualMemMB,psztNewMaxVirtualMemMB) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IGCHostControl_RequestVirtualMemLimit_Proxy( + IGCHostControl * This, + /* [in] */ SIZE_T sztMaxVirtualMemMB, + /* [out][in] */ SIZE_T *psztNewMaxVirtualMemMB); + + +void __RPC_STUB IGCHostControl_RequestVirtualMemLimit_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IGCHostControl_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0128 */ +/* [local] */ + +#if (_MSC_VER < 1300 || _WIN32_WINNT < 0x0500) +typedef VOID ( __stdcall *WAITORTIMERCALLBACK )( + PVOID __MIDL_0011, + BOOL __MIDL_0012); + +#endif // (_MSC_VER < 1300 || _WIN32_WINNT < 0x0500) +#ifdef __midl +typedef DWORD ( __stdcall *LPTHREAD_START_ROUTINE )( + LPVOID lpThreadParameter); + +typedef VOID ( *LPOVERLAPPED_COMPLETION_ROUTINE )( + DWORD dwErrorCode, + DWORD dwNumberOfBytesTransfered, + LPVOID lpOverlapped); + +#endif // __midl +typedef VOID ( __stdcall *PTLS_CALLBACK_FUNCTION )( + PVOID __MIDL_0016); + + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0128_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0128_v0_0_s_ifspec; + +#ifndef __ICorThreadpool_INTERFACE_DEFINED__ +#define __ICorThreadpool_INTERFACE_DEFINED__ + +/* interface ICorThreadpool */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICorThreadpool; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("84680D3A-B2C1-46e8-ACC2-DBC0A359159A") + ICorThreadpool : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CorRegisterWaitForSingleObject( + /* [in] */ HANDLE *phNewWaitObject, + /* [in] */ HANDLE hWaitObject, + /* [in] */ WAITORTIMERCALLBACK Callback, + /* [in] */ PVOID Context, + /* [in] */ ULONG timeout, + /* [in] */ BOOL executeOnlyOnce, + /* [out] */ BOOL *result) = 0; + + virtual HRESULT STDMETHODCALLTYPE CorUnregisterWait( + /* [in] */ HANDLE hWaitObject, + /* [in] */ HANDLE CompletionEvent, + /* [out] */ BOOL *result) = 0; + + virtual HRESULT STDMETHODCALLTYPE CorQueueUserWorkItem( + /* [in] */ LPTHREAD_START_ROUTINE Function, + /* [in] */ PVOID Context, + /* [in] */ BOOL executeOnlyOnce, + /* [out] */ BOOL *result) = 0; + + virtual HRESULT STDMETHODCALLTYPE CorCreateTimer( + /* [in] */ HANDLE *phNewTimer, + /* [in] */ WAITORTIMERCALLBACK Callback, + /* [in] */ PVOID Parameter, + /* [in] */ DWORD DueTime, + /* [in] */ DWORD Period, + /* [out] */ BOOL *result) = 0; + + virtual HRESULT STDMETHODCALLTYPE CorChangeTimer( + /* [in] */ HANDLE Timer, + /* [in] */ ULONG DueTime, + /* [in] */ ULONG Period, + /* [out] */ BOOL *result) = 0; + + virtual HRESULT STDMETHODCALLTYPE CorDeleteTimer( + /* [in] */ HANDLE Timer, + /* [in] */ HANDLE CompletionEvent, + /* [out] */ BOOL *result) = 0; + + virtual HRESULT STDMETHODCALLTYPE CorBindIoCompletionCallback( + /* [in] */ HANDLE fileHandle, + /* [in] */ LPOVERLAPPED_COMPLETION_ROUTINE callback) = 0; + + virtual HRESULT STDMETHODCALLTYPE CorCallOrQueueUserWorkItem( + /* [in] */ LPTHREAD_START_ROUTINE Function, + /* [in] */ PVOID Context, + /* [out] */ BOOL *result) = 0; + + virtual HRESULT STDMETHODCALLTYPE CorSetMaxThreads( + /* [in] */ DWORD MaxWorkerThreads, + /* [in] */ DWORD MaxIOCompletionThreads) = 0; + + virtual HRESULT STDMETHODCALLTYPE CorGetMaxThreads( + /* [out] */ DWORD *MaxWorkerThreads, + /* [out] */ DWORD *MaxIOCompletionThreads) = 0; + + virtual HRESULT STDMETHODCALLTYPE CorGetAvailableThreads( + /* [out] */ DWORD *AvailableWorkerThreads, + /* [out] */ DWORD *AvailableIOCompletionThreads) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICorThreadpoolVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorThreadpool * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorThreadpool * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorThreadpool * This); + + HRESULT ( STDMETHODCALLTYPE *CorRegisterWaitForSingleObject )( + ICorThreadpool * This, + /* [in] */ HANDLE *phNewWaitObject, + /* [in] */ HANDLE hWaitObject, + /* [in] */ WAITORTIMERCALLBACK Callback, + /* [in] */ PVOID Context, + /* [in] */ ULONG timeout, + /* [in] */ BOOL executeOnlyOnce, + /* [out] */ BOOL *result); + + HRESULT ( STDMETHODCALLTYPE *CorUnregisterWait )( + ICorThreadpool * This, + /* [in] */ HANDLE hWaitObject, + /* [in] */ HANDLE CompletionEvent, + /* [out] */ BOOL *result); + + HRESULT ( STDMETHODCALLTYPE *CorQueueUserWorkItem )( + ICorThreadpool * This, + /* [in] */ LPTHREAD_START_ROUTINE Function, + /* [in] */ PVOID Context, + /* [in] */ BOOL executeOnlyOnce, + /* [out] */ BOOL *result); + + HRESULT ( STDMETHODCALLTYPE *CorCreateTimer )( + ICorThreadpool * This, + /* [in] */ HANDLE *phNewTimer, + /* [in] */ WAITORTIMERCALLBACK Callback, + /* [in] */ PVOID Parameter, + /* [in] */ DWORD DueTime, + /* [in] */ DWORD Period, + /* [out] */ BOOL *result); + + HRESULT ( STDMETHODCALLTYPE *CorChangeTimer )( + ICorThreadpool * This, + /* [in] */ HANDLE Timer, + /* [in] */ ULONG DueTime, + /* [in] */ ULONG Period, + /* [out] */ BOOL *result); + + HRESULT ( STDMETHODCALLTYPE *CorDeleteTimer )( + ICorThreadpool * This, + /* [in] */ HANDLE Timer, + /* [in] */ HANDLE CompletionEvent, + /* [out] */ BOOL *result); + + HRESULT ( STDMETHODCALLTYPE *CorBindIoCompletionCallback )( + ICorThreadpool * This, + /* [in] */ HANDLE fileHandle, + /* [in] */ LPOVERLAPPED_COMPLETION_ROUTINE callback); + + HRESULT ( STDMETHODCALLTYPE *CorCallOrQueueUserWorkItem )( + ICorThreadpool * This, + /* [in] */ LPTHREAD_START_ROUTINE Function, + /* [in] */ PVOID Context, + /* [out] */ BOOL *result); + + HRESULT ( STDMETHODCALLTYPE *CorSetMaxThreads )( + ICorThreadpool * This, + /* [in] */ DWORD MaxWorkerThreads, + /* [in] */ DWORD MaxIOCompletionThreads); + + HRESULT ( STDMETHODCALLTYPE *CorGetMaxThreads )( + ICorThreadpool * This, + /* [out] */ DWORD *MaxWorkerThreads, + /* [out] */ DWORD *MaxIOCompletionThreads); + + HRESULT ( STDMETHODCALLTYPE *CorGetAvailableThreads )( + ICorThreadpool * This, + /* [out] */ DWORD *AvailableWorkerThreads, + /* [out] */ DWORD *AvailableIOCompletionThreads); + + END_INTERFACE + } ICorThreadpoolVtbl; + + interface ICorThreadpool + { + CONST_VTBL struct ICorThreadpoolVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorThreadpool_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICorThreadpool_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICorThreadpool_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICorThreadpool_CorRegisterWaitForSingleObject(This,phNewWaitObject,hWaitObject,Callback,Context,timeout,executeOnlyOnce,result) \ + (This)->lpVtbl -> CorRegisterWaitForSingleObject(This,phNewWaitObject,hWaitObject,Callback,Context,timeout,executeOnlyOnce,result) + +#define ICorThreadpool_CorUnregisterWait(This,hWaitObject,CompletionEvent,result) \ + (This)->lpVtbl -> CorUnregisterWait(This,hWaitObject,CompletionEvent,result) + +#define ICorThreadpool_CorQueueUserWorkItem(This,Function,Context,executeOnlyOnce,result) \ + (This)->lpVtbl -> CorQueueUserWorkItem(This,Function,Context,executeOnlyOnce,result) + +#define ICorThreadpool_CorCreateTimer(This,phNewTimer,Callback,Parameter,DueTime,Period,result) \ + (This)->lpVtbl -> CorCreateTimer(This,phNewTimer,Callback,Parameter,DueTime,Period,result) + +#define ICorThreadpool_CorChangeTimer(This,Timer,DueTime,Period,result) \ + (This)->lpVtbl -> CorChangeTimer(This,Timer,DueTime,Period,result) + +#define ICorThreadpool_CorDeleteTimer(This,Timer,CompletionEvent,result) \ + (This)->lpVtbl -> CorDeleteTimer(This,Timer,CompletionEvent,result) + +#define ICorThreadpool_CorBindIoCompletionCallback(This,fileHandle,callback) \ + (This)->lpVtbl -> CorBindIoCompletionCallback(This,fileHandle,callback) + +#define ICorThreadpool_CorCallOrQueueUserWorkItem(This,Function,Context,result) \ + (This)->lpVtbl -> CorCallOrQueueUserWorkItem(This,Function,Context,result) + +#define ICorThreadpool_CorSetMaxThreads(This,MaxWorkerThreads,MaxIOCompletionThreads) \ + (This)->lpVtbl -> CorSetMaxThreads(This,MaxWorkerThreads,MaxIOCompletionThreads) + +#define ICorThreadpool_CorGetMaxThreads(This,MaxWorkerThreads,MaxIOCompletionThreads) \ + (This)->lpVtbl -> CorGetMaxThreads(This,MaxWorkerThreads,MaxIOCompletionThreads) + +#define ICorThreadpool_CorGetAvailableThreads(This,AvailableWorkerThreads,AvailableIOCompletionThreads) \ + (This)->lpVtbl -> CorGetAvailableThreads(This,AvailableWorkerThreads,AvailableIOCompletionThreads) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICorThreadpool_CorRegisterWaitForSingleObject_Proxy( + ICorThreadpool * This, + /* [in] */ HANDLE *phNewWaitObject, + /* [in] */ HANDLE hWaitObject, + /* [in] */ WAITORTIMERCALLBACK Callback, + /* [in] */ PVOID Context, + /* [in] */ ULONG timeout, + /* [in] */ BOOL executeOnlyOnce, + /* [out] */ BOOL *result); + + +void __RPC_STUB ICorThreadpool_CorRegisterWaitForSingleObject_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorThreadpool_CorUnregisterWait_Proxy( + ICorThreadpool * This, + /* [in] */ HANDLE hWaitObject, + /* [in] */ HANDLE CompletionEvent, + /* [out] */ BOOL *result); + + +void __RPC_STUB ICorThreadpool_CorUnregisterWait_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorThreadpool_CorQueueUserWorkItem_Proxy( + ICorThreadpool * This, + /* [in] */ LPTHREAD_START_ROUTINE Function, + /* [in] */ PVOID Context, + /* [in] */ BOOL executeOnlyOnce, + /* [out] */ BOOL *result); + + +void __RPC_STUB ICorThreadpool_CorQueueUserWorkItem_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorThreadpool_CorCreateTimer_Proxy( + ICorThreadpool * This, + /* [in] */ HANDLE *phNewTimer, + /* [in] */ WAITORTIMERCALLBACK Callback, + /* [in] */ PVOID Parameter, + /* [in] */ DWORD DueTime, + /* [in] */ DWORD Period, + /* [out] */ BOOL *result); + + +void __RPC_STUB ICorThreadpool_CorCreateTimer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorThreadpool_CorChangeTimer_Proxy( + ICorThreadpool * This, + /* [in] */ HANDLE Timer, + /* [in] */ ULONG DueTime, + /* [in] */ ULONG Period, + /* [out] */ BOOL *result); + + +void __RPC_STUB ICorThreadpool_CorChangeTimer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorThreadpool_CorDeleteTimer_Proxy( + ICorThreadpool * This, + /* [in] */ HANDLE Timer, + /* [in] */ HANDLE CompletionEvent, + /* [out] */ BOOL *result); + + +void __RPC_STUB ICorThreadpool_CorDeleteTimer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorThreadpool_CorBindIoCompletionCallback_Proxy( + ICorThreadpool * This, + /* [in] */ HANDLE fileHandle, + /* [in] */ LPOVERLAPPED_COMPLETION_ROUTINE callback); + + +void __RPC_STUB ICorThreadpool_CorBindIoCompletionCallback_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorThreadpool_CorCallOrQueueUserWorkItem_Proxy( + ICorThreadpool * This, + /* [in] */ LPTHREAD_START_ROUTINE Function, + /* [in] */ PVOID Context, + /* [out] */ BOOL *result); + + +void __RPC_STUB ICorThreadpool_CorCallOrQueueUserWorkItem_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorThreadpool_CorSetMaxThreads_Proxy( + ICorThreadpool * This, + /* [in] */ DWORD MaxWorkerThreads, + /* [in] */ DWORD MaxIOCompletionThreads); + + +void __RPC_STUB ICorThreadpool_CorSetMaxThreads_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorThreadpool_CorGetMaxThreads_Proxy( + ICorThreadpool * This, + /* [out] */ DWORD *MaxWorkerThreads, + /* [out] */ DWORD *MaxIOCompletionThreads); + + +void __RPC_STUB ICorThreadpool_CorGetMaxThreads_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorThreadpool_CorGetAvailableThreads_Proxy( + ICorThreadpool * This, + /* [out] */ DWORD *AvailableWorkerThreads, + /* [out] */ DWORD *AvailableIOCompletionThreads); + + +void __RPC_STUB ICorThreadpool_CorGetAvailableThreads_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICorThreadpool_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0129 */ +/* [local] */ + +EXTERN_GUID(IID_IDebuggerThreadControl, 0x23d86786, 0x0bb5, 0x4774, 0x8f, 0xb5, 0xe3, 0x52, 0x2a, 0xdd, 0x62, 0x46); + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0129_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0129_v0_0_s_ifspec; + +#ifndef __IDebuggerThreadControl_INTERFACE_DEFINED__ +#define __IDebuggerThreadControl_INTERFACE_DEFINED__ + +/* interface IDebuggerThreadControl */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IDebuggerThreadControl; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("23D86786-0BB5-4774-8FB5-E3522ADD6246") + IDebuggerThreadControl : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE ThreadIsBlockingForDebugger( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReleaseAllRuntimeThreads( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartBlockingForDebugger( + DWORD dwUnused) = 0; + + }; + +#else /* C style interface */ + + typedef struct IDebuggerThreadControlVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDebuggerThreadControl * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDebuggerThreadControl * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDebuggerThreadControl * This); + + HRESULT ( STDMETHODCALLTYPE *ThreadIsBlockingForDebugger )( + IDebuggerThreadControl * This); + + HRESULT ( STDMETHODCALLTYPE *ReleaseAllRuntimeThreads )( + IDebuggerThreadControl * This); + + HRESULT ( STDMETHODCALLTYPE *StartBlockingForDebugger )( + IDebuggerThreadControl * This, + DWORD dwUnused); + + END_INTERFACE + } IDebuggerThreadControlVtbl; + + interface IDebuggerThreadControl + { + CONST_VTBL struct IDebuggerThreadControlVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDebuggerThreadControl_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IDebuggerThreadControl_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IDebuggerThreadControl_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IDebuggerThreadControl_ThreadIsBlockingForDebugger(This) \ + (This)->lpVtbl -> ThreadIsBlockingForDebugger(This) + +#define IDebuggerThreadControl_ReleaseAllRuntimeThreads(This) \ + (This)->lpVtbl -> ReleaseAllRuntimeThreads(This) + +#define IDebuggerThreadControl_StartBlockingForDebugger(This,dwUnused) \ + (This)->lpVtbl -> StartBlockingForDebugger(This,dwUnused) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IDebuggerThreadControl_ThreadIsBlockingForDebugger_Proxy( + IDebuggerThreadControl * This); + + +void __RPC_STUB IDebuggerThreadControl_ThreadIsBlockingForDebugger_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDebuggerThreadControl_ReleaseAllRuntimeThreads_Proxy( + IDebuggerThreadControl * This); + + +void __RPC_STUB IDebuggerThreadControl_ReleaseAllRuntimeThreads_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDebuggerThreadControl_StartBlockingForDebugger_Proxy( + IDebuggerThreadControl * This, + DWORD dwUnused); + + +void __RPC_STUB IDebuggerThreadControl_StartBlockingForDebugger_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IDebuggerThreadControl_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0130 */ +/* [local] */ + +EXTERN_GUID(IID_IDebuggerInfo, 0xbf24142d, 0xa47d, 0x4d24, 0xa6, 0x6d, 0x8c, 0x21, 0x41, 0x94, 0x4e, 0x44); + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0130_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0130_v0_0_s_ifspec; + +#ifndef __IDebuggerInfo_INTERFACE_DEFINED__ +#define __IDebuggerInfo_INTERFACE_DEFINED__ + +/* interface IDebuggerInfo */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IDebuggerInfo; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("BF24142D-A47D-4d24-A66D-8C2141944E44") + IDebuggerInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE IsDebuggerAttached( + /* [out] */ BOOL *pbAttached) = 0; + + }; + +#else /* C style interface */ + + typedef struct IDebuggerInfoVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDebuggerInfo * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDebuggerInfo * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDebuggerInfo * This); + + HRESULT ( STDMETHODCALLTYPE *IsDebuggerAttached )( + IDebuggerInfo * This, + /* [out] */ BOOL *pbAttached); + + END_INTERFACE + } IDebuggerInfoVtbl; + + interface IDebuggerInfo + { + CONST_VTBL struct IDebuggerInfoVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDebuggerInfo_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IDebuggerInfo_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IDebuggerInfo_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IDebuggerInfo_IsDebuggerAttached(This,pbAttached) \ + (This)->lpVtbl -> IsDebuggerAttached(This,pbAttached) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IDebuggerInfo_IsDebuggerAttached_Proxy( + IDebuggerInfo * This, + /* [out] */ BOOL *pbAttached); + + +void __RPC_STUB IDebuggerInfo_IsDebuggerAttached_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IDebuggerInfo_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0131 */ +/* [local] */ + +EXTERN_GUID(IID_ICorConfiguration, 0x5c2b07a5, 0x1e98, 0x11d3, 0x87, 0x2f, 0x00, 0xc0, 0x4f, 0x79, 0xed, 0x0d); + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0131_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0131_v0_0_s_ifspec; + +#ifndef __ICorConfiguration_INTERFACE_DEFINED__ +#define __ICorConfiguration_INTERFACE_DEFINED__ + +/* interface ICorConfiguration */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICorConfiguration; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5C2B07A5-1E98-11d3-872F-00C04F79ED0D") + ICorConfiguration : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetGCThreadControl( + /* [in] */ IGCThreadControl *pGCThreadControl) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetGCHostControl( + /* [in] */ IGCHostControl *pGCHostControl) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetDebuggerThreadControl( + /* [in] */ IDebuggerThreadControl *pDebuggerThreadControl) = 0; + + virtual HRESULT STDMETHODCALLTYPE AddDebuggerSpecialThread( + /* [in] */ DWORD dwSpecialThreadId) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICorConfigurationVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorConfiguration * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorConfiguration * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorConfiguration * This); + + HRESULT ( STDMETHODCALLTYPE *SetGCThreadControl )( + ICorConfiguration * This, + /* [in] */ IGCThreadControl *pGCThreadControl); + + HRESULT ( STDMETHODCALLTYPE *SetGCHostControl )( + ICorConfiguration * This, + /* [in] */ IGCHostControl *pGCHostControl); + + HRESULT ( STDMETHODCALLTYPE *SetDebuggerThreadControl )( + ICorConfiguration * This, + /* [in] */ IDebuggerThreadControl *pDebuggerThreadControl); + + HRESULT ( STDMETHODCALLTYPE *AddDebuggerSpecialThread )( + ICorConfiguration * This, + /* [in] */ DWORD dwSpecialThreadId); + + END_INTERFACE + } ICorConfigurationVtbl; + + interface ICorConfiguration + { + CONST_VTBL struct ICorConfigurationVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorConfiguration_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICorConfiguration_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICorConfiguration_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICorConfiguration_SetGCThreadControl(This,pGCThreadControl) \ + (This)->lpVtbl -> SetGCThreadControl(This,pGCThreadControl) + +#define ICorConfiguration_SetGCHostControl(This,pGCHostControl) \ + (This)->lpVtbl -> SetGCHostControl(This,pGCHostControl) + +#define ICorConfiguration_SetDebuggerThreadControl(This,pDebuggerThreadControl) \ + (This)->lpVtbl -> SetDebuggerThreadControl(This,pDebuggerThreadControl) + +#define ICorConfiguration_AddDebuggerSpecialThread(This,dwSpecialThreadId) \ + (This)->lpVtbl -> AddDebuggerSpecialThread(This,dwSpecialThreadId) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICorConfiguration_SetGCThreadControl_Proxy( + ICorConfiguration * This, + /* [in] */ IGCThreadControl *pGCThreadControl); + + +void __RPC_STUB ICorConfiguration_SetGCThreadControl_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorConfiguration_SetGCHostControl_Proxy( + ICorConfiguration * This, + /* [in] */ IGCHostControl *pGCHostControl); + + +void __RPC_STUB ICorConfiguration_SetGCHostControl_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorConfiguration_SetDebuggerThreadControl_Proxy( + ICorConfiguration * This, + /* [in] */ IDebuggerThreadControl *pDebuggerThreadControl); + + +void __RPC_STUB ICorConfiguration_SetDebuggerThreadControl_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorConfiguration_AddDebuggerSpecialThread_Proxy( + ICorConfiguration * This, + /* [in] */ DWORD dwSpecialThreadId); + + +void __RPC_STUB ICorConfiguration_AddDebuggerSpecialThread_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICorConfiguration_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0132 */ +/* [local] */ + +typedef void *HDOMAINENUM; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0132_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0132_v0_0_s_ifspec; + +#ifndef __ICorRuntimeHost_INTERFACE_DEFINED__ +#define __ICorRuntimeHost_INTERFACE_DEFINED__ + +/* interface ICorRuntimeHost */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICorRuntimeHost; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CB2F6722-AB3A-11d2-9C40-00C04FA30A3E") + ICorRuntimeHost : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateLogicalThreadState( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE DeleteLogicalThreadState( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SwitchInLogicalThreadState( + /* [in] */ DWORD *pFiberCookie) = 0; + + virtual HRESULT STDMETHODCALLTYPE SwitchOutLogicalThreadState( + /* [out] */ DWORD **pFiberCookie) = 0; + + virtual HRESULT STDMETHODCALLTYPE LocksHeldByLogicalThread( + /* [out] */ DWORD *pCount) = 0; + + virtual HRESULT STDMETHODCALLTYPE MapFile( + /* [in] */ HANDLE hFile, + /* [out] */ HMODULE *hMapAddress) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetConfiguration( + /* [out] */ ICorConfiguration **pConfiguration) = 0; + + virtual HRESULT STDMETHODCALLTYPE Start( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Stop( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateDomain( + /* [in] */ LPCWSTR pwzFriendlyName, + /* [in] */ IUnknown *pIdentityArray, + /* [out] */ IUnknown **pAppDomain) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDefaultDomain( + /* [out] */ IUnknown **pAppDomain) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumDomains( + /* [out] */ HDOMAINENUM *hEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE NextDomain( + /* [in] */ HDOMAINENUM hEnum, + /* [out] */ IUnknown **pAppDomain) = 0; + + virtual HRESULT STDMETHODCALLTYPE CloseEnum( + /* [in] */ HDOMAINENUM hEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateDomainEx( + /* [in] */ LPCWSTR pwzFriendlyName, + /* [in] */ IUnknown *pSetup, + /* [in] */ IUnknown *pEvidence, + /* [out] */ IUnknown **pAppDomain) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateDomainSetup( + /* [out] */ IUnknown **pAppDomainSetup) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateEvidence( + /* [out] */ IUnknown **pEvidence) = 0; + + virtual HRESULT STDMETHODCALLTYPE UnloadDomain( + /* [in] */ IUnknown *pAppDomain) = 0; + + virtual HRESULT STDMETHODCALLTYPE CurrentDomain( + /* [out] */ IUnknown **pAppDomain) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICorRuntimeHostVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorRuntimeHost * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorRuntimeHost * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorRuntimeHost * This); + + HRESULT ( STDMETHODCALLTYPE *CreateLogicalThreadState )( + ICorRuntimeHost * This); + + HRESULT ( STDMETHODCALLTYPE *DeleteLogicalThreadState )( + ICorRuntimeHost * This); + + HRESULT ( STDMETHODCALLTYPE *SwitchInLogicalThreadState )( + ICorRuntimeHost * This, + /* [in] */ DWORD *pFiberCookie); + + HRESULT ( STDMETHODCALLTYPE *SwitchOutLogicalThreadState )( + ICorRuntimeHost * This, + /* [out] */ DWORD **pFiberCookie); + + HRESULT ( STDMETHODCALLTYPE *LocksHeldByLogicalThread )( + ICorRuntimeHost * This, + /* [out] */ DWORD *pCount); + + HRESULT ( STDMETHODCALLTYPE *MapFile )( + ICorRuntimeHost * This, + /* [in] */ HANDLE hFile, + /* [out] */ HMODULE *hMapAddress); + + HRESULT ( STDMETHODCALLTYPE *GetConfiguration )( + ICorRuntimeHost * This, + /* [out] */ ICorConfiguration **pConfiguration); + + HRESULT ( STDMETHODCALLTYPE *Start )( + ICorRuntimeHost * This); + + HRESULT ( STDMETHODCALLTYPE *Stop )( + ICorRuntimeHost * This); + + HRESULT ( STDMETHODCALLTYPE *CreateDomain )( + ICorRuntimeHost * This, + /* [in] */ LPCWSTR pwzFriendlyName, + /* [in] */ IUnknown *pIdentityArray, + /* [out] */ IUnknown **pAppDomain); + + HRESULT ( STDMETHODCALLTYPE *GetDefaultDomain )( + ICorRuntimeHost * This, + /* [out] */ IUnknown **pAppDomain); + + HRESULT ( STDMETHODCALLTYPE *EnumDomains )( + ICorRuntimeHost * This, + /* [out] */ HDOMAINENUM *hEnum); + + HRESULT ( STDMETHODCALLTYPE *NextDomain )( + ICorRuntimeHost * This, + /* [in] */ HDOMAINENUM hEnum, + /* [out] */ IUnknown **pAppDomain); + + HRESULT ( STDMETHODCALLTYPE *CloseEnum )( + ICorRuntimeHost * This, + /* [in] */ HDOMAINENUM hEnum); + + HRESULT ( STDMETHODCALLTYPE *CreateDomainEx )( + ICorRuntimeHost * This, + /* [in] */ LPCWSTR pwzFriendlyName, + /* [in] */ IUnknown *pSetup, + /* [in] */ IUnknown *pEvidence, + /* [out] */ IUnknown **pAppDomain); + + HRESULT ( STDMETHODCALLTYPE *CreateDomainSetup )( + ICorRuntimeHost * This, + /* [out] */ IUnknown **pAppDomainSetup); + + HRESULT ( STDMETHODCALLTYPE *CreateEvidence )( + ICorRuntimeHost * This, + /* [out] */ IUnknown **pEvidence); + + HRESULT ( STDMETHODCALLTYPE *UnloadDomain )( + ICorRuntimeHost * This, + /* [in] */ IUnknown *pAppDomain); + + HRESULT ( STDMETHODCALLTYPE *CurrentDomain )( + ICorRuntimeHost * This, + /* [out] */ IUnknown **pAppDomain); + + END_INTERFACE + } ICorRuntimeHostVtbl; + + interface ICorRuntimeHost + { + CONST_VTBL struct ICorRuntimeHostVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorRuntimeHost_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICorRuntimeHost_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICorRuntimeHost_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICorRuntimeHost_CreateLogicalThreadState(This) \ + (This)->lpVtbl -> CreateLogicalThreadState(This) + +#define ICorRuntimeHost_DeleteLogicalThreadState(This) \ + (This)->lpVtbl -> DeleteLogicalThreadState(This) + +#define ICorRuntimeHost_SwitchInLogicalThreadState(This,pFiberCookie) \ + (This)->lpVtbl -> SwitchInLogicalThreadState(This,pFiberCookie) + +#define ICorRuntimeHost_SwitchOutLogicalThreadState(This,pFiberCookie) \ + (This)->lpVtbl -> SwitchOutLogicalThreadState(This,pFiberCookie) + +#define ICorRuntimeHost_LocksHeldByLogicalThread(This,pCount) \ + (This)->lpVtbl -> LocksHeldByLogicalThread(This,pCount) + +#define ICorRuntimeHost_MapFile(This,hFile,hMapAddress) \ + (This)->lpVtbl -> MapFile(This,hFile,hMapAddress) + +#define ICorRuntimeHost_GetConfiguration(This,pConfiguration) \ + (This)->lpVtbl -> GetConfiguration(This,pConfiguration) + +#define ICorRuntimeHost_Start(This) \ + (This)->lpVtbl -> Start(This) + +#define ICorRuntimeHost_Stop(This) \ + (This)->lpVtbl -> Stop(This) + +#define ICorRuntimeHost_CreateDomain(This,pwzFriendlyName,pIdentityArray,pAppDomain) \ + (This)->lpVtbl -> CreateDomain(This,pwzFriendlyName,pIdentityArray,pAppDomain) + +#define ICorRuntimeHost_GetDefaultDomain(This,pAppDomain) \ + (This)->lpVtbl -> GetDefaultDomain(This,pAppDomain) + +#define ICorRuntimeHost_EnumDomains(This,hEnum) \ + (This)->lpVtbl -> EnumDomains(This,hEnum) + +#define ICorRuntimeHost_NextDomain(This,hEnum,pAppDomain) \ + (This)->lpVtbl -> NextDomain(This,hEnum,pAppDomain) + +#define ICorRuntimeHost_CloseEnum(This,hEnum) \ + (This)->lpVtbl -> CloseEnum(This,hEnum) + +#define ICorRuntimeHost_CreateDomainEx(This,pwzFriendlyName,pSetup,pEvidence,pAppDomain) \ + (This)->lpVtbl -> CreateDomainEx(This,pwzFriendlyName,pSetup,pEvidence,pAppDomain) + +#define ICorRuntimeHost_CreateDomainSetup(This,pAppDomainSetup) \ + (This)->lpVtbl -> CreateDomainSetup(This,pAppDomainSetup) + +#define ICorRuntimeHost_CreateEvidence(This,pEvidence) \ + (This)->lpVtbl -> CreateEvidence(This,pEvidence) + +#define ICorRuntimeHost_UnloadDomain(This,pAppDomain) \ + (This)->lpVtbl -> UnloadDomain(This,pAppDomain) + +#define ICorRuntimeHost_CurrentDomain(This,pAppDomain) \ + (This)->lpVtbl -> CurrentDomain(This,pAppDomain) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_CreateLogicalThreadState_Proxy( + ICorRuntimeHost * This); + + +void __RPC_STUB ICorRuntimeHost_CreateLogicalThreadState_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_DeleteLogicalThreadState_Proxy( + ICorRuntimeHost * This); + + +void __RPC_STUB ICorRuntimeHost_DeleteLogicalThreadState_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_SwitchInLogicalThreadState_Proxy( + ICorRuntimeHost * This, + /* [in] */ DWORD *pFiberCookie); + + +void __RPC_STUB ICorRuntimeHost_SwitchInLogicalThreadState_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_SwitchOutLogicalThreadState_Proxy( + ICorRuntimeHost * This, + /* [out] */ DWORD **pFiberCookie); + + +void __RPC_STUB ICorRuntimeHost_SwitchOutLogicalThreadState_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_LocksHeldByLogicalThread_Proxy( + ICorRuntimeHost * This, + /* [out] */ DWORD *pCount); + + +void __RPC_STUB ICorRuntimeHost_LocksHeldByLogicalThread_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_MapFile_Proxy( + ICorRuntimeHost * This, + /* [in] */ HANDLE hFile, + /* [out] */ HMODULE *hMapAddress); + + +void __RPC_STUB ICorRuntimeHost_MapFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_GetConfiguration_Proxy( + ICorRuntimeHost * This, + /* [out] */ ICorConfiguration **pConfiguration); + + +void __RPC_STUB ICorRuntimeHost_GetConfiguration_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_Start_Proxy( + ICorRuntimeHost * This); + + +void __RPC_STUB ICorRuntimeHost_Start_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_Stop_Proxy( + ICorRuntimeHost * This); + + +void __RPC_STUB ICorRuntimeHost_Stop_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_CreateDomain_Proxy( + ICorRuntimeHost * This, + /* [in] */ LPCWSTR pwzFriendlyName, + /* [in] */ IUnknown *pIdentityArray, + /* [out] */ IUnknown **pAppDomain); + + +void __RPC_STUB ICorRuntimeHost_CreateDomain_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_GetDefaultDomain_Proxy( + ICorRuntimeHost * This, + /* [out] */ IUnknown **pAppDomain); + + +void __RPC_STUB ICorRuntimeHost_GetDefaultDomain_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_EnumDomains_Proxy( + ICorRuntimeHost * This, + /* [out] */ HDOMAINENUM *hEnum); + + +void __RPC_STUB ICorRuntimeHost_EnumDomains_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_NextDomain_Proxy( + ICorRuntimeHost * This, + /* [in] */ HDOMAINENUM hEnum, + /* [out] */ IUnknown **pAppDomain); + + +void __RPC_STUB ICorRuntimeHost_NextDomain_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_CloseEnum_Proxy( + ICorRuntimeHost * This, + /* [in] */ HDOMAINENUM hEnum); + + +void __RPC_STUB ICorRuntimeHost_CloseEnum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_CreateDomainEx_Proxy( + ICorRuntimeHost * This, + /* [in] */ LPCWSTR pwzFriendlyName, + /* [in] */ IUnknown *pSetup, + /* [in] */ IUnknown *pEvidence, + /* [out] */ IUnknown **pAppDomain); + + +void __RPC_STUB ICorRuntimeHost_CreateDomainEx_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_CreateDomainSetup_Proxy( + ICorRuntimeHost * This, + /* [out] */ IUnknown **pAppDomainSetup); + + +void __RPC_STUB ICorRuntimeHost_CreateDomainSetup_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_CreateEvidence_Proxy( + ICorRuntimeHost * This, + /* [out] */ IUnknown **pEvidence); + + +void __RPC_STUB ICorRuntimeHost_CreateEvidence_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_UnloadDomain_Proxy( + ICorRuntimeHost * This, + /* [in] */ IUnknown *pAppDomain); + + +void __RPC_STUB ICorRuntimeHost_UnloadDomain_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICorRuntimeHost_CurrentDomain_Proxy( + ICorRuntimeHost * This, + /* [out] */ IUnknown **pAppDomain); + + +void __RPC_STUB ICorRuntimeHost_CurrentDomain_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICorRuntimeHost_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0133 */ +/* [local] */ + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_mscoree_0133_0001 + { eMemoryAvailableLow = 1, + eMemoryAvailableNeutral = 2, + eMemoryAvailableHigh = 3 + } EMemoryAvailable; + +typedef /* [public][public][public][public] */ +enum __MIDL___MIDL_itf_mscoree_0133_0002 + { eTaskCritical = 0, + eAppDomainCritical = 1, + eProcessCritical = 2 + } EMemoryCriticalLevel; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscoree_0133_0003 + { WAIT_MSGPUMP = 0x1, + WAIT_ALERTABLE = 0x2, + WAIT_NOTINDEADLOCK = 0x4 + } WAIT_OPTION; + +EXTERN_GUID(IID_ICLRMemoryNotificationCallback, 0x47EB8E57, 0x0846, 0x4546, 0xAF, 0x76, 0x6F, 0x42, 0xFC, 0xFC, 0x26, 0x49); + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0133_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0133_v0_0_s_ifspec; + +#ifndef __ICLRMemoryNotificationCallback_INTERFACE_DEFINED__ +#define __ICLRMemoryNotificationCallback_INTERFACE_DEFINED__ + +/* interface ICLRMemoryNotificationCallback */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRMemoryNotificationCallback; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("47EB8E57-0846-4546-AF76-6F42FCFC2649") + ICLRMemoryNotificationCallback : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE OnMemoryNotification( + /* [in] */ EMemoryAvailable eMemoryAvailable) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLRMemoryNotificationCallbackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRMemoryNotificationCallback * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRMemoryNotificationCallback * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRMemoryNotificationCallback * This); + + HRESULT ( STDMETHODCALLTYPE *OnMemoryNotification )( + ICLRMemoryNotificationCallback * This, + /* [in] */ EMemoryAvailable eMemoryAvailable); + + END_INTERFACE + } ICLRMemoryNotificationCallbackVtbl; + + interface ICLRMemoryNotificationCallback + { + CONST_VTBL struct ICLRMemoryNotificationCallbackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRMemoryNotificationCallback_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLRMemoryNotificationCallback_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLRMemoryNotificationCallback_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLRMemoryNotificationCallback_OnMemoryNotification(This,eMemoryAvailable) \ + (This)->lpVtbl -> OnMemoryNotification(This,eMemoryAvailable) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLRMemoryNotificationCallback_OnMemoryNotification_Proxy( + ICLRMemoryNotificationCallback * This, + /* [in] */ EMemoryAvailable eMemoryAvailable); + + +void __RPC_STUB ICLRMemoryNotificationCallback_OnMemoryNotification_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLRMemoryNotificationCallback_INTERFACE_DEFINED__ */ + + +#ifndef __IHostMalloc_INTERFACE_DEFINED__ +#define __IHostMalloc_INTERFACE_DEFINED__ + +/* interface IHostMalloc */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IHostMalloc; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("1831991C-CC53-4A31-B218-04E910446479") + IHostMalloc : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Alloc( + /* [in] */ SIZE_T cbSize, + /* [in] */ EMemoryCriticalLevel eCriticalLevel, + /* [out] */ void **ppMem) = 0; + + virtual HRESULT STDMETHODCALLTYPE DebugAlloc( + /* [in] */ SIZE_T cbSize, + /* [in] */ EMemoryCriticalLevel eCriticalLevel, + /* [in] */ char *pszFileName, + /* [in] */ int iLineNo, + /* [out] */ void **ppMem) = 0; + + virtual HRESULT STDMETHODCALLTYPE Free( + /* [in] */ void *pMem) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostMallocVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostMalloc * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostMalloc * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostMalloc * This); + + HRESULT ( STDMETHODCALLTYPE *Alloc )( + IHostMalloc * This, + /* [in] */ SIZE_T cbSize, + /* [in] */ EMemoryCriticalLevel eCriticalLevel, + /* [out] */ void **ppMem); + + HRESULT ( STDMETHODCALLTYPE *DebugAlloc )( + IHostMalloc * This, + /* [in] */ SIZE_T cbSize, + /* [in] */ EMemoryCriticalLevel eCriticalLevel, + /* [in] */ char *pszFileName, + /* [in] */ int iLineNo, + /* [out] */ void **ppMem); + + HRESULT ( STDMETHODCALLTYPE *Free )( + IHostMalloc * This, + /* [in] */ void *pMem); + + END_INTERFACE + } IHostMallocVtbl; + + interface IHostMalloc + { + CONST_VTBL struct IHostMallocVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostMalloc_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostMalloc_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostMalloc_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostMalloc_Alloc(This,cbSize,eCriticalLevel,ppMem) \ + (This)->lpVtbl -> Alloc(This,cbSize,eCriticalLevel,ppMem) + +#define IHostMalloc_DebugAlloc(This,cbSize,eCriticalLevel,pszFileName,iLineNo,ppMem) \ + (This)->lpVtbl -> DebugAlloc(This,cbSize,eCriticalLevel,pszFileName,iLineNo,ppMem) + +#define IHostMalloc_Free(This,pMem) \ + (This)->lpVtbl -> Free(This,pMem) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostMalloc_Alloc_Proxy( + IHostMalloc * This, + /* [in] */ SIZE_T cbSize, + /* [in] */ EMemoryCriticalLevel eCriticalLevel, + /* [out] */ void **ppMem); + + +void __RPC_STUB IHostMalloc_Alloc_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostMalloc_DebugAlloc_Proxy( + IHostMalloc * This, + /* [in] */ SIZE_T cbSize, + /* [in] */ EMemoryCriticalLevel eCriticalLevel, + /* [in] */ char *pszFileName, + /* [in] */ int iLineNo, + /* [out] */ void **ppMem); + + +void __RPC_STUB IHostMalloc_DebugAlloc_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostMalloc_Free_Proxy( + IHostMalloc * This, + /* [in] */ void *pMem); + + +void __RPC_STUB IHostMalloc_Free_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostMalloc_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0135 */ +/* [local] */ + +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscoree_0135_0001 + { MALLOC_THREADSAFE = 0x1, + MALLOC_EXECUTABLE = 0x2 + } MALLOC_TYPE; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0135_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0135_v0_0_s_ifspec; + +#ifndef __IHostMemoryManager_INTERFACE_DEFINED__ +#define __IHostMemoryManager_INTERFACE_DEFINED__ + +/* interface IHostMemoryManager */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IHostMemoryManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("7BC698D1-F9E3-4460-9CDE-D04248E9FA25") + IHostMemoryManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateMalloc( + /* [in] */ DWORD dwMallocType, + /* [out] */ IHostMalloc **ppMalloc) = 0; + + virtual HRESULT STDMETHODCALLTYPE VirtualAlloc( + /* [in] */ void *pAddress, + /* [in] */ SIZE_T dwSize, + /* [in] */ DWORD flAllocationType, + /* [in] */ DWORD flProtect, + /* [in] */ EMemoryCriticalLevel eCriticalLevel, + /* [out] */ void **ppMem) = 0; + + virtual HRESULT STDMETHODCALLTYPE VirtualFree( + /* [in] */ LPVOID lpAddress, + /* [in] */ SIZE_T dwSize, + /* [in] */ DWORD dwFreeType) = 0; + + virtual HRESULT STDMETHODCALLTYPE VirtualQuery( + /* [in] */ void *lpAddress, + /* [out] */ void *lpBuffer, + /* [in] */ SIZE_T dwLength, + /* [out] */ SIZE_T *pResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE VirtualProtect( + /* [in] */ void *lpAddress, + /* [in] */ SIZE_T dwSize, + /* [in] */ DWORD flNewProtect, + /* [out] */ DWORD *pflOldProtect) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMemoryLoad( + /* [out] */ DWORD *pMemoryLoad, + /* [out] */ SIZE_T *pAvailableBytes) = 0; + + virtual HRESULT STDMETHODCALLTYPE RegisterMemoryNotificationCallback( + /* [in] */ ICLRMemoryNotificationCallback *pCallback) = 0; + + virtual HRESULT STDMETHODCALLTYPE NeedsVirtualAddressSpace( + /* [in] */ LPVOID startAddress, + /* [in] */ SIZE_T size) = 0; + + virtual HRESULT STDMETHODCALLTYPE AcquiredVirtualAddressSpace( + /* [in] */ LPVOID startAddress, + /* [in] */ SIZE_T size) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReleasedVirtualAddressSpace( + /* [in] */ LPVOID startAddress) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostMemoryManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostMemoryManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostMemoryManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostMemoryManager * This); + + HRESULT ( STDMETHODCALLTYPE *CreateMalloc )( + IHostMemoryManager * This, + /* [in] */ DWORD dwMallocType, + /* [out] */ IHostMalloc **ppMalloc); + + HRESULT ( STDMETHODCALLTYPE *VirtualAlloc )( + IHostMemoryManager * This, + /* [in] */ void *pAddress, + /* [in] */ SIZE_T dwSize, + /* [in] */ DWORD flAllocationType, + /* [in] */ DWORD flProtect, + /* [in] */ EMemoryCriticalLevel eCriticalLevel, + /* [out] */ void **ppMem); + + HRESULT ( STDMETHODCALLTYPE *VirtualFree )( + IHostMemoryManager * This, + /* [in] */ LPVOID lpAddress, + /* [in] */ SIZE_T dwSize, + /* [in] */ DWORD dwFreeType); + + HRESULT ( STDMETHODCALLTYPE *VirtualQuery )( + IHostMemoryManager * This, + /* [in] */ void *lpAddress, + /* [out] */ void *lpBuffer, + /* [in] */ SIZE_T dwLength, + /* [out] */ SIZE_T *pResult); + + HRESULT ( STDMETHODCALLTYPE *VirtualProtect )( + IHostMemoryManager * This, + /* [in] */ void *lpAddress, + /* [in] */ SIZE_T dwSize, + /* [in] */ DWORD flNewProtect, + /* [out] */ DWORD *pflOldProtect); + + HRESULT ( STDMETHODCALLTYPE *GetMemoryLoad )( + IHostMemoryManager * This, + /* [out] */ DWORD *pMemoryLoad, + /* [out] */ SIZE_T *pAvailableBytes); + + HRESULT ( STDMETHODCALLTYPE *RegisterMemoryNotificationCallback )( + IHostMemoryManager * This, + /* [in] */ ICLRMemoryNotificationCallback *pCallback); + + HRESULT ( STDMETHODCALLTYPE *NeedsVirtualAddressSpace )( + IHostMemoryManager * This, + /* [in] */ LPVOID startAddress, + /* [in] */ SIZE_T size); + + HRESULT ( STDMETHODCALLTYPE *AcquiredVirtualAddressSpace )( + IHostMemoryManager * This, + /* [in] */ LPVOID startAddress, + /* [in] */ SIZE_T size); + + HRESULT ( STDMETHODCALLTYPE *ReleasedVirtualAddressSpace )( + IHostMemoryManager * This, + /* [in] */ LPVOID startAddress); + + END_INTERFACE + } IHostMemoryManagerVtbl; + + interface IHostMemoryManager + { + CONST_VTBL struct IHostMemoryManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostMemoryManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostMemoryManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostMemoryManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostMemoryManager_CreateMalloc(This,dwMallocType,ppMalloc) \ + (This)->lpVtbl -> CreateMalloc(This,dwMallocType,ppMalloc) + +#define IHostMemoryManager_VirtualAlloc(This,pAddress,dwSize,flAllocationType,flProtect,eCriticalLevel,ppMem) \ + (This)->lpVtbl -> VirtualAlloc(This,pAddress,dwSize,flAllocationType,flProtect,eCriticalLevel,ppMem) + +#define IHostMemoryManager_VirtualFree(This,lpAddress,dwSize,dwFreeType) \ + (This)->lpVtbl -> VirtualFree(This,lpAddress,dwSize,dwFreeType) + +#define IHostMemoryManager_VirtualQuery(This,lpAddress,lpBuffer,dwLength,pResult) \ + (This)->lpVtbl -> VirtualQuery(This,lpAddress,lpBuffer,dwLength,pResult) + +#define IHostMemoryManager_VirtualProtect(This,lpAddress,dwSize,flNewProtect,pflOldProtect) \ + (This)->lpVtbl -> VirtualProtect(This,lpAddress,dwSize,flNewProtect,pflOldProtect) + +#define IHostMemoryManager_GetMemoryLoad(This,pMemoryLoad,pAvailableBytes) \ + (This)->lpVtbl -> GetMemoryLoad(This,pMemoryLoad,pAvailableBytes) + +#define IHostMemoryManager_RegisterMemoryNotificationCallback(This,pCallback) \ + (This)->lpVtbl -> RegisterMemoryNotificationCallback(This,pCallback) + +#define IHostMemoryManager_NeedsVirtualAddressSpace(This,startAddress,size) \ + (This)->lpVtbl -> NeedsVirtualAddressSpace(This,startAddress,size) + +#define IHostMemoryManager_AcquiredVirtualAddressSpace(This,startAddress,size) \ + (This)->lpVtbl -> AcquiredVirtualAddressSpace(This,startAddress,size) + +#define IHostMemoryManager_ReleasedVirtualAddressSpace(This,startAddress) \ + (This)->lpVtbl -> ReleasedVirtualAddressSpace(This,startAddress) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostMemoryManager_CreateMalloc_Proxy( + IHostMemoryManager * This, + /* [in] */ DWORD dwMallocType, + /* [out] */ IHostMalloc **ppMalloc); + + +void __RPC_STUB IHostMemoryManager_CreateMalloc_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostMemoryManager_VirtualAlloc_Proxy( + IHostMemoryManager * This, + /* [in] */ void *pAddress, + /* [in] */ SIZE_T dwSize, + /* [in] */ DWORD flAllocationType, + /* [in] */ DWORD flProtect, + /* [in] */ EMemoryCriticalLevel eCriticalLevel, + /* [out] */ void **ppMem); + + +void __RPC_STUB IHostMemoryManager_VirtualAlloc_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostMemoryManager_VirtualFree_Proxy( + IHostMemoryManager * This, + /* [in] */ LPVOID lpAddress, + /* [in] */ SIZE_T dwSize, + /* [in] */ DWORD dwFreeType); + + +void __RPC_STUB IHostMemoryManager_VirtualFree_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostMemoryManager_VirtualQuery_Proxy( + IHostMemoryManager * This, + /* [in] */ void *lpAddress, + /* [out] */ void *lpBuffer, + /* [in] */ SIZE_T dwLength, + /* [out] */ SIZE_T *pResult); + + +void __RPC_STUB IHostMemoryManager_VirtualQuery_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostMemoryManager_VirtualProtect_Proxy( + IHostMemoryManager * This, + /* [in] */ void *lpAddress, + /* [in] */ SIZE_T dwSize, + /* [in] */ DWORD flNewProtect, + /* [out] */ DWORD *pflOldProtect); + + +void __RPC_STUB IHostMemoryManager_VirtualProtect_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostMemoryManager_GetMemoryLoad_Proxy( + IHostMemoryManager * This, + /* [out] */ DWORD *pMemoryLoad, + /* [out] */ SIZE_T *pAvailableBytes); + + +void __RPC_STUB IHostMemoryManager_GetMemoryLoad_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostMemoryManager_RegisterMemoryNotificationCallback_Proxy( + IHostMemoryManager * This, + /* [in] */ ICLRMemoryNotificationCallback *pCallback); + + +void __RPC_STUB IHostMemoryManager_RegisterMemoryNotificationCallback_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostMemoryManager_NeedsVirtualAddressSpace_Proxy( + IHostMemoryManager * This, + /* [in] */ LPVOID startAddress, + /* [in] */ SIZE_T size); + + +void __RPC_STUB IHostMemoryManager_NeedsVirtualAddressSpace_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostMemoryManager_AcquiredVirtualAddressSpace_Proxy( + IHostMemoryManager * This, + /* [in] */ LPVOID startAddress, + /* [in] */ SIZE_T size); + + +void __RPC_STUB IHostMemoryManager_AcquiredVirtualAddressSpace_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostMemoryManager_ReleasedVirtualAddressSpace_Proxy( + IHostMemoryManager * This, + /* [in] */ LPVOID startAddress); + + +void __RPC_STUB IHostMemoryManager_ReleasedVirtualAddressSpace_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostMemoryManager_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0136 */ +/* [local] */ + +typedef UINT64 TASKID; + +typedef DWORD CONNID; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0136_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0136_v0_0_s_ifspec; + +#ifndef __ICLRTask_INTERFACE_DEFINED__ +#define __ICLRTask_INTERFACE_DEFINED__ + +/* interface ICLRTask */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRTask; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("28E66A4A-9906-4225-B231-9187C3EB8611") + ICLRTask : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SwitchIn( + /* [in] */ HANDLE threadHandle) = 0; + + virtual HRESULT STDMETHODCALLTYPE SwitchOut( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMemStats( + /* [out] */ COR_GC_THREAD_STATS *memUsage) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( + BOOL fFull) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExitTask( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Abort( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE RudeAbort( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE NeedsPriorityScheduling( + /* [out] */ BOOL *pbNeedsPriorityScheduling) = 0; + + virtual HRESULT STDMETHODCALLTYPE YieldTask( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE LocksHeld( + /* [out] */ SIZE_T *pLockCount) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetTaskIdentifier( + /* [in] */ TASKID asked) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLRTaskVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRTask * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRTask * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRTask * This); + + HRESULT ( STDMETHODCALLTYPE *SwitchIn )( + ICLRTask * This, + /* [in] */ HANDLE threadHandle); + + HRESULT ( STDMETHODCALLTYPE *SwitchOut )( + ICLRTask * This); + + HRESULT ( STDMETHODCALLTYPE *GetMemStats )( + ICLRTask * This, + /* [out] */ COR_GC_THREAD_STATS *memUsage); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICLRTask * This, + BOOL fFull); + + HRESULT ( STDMETHODCALLTYPE *ExitTask )( + ICLRTask * This); + + HRESULT ( STDMETHODCALLTYPE *Abort )( + ICLRTask * This); + + HRESULT ( STDMETHODCALLTYPE *RudeAbort )( + ICLRTask * This); + + HRESULT ( STDMETHODCALLTYPE *NeedsPriorityScheduling )( + ICLRTask * This, + /* [out] */ BOOL *pbNeedsPriorityScheduling); + + HRESULT ( STDMETHODCALLTYPE *YieldTask )( + ICLRTask * This); + + HRESULT ( STDMETHODCALLTYPE *LocksHeld )( + ICLRTask * This, + /* [out] */ SIZE_T *pLockCount); + + HRESULT ( STDMETHODCALLTYPE *SetTaskIdentifier )( + ICLRTask * This, + /* [in] */ TASKID asked); + + END_INTERFACE + } ICLRTaskVtbl; + + interface ICLRTask + { + CONST_VTBL struct ICLRTaskVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRTask_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLRTask_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLRTask_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLRTask_SwitchIn(This,threadHandle) \ + (This)->lpVtbl -> SwitchIn(This,threadHandle) + +#define ICLRTask_SwitchOut(This) \ + (This)->lpVtbl -> SwitchOut(This) + +#define ICLRTask_GetMemStats(This,memUsage) \ + (This)->lpVtbl -> GetMemStats(This,memUsage) + +#define ICLRTask_Reset(This,fFull) \ + (This)->lpVtbl -> Reset(This,fFull) + +#define ICLRTask_ExitTask(This) \ + (This)->lpVtbl -> ExitTask(This) + +#define ICLRTask_Abort(This) \ + (This)->lpVtbl -> Abort(This) + +#define ICLRTask_RudeAbort(This) \ + (This)->lpVtbl -> RudeAbort(This) + +#define ICLRTask_NeedsPriorityScheduling(This,pbNeedsPriorityScheduling) \ + (This)->lpVtbl -> NeedsPriorityScheduling(This,pbNeedsPriorityScheduling) + +#define ICLRTask_YieldTask(This) \ + (This)->lpVtbl -> YieldTask(This) + +#define ICLRTask_LocksHeld(This,pLockCount) \ + (This)->lpVtbl -> LocksHeld(This,pLockCount) + +#define ICLRTask_SetTaskIdentifier(This,asked) \ + (This)->lpVtbl -> SetTaskIdentifier(This,asked) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLRTask_SwitchIn_Proxy( + ICLRTask * This, + /* [in] */ HANDLE threadHandle); + + +void __RPC_STUB ICLRTask_SwitchIn_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRTask_SwitchOut_Proxy( + ICLRTask * This); + + +void __RPC_STUB ICLRTask_SwitchOut_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRTask_GetMemStats_Proxy( + ICLRTask * This, + /* [out] */ COR_GC_THREAD_STATS *memUsage); + + +void __RPC_STUB ICLRTask_GetMemStats_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRTask_Reset_Proxy( + ICLRTask * This, + BOOL fFull); + + +void __RPC_STUB ICLRTask_Reset_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRTask_ExitTask_Proxy( + ICLRTask * This); + + +void __RPC_STUB ICLRTask_ExitTask_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRTask_Abort_Proxy( + ICLRTask * This); + + +void __RPC_STUB ICLRTask_Abort_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRTask_RudeAbort_Proxy( + ICLRTask * This); + + +void __RPC_STUB ICLRTask_RudeAbort_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRTask_NeedsPriorityScheduling_Proxy( + ICLRTask * This, + /* [out] */ BOOL *pbNeedsPriorityScheduling); + + +void __RPC_STUB ICLRTask_NeedsPriorityScheduling_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRTask_YieldTask_Proxy( + ICLRTask * This); + + +void __RPC_STUB ICLRTask_YieldTask_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRTask_LocksHeld_Proxy( + ICLRTask * This, + /* [out] */ SIZE_T *pLockCount); + + +void __RPC_STUB ICLRTask_LocksHeld_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRTask_SetTaskIdentifier_Proxy( + ICLRTask * This, + /* [in] */ TASKID asked); + + +void __RPC_STUB ICLRTask_SetTaskIdentifier_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLRTask_INTERFACE_DEFINED__ */ + + +#ifndef __IHostTask_INTERFACE_DEFINED__ +#define __IHostTask_INTERFACE_DEFINED__ + +/* interface IHostTask */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IHostTask; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("C2275828-C4B1-4B55-82C9-92135F74DF1A") + IHostTask : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Start( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Alert( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Join( + /* [in] */ DWORD dwMilliseconds, + /* [in] */ DWORD option) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetPriority( + /* [in] */ int newPriority) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetPriority( + /* [out] */ int *pPriority) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetCLRTask( + /* [in] */ ICLRTask *pCLRTask) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostTaskVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostTask * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostTask * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostTask * This); + + HRESULT ( STDMETHODCALLTYPE *Start )( + IHostTask * This); + + HRESULT ( STDMETHODCALLTYPE *Alert )( + IHostTask * This); + + HRESULT ( STDMETHODCALLTYPE *Join )( + IHostTask * This, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ DWORD option); + + HRESULT ( STDMETHODCALLTYPE *SetPriority )( + IHostTask * This, + /* [in] */ int newPriority); + + HRESULT ( STDMETHODCALLTYPE *GetPriority )( + IHostTask * This, + /* [out] */ int *pPriority); + + HRESULT ( STDMETHODCALLTYPE *SetCLRTask )( + IHostTask * This, + /* [in] */ ICLRTask *pCLRTask); + + END_INTERFACE + } IHostTaskVtbl; + + interface IHostTask + { + CONST_VTBL struct IHostTaskVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostTask_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostTask_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostTask_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostTask_Start(This) \ + (This)->lpVtbl -> Start(This) + +#define IHostTask_Alert(This) \ + (This)->lpVtbl -> Alert(This) + +#define IHostTask_Join(This,dwMilliseconds,option) \ + (This)->lpVtbl -> Join(This,dwMilliseconds,option) + +#define IHostTask_SetPriority(This,newPriority) \ + (This)->lpVtbl -> SetPriority(This,newPriority) + +#define IHostTask_GetPriority(This,pPriority) \ + (This)->lpVtbl -> GetPriority(This,pPriority) + +#define IHostTask_SetCLRTask(This,pCLRTask) \ + (This)->lpVtbl -> SetCLRTask(This,pCLRTask) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostTask_Start_Proxy( + IHostTask * This); + + +void __RPC_STUB IHostTask_Start_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTask_Alert_Proxy( + IHostTask * This); + + +void __RPC_STUB IHostTask_Alert_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTask_Join_Proxy( + IHostTask * This, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ DWORD option); + + +void __RPC_STUB IHostTask_Join_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTask_SetPriority_Proxy( + IHostTask * This, + /* [in] */ int newPriority); + + +void __RPC_STUB IHostTask_SetPriority_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTask_GetPriority_Proxy( + IHostTask * This, + /* [out] */ int *pPriority); + + +void __RPC_STUB IHostTask_GetPriority_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTask_SetCLRTask_Proxy( + IHostTask * This, + /* [in] */ ICLRTask *pCLRTask); + + +void __RPC_STUB IHostTask_SetCLRTask_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostTask_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0138 */ +/* [local] */ + +typedef +enum ETaskType + { TT_DEBUGGERHELPER = 0x1, + TT_GC = 0x2, + TT_FINALIZER = 0x4, + TT_THREADPOOL_TIMER = 0x8, + TT_THREADPOOL_GATE = 0x10, + TT_THREADPOOL_WORKER = 0x20, + TT_THREADPOOL_IOCOMPLETION = 0x40, + TT_ADUNLOAD = 0x80, + TT_USER = 0x100, + TT_THREADPOOL_WAIT = 0x200, + TT_UNKNOWN = 0x80000000 + } ETaskType; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0138_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0138_v0_0_s_ifspec; + +#ifndef __ICLRTaskManager_INTERFACE_DEFINED__ +#define __ICLRTaskManager_INTERFACE_DEFINED__ + +/* interface ICLRTaskManager */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRTaskManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("4862efbe-3ae5-44f8-8feb-346190ee8a34") + ICLRTaskManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateTask( + /* [out] */ ICLRTask **pTask) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCurrentTask( + /* [out] */ ICLRTask **pTask) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetUILocale( + /* [in] */ LCID lcid) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetLocale( + /* [in] */ LCID lcid) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCurrentTaskType( + /* [out] */ ETaskType *pTaskType) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLRTaskManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRTaskManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRTaskManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRTaskManager * This); + + HRESULT ( STDMETHODCALLTYPE *CreateTask )( + ICLRTaskManager * This, + /* [out] */ ICLRTask **pTask); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentTask )( + ICLRTaskManager * This, + /* [out] */ ICLRTask **pTask); + + HRESULT ( STDMETHODCALLTYPE *SetUILocale )( + ICLRTaskManager * This, + /* [in] */ LCID lcid); + + HRESULT ( STDMETHODCALLTYPE *SetLocale )( + ICLRTaskManager * This, + /* [in] */ LCID lcid); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentTaskType )( + ICLRTaskManager * This, + /* [out] */ ETaskType *pTaskType); + + END_INTERFACE + } ICLRTaskManagerVtbl; + + interface ICLRTaskManager + { + CONST_VTBL struct ICLRTaskManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRTaskManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLRTaskManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLRTaskManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLRTaskManager_CreateTask(This,pTask) \ + (This)->lpVtbl -> CreateTask(This,pTask) + +#define ICLRTaskManager_GetCurrentTask(This,pTask) \ + (This)->lpVtbl -> GetCurrentTask(This,pTask) + +#define ICLRTaskManager_SetUILocale(This,lcid) \ + (This)->lpVtbl -> SetUILocale(This,lcid) + +#define ICLRTaskManager_SetLocale(This,lcid) \ + (This)->lpVtbl -> SetLocale(This,lcid) + +#define ICLRTaskManager_GetCurrentTaskType(This,pTaskType) \ + (This)->lpVtbl -> GetCurrentTaskType(This,pTaskType) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLRTaskManager_CreateTask_Proxy( + ICLRTaskManager * This, + /* [out] */ ICLRTask **pTask); + + +void __RPC_STUB ICLRTaskManager_CreateTask_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRTaskManager_GetCurrentTask_Proxy( + ICLRTaskManager * This, + /* [out] */ ICLRTask **pTask); + + +void __RPC_STUB ICLRTaskManager_GetCurrentTask_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRTaskManager_SetUILocale_Proxy( + ICLRTaskManager * This, + /* [in] */ LCID lcid); + + +void __RPC_STUB ICLRTaskManager_SetUILocale_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRTaskManager_SetLocale_Proxy( + ICLRTaskManager * This, + /* [in] */ LCID lcid); + + +void __RPC_STUB ICLRTaskManager_SetLocale_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRTaskManager_GetCurrentTaskType_Proxy( + ICLRTaskManager * This, + /* [out] */ ETaskType *pTaskType); + + +void __RPC_STUB ICLRTaskManager_GetCurrentTaskType_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLRTaskManager_INTERFACE_DEFINED__ */ + + +#ifndef __IHostTaskManager_INTERFACE_DEFINED__ +#define __IHostTaskManager_INTERFACE_DEFINED__ + +/* interface IHostTaskManager */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IHostTaskManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("997FF24C-43B7-4352-8667-0DC04FAFD354") + IHostTaskManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetCurrentTask( + /* [out] */ IHostTask **pTask) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateTask( + /* [in] */ DWORD dwStackSize, + /* [in] */ LPTHREAD_START_ROUTINE pStartAddress, + /* [in] */ PVOID pParameter, + /* [out] */ IHostTask **ppTask) = 0; + + virtual HRESULT STDMETHODCALLTYPE Sleep( + /* [in] */ DWORD dwMilliseconds, + /* [in] */ DWORD option) = 0; + + virtual HRESULT STDMETHODCALLTYPE SwitchToTask( + /* [in] */ DWORD option) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetUILocale( + /* [in] */ LCID lcid) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetLocale( + /* [in] */ LCID lcid) = 0; + + virtual HRESULT STDMETHODCALLTYPE CallNeedsHostHook( + /* [in] */ SIZE_T target, + /* [out] */ BOOL *pbCallNeedsHostHook) = 0; + + virtual HRESULT STDMETHODCALLTYPE LeaveRuntime( + /* [in] */ SIZE_T target) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnterRuntime( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReverseLeaveRuntime( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReverseEnterRuntime( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginDelayAbort( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndDelayAbort( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginThreadAffinity( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndThreadAffinity( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetStackGuarantee( + /* [in] */ ULONG guarantee) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStackGuarantee( + /* [out] */ ULONG *pGuarantee) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetCLRTaskManager( + /* [in] */ ICLRTaskManager *ppManager) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostTaskManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostTaskManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostTaskManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostTaskManager * This); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentTask )( + IHostTaskManager * This, + /* [out] */ IHostTask **pTask); + + HRESULT ( STDMETHODCALLTYPE *CreateTask )( + IHostTaskManager * This, + /* [in] */ DWORD dwStackSize, + /* [in] */ LPTHREAD_START_ROUTINE pStartAddress, + /* [in] */ PVOID pParameter, + /* [out] */ IHostTask **ppTask); + + HRESULT ( STDMETHODCALLTYPE *Sleep )( + IHostTaskManager * This, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ DWORD option); + + HRESULT ( STDMETHODCALLTYPE *SwitchToTask )( + IHostTaskManager * This, + /* [in] */ DWORD option); + + HRESULT ( STDMETHODCALLTYPE *SetUILocale )( + IHostTaskManager * This, + /* [in] */ LCID lcid); + + HRESULT ( STDMETHODCALLTYPE *SetLocale )( + IHostTaskManager * This, + /* [in] */ LCID lcid); + + HRESULT ( STDMETHODCALLTYPE *CallNeedsHostHook )( + IHostTaskManager * This, + /* [in] */ SIZE_T target, + /* [out] */ BOOL *pbCallNeedsHostHook); + + HRESULT ( STDMETHODCALLTYPE *LeaveRuntime )( + IHostTaskManager * This, + /* [in] */ SIZE_T target); + + HRESULT ( STDMETHODCALLTYPE *EnterRuntime )( + IHostTaskManager * This); + + HRESULT ( STDMETHODCALLTYPE *ReverseLeaveRuntime )( + IHostTaskManager * This); + + HRESULT ( STDMETHODCALLTYPE *ReverseEnterRuntime )( + IHostTaskManager * This); + + HRESULT ( STDMETHODCALLTYPE *BeginDelayAbort )( + IHostTaskManager * This); + + HRESULT ( STDMETHODCALLTYPE *EndDelayAbort )( + IHostTaskManager * This); + + HRESULT ( STDMETHODCALLTYPE *BeginThreadAffinity )( + IHostTaskManager * This); + + HRESULT ( STDMETHODCALLTYPE *EndThreadAffinity )( + IHostTaskManager * This); + + HRESULT ( STDMETHODCALLTYPE *SetStackGuarantee )( + IHostTaskManager * This, + /* [in] */ ULONG guarantee); + + HRESULT ( STDMETHODCALLTYPE *GetStackGuarantee )( + IHostTaskManager * This, + /* [out] */ ULONG *pGuarantee); + + HRESULT ( STDMETHODCALLTYPE *SetCLRTaskManager )( + IHostTaskManager * This, + /* [in] */ ICLRTaskManager *ppManager); + + END_INTERFACE + } IHostTaskManagerVtbl; + + interface IHostTaskManager + { + CONST_VTBL struct IHostTaskManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostTaskManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostTaskManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostTaskManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostTaskManager_GetCurrentTask(This,pTask) \ + (This)->lpVtbl -> GetCurrentTask(This,pTask) + +#define IHostTaskManager_CreateTask(This,dwStackSize,pStartAddress,pParameter,ppTask) \ + (This)->lpVtbl -> CreateTask(This,dwStackSize,pStartAddress,pParameter,ppTask) + +#define IHostTaskManager_Sleep(This,dwMilliseconds,option) \ + (This)->lpVtbl -> Sleep(This,dwMilliseconds,option) + +#define IHostTaskManager_SwitchToTask(This,option) \ + (This)->lpVtbl -> SwitchToTask(This,option) + +#define IHostTaskManager_SetUILocale(This,lcid) \ + (This)->lpVtbl -> SetUILocale(This,lcid) + +#define IHostTaskManager_SetLocale(This,lcid) \ + (This)->lpVtbl -> SetLocale(This,lcid) + +#define IHostTaskManager_CallNeedsHostHook(This,target,pbCallNeedsHostHook) \ + (This)->lpVtbl -> CallNeedsHostHook(This,target,pbCallNeedsHostHook) + +#define IHostTaskManager_LeaveRuntime(This,target) \ + (This)->lpVtbl -> LeaveRuntime(This,target) + +#define IHostTaskManager_EnterRuntime(This) \ + (This)->lpVtbl -> EnterRuntime(This) + +#define IHostTaskManager_ReverseLeaveRuntime(This) \ + (This)->lpVtbl -> ReverseLeaveRuntime(This) + +#define IHostTaskManager_ReverseEnterRuntime(This) \ + (This)->lpVtbl -> ReverseEnterRuntime(This) + +#define IHostTaskManager_BeginDelayAbort(This) \ + (This)->lpVtbl -> BeginDelayAbort(This) + +#define IHostTaskManager_EndDelayAbort(This) \ + (This)->lpVtbl -> EndDelayAbort(This) + +#define IHostTaskManager_BeginThreadAffinity(This) \ + (This)->lpVtbl -> BeginThreadAffinity(This) + +#define IHostTaskManager_EndThreadAffinity(This) \ + (This)->lpVtbl -> EndThreadAffinity(This) + +#define IHostTaskManager_SetStackGuarantee(This,guarantee) \ + (This)->lpVtbl -> SetStackGuarantee(This,guarantee) + +#define IHostTaskManager_GetStackGuarantee(This,pGuarantee) \ + (This)->lpVtbl -> GetStackGuarantee(This,pGuarantee) + +#define IHostTaskManager_SetCLRTaskManager(This,ppManager) \ + (This)->lpVtbl -> SetCLRTaskManager(This,ppManager) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_GetCurrentTask_Proxy( + IHostTaskManager * This, + /* [out] */ IHostTask **pTask); + + +void __RPC_STUB IHostTaskManager_GetCurrentTask_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_CreateTask_Proxy( + IHostTaskManager * This, + /* [in] */ DWORD dwStackSize, + /* [in] */ LPTHREAD_START_ROUTINE pStartAddress, + /* [in] */ PVOID pParameter, + /* [out] */ IHostTask **ppTask); + + +void __RPC_STUB IHostTaskManager_CreateTask_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_Sleep_Proxy( + IHostTaskManager * This, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ DWORD option); + + +void __RPC_STUB IHostTaskManager_Sleep_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_SwitchToTask_Proxy( + IHostTaskManager * This, + /* [in] */ DWORD option); + + +void __RPC_STUB IHostTaskManager_SwitchToTask_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_SetUILocale_Proxy( + IHostTaskManager * This, + /* [in] */ LCID lcid); + + +void __RPC_STUB IHostTaskManager_SetUILocale_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_SetLocale_Proxy( + IHostTaskManager * This, + /* [in] */ LCID lcid); + + +void __RPC_STUB IHostTaskManager_SetLocale_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_CallNeedsHostHook_Proxy( + IHostTaskManager * This, + /* [in] */ SIZE_T target, + /* [out] */ BOOL *pbCallNeedsHostHook); + + +void __RPC_STUB IHostTaskManager_CallNeedsHostHook_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_LeaveRuntime_Proxy( + IHostTaskManager * This, + /* [in] */ SIZE_T target); + + +void __RPC_STUB IHostTaskManager_LeaveRuntime_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_EnterRuntime_Proxy( + IHostTaskManager * This); + + +void __RPC_STUB IHostTaskManager_EnterRuntime_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_ReverseLeaveRuntime_Proxy( + IHostTaskManager * This); + + +void __RPC_STUB IHostTaskManager_ReverseLeaveRuntime_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_ReverseEnterRuntime_Proxy( + IHostTaskManager * This); + + +void __RPC_STUB IHostTaskManager_ReverseEnterRuntime_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_BeginDelayAbort_Proxy( + IHostTaskManager * This); + + +void __RPC_STUB IHostTaskManager_BeginDelayAbort_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_EndDelayAbort_Proxy( + IHostTaskManager * This); + + +void __RPC_STUB IHostTaskManager_EndDelayAbort_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_BeginThreadAffinity_Proxy( + IHostTaskManager * This); + + +void __RPC_STUB IHostTaskManager_BeginThreadAffinity_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_EndThreadAffinity_Proxy( + IHostTaskManager * This); + + +void __RPC_STUB IHostTaskManager_EndThreadAffinity_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_SetStackGuarantee_Proxy( + IHostTaskManager * This, + /* [in] */ ULONG guarantee); + + +void __RPC_STUB IHostTaskManager_SetStackGuarantee_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_GetStackGuarantee_Proxy( + IHostTaskManager * This, + /* [out] */ ULONG *pGuarantee); + + +void __RPC_STUB IHostTaskManager_GetStackGuarantee_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostTaskManager_SetCLRTaskManager_Proxy( + IHostTaskManager * This, + /* [in] */ ICLRTaskManager *ppManager); + + +void __RPC_STUB IHostTaskManager_SetCLRTaskManager_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostTaskManager_INTERFACE_DEFINED__ */ + + +#ifndef __IHostThreadpoolManager_INTERFACE_DEFINED__ +#define __IHostThreadpoolManager_INTERFACE_DEFINED__ + +/* interface IHostThreadpoolManager */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IHostThreadpoolManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("983D50E2-CB15-466B-80FC-845DC6E8C5FD") + IHostThreadpoolManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE QueueUserWorkItem( + /* [in] */ LPTHREAD_START_ROUTINE Function, + /* [in] */ PVOID Context, + /* [in] */ ULONG Flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetMaxThreads( + /* [in] */ DWORD dwMaxWorkerThreads) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMaxThreads( + /* [out] */ DWORD *pdwMaxWorkerThreads) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAvailableThreads( + /* [out] */ DWORD *pdwAvailableWorkerThreads) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetMinThreads( + /* [in] */ DWORD dwMinIOCompletionThreads) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMinThreads( + /* [out] */ DWORD *pdwMinIOCompletionThreads) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostThreadpoolManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostThreadpoolManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostThreadpoolManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostThreadpoolManager * This); + + HRESULT ( STDMETHODCALLTYPE *QueueUserWorkItem )( + IHostThreadpoolManager * This, + /* [in] */ LPTHREAD_START_ROUTINE Function, + /* [in] */ PVOID Context, + /* [in] */ ULONG Flags); + + HRESULT ( STDMETHODCALLTYPE *SetMaxThreads )( + IHostThreadpoolManager * This, + /* [in] */ DWORD dwMaxWorkerThreads); + + HRESULT ( STDMETHODCALLTYPE *GetMaxThreads )( + IHostThreadpoolManager * This, + /* [out] */ DWORD *pdwMaxWorkerThreads); + + HRESULT ( STDMETHODCALLTYPE *GetAvailableThreads )( + IHostThreadpoolManager * This, + /* [out] */ DWORD *pdwAvailableWorkerThreads); + + HRESULT ( STDMETHODCALLTYPE *SetMinThreads )( + IHostThreadpoolManager * This, + /* [in] */ DWORD dwMinIOCompletionThreads); + + HRESULT ( STDMETHODCALLTYPE *GetMinThreads )( + IHostThreadpoolManager * This, + /* [out] */ DWORD *pdwMinIOCompletionThreads); + + END_INTERFACE + } IHostThreadpoolManagerVtbl; + + interface IHostThreadpoolManager + { + CONST_VTBL struct IHostThreadpoolManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostThreadpoolManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostThreadpoolManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostThreadpoolManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostThreadpoolManager_QueueUserWorkItem(This,Function,Context,Flags) \ + (This)->lpVtbl -> QueueUserWorkItem(This,Function,Context,Flags) + +#define IHostThreadpoolManager_SetMaxThreads(This,dwMaxWorkerThreads) \ + (This)->lpVtbl -> SetMaxThreads(This,dwMaxWorkerThreads) + +#define IHostThreadpoolManager_GetMaxThreads(This,pdwMaxWorkerThreads) \ + (This)->lpVtbl -> GetMaxThreads(This,pdwMaxWorkerThreads) + +#define IHostThreadpoolManager_GetAvailableThreads(This,pdwAvailableWorkerThreads) \ + (This)->lpVtbl -> GetAvailableThreads(This,pdwAvailableWorkerThreads) + +#define IHostThreadpoolManager_SetMinThreads(This,dwMinIOCompletionThreads) \ + (This)->lpVtbl -> SetMinThreads(This,dwMinIOCompletionThreads) + +#define IHostThreadpoolManager_GetMinThreads(This,pdwMinIOCompletionThreads) \ + (This)->lpVtbl -> GetMinThreads(This,pdwMinIOCompletionThreads) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostThreadpoolManager_QueueUserWorkItem_Proxy( + IHostThreadpoolManager * This, + /* [in] */ LPTHREAD_START_ROUTINE Function, + /* [in] */ PVOID Context, + /* [in] */ ULONG Flags); + + +void __RPC_STUB IHostThreadpoolManager_QueueUserWorkItem_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostThreadpoolManager_SetMaxThreads_Proxy( + IHostThreadpoolManager * This, + /* [in] */ DWORD dwMaxWorkerThreads); + + +void __RPC_STUB IHostThreadpoolManager_SetMaxThreads_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostThreadpoolManager_GetMaxThreads_Proxy( + IHostThreadpoolManager * This, + /* [out] */ DWORD *pdwMaxWorkerThreads); + + +void __RPC_STUB IHostThreadpoolManager_GetMaxThreads_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostThreadpoolManager_GetAvailableThreads_Proxy( + IHostThreadpoolManager * This, + /* [out] */ DWORD *pdwAvailableWorkerThreads); + + +void __RPC_STUB IHostThreadpoolManager_GetAvailableThreads_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostThreadpoolManager_SetMinThreads_Proxy( + IHostThreadpoolManager * This, + /* [in] */ DWORD dwMinIOCompletionThreads); + + +void __RPC_STUB IHostThreadpoolManager_SetMinThreads_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostThreadpoolManager_GetMinThreads_Proxy( + IHostThreadpoolManager * This, + /* [out] */ DWORD *pdwMinIOCompletionThreads); + + +void __RPC_STUB IHostThreadpoolManager_GetMinThreads_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostThreadpoolManager_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRIoCompletionManager_INTERFACE_DEFINED__ +#define __ICLRIoCompletionManager_INTERFACE_DEFINED__ + +/* interface ICLRIoCompletionManager */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRIoCompletionManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2d74ce86-b8d6-4c84-b3a7-9768933b3c12") + ICLRIoCompletionManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE OnComplete( + /* [in] */ DWORD dwErrorCode, + /* [in] */ DWORD NumberOfBytesTransferred, + /* [in] */ void *pvOverlapped) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLRIoCompletionManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRIoCompletionManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRIoCompletionManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRIoCompletionManager * This); + + HRESULT ( STDMETHODCALLTYPE *OnComplete )( + ICLRIoCompletionManager * This, + /* [in] */ DWORD dwErrorCode, + /* [in] */ DWORD NumberOfBytesTransferred, + /* [in] */ void *pvOverlapped); + + END_INTERFACE + } ICLRIoCompletionManagerVtbl; + + interface ICLRIoCompletionManager + { + CONST_VTBL struct ICLRIoCompletionManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRIoCompletionManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLRIoCompletionManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLRIoCompletionManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLRIoCompletionManager_OnComplete(This,dwErrorCode,NumberOfBytesTransferred,pvOverlapped) \ + (This)->lpVtbl -> OnComplete(This,dwErrorCode,NumberOfBytesTransferred,pvOverlapped) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLRIoCompletionManager_OnComplete_Proxy( + ICLRIoCompletionManager * This, + /* [in] */ DWORD dwErrorCode, + /* [in] */ DWORD NumberOfBytesTransferred, + /* [in] */ void *pvOverlapped); + + +void __RPC_STUB ICLRIoCompletionManager_OnComplete_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLRIoCompletionManager_INTERFACE_DEFINED__ */ + + +#ifndef __IHostIoCompletionManager_INTERFACE_DEFINED__ +#define __IHostIoCompletionManager_INTERFACE_DEFINED__ + +/* interface IHostIoCompletionManager */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IHostIoCompletionManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("8bde9d80-ec06-41d6-83e6-22580effcc20") + IHostIoCompletionManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateIoCompletionPort( + /* [out] */ HANDLE *phPort) = 0; + + virtual HRESULT STDMETHODCALLTYPE CloseIoCompletionPort( + /* [in] */ HANDLE hPort) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetMaxThreads( + /* [in] */ DWORD dwMaxIOCompletionThreads) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMaxThreads( + /* [out] */ DWORD *pdwMaxIOCompletionThreads) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAvailableThreads( + /* [out] */ DWORD *pdwAvailableIOCompletionThreads) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHostOverlappedSize( + /* [out] */ DWORD *pcbSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetCLRIoCompletionManager( + /* [in] */ ICLRIoCompletionManager *pManager) = 0; + + virtual HRESULT STDMETHODCALLTYPE InitializeHostOverlapped( + /* [in] */ void *pvOverlapped) = 0; + + virtual HRESULT STDMETHODCALLTYPE Bind( + /* [in] */ HANDLE hPort, + /* [in] */ HANDLE hHandle) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetMinThreads( + /* [in] */ DWORD dwMinIOCompletionThreads) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMinThreads( + /* [out] */ DWORD *pdwMinIOCompletionThreads) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostIoCompletionManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostIoCompletionManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostIoCompletionManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostIoCompletionManager * This); + + HRESULT ( STDMETHODCALLTYPE *CreateIoCompletionPort )( + IHostIoCompletionManager * This, + /* [out] */ HANDLE *phPort); + + HRESULT ( STDMETHODCALLTYPE *CloseIoCompletionPort )( + IHostIoCompletionManager * This, + /* [in] */ HANDLE hPort); + + HRESULT ( STDMETHODCALLTYPE *SetMaxThreads )( + IHostIoCompletionManager * This, + /* [in] */ DWORD dwMaxIOCompletionThreads); + + HRESULT ( STDMETHODCALLTYPE *GetMaxThreads )( + IHostIoCompletionManager * This, + /* [out] */ DWORD *pdwMaxIOCompletionThreads); + + HRESULT ( STDMETHODCALLTYPE *GetAvailableThreads )( + IHostIoCompletionManager * This, + /* [out] */ DWORD *pdwAvailableIOCompletionThreads); + + HRESULT ( STDMETHODCALLTYPE *GetHostOverlappedSize )( + IHostIoCompletionManager * This, + /* [out] */ DWORD *pcbSize); + + HRESULT ( STDMETHODCALLTYPE *SetCLRIoCompletionManager )( + IHostIoCompletionManager * This, + /* [in] */ ICLRIoCompletionManager *pManager); + + HRESULT ( STDMETHODCALLTYPE *InitializeHostOverlapped )( + IHostIoCompletionManager * This, + /* [in] */ void *pvOverlapped); + + HRESULT ( STDMETHODCALLTYPE *Bind )( + IHostIoCompletionManager * This, + /* [in] */ HANDLE hPort, + /* [in] */ HANDLE hHandle); + + HRESULT ( STDMETHODCALLTYPE *SetMinThreads )( + IHostIoCompletionManager * This, + /* [in] */ DWORD dwMinIOCompletionThreads); + + HRESULT ( STDMETHODCALLTYPE *GetMinThreads )( + IHostIoCompletionManager * This, + /* [out] */ DWORD *pdwMinIOCompletionThreads); + + END_INTERFACE + } IHostIoCompletionManagerVtbl; + + interface IHostIoCompletionManager + { + CONST_VTBL struct IHostIoCompletionManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostIoCompletionManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostIoCompletionManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostIoCompletionManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostIoCompletionManager_CreateIoCompletionPort(This,phPort) \ + (This)->lpVtbl -> CreateIoCompletionPort(This,phPort) + +#define IHostIoCompletionManager_CloseIoCompletionPort(This,hPort) \ + (This)->lpVtbl -> CloseIoCompletionPort(This,hPort) + +#define IHostIoCompletionManager_SetMaxThreads(This,dwMaxIOCompletionThreads) \ + (This)->lpVtbl -> SetMaxThreads(This,dwMaxIOCompletionThreads) + +#define IHostIoCompletionManager_GetMaxThreads(This,pdwMaxIOCompletionThreads) \ + (This)->lpVtbl -> GetMaxThreads(This,pdwMaxIOCompletionThreads) + +#define IHostIoCompletionManager_GetAvailableThreads(This,pdwAvailableIOCompletionThreads) \ + (This)->lpVtbl -> GetAvailableThreads(This,pdwAvailableIOCompletionThreads) + +#define IHostIoCompletionManager_GetHostOverlappedSize(This,pcbSize) \ + (This)->lpVtbl -> GetHostOverlappedSize(This,pcbSize) + +#define IHostIoCompletionManager_SetCLRIoCompletionManager(This,pManager) \ + (This)->lpVtbl -> SetCLRIoCompletionManager(This,pManager) + +#define IHostIoCompletionManager_InitializeHostOverlapped(This,pvOverlapped) \ + (This)->lpVtbl -> InitializeHostOverlapped(This,pvOverlapped) + +#define IHostIoCompletionManager_Bind(This,hPort,hHandle) \ + (This)->lpVtbl -> Bind(This,hPort,hHandle) + +#define IHostIoCompletionManager_SetMinThreads(This,dwMinIOCompletionThreads) \ + (This)->lpVtbl -> SetMinThreads(This,dwMinIOCompletionThreads) + +#define IHostIoCompletionManager_GetMinThreads(This,pdwMinIOCompletionThreads) \ + (This)->lpVtbl -> GetMinThreads(This,pdwMinIOCompletionThreads) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostIoCompletionManager_CreateIoCompletionPort_Proxy( + IHostIoCompletionManager * This, + /* [out] */ HANDLE *phPort); + + +void __RPC_STUB IHostIoCompletionManager_CreateIoCompletionPort_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostIoCompletionManager_CloseIoCompletionPort_Proxy( + IHostIoCompletionManager * This, + /* [in] */ HANDLE hPort); + + +void __RPC_STUB IHostIoCompletionManager_CloseIoCompletionPort_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostIoCompletionManager_SetMaxThreads_Proxy( + IHostIoCompletionManager * This, + /* [in] */ DWORD dwMaxIOCompletionThreads); + + +void __RPC_STUB IHostIoCompletionManager_SetMaxThreads_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostIoCompletionManager_GetMaxThreads_Proxy( + IHostIoCompletionManager * This, + /* [out] */ DWORD *pdwMaxIOCompletionThreads); + + +void __RPC_STUB IHostIoCompletionManager_GetMaxThreads_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostIoCompletionManager_GetAvailableThreads_Proxy( + IHostIoCompletionManager * This, + /* [out] */ DWORD *pdwAvailableIOCompletionThreads); + + +void __RPC_STUB IHostIoCompletionManager_GetAvailableThreads_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostIoCompletionManager_GetHostOverlappedSize_Proxy( + IHostIoCompletionManager * This, + /* [out] */ DWORD *pcbSize); + + +void __RPC_STUB IHostIoCompletionManager_GetHostOverlappedSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostIoCompletionManager_SetCLRIoCompletionManager_Proxy( + IHostIoCompletionManager * This, + /* [in] */ ICLRIoCompletionManager *pManager); + + +void __RPC_STUB IHostIoCompletionManager_SetCLRIoCompletionManager_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostIoCompletionManager_InitializeHostOverlapped_Proxy( + IHostIoCompletionManager * This, + /* [in] */ void *pvOverlapped); + + +void __RPC_STUB IHostIoCompletionManager_InitializeHostOverlapped_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostIoCompletionManager_Bind_Proxy( + IHostIoCompletionManager * This, + /* [in] */ HANDLE hPort, + /* [in] */ HANDLE hHandle); + + +void __RPC_STUB IHostIoCompletionManager_Bind_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostIoCompletionManager_SetMinThreads_Proxy( + IHostIoCompletionManager * This, + /* [in] */ DWORD dwMinIOCompletionThreads); + + +void __RPC_STUB IHostIoCompletionManager_SetMinThreads_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostIoCompletionManager_GetMinThreads_Proxy( + IHostIoCompletionManager * This, + /* [out] */ DWORD *pdwMinIOCompletionThreads); + + +void __RPC_STUB IHostIoCompletionManager_GetMinThreads_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostIoCompletionManager_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0143 */ +/* [local] */ + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_mscoree_0143_0001 + { eSymbolReadingNever = 0, + eSymbolReadingAlways = 1, + eSymbolReadingFullTrustOnly = 2 + } ESymbolReadingPolicy; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0143_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0143_v0_0_s_ifspec; + +#ifndef __ICLRDebugManager_INTERFACE_DEFINED__ +#define __ICLRDebugManager_INTERFACE_DEFINED__ + +/* interface ICLRDebugManager */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRDebugManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("00DCAEC6-2AC0-43a9-ACF9-1E36C139B10D") + ICLRDebugManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE BeginConnection( + /* [in] */ CONNID dwConnectionId, + /* [string][in] */ wchar_t *szConnectionName) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetConnectionTasks( + /* [in] */ CONNID id, + /* [in] */ DWORD dwCount, + /* [size_is][in] */ ICLRTask **ppCLRTask) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndConnection( + /* [in] */ CONNID dwConnectionId) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetDacl( + /* [in] */ PACL pacl) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDacl( + /* [out] */ PACL *pacl) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsDebuggerAttached( + /* [out] */ BOOL *pbAttached) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetSymbolReadingPolicy( + /* [in] */ ESymbolReadingPolicy policy) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLRDebugManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRDebugManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRDebugManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRDebugManager * This); + + HRESULT ( STDMETHODCALLTYPE *BeginConnection )( + ICLRDebugManager * This, + /* [in] */ CONNID dwConnectionId, + /* [string][in] */ wchar_t *szConnectionName); + + HRESULT ( STDMETHODCALLTYPE *SetConnectionTasks )( + ICLRDebugManager * This, + /* [in] */ CONNID id, + /* [in] */ DWORD dwCount, + /* [size_is][in] */ ICLRTask **ppCLRTask); + + HRESULT ( STDMETHODCALLTYPE *EndConnection )( + ICLRDebugManager * This, + /* [in] */ CONNID dwConnectionId); + + HRESULT ( STDMETHODCALLTYPE *SetDacl )( + ICLRDebugManager * This, + /* [in] */ PACL pacl); + + HRESULT ( STDMETHODCALLTYPE *GetDacl )( + ICLRDebugManager * This, + /* [out] */ PACL *pacl); + + HRESULT ( STDMETHODCALLTYPE *IsDebuggerAttached )( + ICLRDebugManager * This, + /* [out] */ BOOL *pbAttached); + + HRESULT ( STDMETHODCALLTYPE *SetSymbolReadingPolicy )( + ICLRDebugManager * This, + /* [in] */ ESymbolReadingPolicy policy); + + END_INTERFACE + } ICLRDebugManagerVtbl; + + interface ICLRDebugManager + { + CONST_VTBL struct ICLRDebugManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRDebugManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLRDebugManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLRDebugManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLRDebugManager_BeginConnection(This,dwConnectionId,szConnectionName) \ + (This)->lpVtbl -> BeginConnection(This,dwConnectionId,szConnectionName) + +#define ICLRDebugManager_SetConnectionTasks(This,id,dwCount,ppCLRTask) \ + (This)->lpVtbl -> SetConnectionTasks(This,id,dwCount,ppCLRTask) + +#define ICLRDebugManager_EndConnection(This,dwConnectionId) \ + (This)->lpVtbl -> EndConnection(This,dwConnectionId) + +#define ICLRDebugManager_SetDacl(This,pacl) \ + (This)->lpVtbl -> SetDacl(This,pacl) + +#define ICLRDebugManager_GetDacl(This,pacl) \ + (This)->lpVtbl -> GetDacl(This,pacl) + +#define ICLRDebugManager_IsDebuggerAttached(This,pbAttached) \ + (This)->lpVtbl -> IsDebuggerAttached(This,pbAttached) + +#define ICLRDebugManager_SetSymbolReadingPolicy(This,policy) \ + (This)->lpVtbl -> SetSymbolReadingPolicy(This,policy) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLRDebugManager_BeginConnection_Proxy( + ICLRDebugManager * This, + /* [in] */ CONNID dwConnectionId, + /* [string][in] */ wchar_t *szConnectionName); + + +void __RPC_STUB ICLRDebugManager_BeginConnection_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRDebugManager_SetConnectionTasks_Proxy( + ICLRDebugManager * This, + /* [in] */ CONNID id, + /* [in] */ DWORD dwCount, + /* [size_is][in] */ ICLRTask **ppCLRTask); + + +void __RPC_STUB ICLRDebugManager_SetConnectionTasks_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRDebugManager_EndConnection_Proxy( + ICLRDebugManager * This, + /* [in] */ CONNID dwConnectionId); + + +void __RPC_STUB ICLRDebugManager_EndConnection_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRDebugManager_SetDacl_Proxy( + ICLRDebugManager * This, + /* [in] */ PACL pacl); + + +void __RPC_STUB ICLRDebugManager_SetDacl_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRDebugManager_GetDacl_Proxy( + ICLRDebugManager * This, + /* [out] */ PACL *pacl); + + +void __RPC_STUB ICLRDebugManager_GetDacl_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRDebugManager_IsDebuggerAttached_Proxy( + ICLRDebugManager * This, + /* [out] */ BOOL *pbAttached); + + +void __RPC_STUB ICLRDebugManager_IsDebuggerAttached_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRDebugManager_SetSymbolReadingPolicy_Proxy( + ICLRDebugManager * This, + /* [in] */ ESymbolReadingPolicy policy); + + +void __RPC_STUB ICLRDebugManager_SetSymbolReadingPolicy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLRDebugManager_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0144 */ +/* [local] */ + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_mscoree_0144_0001 + { DUMP_FLAVOR_Mini = 0, + DUMP_FLAVOR_CriticalCLRState = 1, + DUMP_FLAVOR_NonHeapCLRState = 2, + DUMP_FLAVOR_Default = DUMP_FLAVOR_Mini + } ECustomDumpFlavor; + +typedef /* [public][public][public] */ +enum __MIDL___MIDL_itf_mscoree_0144_0002 + { DUMP_ITEM_None = 0 + } ECustomDumpItemKind; + +typedef /* [public][public] */ struct __MIDL___MIDL_itf_mscoree_0144_0003 + { + ECustomDumpItemKind itemKind; + union + { + UINT_PTR pReserved; + } ; + } CustomDumpItem; + +typedef struct _BucketParameters + { + BOOL fInited; + WCHAR pszEventTypeName[ 255 ]; + WCHAR pszParams[ 10 ][ 255 ]; + } BucketParameters; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0144_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0144_v0_0_s_ifspec; + +#ifndef __ICLRErrorReportingManager_INTERFACE_DEFINED__ +#define __ICLRErrorReportingManager_INTERFACE_DEFINED__ + +/* interface ICLRErrorReportingManager */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRErrorReportingManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("980D2F1A-BF79-4c08-812A-BB9778928F78") + ICLRErrorReportingManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetBucketParametersForCurrentException( + /* [out] */ BucketParameters *pParams) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginCustomDump( + /* [in] */ ECustomDumpFlavor dwFlavor, + /* [in] */ DWORD dwNumItems, + /* [length_is][size_is][in] */ CustomDumpItem *items, + DWORD dwReserved) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndCustomDump( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLRErrorReportingManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRErrorReportingManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRErrorReportingManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRErrorReportingManager * This); + + HRESULT ( STDMETHODCALLTYPE *GetBucketParametersForCurrentException )( + ICLRErrorReportingManager * This, + /* [out] */ BucketParameters *pParams); + + HRESULT ( STDMETHODCALLTYPE *BeginCustomDump )( + ICLRErrorReportingManager * This, + /* [in] */ ECustomDumpFlavor dwFlavor, + /* [in] */ DWORD dwNumItems, + /* [length_is][size_is][in] */ CustomDumpItem *items, + DWORD dwReserved); + + HRESULT ( STDMETHODCALLTYPE *EndCustomDump )( + ICLRErrorReportingManager * This); + + END_INTERFACE + } ICLRErrorReportingManagerVtbl; + + interface ICLRErrorReportingManager + { + CONST_VTBL struct ICLRErrorReportingManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRErrorReportingManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLRErrorReportingManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLRErrorReportingManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLRErrorReportingManager_GetBucketParametersForCurrentException(This,pParams) \ + (This)->lpVtbl -> GetBucketParametersForCurrentException(This,pParams) + +#define ICLRErrorReportingManager_BeginCustomDump(This,dwFlavor,dwNumItems,items,dwReserved) \ + (This)->lpVtbl -> BeginCustomDump(This,dwFlavor,dwNumItems,items,dwReserved) + +#define ICLRErrorReportingManager_EndCustomDump(This) \ + (This)->lpVtbl -> EndCustomDump(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLRErrorReportingManager_GetBucketParametersForCurrentException_Proxy( + ICLRErrorReportingManager * This, + /* [out] */ BucketParameters *pParams); + + +void __RPC_STUB ICLRErrorReportingManager_GetBucketParametersForCurrentException_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRErrorReportingManager_BeginCustomDump_Proxy( + ICLRErrorReportingManager * This, + /* [in] */ ECustomDumpFlavor dwFlavor, + /* [in] */ DWORD dwNumItems, + /* [length_is][size_is][in] */ CustomDumpItem *items, + DWORD dwReserved); + + +void __RPC_STUB ICLRErrorReportingManager_BeginCustomDump_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRErrorReportingManager_EndCustomDump_Proxy( + ICLRErrorReportingManager * This); + + +void __RPC_STUB ICLRErrorReportingManager_EndCustomDump_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLRErrorReportingManager_INTERFACE_DEFINED__ */ + + +#ifndef __IHostCrst_INTERFACE_DEFINED__ +#define __IHostCrst_INTERFACE_DEFINED__ + +/* interface IHostCrst */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IHostCrst; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("6DF710A6-26A4-4a65-8CD5-7237B8BDA8DC") + IHostCrst : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Enter( + /* [in] */ DWORD option) = 0; + + virtual HRESULT STDMETHODCALLTYPE Leave( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE TryEnter( + /* [in] */ DWORD option, + /* [out] */ BOOL *pbSucceeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetSpinCount( + /* [in] */ DWORD dwSpinCount) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostCrstVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostCrst * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostCrst * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostCrst * This); + + HRESULT ( STDMETHODCALLTYPE *Enter )( + IHostCrst * This, + /* [in] */ DWORD option); + + HRESULT ( STDMETHODCALLTYPE *Leave )( + IHostCrst * This); + + HRESULT ( STDMETHODCALLTYPE *TryEnter )( + IHostCrst * This, + /* [in] */ DWORD option, + /* [out] */ BOOL *pbSucceeded); + + HRESULT ( STDMETHODCALLTYPE *SetSpinCount )( + IHostCrst * This, + /* [in] */ DWORD dwSpinCount); + + END_INTERFACE + } IHostCrstVtbl; + + interface IHostCrst + { + CONST_VTBL struct IHostCrstVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostCrst_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostCrst_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostCrst_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostCrst_Enter(This,option) \ + (This)->lpVtbl -> Enter(This,option) + +#define IHostCrst_Leave(This) \ + (This)->lpVtbl -> Leave(This) + +#define IHostCrst_TryEnter(This,option,pbSucceeded) \ + (This)->lpVtbl -> TryEnter(This,option,pbSucceeded) + +#define IHostCrst_SetSpinCount(This,dwSpinCount) \ + (This)->lpVtbl -> SetSpinCount(This,dwSpinCount) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostCrst_Enter_Proxy( + IHostCrst * This, + /* [in] */ DWORD option); + + +void __RPC_STUB IHostCrst_Enter_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostCrst_Leave_Proxy( + IHostCrst * This); + + +void __RPC_STUB IHostCrst_Leave_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostCrst_TryEnter_Proxy( + IHostCrst * This, + /* [in] */ DWORD option, + /* [out] */ BOOL *pbSucceeded); + + +void __RPC_STUB IHostCrst_TryEnter_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostCrst_SetSpinCount_Proxy( + IHostCrst * This, + /* [in] */ DWORD dwSpinCount); + + +void __RPC_STUB IHostCrst_SetSpinCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostCrst_INTERFACE_DEFINED__ */ + + +#ifndef __IHostAutoEvent_INTERFACE_DEFINED__ +#define __IHostAutoEvent_INTERFACE_DEFINED__ + +/* interface IHostAutoEvent */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IHostAutoEvent; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("50B0CFCE-4063-4278-9673-E5CB4ED0BDB8") + IHostAutoEvent : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Wait( + /* [in] */ DWORD dwMilliseconds, + /* [in] */ DWORD option) = 0; + + virtual HRESULT STDMETHODCALLTYPE Set( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostAutoEventVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostAutoEvent * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostAutoEvent * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostAutoEvent * This); + + HRESULT ( STDMETHODCALLTYPE *Wait )( + IHostAutoEvent * This, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ DWORD option); + + HRESULT ( STDMETHODCALLTYPE *Set )( + IHostAutoEvent * This); + + END_INTERFACE + } IHostAutoEventVtbl; + + interface IHostAutoEvent + { + CONST_VTBL struct IHostAutoEventVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostAutoEvent_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostAutoEvent_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostAutoEvent_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostAutoEvent_Wait(This,dwMilliseconds,option) \ + (This)->lpVtbl -> Wait(This,dwMilliseconds,option) + +#define IHostAutoEvent_Set(This) \ + (This)->lpVtbl -> Set(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostAutoEvent_Wait_Proxy( + IHostAutoEvent * This, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ DWORD option); + + +void __RPC_STUB IHostAutoEvent_Wait_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostAutoEvent_Set_Proxy( + IHostAutoEvent * This); + + +void __RPC_STUB IHostAutoEvent_Set_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostAutoEvent_INTERFACE_DEFINED__ */ + + +#ifndef __IHostManualEvent_INTERFACE_DEFINED__ +#define __IHostManualEvent_INTERFACE_DEFINED__ + +/* interface IHostManualEvent */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IHostManualEvent; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("1BF4EC38-AFFE-4fb9-85A6-525268F15B54") + IHostManualEvent : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Wait( + /* [in] */ DWORD dwMilliseconds, + /* [in] */ DWORD option) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Set( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostManualEventVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostManualEvent * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostManualEvent * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostManualEvent * This); + + HRESULT ( STDMETHODCALLTYPE *Wait )( + IHostManualEvent * This, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ DWORD option); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + IHostManualEvent * This); + + HRESULT ( STDMETHODCALLTYPE *Set )( + IHostManualEvent * This); + + END_INTERFACE + } IHostManualEventVtbl; + + interface IHostManualEvent + { + CONST_VTBL struct IHostManualEventVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostManualEvent_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostManualEvent_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostManualEvent_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostManualEvent_Wait(This,dwMilliseconds,option) \ + (This)->lpVtbl -> Wait(This,dwMilliseconds,option) + +#define IHostManualEvent_Reset(This) \ + (This)->lpVtbl -> Reset(This) + +#define IHostManualEvent_Set(This) \ + (This)->lpVtbl -> Set(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostManualEvent_Wait_Proxy( + IHostManualEvent * This, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ DWORD option); + + +void __RPC_STUB IHostManualEvent_Wait_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostManualEvent_Reset_Proxy( + IHostManualEvent * This); + + +void __RPC_STUB IHostManualEvent_Reset_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostManualEvent_Set_Proxy( + IHostManualEvent * This); + + +void __RPC_STUB IHostManualEvent_Set_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostManualEvent_INTERFACE_DEFINED__ */ + + +#ifndef __IHostSemaphore_INTERFACE_DEFINED__ +#define __IHostSemaphore_INTERFACE_DEFINED__ + +/* interface IHostSemaphore */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IHostSemaphore; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("855efd47-cc09-463a-a97d-16acab882661") + IHostSemaphore : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Wait( + /* [in] */ DWORD dwMilliseconds, + /* [in] */ DWORD option) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReleaseSemaphore( + /* [in] */ LONG lReleaseCount, + /* [out] */ LONG *lpPreviousCount) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostSemaphoreVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostSemaphore * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostSemaphore * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostSemaphore * This); + + HRESULT ( STDMETHODCALLTYPE *Wait )( + IHostSemaphore * This, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ DWORD option); + + HRESULT ( STDMETHODCALLTYPE *ReleaseSemaphore )( + IHostSemaphore * This, + /* [in] */ LONG lReleaseCount, + /* [out] */ LONG *lpPreviousCount); + + END_INTERFACE + } IHostSemaphoreVtbl; + + interface IHostSemaphore + { + CONST_VTBL struct IHostSemaphoreVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostSemaphore_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostSemaphore_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostSemaphore_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostSemaphore_Wait(This,dwMilliseconds,option) \ + (This)->lpVtbl -> Wait(This,dwMilliseconds,option) + +#define IHostSemaphore_ReleaseSemaphore(This,lReleaseCount,lpPreviousCount) \ + (This)->lpVtbl -> ReleaseSemaphore(This,lReleaseCount,lpPreviousCount) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostSemaphore_Wait_Proxy( + IHostSemaphore * This, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ DWORD option); + + +void __RPC_STUB IHostSemaphore_Wait_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostSemaphore_ReleaseSemaphore_Proxy( + IHostSemaphore * This, + /* [in] */ LONG lReleaseCount, + /* [out] */ LONG *lpPreviousCount); + + +void __RPC_STUB IHostSemaphore_ReleaseSemaphore_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostSemaphore_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRSyncManager_INTERFACE_DEFINED__ +#define __ICLRSyncManager_INTERFACE_DEFINED__ + +/* interface ICLRSyncManager */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRSyncManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("55FF199D-AD21-48f9-A16C-F24EBBB8727D") + ICLRSyncManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetMonitorOwner( + /* [in] */ SIZE_T Cookie, + /* [out] */ IHostTask **ppOwnerHostTask) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateRWLockOwnerIterator( + /* [in] */ SIZE_T Cookie, + /* [out] */ SIZE_T *pIterator) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRWLockOwnerNext( + /* [in] */ SIZE_T Iterator, + /* [out] */ IHostTask **ppOwnerHostTask) = 0; + + virtual HRESULT STDMETHODCALLTYPE DeleteRWLockOwnerIterator( + /* [in] */ SIZE_T Iterator) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLRSyncManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRSyncManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRSyncManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRSyncManager * This); + + HRESULT ( STDMETHODCALLTYPE *GetMonitorOwner )( + ICLRSyncManager * This, + /* [in] */ SIZE_T Cookie, + /* [out] */ IHostTask **ppOwnerHostTask); + + HRESULT ( STDMETHODCALLTYPE *CreateRWLockOwnerIterator )( + ICLRSyncManager * This, + /* [in] */ SIZE_T Cookie, + /* [out] */ SIZE_T *pIterator); + + HRESULT ( STDMETHODCALLTYPE *GetRWLockOwnerNext )( + ICLRSyncManager * This, + /* [in] */ SIZE_T Iterator, + /* [out] */ IHostTask **ppOwnerHostTask); + + HRESULT ( STDMETHODCALLTYPE *DeleteRWLockOwnerIterator )( + ICLRSyncManager * This, + /* [in] */ SIZE_T Iterator); + + END_INTERFACE + } ICLRSyncManagerVtbl; + + interface ICLRSyncManager + { + CONST_VTBL struct ICLRSyncManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRSyncManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLRSyncManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLRSyncManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLRSyncManager_GetMonitorOwner(This,Cookie,ppOwnerHostTask) \ + (This)->lpVtbl -> GetMonitorOwner(This,Cookie,ppOwnerHostTask) + +#define ICLRSyncManager_CreateRWLockOwnerIterator(This,Cookie,pIterator) \ + (This)->lpVtbl -> CreateRWLockOwnerIterator(This,Cookie,pIterator) + +#define ICLRSyncManager_GetRWLockOwnerNext(This,Iterator,ppOwnerHostTask) \ + (This)->lpVtbl -> GetRWLockOwnerNext(This,Iterator,ppOwnerHostTask) + +#define ICLRSyncManager_DeleteRWLockOwnerIterator(This,Iterator) \ + (This)->lpVtbl -> DeleteRWLockOwnerIterator(This,Iterator) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLRSyncManager_GetMonitorOwner_Proxy( + ICLRSyncManager * This, + /* [in] */ SIZE_T Cookie, + /* [out] */ IHostTask **ppOwnerHostTask); + + +void __RPC_STUB ICLRSyncManager_GetMonitorOwner_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRSyncManager_CreateRWLockOwnerIterator_Proxy( + ICLRSyncManager * This, + /* [in] */ SIZE_T Cookie, + /* [out] */ SIZE_T *pIterator); + + +void __RPC_STUB ICLRSyncManager_CreateRWLockOwnerIterator_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRSyncManager_GetRWLockOwnerNext_Proxy( + ICLRSyncManager * This, + /* [in] */ SIZE_T Iterator, + /* [out] */ IHostTask **ppOwnerHostTask); + + +void __RPC_STUB ICLRSyncManager_GetRWLockOwnerNext_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRSyncManager_DeleteRWLockOwnerIterator_Proxy( + ICLRSyncManager * This, + /* [in] */ SIZE_T Iterator); + + +void __RPC_STUB ICLRSyncManager_DeleteRWLockOwnerIterator_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLRSyncManager_INTERFACE_DEFINED__ */ + + +#ifndef __IHostSyncManager_INTERFACE_DEFINED__ +#define __IHostSyncManager_INTERFACE_DEFINED__ + +/* interface IHostSyncManager */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IHostSyncManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("234330c7-5f10-4f20-9615-5122dab7a0ac") + IHostSyncManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetCLRSyncManager( + /* [in] */ ICLRSyncManager *pManager) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateCrst( + /* [out] */ IHostCrst **ppCrst) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateCrstWithSpinCount( + /* [in] */ DWORD dwSpinCount, + /* [out] */ IHostCrst **ppCrst) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateAutoEvent( + /* [out] */ IHostAutoEvent **ppEvent) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateManualEvent( + /* [in] */ BOOL bInitialState, + /* [out] */ IHostManualEvent **ppEvent) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateMonitorEvent( + /* [in] */ SIZE_T Cookie, + /* [out] */ IHostAutoEvent **ppEvent) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateRWLockWriterEvent( + /* [in] */ SIZE_T Cookie, + /* [out] */ IHostAutoEvent **ppEvent) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateRWLockReaderEvent( + /* [in] */ BOOL bInitialState, + /* [in] */ SIZE_T Cookie, + /* [out] */ IHostManualEvent **ppEvent) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateSemaphore( + /* [in] */ DWORD dwInitial, + /* [in] */ DWORD dwMax, + /* [out] */ IHostSemaphore **ppSemaphore) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostSyncManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostSyncManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostSyncManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostSyncManager * This); + + HRESULT ( STDMETHODCALLTYPE *SetCLRSyncManager )( + IHostSyncManager * This, + /* [in] */ ICLRSyncManager *pManager); + + HRESULT ( STDMETHODCALLTYPE *CreateCrst )( + IHostSyncManager * This, + /* [out] */ IHostCrst **ppCrst); + + HRESULT ( STDMETHODCALLTYPE *CreateCrstWithSpinCount )( + IHostSyncManager * This, + /* [in] */ DWORD dwSpinCount, + /* [out] */ IHostCrst **ppCrst); + + HRESULT ( STDMETHODCALLTYPE *CreateAutoEvent )( + IHostSyncManager * This, + /* [out] */ IHostAutoEvent **ppEvent); + + HRESULT ( STDMETHODCALLTYPE *CreateManualEvent )( + IHostSyncManager * This, + /* [in] */ BOOL bInitialState, + /* [out] */ IHostManualEvent **ppEvent); + + HRESULT ( STDMETHODCALLTYPE *CreateMonitorEvent )( + IHostSyncManager * This, + /* [in] */ SIZE_T Cookie, + /* [out] */ IHostAutoEvent **ppEvent); + + HRESULT ( STDMETHODCALLTYPE *CreateRWLockWriterEvent )( + IHostSyncManager * This, + /* [in] */ SIZE_T Cookie, + /* [out] */ IHostAutoEvent **ppEvent); + + HRESULT ( STDMETHODCALLTYPE *CreateRWLockReaderEvent )( + IHostSyncManager * This, + /* [in] */ BOOL bInitialState, + /* [in] */ SIZE_T Cookie, + /* [out] */ IHostManualEvent **ppEvent); + + HRESULT ( STDMETHODCALLTYPE *CreateSemaphore )( + IHostSyncManager * This, + /* [in] */ DWORD dwInitial, + /* [in] */ DWORD dwMax, + /* [out] */ IHostSemaphore **ppSemaphore); + + END_INTERFACE + } IHostSyncManagerVtbl; + + interface IHostSyncManager + { + CONST_VTBL struct IHostSyncManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostSyncManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostSyncManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostSyncManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostSyncManager_SetCLRSyncManager(This,pManager) \ + (This)->lpVtbl -> SetCLRSyncManager(This,pManager) + +#define IHostSyncManager_CreateCrst(This,ppCrst) \ + (This)->lpVtbl -> CreateCrst(This,ppCrst) + +#define IHostSyncManager_CreateCrstWithSpinCount(This,dwSpinCount,ppCrst) \ + (This)->lpVtbl -> CreateCrstWithSpinCount(This,dwSpinCount,ppCrst) + +#define IHostSyncManager_CreateAutoEvent(This,ppEvent) \ + (This)->lpVtbl -> CreateAutoEvent(This,ppEvent) + +#define IHostSyncManager_CreateManualEvent(This,bInitialState,ppEvent) \ + (This)->lpVtbl -> CreateManualEvent(This,bInitialState,ppEvent) + +#define IHostSyncManager_CreateMonitorEvent(This,Cookie,ppEvent) \ + (This)->lpVtbl -> CreateMonitorEvent(This,Cookie,ppEvent) + +#define IHostSyncManager_CreateRWLockWriterEvent(This,Cookie,ppEvent) \ + (This)->lpVtbl -> CreateRWLockWriterEvent(This,Cookie,ppEvent) + +#define IHostSyncManager_CreateRWLockReaderEvent(This,bInitialState,Cookie,ppEvent) \ + (This)->lpVtbl -> CreateRWLockReaderEvent(This,bInitialState,Cookie,ppEvent) + +#define IHostSyncManager_CreateSemaphore(This,dwInitial,dwMax,ppSemaphore) \ + (This)->lpVtbl -> CreateSemaphore(This,dwInitial,dwMax,ppSemaphore) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostSyncManager_SetCLRSyncManager_Proxy( + IHostSyncManager * This, + /* [in] */ ICLRSyncManager *pManager); + + +void __RPC_STUB IHostSyncManager_SetCLRSyncManager_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostSyncManager_CreateCrst_Proxy( + IHostSyncManager * This, + /* [out] */ IHostCrst **ppCrst); + + +void __RPC_STUB IHostSyncManager_CreateCrst_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostSyncManager_CreateCrstWithSpinCount_Proxy( + IHostSyncManager * This, + /* [in] */ DWORD dwSpinCount, + /* [out] */ IHostCrst **ppCrst); + + +void __RPC_STUB IHostSyncManager_CreateCrstWithSpinCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostSyncManager_CreateAutoEvent_Proxy( + IHostSyncManager * This, + /* [out] */ IHostAutoEvent **ppEvent); + + +void __RPC_STUB IHostSyncManager_CreateAutoEvent_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostSyncManager_CreateManualEvent_Proxy( + IHostSyncManager * This, + /* [in] */ BOOL bInitialState, + /* [out] */ IHostManualEvent **ppEvent); + + +void __RPC_STUB IHostSyncManager_CreateManualEvent_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostSyncManager_CreateMonitorEvent_Proxy( + IHostSyncManager * This, + /* [in] */ SIZE_T Cookie, + /* [out] */ IHostAutoEvent **ppEvent); + + +void __RPC_STUB IHostSyncManager_CreateMonitorEvent_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostSyncManager_CreateRWLockWriterEvent_Proxy( + IHostSyncManager * This, + /* [in] */ SIZE_T Cookie, + /* [out] */ IHostAutoEvent **ppEvent); + + +void __RPC_STUB IHostSyncManager_CreateRWLockWriterEvent_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostSyncManager_CreateRWLockReaderEvent_Proxy( + IHostSyncManager * This, + /* [in] */ BOOL bInitialState, + /* [in] */ SIZE_T Cookie, + /* [out] */ IHostManualEvent **ppEvent); + + +void __RPC_STUB IHostSyncManager_CreateRWLockReaderEvent_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostSyncManager_CreateSemaphore_Proxy( + IHostSyncManager * This, + /* [in] */ DWORD dwInitial, + /* [in] */ DWORD dwMax, + /* [out] */ IHostSemaphore **ppSemaphore); + + +void __RPC_STUB IHostSyncManager_CreateSemaphore_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostSyncManager_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0151 */ +/* [local] */ + +typedef /* [public][public][public][public][public][public][public] */ +enum __MIDL___MIDL_itf_mscoree_0151_0001 + { OPR_ThreadAbort = 0, + OPR_ThreadRudeAbortInNonCriticalRegion = OPR_ThreadAbort + 1, + OPR_ThreadRudeAbortInCriticalRegion = OPR_ThreadRudeAbortInNonCriticalRegion + 1, + OPR_AppDomainUnload = OPR_ThreadRudeAbortInCriticalRegion + 1, + OPR_AppDomainRudeUnload = OPR_AppDomainUnload + 1, + OPR_ProcessExit = OPR_AppDomainRudeUnload + 1, + OPR_FinalizerRun = OPR_ProcessExit + 1, + MaxClrOperation = OPR_FinalizerRun + 1 + } EClrOperation; + +typedef /* [public][public][public] */ +enum __MIDL___MIDL_itf_mscoree_0151_0002 + { FAIL_NonCriticalResource = 0, + FAIL_CriticalResource = FAIL_NonCriticalResource + 1, + FAIL_FatalRuntime = FAIL_CriticalResource + 1, + FAIL_OrphanedLock = FAIL_FatalRuntime + 1, + FAIL_StackOverflow = FAIL_OrphanedLock + 1, + MaxClrFailure = FAIL_StackOverflow + 1 + } EClrFailure; + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_mscoree_0151_0003 + { eRuntimeDeterminedPolicy = 0, + eHostDeterminedPolicy = eRuntimeDeterminedPolicy + 1 + } EClrUnhandledException; + +typedef /* [public][public][public][public][public][public][public][public] */ +enum __MIDL___MIDL_itf_mscoree_0151_0004 + { eNoAction = 0, + eThrowException = eNoAction + 1, + eAbortThread = eThrowException + 1, + eRudeAbortThread = eAbortThread + 1, + eUnloadAppDomain = eRudeAbortThread + 1, + eRudeUnloadAppDomain = eUnloadAppDomain + 1, + eExitProcess = eRudeUnloadAppDomain + 1, + eFastExitProcess = eExitProcess + 1, + eRudeExitProcess = eFastExitProcess + 1, + eDisableRuntime = eRudeExitProcess + 1, + MaxPolicyAction = eDisableRuntime + 1 + } EPolicyAction; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0151_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0151_v0_0_s_ifspec; + +#ifndef __ICLRPolicyManager_INTERFACE_DEFINED__ +#define __ICLRPolicyManager_INTERFACE_DEFINED__ + +/* interface ICLRPolicyManager */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRPolicyManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("7D290010-D781-45da-A6F8-AA5D711A730E") + ICLRPolicyManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetDefaultAction( + /* [in] */ EClrOperation operation, + /* [in] */ EPolicyAction action) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetTimeout( + /* [in] */ EClrOperation operation, + /* [in] */ DWORD dwMilliseconds) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetActionOnTimeout( + /* [in] */ EClrOperation operation, + /* [in] */ EPolicyAction action) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetTimeoutAndAction( + /* [in] */ EClrOperation operation, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ EPolicyAction action) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetActionOnFailure( + /* [in] */ EClrFailure failure, + /* [in] */ EPolicyAction action) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetUnhandledExceptionPolicy( + /* [in] */ EClrUnhandledException policy) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLRPolicyManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRPolicyManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRPolicyManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRPolicyManager * This); + + HRESULT ( STDMETHODCALLTYPE *SetDefaultAction )( + ICLRPolicyManager * This, + /* [in] */ EClrOperation operation, + /* [in] */ EPolicyAction action); + + HRESULT ( STDMETHODCALLTYPE *SetTimeout )( + ICLRPolicyManager * This, + /* [in] */ EClrOperation operation, + /* [in] */ DWORD dwMilliseconds); + + HRESULT ( STDMETHODCALLTYPE *SetActionOnTimeout )( + ICLRPolicyManager * This, + /* [in] */ EClrOperation operation, + /* [in] */ EPolicyAction action); + + HRESULT ( STDMETHODCALLTYPE *SetTimeoutAndAction )( + ICLRPolicyManager * This, + /* [in] */ EClrOperation operation, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ EPolicyAction action); + + HRESULT ( STDMETHODCALLTYPE *SetActionOnFailure )( + ICLRPolicyManager * This, + /* [in] */ EClrFailure failure, + /* [in] */ EPolicyAction action); + + HRESULT ( STDMETHODCALLTYPE *SetUnhandledExceptionPolicy )( + ICLRPolicyManager * This, + /* [in] */ EClrUnhandledException policy); + + END_INTERFACE + } ICLRPolicyManagerVtbl; + + interface ICLRPolicyManager + { + CONST_VTBL struct ICLRPolicyManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRPolicyManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLRPolicyManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLRPolicyManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLRPolicyManager_SetDefaultAction(This,operation,action) \ + (This)->lpVtbl -> SetDefaultAction(This,operation,action) + +#define ICLRPolicyManager_SetTimeout(This,operation,dwMilliseconds) \ + (This)->lpVtbl -> SetTimeout(This,operation,dwMilliseconds) + +#define ICLRPolicyManager_SetActionOnTimeout(This,operation,action) \ + (This)->lpVtbl -> SetActionOnTimeout(This,operation,action) + +#define ICLRPolicyManager_SetTimeoutAndAction(This,operation,dwMilliseconds,action) \ + (This)->lpVtbl -> SetTimeoutAndAction(This,operation,dwMilliseconds,action) + +#define ICLRPolicyManager_SetActionOnFailure(This,failure,action) \ + (This)->lpVtbl -> SetActionOnFailure(This,failure,action) + +#define ICLRPolicyManager_SetUnhandledExceptionPolicy(This,policy) \ + (This)->lpVtbl -> SetUnhandledExceptionPolicy(This,policy) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLRPolicyManager_SetDefaultAction_Proxy( + ICLRPolicyManager * This, + /* [in] */ EClrOperation operation, + /* [in] */ EPolicyAction action); + + +void __RPC_STUB ICLRPolicyManager_SetDefaultAction_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRPolicyManager_SetTimeout_Proxy( + ICLRPolicyManager * This, + /* [in] */ EClrOperation operation, + /* [in] */ DWORD dwMilliseconds); + + +void __RPC_STUB ICLRPolicyManager_SetTimeout_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRPolicyManager_SetActionOnTimeout_Proxy( + ICLRPolicyManager * This, + /* [in] */ EClrOperation operation, + /* [in] */ EPolicyAction action); + + +void __RPC_STUB ICLRPolicyManager_SetActionOnTimeout_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRPolicyManager_SetTimeoutAndAction_Proxy( + ICLRPolicyManager * This, + /* [in] */ EClrOperation operation, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ EPolicyAction action); + + +void __RPC_STUB ICLRPolicyManager_SetTimeoutAndAction_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRPolicyManager_SetActionOnFailure_Proxy( + ICLRPolicyManager * This, + /* [in] */ EClrFailure failure, + /* [in] */ EPolicyAction action); + + +void __RPC_STUB ICLRPolicyManager_SetActionOnFailure_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRPolicyManager_SetUnhandledExceptionPolicy_Proxy( + ICLRPolicyManager * This, + /* [in] */ EClrUnhandledException policy); + + +void __RPC_STUB ICLRPolicyManager_SetUnhandledExceptionPolicy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLRPolicyManager_INTERFACE_DEFINED__ */ + + +#ifndef __IHostPolicyManager_INTERFACE_DEFINED__ +#define __IHostPolicyManager_INTERFACE_DEFINED__ + +/* interface IHostPolicyManager */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IHostPolicyManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("7AE49844-B1E3-4683-BA7C-1E8212EA3B79") + IHostPolicyManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE OnDefaultAction( + /* [in] */ EClrOperation operation, + /* [in] */ EPolicyAction action) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnTimeout( + /* [in] */ EClrOperation operation, + /* [in] */ EPolicyAction action) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnFailure( + /* [in] */ EClrFailure failure, + /* [in] */ EPolicyAction action) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostPolicyManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostPolicyManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostPolicyManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostPolicyManager * This); + + HRESULT ( STDMETHODCALLTYPE *OnDefaultAction )( + IHostPolicyManager * This, + /* [in] */ EClrOperation operation, + /* [in] */ EPolicyAction action); + + HRESULT ( STDMETHODCALLTYPE *OnTimeout )( + IHostPolicyManager * This, + /* [in] */ EClrOperation operation, + /* [in] */ EPolicyAction action); + + HRESULT ( STDMETHODCALLTYPE *OnFailure )( + IHostPolicyManager * This, + /* [in] */ EClrFailure failure, + /* [in] */ EPolicyAction action); + + END_INTERFACE + } IHostPolicyManagerVtbl; + + interface IHostPolicyManager + { + CONST_VTBL struct IHostPolicyManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostPolicyManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostPolicyManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostPolicyManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostPolicyManager_OnDefaultAction(This,operation,action) \ + (This)->lpVtbl -> OnDefaultAction(This,operation,action) + +#define IHostPolicyManager_OnTimeout(This,operation,action) \ + (This)->lpVtbl -> OnTimeout(This,operation,action) + +#define IHostPolicyManager_OnFailure(This,failure,action) \ + (This)->lpVtbl -> OnFailure(This,failure,action) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostPolicyManager_OnDefaultAction_Proxy( + IHostPolicyManager * This, + /* [in] */ EClrOperation operation, + /* [in] */ EPolicyAction action); + + +void __RPC_STUB IHostPolicyManager_OnDefaultAction_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostPolicyManager_OnTimeout_Proxy( + IHostPolicyManager * This, + /* [in] */ EClrOperation operation, + /* [in] */ EPolicyAction action); + + +void __RPC_STUB IHostPolicyManager_OnTimeout_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostPolicyManager_OnFailure_Proxy( + IHostPolicyManager * This, + /* [in] */ EClrFailure failure, + /* [in] */ EPolicyAction action); + + +void __RPC_STUB IHostPolicyManager_OnFailure_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostPolicyManager_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0153 */ +/* [local] */ + +typedef /* [public][public][public][public] */ +enum __MIDL___MIDL_itf_mscoree_0153_0001 + { Event_DomainUnload = 0, + Event_ClrDisabled = Event_DomainUnload + 1, + Event_MDAFired = Event_ClrDisabled + 1, + Event_StackOverflow = Event_MDAFired + 1, + MaxClrEvent = Event_StackOverflow + 1 + } EClrEvent; + +typedef struct _MDAInfo + { + LPCWSTR lpMDACaption; + LPCWSTR lpMDAMessage; + LPCWSTR lpStackTrace; + } MDAInfo; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscoree_0153_0002 + { SO_Managed = 0, + SO_ClrEngine = SO_Managed + 1, + SO_Other = SO_ClrEngine + 1 + } StackOverflowType; + +typedef struct _StackOverflowInfo +{ + StackOverflowType soType; + EXCEPTION_POINTERS *pExceptionInfo; +} StackOverflowInfo; + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0153_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0153_v0_0_s_ifspec; + +#ifndef __IActionOnCLREvent_INTERFACE_DEFINED__ +#define __IActionOnCLREvent_INTERFACE_DEFINED__ + +/* interface IActionOnCLREvent */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IActionOnCLREvent; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("607BE24B-D91B-4E28-A242-61871CE56E35") + IActionOnCLREvent : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE OnEvent( + /* [in] */ EClrEvent event, + /* [in] */ PVOID data) = 0; + + }; + +#else /* C style interface */ + + typedef struct IActionOnCLREventVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IActionOnCLREvent * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IActionOnCLREvent * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IActionOnCLREvent * This); + + HRESULT ( STDMETHODCALLTYPE *OnEvent )( + IActionOnCLREvent * This, + /* [in] */ EClrEvent event, + /* [in] */ PVOID data); + + END_INTERFACE + } IActionOnCLREventVtbl; + + interface IActionOnCLREvent + { + CONST_VTBL struct IActionOnCLREventVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IActionOnCLREvent_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IActionOnCLREvent_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IActionOnCLREvent_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IActionOnCLREvent_OnEvent(This,event,data) \ + (This)->lpVtbl -> OnEvent(This,event,data) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IActionOnCLREvent_OnEvent_Proxy( + IActionOnCLREvent * This, + /* [in] */ EClrEvent event, + /* [in] */ PVOID data); + + +void __RPC_STUB IActionOnCLREvent_OnEvent_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IActionOnCLREvent_INTERFACE_DEFINED__ */ + + +#ifndef __ICLROnEventManager_INTERFACE_DEFINED__ +#define __ICLROnEventManager_INTERFACE_DEFINED__ + +/* interface ICLROnEventManager */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLROnEventManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("1D0E0132-E64F-493D-9260-025C0E32C175") + ICLROnEventManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE RegisterActionOnEvent( + /* [in] */ EClrEvent event, + /* [in] */ IActionOnCLREvent *pAction) = 0; + + virtual HRESULT STDMETHODCALLTYPE UnregisterActionOnEvent( + /* [in] */ EClrEvent event, + /* [in] */ IActionOnCLREvent *pAction) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLROnEventManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLROnEventManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLROnEventManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLROnEventManager * This); + + HRESULT ( STDMETHODCALLTYPE *RegisterActionOnEvent )( + ICLROnEventManager * This, + /* [in] */ EClrEvent event, + /* [in] */ IActionOnCLREvent *pAction); + + HRESULT ( STDMETHODCALLTYPE *UnregisterActionOnEvent )( + ICLROnEventManager * This, + /* [in] */ EClrEvent event, + /* [in] */ IActionOnCLREvent *pAction); + + END_INTERFACE + } ICLROnEventManagerVtbl; + + interface ICLROnEventManager + { + CONST_VTBL struct ICLROnEventManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLROnEventManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLROnEventManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLROnEventManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLROnEventManager_RegisterActionOnEvent(This,event,pAction) \ + (This)->lpVtbl -> RegisterActionOnEvent(This,event,pAction) + +#define ICLROnEventManager_UnregisterActionOnEvent(This,event,pAction) \ + (This)->lpVtbl -> UnregisterActionOnEvent(This,event,pAction) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLROnEventManager_RegisterActionOnEvent_Proxy( + ICLROnEventManager * This, + /* [in] */ EClrEvent event, + /* [in] */ IActionOnCLREvent *pAction); + + +void __RPC_STUB ICLROnEventManager_RegisterActionOnEvent_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLROnEventManager_UnregisterActionOnEvent_Proxy( + ICLROnEventManager * This, + /* [in] */ EClrEvent event, + /* [in] */ IActionOnCLREvent *pAction); + + +void __RPC_STUB ICLROnEventManager_UnregisterActionOnEvent_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLROnEventManager_INTERFACE_DEFINED__ */ + + +#ifndef __IHostGCManager_INTERFACE_DEFINED__ +#define __IHostGCManager_INTERFACE_DEFINED__ + +/* interface IHostGCManager */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IHostGCManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5D4EC34E-F248-457B-B603-255FAABA0D21") + IHostGCManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE ThreadIsBlockingForSuspension( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SuspensionStarting( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SuspensionEnding( + DWORD Generation) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostGCManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostGCManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostGCManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostGCManager * This); + + HRESULT ( STDMETHODCALLTYPE *ThreadIsBlockingForSuspension )( + IHostGCManager * This); + + HRESULT ( STDMETHODCALLTYPE *SuspensionStarting )( + IHostGCManager * This); + + HRESULT ( STDMETHODCALLTYPE *SuspensionEnding )( + IHostGCManager * This, + DWORD Generation); + + END_INTERFACE + } IHostGCManagerVtbl; + + interface IHostGCManager + { + CONST_VTBL struct IHostGCManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostGCManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostGCManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostGCManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostGCManager_ThreadIsBlockingForSuspension(This) \ + (This)->lpVtbl -> ThreadIsBlockingForSuspension(This) + +#define IHostGCManager_SuspensionStarting(This) \ + (This)->lpVtbl -> SuspensionStarting(This) + +#define IHostGCManager_SuspensionEnding(This,Generation) \ + (This)->lpVtbl -> SuspensionEnding(This,Generation) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostGCManager_ThreadIsBlockingForSuspension_Proxy( + IHostGCManager * This); + + +void __RPC_STUB IHostGCManager_ThreadIsBlockingForSuspension_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostGCManager_SuspensionStarting_Proxy( + IHostGCManager * This); + + +void __RPC_STUB IHostGCManager_SuspensionStarting_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostGCManager_SuspensionEnding_Proxy( + IHostGCManager * This, + DWORD Generation); + + +void __RPC_STUB IHostGCManager_SuspensionEnding_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostGCManager_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRGCManager_INTERFACE_DEFINED__ +#define __ICLRGCManager_INTERFACE_DEFINED__ + +/* interface ICLRGCManager */ +/* [object][local][unique][version][uuid] */ + + +EXTERN_C const IID IID_ICLRGCManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("54D9007E-A8E2-4885-B7BF-F998DEEE4F2A") + ICLRGCManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Collect( + /* [in] */ LONG Generation) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStats( + /* [out][in] */ COR_GC_STATS *pStats) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetGCStartupLimits( + /* [in] */ DWORD SegmentSize, + /* [in] */ DWORD MaxGen0Size) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLRGCManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRGCManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRGCManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRGCManager * This); + + HRESULT ( STDMETHODCALLTYPE *Collect )( + ICLRGCManager * This, + /* [in] */ LONG Generation); + + HRESULT ( STDMETHODCALLTYPE *GetStats )( + ICLRGCManager * This, + /* [out][in] */ COR_GC_STATS *pStats); + + HRESULT ( STDMETHODCALLTYPE *SetGCStartupLimits )( + ICLRGCManager * This, + /* [in] */ DWORD SegmentSize, + /* [in] */ DWORD MaxGen0Size); + + END_INTERFACE + } ICLRGCManagerVtbl; + + interface ICLRGCManager + { + CONST_VTBL struct ICLRGCManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRGCManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLRGCManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLRGCManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLRGCManager_Collect(This,Generation) \ + (This)->lpVtbl -> Collect(This,Generation) + +#define ICLRGCManager_GetStats(This,pStats) \ + (This)->lpVtbl -> GetStats(This,pStats) + +#define ICLRGCManager_SetGCStartupLimits(This,SegmentSize,MaxGen0Size) \ + (This)->lpVtbl -> SetGCStartupLimits(This,SegmentSize,MaxGen0Size) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLRGCManager_Collect_Proxy( + ICLRGCManager * This, + /* [in] */ LONG Generation); + + +void __RPC_STUB ICLRGCManager_Collect_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRGCManager_GetStats_Proxy( + ICLRGCManager * This, + /* [out][in] */ COR_GC_STATS *pStats); + + +void __RPC_STUB ICLRGCManager_GetStats_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRGCManager_SetGCStartupLimits_Proxy( + ICLRGCManager * This, + /* [in] */ DWORD SegmentSize, + /* [in] */ DWORD MaxGen0Size); + + +void __RPC_STUB ICLRGCManager_SetGCStartupLimits_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLRGCManager_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRAssemblyReferenceList_INTERFACE_DEFINED__ +#define __ICLRAssemblyReferenceList_INTERFACE_DEFINED__ + +/* interface ICLRAssemblyReferenceList */ +/* [local][unique][helpstring][uuid][version][object] */ + + +EXTERN_C const IID IID_ICLRAssemblyReferenceList; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("1b2c9750-2e66-4bda-8b44-0a642c5cd733") + ICLRAssemblyReferenceList : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE IsStringAssemblyReferenceInList( + /* [in] */ LPCWSTR pwzAssemblyName) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsAssemblyReferenceInList( + /* [in] */ IUnknown *pName) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLRAssemblyReferenceListVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRAssemblyReferenceList * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRAssemblyReferenceList * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRAssemblyReferenceList * This); + + HRESULT ( STDMETHODCALLTYPE *IsStringAssemblyReferenceInList )( + ICLRAssemblyReferenceList * This, + /* [in] */ LPCWSTR pwzAssemblyName); + + HRESULT ( STDMETHODCALLTYPE *IsAssemblyReferenceInList )( + ICLRAssemblyReferenceList * This, + /* [in] */ IUnknown *pName); + + END_INTERFACE + } ICLRAssemblyReferenceListVtbl; + + interface ICLRAssemblyReferenceList + { + CONST_VTBL struct ICLRAssemblyReferenceListVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRAssemblyReferenceList_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLRAssemblyReferenceList_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLRAssemblyReferenceList_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLRAssemblyReferenceList_IsStringAssemblyReferenceInList(This,pwzAssemblyName) \ + (This)->lpVtbl -> IsStringAssemblyReferenceInList(This,pwzAssemblyName) + +#define ICLRAssemblyReferenceList_IsAssemblyReferenceInList(This,pName) \ + (This)->lpVtbl -> IsAssemblyReferenceInList(This,pName) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLRAssemblyReferenceList_IsStringAssemblyReferenceInList_Proxy( + ICLRAssemblyReferenceList * This, + /* [in] */ LPCWSTR pwzAssemblyName); + + +void __RPC_STUB ICLRAssemblyReferenceList_IsStringAssemblyReferenceInList_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRAssemblyReferenceList_IsAssemblyReferenceInList_Proxy( + ICLRAssemblyReferenceList * This, + /* [in] */ IUnknown *pName); + + +void __RPC_STUB ICLRAssemblyReferenceList_IsAssemblyReferenceInList_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLRAssemblyReferenceList_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRReferenceAssemblyEnum_INTERFACE_DEFINED__ +#define __ICLRReferenceAssemblyEnum_INTERFACE_DEFINED__ + +/* interface ICLRReferenceAssemblyEnum */ +/* [local][unique][helpstring][uuid][version][object] */ + + +EXTERN_C const IID IID_ICLRReferenceAssemblyEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("d509cb5d-cf32-4876-ae61-67770cf91973") + ICLRReferenceAssemblyEnum : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Get( + /* [in] */ DWORD dwIndex, + /* [size_is][out] */ LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBufferSize) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLRReferenceAssemblyEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRReferenceAssemblyEnum * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRReferenceAssemblyEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRReferenceAssemblyEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Get )( + ICLRReferenceAssemblyEnum * This, + /* [in] */ DWORD dwIndex, + /* [size_is][out] */ LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBufferSize); + + END_INTERFACE + } ICLRReferenceAssemblyEnumVtbl; + + interface ICLRReferenceAssemblyEnum + { + CONST_VTBL struct ICLRReferenceAssemblyEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRReferenceAssemblyEnum_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLRReferenceAssemblyEnum_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLRReferenceAssemblyEnum_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLRReferenceAssemblyEnum_Get(This,dwIndex,pwzBuffer,pcchBufferSize) \ + (This)->lpVtbl -> Get(This,dwIndex,pwzBuffer,pcchBufferSize) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLRReferenceAssemblyEnum_Get_Proxy( + ICLRReferenceAssemblyEnum * This, + /* [in] */ DWORD dwIndex, + /* [size_is][out] */ LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBufferSize); + + +void __RPC_STUB ICLRReferenceAssemblyEnum_Get_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLRReferenceAssemblyEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRProbingAssemblyEnum_INTERFACE_DEFINED__ +#define __ICLRProbingAssemblyEnum_INTERFACE_DEFINED__ + +/* interface ICLRProbingAssemblyEnum */ +/* [local][unique][helpstring][uuid][version][object] */ + + +EXTERN_C const IID IID_ICLRProbingAssemblyEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("d0c5fb1f-416b-4f97-81f4-7ac7dc24dd5d") + ICLRProbingAssemblyEnum : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Get( + /* [in] */ DWORD dwIndex, + /* [size_is][out] */ LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBufferSize) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLRProbingAssemblyEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRProbingAssemblyEnum * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRProbingAssemblyEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRProbingAssemblyEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Get )( + ICLRProbingAssemblyEnum * This, + /* [in] */ DWORD dwIndex, + /* [size_is][out] */ LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBufferSize); + + END_INTERFACE + } ICLRProbingAssemblyEnumVtbl; + + interface ICLRProbingAssemblyEnum + { + CONST_VTBL struct ICLRProbingAssemblyEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRProbingAssemblyEnum_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLRProbingAssemblyEnum_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLRProbingAssemblyEnum_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLRProbingAssemblyEnum_Get(This,dwIndex,pwzBuffer,pcchBufferSize) \ + (This)->lpVtbl -> Get(This,dwIndex,pwzBuffer,pcchBufferSize) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLRProbingAssemblyEnum_Get_Proxy( + ICLRProbingAssemblyEnum * This, + /* [in] */ DWORD dwIndex, + /* [size_is][out] */ LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBufferSize); + + +void __RPC_STUB ICLRProbingAssemblyEnum_Get_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLRProbingAssemblyEnum_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0160 */ +/* [local] */ + +typedef +enum _CLRAssemblyIdentityFlags + { CLR_ASSEMBLY_IDENTITY_FLAGS_DEFAULT = 0 + } ECLRAssemblyIdentityFlags; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0160_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0160_v0_0_s_ifspec; + +#ifndef __ICLRAssemblyIdentityManager_INTERFACE_DEFINED__ +#define __ICLRAssemblyIdentityManager_INTERFACE_DEFINED__ + +/* interface ICLRAssemblyIdentityManager */ +/* [local][unique][helpstring][uuid][version][object] */ + + +EXTERN_C const IID IID_ICLRAssemblyIdentityManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("15f0a9da-3ff6-4393-9da9-fdfd284e6972") + ICLRAssemblyIdentityManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetCLRAssemblyReferenceList( + /* [in] */ LPCWSTR *ppwzAssemblyReferences, + /* [in] */ DWORD dwNumOfReferences, + /* [out] */ ICLRAssemblyReferenceList **ppReferenceList) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetBindingIdentityFromFile( + /* [in] */ LPCWSTR pwzFilePath, + /* [in] */ DWORD dwFlags, + /* [size_is][out] */ LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBufferSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetBindingIdentityFromStream( + /* [in] */ IStream *pStream, + /* [in] */ DWORD dwFlags, + /* [size_is][out] */ LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBufferSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetReferencedAssembliesFromFile( + /* [in] */ LPCWSTR pwzFilePath, + /* [in] */ DWORD dwFlags, + /* [in] */ ICLRAssemblyReferenceList *pExcludeAssembliesList, + /* [out] */ ICLRReferenceAssemblyEnum **ppReferenceEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetReferencedAssembliesFromStream( + /* [in] */ IStream *pStream, + /* [in] */ DWORD dwFlags, + /* [in] */ ICLRAssemblyReferenceList *pExcludeAssembliesList, + /* [out] */ ICLRReferenceAssemblyEnum **ppReferenceEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetProbingAssembliesFromReference( + /* [in] */ DWORD dwMachineType, + /* [in] */ DWORD dwFlags, + /* [in] */ LPCWSTR pwzReferenceIdentity, + /* [out] */ ICLRProbingAssemblyEnum **ppProbingAssemblyEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsStronglyNamed( + /* [in] */ LPCWSTR pwzAssemblyIdentity, + /* [out] */ BOOL *pbIsStronglyNamed) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLRAssemblyIdentityManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRAssemblyIdentityManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRAssemblyIdentityManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRAssemblyIdentityManager * This); + + HRESULT ( STDMETHODCALLTYPE *GetCLRAssemblyReferenceList )( + ICLRAssemblyIdentityManager * This, + /* [in] */ LPCWSTR *ppwzAssemblyReferences, + /* [in] */ DWORD dwNumOfReferences, + /* [out] */ ICLRAssemblyReferenceList **ppReferenceList); + + HRESULT ( STDMETHODCALLTYPE *GetBindingIdentityFromFile )( + ICLRAssemblyIdentityManager * This, + /* [in] */ LPCWSTR pwzFilePath, + /* [in] */ DWORD dwFlags, + /* [size_is][out] */ LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBufferSize); + + HRESULT ( STDMETHODCALLTYPE *GetBindingIdentityFromStream )( + ICLRAssemblyIdentityManager * This, + /* [in] */ IStream *pStream, + /* [in] */ DWORD dwFlags, + /* [size_is][out] */ LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBufferSize); + + HRESULT ( STDMETHODCALLTYPE *GetReferencedAssembliesFromFile )( + ICLRAssemblyIdentityManager * This, + /* [in] */ LPCWSTR pwzFilePath, + /* [in] */ DWORD dwFlags, + /* [in] */ ICLRAssemblyReferenceList *pExcludeAssembliesList, + /* [out] */ ICLRReferenceAssemblyEnum **ppReferenceEnum); + + HRESULT ( STDMETHODCALLTYPE *GetReferencedAssembliesFromStream )( + ICLRAssemblyIdentityManager * This, + /* [in] */ IStream *pStream, + /* [in] */ DWORD dwFlags, + /* [in] */ ICLRAssemblyReferenceList *pExcludeAssembliesList, + /* [out] */ ICLRReferenceAssemblyEnum **ppReferenceEnum); + + HRESULT ( STDMETHODCALLTYPE *GetProbingAssembliesFromReference )( + ICLRAssemblyIdentityManager * This, + /* [in] */ DWORD dwMachineType, + /* [in] */ DWORD dwFlags, + /* [in] */ LPCWSTR pwzReferenceIdentity, + /* [out] */ ICLRProbingAssemblyEnum **ppProbingAssemblyEnum); + + HRESULT ( STDMETHODCALLTYPE *IsStronglyNamed )( + ICLRAssemblyIdentityManager * This, + /* [in] */ LPCWSTR pwzAssemblyIdentity, + /* [out] */ BOOL *pbIsStronglyNamed); + + END_INTERFACE + } ICLRAssemblyIdentityManagerVtbl; + + interface ICLRAssemblyIdentityManager + { + CONST_VTBL struct ICLRAssemblyIdentityManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRAssemblyIdentityManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLRAssemblyIdentityManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLRAssemblyIdentityManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLRAssemblyIdentityManager_GetCLRAssemblyReferenceList(This,ppwzAssemblyReferences,dwNumOfReferences,ppReferenceList) \ + (This)->lpVtbl -> GetCLRAssemblyReferenceList(This,ppwzAssemblyReferences,dwNumOfReferences,ppReferenceList) + +#define ICLRAssemblyIdentityManager_GetBindingIdentityFromFile(This,pwzFilePath,dwFlags,pwzBuffer,pcchBufferSize) \ + (This)->lpVtbl -> GetBindingIdentityFromFile(This,pwzFilePath,dwFlags,pwzBuffer,pcchBufferSize) + +#define ICLRAssemblyIdentityManager_GetBindingIdentityFromStream(This,pStream,dwFlags,pwzBuffer,pcchBufferSize) \ + (This)->lpVtbl -> GetBindingIdentityFromStream(This,pStream,dwFlags,pwzBuffer,pcchBufferSize) + +#define ICLRAssemblyIdentityManager_GetReferencedAssembliesFromFile(This,pwzFilePath,dwFlags,pExcludeAssembliesList,ppReferenceEnum) \ + (This)->lpVtbl -> GetReferencedAssembliesFromFile(This,pwzFilePath,dwFlags,pExcludeAssembliesList,ppReferenceEnum) + +#define ICLRAssemblyIdentityManager_GetReferencedAssembliesFromStream(This,pStream,dwFlags,pExcludeAssembliesList,ppReferenceEnum) \ + (This)->lpVtbl -> GetReferencedAssembliesFromStream(This,pStream,dwFlags,pExcludeAssembliesList,ppReferenceEnum) + +#define ICLRAssemblyIdentityManager_GetProbingAssembliesFromReference(This,dwMachineType,dwFlags,pwzReferenceIdentity,ppProbingAssemblyEnum) \ + (This)->lpVtbl -> GetProbingAssembliesFromReference(This,dwMachineType,dwFlags,pwzReferenceIdentity,ppProbingAssemblyEnum) + +#define ICLRAssemblyIdentityManager_IsStronglyNamed(This,pwzAssemblyIdentity,pbIsStronglyNamed) \ + (This)->lpVtbl -> IsStronglyNamed(This,pwzAssemblyIdentity,pbIsStronglyNamed) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLRAssemblyIdentityManager_GetCLRAssemblyReferenceList_Proxy( + ICLRAssemblyIdentityManager * This, + /* [in] */ LPCWSTR *ppwzAssemblyReferences, + /* [in] */ DWORD dwNumOfReferences, + /* [out] */ ICLRAssemblyReferenceList **ppReferenceList); + + +void __RPC_STUB ICLRAssemblyIdentityManager_GetCLRAssemblyReferenceList_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRAssemblyIdentityManager_GetBindingIdentityFromFile_Proxy( + ICLRAssemblyIdentityManager * This, + /* [in] */ LPCWSTR pwzFilePath, + /* [in] */ DWORD dwFlags, + /* [size_is][out] */ LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBufferSize); + + +void __RPC_STUB ICLRAssemblyIdentityManager_GetBindingIdentityFromFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRAssemblyIdentityManager_GetBindingIdentityFromStream_Proxy( + ICLRAssemblyIdentityManager * This, + /* [in] */ IStream *pStream, + /* [in] */ DWORD dwFlags, + /* [size_is][out] */ LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBufferSize); + + +void __RPC_STUB ICLRAssemblyIdentityManager_GetBindingIdentityFromStream_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRAssemblyIdentityManager_GetReferencedAssembliesFromFile_Proxy( + ICLRAssemblyIdentityManager * This, + /* [in] */ LPCWSTR pwzFilePath, + /* [in] */ DWORD dwFlags, + /* [in] */ ICLRAssemblyReferenceList *pExcludeAssembliesList, + /* [out] */ ICLRReferenceAssemblyEnum **ppReferenceEnum); + + +void __RPC_STUB ICLRAssemblyIdentityManager_GetReferencedAssembliesFromFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRAssemblyIdentityManager_GetReferencedAssembliesFromStream_Proxy( + ICLRAssemblyIdentityManager * This, + /* [in] */ IStream *pStream, + /* [in] */ DWORD dwFlags, + /* [in] */ ICLRAssemblyReferenceList *pExcludeAssembliesList, + /* [out] */ ICLRReferenceAssemblyEnum **ppReferenceEnum); + + +void __RPC_STUB ICLRAssemblyIdentityManager_GetReferencedAssembliesFromStream_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRAssemblyIdentityManager_GetProbingAssembliesFromReference_Proxy( + ICLRAssemblyIdentityManager * This, + /* [in] */ DWORD dwMachineType, + /* [in] */ DWORD dwFlags, + /* [in] */ LPCWSTR pwzReferenceIdentity, + /* [out] */ ICLRProbingAssemblyEnum **ppProbingAssemblyEnum); + + +void __RPC_STUB ICLRAssemblyIdentityManager_GetProbingAssembliesFromReference_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRAssemblyIdentityManager_IsStronglyNamed_Proxy( + ICLRAssemblyIdentityManager * This, + /* [in] */ LPCWSTR pwzAssemblyIdentity, + /* [out] */ BOOL *pbIsStronglyNamed); + + +void __RPC_STUB ICLRAssemblyIdentityManager_IsStronglyNamed_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLRAssemblyIdentityManager_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0161 */ +/* [local] */ + +typedef +enum _hostBiningPolicyModifyFlags + { HOST_BINDING_POLICY_MODIFY_DEFAULT = 0, + HOST_BINDING_POLICY_MODIFY_CHAIN = 1, + HOST_BINDING_POLICY_MODIFY_REMOVE = 2, + HOST_BINDING_POLICY_MODIFY_MAX = 3 + } EHostBindingPolicyModifyFlags; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0161_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0161_v0_0_s_ifspec; + +#ifndef __ICLRHostBindingPolicyManager_INTERFACE_DEFINED__ +#define __ICLRHostBindingPolicyManager_INTERFACE_DEFINED__ + +/* interface ICLRHostBindingPolicyManager */ +/* [local][unique][helpstring][uuid][version][object] */ + + +EXTERN_C const IID IID_ICLRHostBindingPolicyManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("4b3545e7-1856-48c9-a8ba-24b21a753c09") + ICLRHostBindingPolicyManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE ModifyApplicationPolicy( + /* [in] */ LPCWSTR pwzSourceAssemblyIdentity, + /* [in] */ LPCWSTR pwzTargetAssemblyIdentity, + /* [in] */ BYTE *pbApplicationPolicy, + /* [in] */ DWORD cbAppPolicySize, + /* [in] */ DWORD dwPolicyModifyFlags, + /* [size_is][out] */ BYTE *pbNewApplicationPolicy, + /* [out][in] */ DWORD *pcbNewAppPolicySize) = 0; + + virtual HRESULT STDMETHODCALLTYPE EvaluatePolicy( + /* [in] */ LPCWSTR pwzReferenceIdentity, + /* [in] */ BYTE *pbApplicationPolicy, + /* [in] */ DWORD cbAppPolicySize, + /* [size_is][out] */ LPWSTR pwzPostPolicyReferenceIdentity, + /* [out][in] */ DWORD *pcchPostPolicyReferenceIdentity, + /* [out] */ DWORD *pdwPoliciesApplied) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLRHostBindingPolicyManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRHostBindingPolicyManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRHostBindingPolicyManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRHostBindingPolicyManager * This); + + HRESULT ( STDMETHODCALLTYPE *ModifyApplicationPolicy )( + ICLRHostBindingPolicyManager * This, + /* [in] */ LPCWSTR pwzSourceAssemblyIdentity, + /* [in] */ LPCWSTR pwzTargetAssemblyIdentity, + /* [in] */ BYTE *pbApplicationPolicy, + /* [in] */ DWORD cbAppPolicySize, + /* [in] */ DWORD dwPolicyModifyFlags, + /* [size_is][out] */ BYTE *pbNewApplicationPolicy, + /* [out][in] */ DWORD *pcbNewAppPolicySize); + + HRESULT ( STDMETHODCALLTYPE *EvaluatePolicy )( + ICLRHostBindingPolicyManager * This, + /* [in] */ LPCWSTR pwzReferenceIdentity, + /* [in] */ BYTE *pbApplicationPolicy, + /* [in] */ DWORD cbAppPolicySize, + /* [size_is][out] */ LPWSTR pwzPostPolicyReferenceIdentity, + /* [out][in] */ DWORD *pcchPostPolicyReferenceIdentity, + /* [out] */ DWORD *pdwPoliciesApplied); + + END_INTERFACE + } ICLRHostBindingPolicyManagerVtbl; + + interface ICLRHostBindingPolicyManager + { + CONST_VTBL struct ICLRHostBindingPolicyManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRHostBindingPolicyManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLRHostBindingPolicyManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLRHostBindingPolicyManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLRHostBindingPolicyManager_ModifyApplicationPolicy(This,pwzSourceAssemblyIdentity,pwzTargetAssemblyIdentity,pbApplicationPolicy,cbAppPolicySize,dwPolicyModifyFlags,pbNewApplicationPolicy,pcbNewAppPolicySize) \ + (This)->lpVtbl -> ModifyApplicationPolicy(This,pwzSourceAssemblyIdentity,pwzTargetAssemblyIdentity,pbApplicationPolicy,cbAppPolicySize,dwPolicyModifyFlags,pbNewApplicationPolicy,pcbNewAppPolicySize) + +#define ICLRHostBindingPolicyManager_EvaluatePolicy(This,pwzReferenceIdentity,pbApplicationPolicy,cbAppPolicySize,pwzPostPolicyReferenceIdentity,pcchPostPolicyReferenceIdentity,pdwPoliciesApplied) \ + (This)->lpVtbl -> EvaluatePolicy(This,pwzReferenceIdentity,pbApplicationPolicy,cbAppPolicySize,pwzPostPolicyReferenceIdentity,pcchPostPolicyReferenceIdentity,pdwPoliciesApplied) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLRHostBindingPolicyManager_ModifyApplicationPolicy_Proxy( + ICLRHostBindingPolicyManager * This, + /* [in] */ LPCWSTR pwzSourceAssemblyIdentity, + /* [in] */ LPCWSTR pwzTargetAssemblyIdentity, + /* [in] */ BYTE *pbApplicationPolicy, + /* [in] */ DWORD cbAppPolicySize, + /* [in] */ DWORD dwPolicyModifyFlags, + /* [size_is][out] */ BYTE *pbNewApplicationPolicy, + /* [out][in] */ DWORD *pcbNewAppPolicySize); + + +void __RPC_STUB ICLRHostBindingPolicyManager_ModifyApplicationPolicy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRHostBindingPolicyManager_EvaluatePolicy_Proxy( + ICLRHostBindingPolicyManager * This, + /* [in] */ LPCWSTR pwzReferenceIdentity, + /* [in] */ BYTE *pbApplicationPolicy, + /* [in] */ DWORD cbAppPolicySize, + /* [size_is][out] */ LPWSTR pwzPostPolicyReferenceIdentity, + /* [out][in] */ DWORD *pcchPostPolicyReferenceIdentity, + /* [out] */ DWORD *pdwPoliciesApplied); + + +void __RPC_STUB ICLRHostBindingPolicyManager_EvaluatePolicy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLRHostBindingPolicyManager_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0162 */ +/* [local] */ + +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscoree_0162_0001 + { ePolicyLevelNone = 0, + ePolicyLevelRetargetable = 0x1, + ePolicyUnifiedToCLR = 0x2, + ePolicyLevelApp = 0x4, + ePolicyLevelPublisher = 0x8, + ePolicyLevelHost = 0x10, + ePolicyLevelAdmin = 0x20 + } EBindPolicyLevels; + +typedef struct _AssemblyBindInfo + { + DWORD dwAppDomainId; + LPCWSTR lpReferencedIdentity; + LPCWSTR lpPostPolicyIdentity; + DWORD ePolicyLevel; + } AssemblyBindInfo; + +typedef struct _ModuleBindInfo + { + DWORD dwAppDomainId; + LPCWSTR lpAssemblyIdentity; + LPCWSTR lpModuleName; + } ModuleBindInfo; + +typedef +enum _HostApplicationPolicy + { HOST_APPLICATION_BINDING_POLICY = 1 + } EHostApplicationPolicy; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0162_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0162_v0_0_s_ifspec; + +#ifndef __IHostAssemblyStore_INTERFACE_DEFINED__ +#define __IHostAssemblyStore_INTERFACE_DEFINED__ + +/* interface IHostAssemblyStore */ +/* [unique][helpstring][uuid][version][object][local] */ + + +EXTERN_C const IID IID_IHostAssemblyStore; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("7b102a88-3f7f-496d-8fa2-c35374e01af3") + IHostAssemblyStore : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE ProvideAssembly( + /* [in] */ AssemblyBindInfo *pBindInfo, + /* [out] */ UINT64 *pAssemblyId, + /* [out] */ UINT64 *pContext, + /* [out] */ IStream **ppStmAssemblyImage, + /* [out] */ IStream **ppStmPDB) = 0; + + virtual HRESULT STDMETHODCALLTYPE ProvideModule( + /* [in] */ ModuleBindInfo *pBindInfo, + /* [out] */ DWORD *pdwModuleId, + /* [out] */ IStream **ppStmModuleImage, + /* [out] */ IStream **ppStmPDB) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostAssemblyStoreVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostAssemblyStore * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostAssemblyStore * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostAssemblyStore * This); + + HRESULT ( STDMETHODCALLTYPE *ProvideAssembly )( + IHostAssemblyStore * This, + /* [in] */ AssemblyBindInfo *pBindInfo, + /* [out] */ UINT64 *pAssemblyId, + /* [out] */ UINT64 *pContext, + /* [out] */ IStream **ppStmAssemblyImage, + /* [out] */ IStream **ppStmPDB); + + HRESULT ( STDMETHODCALLTYPE *ProvideModule )( + IHostAssemblyStore * This, + /* [in] */ ModuleBindInfo *pBindInfo, + /* [out] */ DWORD *pdwModuleId, + /* [out] */ IStream **ppStmModuleImage, + /* [out] */ IStream **ppStmPDB); + + END_INTERFACE + } IHostAssemblyStoreVtbl; + + interface IHostAssemblyStore + { + CONST_VTBL struct IHostAssemblyStoreVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostAssemblyStore_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostAssemblyStore_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostAssemblyStore_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostAssemblyStore_ProvideAssembly(This,pBindInfo,pAssemblyId,pContext,ppStmAssemblyImage,ppStmPDB) \ + (This)->lpVtbl -> ProvideAssembly(This,pBindInfo,pAssemblyId,pContext,ppStmAssemblyImage,ppStmPDB) + +#define IHostAssemblyStore_ProvideModule(This,pBindInfo,pdwModuleId,ppStmModuleImage,ppStmPDB) \ + (This)->lpVtbl -> ProvideModule(This,pBindInfo,pdwModuleId,ppStmModuleImage,ppStmPDB) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostAssemblyStore_ProvideAssembly_Proxy( + IHostAssemblyStore * This, + /* [in] */ AssemblyBindInfo *pBindInfo, + /* [out] */ UINT64 *pAssemblyId, + /* [out] */ UINT64 *pContext, + /* [out] */ IStream **ppStmAssemblyImage, + /* [out] */ IStream **ppStmPDB); + + +void __RPC_STUB IHostAssemblyStore_ProvideAssembly_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostAssemblyStore_ProvideModule_Proxy( + IHostAssemblyStore * This, + /* [in] */ ModuleBindInfo *pBindInfo, + /* [out] */ DWORD *pdwModuleId, + /* [out] */ IStream **ppStmModuleImage, + /* [out] */ IStream **ppStmPDB); + + +void __RPC_STUB IHostAssemblyStore_ProvideModule_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostAssemblyStore_INTERFACE_DEFINED__ */ + + +#ifndef __IHostAssemblyManager_INTERFACE_DEFINED__ +#define __IHostAssemblyManager_INTERFACE_DEFINED__ + +/* interface IHostAssemblyManager */ +/* [unique][helpstring][uuid][version][object][local] */ + + +EXTERN_C const IID IID_IHostAssemblyManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("613dabd7-62b2-493e-9e65-c1e32a1e0c5e") + IHostAssemblyManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetNonHostStoreAssemblies( + /* [out] */ ICLRAssemblyReferenceList **ppReferenceList) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAssemblyStore( + /* [out] */ IHostAssemblyStore **ppAssemblyStore) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostAssemblyManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostAssemblyManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostAssemblyManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostAssemblyManager * This); + + HRESULT ( STDMETHODCALLTYPE *GetNonHostStoreAssemblies )( + IHostAssemblyManager * This, + /* [out] */ ICLRAssemblyReferenceList **ppReferenceList); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyStore )( + IHostAssemblyManager * This, + /* [out] */ IHostAssemblyStore **ppAssemblyStore); + + END_INTERFACE + } IHostAssemblyManagerVtbl; + + interface IHostAssemblyManager + { + CONST_VTBL struct IHostAssemblyManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostAssemblyManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostAssemblyManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostAssemblyManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostAssemblyManager_GetNonHostStoreAssemblies(This,ppReferenceList) \ + (This)->lpVtbl -> GetNonHostStoreAssemblies(This,ppReferenceList) + +#define IHostAssemblyManager_GetAssemblyStore(This,ppAssemblyStore) \ + (This)->lpVtbl -> GetAssemblyStore(This,ppAssemblyStore) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostAssemblyManager_GetNonHostStoreAssemblies_Proxy( + IHostAssemblyManager * This, + /* [out] */ ICLRAssemblyReferenceList **ppReferenceList); + + +void __RPC_STUB IHostAssemblyManager_GetNonHostStoreAssemblies_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostAssemblyManager_GetAssemblyStore_Proxy( + IHostAssemblyManager * This, + /* [out] */ IHostAssemblyStore **ppAssemblyStore); + + +void __RPC_STUB IHostAssemblyManager_GetAssemblyStore_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostAssemblyManager_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0164 */ +/* [local] */ + +STDAPI GetCLRIdentityManager(REFIID riid, IUnknown **ppManager); +EXTERN_GUID(IID_IHostControl, 0x02CA073C, 0x7079, 0x4860, 0x88, 0x0A, 0xC2, 0xF7, 0xA4, 0x49, 0xC9, 0x91); + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0164_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0164_v0_0_s_ifspec; + +#ifndef __IHostControl_INTERFACE_DEFINED__ +#define __IHostControl_INTERFACE_DEFINED__ + +/* interface IHostControl */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_IHostControl; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("02CA073C-7079-4860-880A-C2F7A449C991") + IHostControl : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetHostManager( + /* [in] */ REFIID riid, + /* [out] */ void **ppObject) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetAppDomainManager( + /* [in] */ DWORD dwAppDomainID, + /* [in] */ IUnknown *pUnkAppDomainManager) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostControlVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostControl * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostControl * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostControl * This); + + HRESULT ( STDMETHODCALLTYPE *GetHostManager )( + IHostControl * This, + /* [in] */ REFIID riid, + /* [out] */ void **ppObject); + + HRESULT ( STDMETHODCALLTYPE *SetAppDomainManager )( + IHostControl * This, + /* [in] */ DWORD dwAppDomainID, + /* [in] */ IUnknown *pUnkAppDomainManager); + + END_INTERFACE + } IHostControlVtbl; + + interface IHostControl + { + CONST_VTBL struct IHostControlVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostControl_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostControl_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostControl_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostControl_GetHostManager(This,riid,ppObject) \ + (This)->lpVtbl -> GetHostManager(This,riid,ppObject) + +#define IHostControl_SetAppDomainManager(This,dwAppDomainID,pUnkAppDomainManager) \ + (This)->lpVtbl -> SetAppDomainManager(This,dwAppDomainID,pUnkAppDomainManager) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostControl_GetHostManager_Proxy( + IHostControl * This, + /* [in] */ REFIID riid, + /* [out] */ void **ppObject); + + +void __RPC_STUB IHostControl_GetHostManager_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostControl_SetAppDomainManager_Proxy( + IHostControl * This, + /* [in] */ DWORD dwAppDomainID, + /* [in] */ IUnknown *pUnkAppDomainManager); + + +void __RPC_STUB IHostControl_SetAppDomainManager_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostControl_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0165 */ +/* [local] */ + +EXTERN_GUID(IID_ICLRControl, 0x9065597E, 0xD1A1, 0x4fb2, 0xB6, 0xBA, 0x7E, 0x1F, 0xCE, 0x23, 0x0F, 0x61); + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0165_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0165_v0_0_s_ifspec; + +#ifndef __ICLRControl_INTERFACE_DEFINED__ +#define __ICLRControl_INTERFACE_DEFINED__ + +/* interface ICLRControl */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRControl; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9065597E-D1A1-4fb2-B6BA-7E1FCE230F61") + ICLRControl : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetCLRManager( + /* [in] */ REFIID riid, + /* [out] */ void **ppObject) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetAppDomainManagerType( + /* [in] */ LPCWSTR pwzAppDomainManagerAssembly, + /* [in] */ LPCWSTR pwzAppDomainManagerType) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLRControlVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRControl * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRControl * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRControl * This); + + HRESULT ( STDMETHODCALLTYPE *GetCLRManager )( + ICLRControl * This, + /* [in] */ REFIID riid, + /* [out] */ void **ppObject); + + HRESULT ( STDMETHODCALLTYPE *SetAppDomainManagerType )( + ICLRControl * This, + /* [in] */ LPCWSTR pwzAppDomainManagerAssembly, + /* [in] */ LPCWSTR pwzAppDomainManagerType); + + END_INTERFACE + } ICLRControlVtbl; + + interface ICLRControl + { + CONST_VTBL struct ICLRControlVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRControl_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLRControl_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLRControl_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLRControl_GetCLRManager(This,riid,ppObject) \ + (This)->lpVtbl -> GetCLRManager(This,riid,ppObject) + +#define ICLRControl_SetAppDomainManagerType(This,pwzAppDomainManagerAssembly,pwzAppDomainManagerType) \ + (This)->lpVtbl -> SetAppDomainManagerType(This,pwzAppDomainManagerAssembly,pwzAppDomainManagerType) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLRControl_GetCLRManager_Proxy( + ICLRControl * This, + /* [in] */ REFIID riid, + /* [out] */ void **ppObject); + + +void __RPC_STUB ICLRControl_GetCLRManager_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRControl_SetAppDomainManagerType_Proxy( + ICLRControl * This, + /* [in] */ LPCWSTR pwzAppDomainManagerAssembly, + /* [in] */ LPCWSTR pwzAppDomainManagerType); + + +void __RPC_STUB ICLRControl_SetAppDomainManagerType_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLRControl_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRRuntimeHost_INTERFACE_DEFINED__ +#define __ICLRRuntimeHost_INTERFACE_DEFINED__ + +/* interface ICLRRuntimeHost */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRRuntimeHost; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("90F1A06C-7712-4762-86B5-7A5EBA6BDB02") + ICLRRuntimeHost : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Start( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Stop( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetHostControl( + /* [in] */ IHostControl *pHostControl) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCLRControl( + /* [out] */ ICLRControl **pCLRControl) = 0; + + virtual HRESULT STDMETHODCALLTYPE UnloadAppDomain( + /* [in] */ DWORD dwAppDomainId, + /* [in] */ BOOL fWaitUntilDone) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExecuteInAppDomain( + /* [in] */ DWORD dwAppDomainId, + /* [in] */ FExecuteInAppDomainCallback pCallback, + /* [in] */ void *cookie) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCurrentAppDomainId( + /* [out] */ DWORD *pdwAppDomainId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExecuteApplication( + /* [in] */ LPCWSTR pwzAppFullName, + /* [in] */ DWORD dwManifestPaths, + /* [in] */ LPCWSTR *ppwzManifestPaths, + /* [in] */ DWORD dwActivationData, + /* [in] */ LPCWSTR *ppwzActivationData, + /* [out] */ int *pReturnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExecuteInDefaultAppDomain( + /* [in] */ LPCWSTR pwzAssemblyPath, + /* [in] */ LPCWSTR pwzTypeName, + /* [in] */ LPCWSTR pwzMethodName, + /* [in] */ LPCWSTR pwzArgument, + /* [out] */ DWORD *pReturnValue) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLRRuntimeHostVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRRuntimeHost * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRRuntimeHost * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRRuntimeHost * This); + + HRESULT ( STDMETHODCALLTYPE *Start )( + ICLRRuntimeHost * This); + + HRESULT ( STDMETHODCALLTYPE *Stop )( + ICLRRuntimeHost * This); + + HRESULT ( STDMETHODCALLTYPE *SetHostControl )( + ICLRRuntimeHost * This, + /* [in] */ IHostControl *pHostControl); + + HRESULT ( STDMETHODCALLTYPE *GetCLRControl )( + ICLRRuntimeHost * This, + /* [out] */ ICLRControl **pCLRControl); + + HRESULT ( STDMETHODCALLTYPE *UnloadAppDomain )( + ICLRRuntimeHost * This, + /* [in] */ DWORD dwAppDomainId, + /* [in] */ BOOL fWaitUntilDone); + + HRESULT ( STDMETHODCALLTYPE *ExecuteInAppDomain )( + ICLRRuntimeHost * This, + /* [in] */ DWORD dwAppDomainId, + /* [in] */ FExecuteInAppDomainCallback pCallback, + /* [in] */ void *cookie); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentAppDomainId )( + ICLRRuntimeHost * This, + /* [out] */ DWORD *pdwAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *ExecuteApplication )( + ICLRRuntimeHost * This, + /* [in] */ LPCWSTR pwzAppFullName, + /* [in] */ DWORD dwManifestPaths, + /* [in] */ LPCWSTR *ppwzManifestPaths, + /* [in] */ DWORD dwActivationData, + /* [in] */ LPCWSTR *ppwzActivationData, + /* [out] */ int *pReturnValue); + + HRESULT ( STDMETHODCALLTYPE *ExecuteInDefaultAppDomain )( + ICLRRuntimeHost * This, + /* [in] */ LPCWSTR pwzAssemblyPath, + /* [in] */ LPCWSTR pwzTypeName, + /* [in] */ LPCWSTR pwzMethodName, + /* [in] */ LPCWSTR pwzArgument, + /* [out] */ DWORD *pReturnValue); + + END_INTERFACE + } ICLRRuntimeHostVtbl; + + interface ICLRRuntimeHost + { + CONST_VTBL struct ICLRRuntimeHostVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRRuntimeHost_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLRRuntimeHost_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLRRuntimeHost_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLRRuntimeHost_Start(This) \ + (This)->lpVtbl -> Start(This) + +#define ICLRRuntimeHost_Stop(This) \ + (This)->lpVtbl -> Stop(This) + +#define ICLRRuntimeHost_SetHostControl(This,pHostControl) \ + (This)->lpVtbl -> SetHostControl(This,pHostControl) + +#define ICLRRuntimeHost_GetCLRControl(This,pCLRControl) \ + (This)->lpVtbl -> GetCLRControl(This,pCLRControl) + +#define ICLRRuntimeHost_UnloadAppDomain(This,dwAppDomainId,fWaitUntilDone) \ + (This)->lpVtbl -> UnloadAppDomain(This,dwAppDomainId,fWaitUntilDone) + +#define ICLRRuntimeHost_ExecuteInAppDomain(This,dwAppDomainId,pCallback,cookie) \ + (This)->lpVtbl -> ExecuteInAppDomain(This,dwAppDomainId,pCallback,cookie) + +#define ICLRRuntimeHost_GetCurrentAppDomainId(This,pdwAppDomainId) \ + (This)->lpVtbl -> GetCurrentAppDomainId(This,pdwAppDomainId) + +#define ICLRRuntimeHost_ExecuteApplication(This,pwzAppFullName,dwManifestPaths,ppwzManifestPaths,dwActivationData,ppwzActivationData,pReturnValue) \ + (This)->lpVtbl -> ExecuteApplication(This,pwzAppFullName,dwManifestPaths,ppwzManifestPaths,dwActivationData,ppwzActivationData,pReturnValue) + +#define ICLRRuntimeHost_ExecuteInDefaultAppDomain(This,pwzAssemblyPath,pwzTypeName,pwzMethodName,pwzArgument,pReturnValue) \ + (This)->lpVtbl -> ExecuteInDefaultAppDomain(This,pwzAssemblyPath,pwzTypeName,pwzMethodName,pwzArgument,pReturnValue) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLRRuntimeHost_Start_Proxy( + ICLRRuntimeHost * This); + + +void __RPC_STUB ICLRRuntimeHost_Start_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRRuntimeHost_Stop_Proxy( + ICLRRuntimeHost * This); + + +void __RPC_STUB ICLRRuntimeHost_Stop_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRRuntimeHost_SetHostControl_Proxy( + ICLRRuntimeHost * This, + /* [in] */ IHostControl *pHostControl); + + +void __RPC_STUB ICLRRuntimeHost_SetHostControl_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRRuntimeHost_GetCLRControl_Proxy( + ICLRRuntimeHost * This, + /* [out] */ ICLRControl **pCLRControl); + + +void __RPC_STUB ICLRRuntimeHost_GetCLRControl_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRRuntimeHost_UnloadAppDomain_Proxy( + ICLRRuntimeHost * This, + /* [in] */ DWORD dwAppDomainId, + /* [in] */ BOOL fWaitUntilDone); + + +void __RPC_STUB ICLRRuntimeHost_UnloadAppDomain_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRRuntimeHost_ExecuteInAppDomain_Proxy( + ICLRRuntimeHost * This, + /* [in] */ DWORD dwAppDomainId, + /* [in] */ FExecuteInAppDomainCallback pCallback, + /* [in] */ void *cookie); + + +void __RPC_STUB ICLRRuntimeHost_ExecuteInAppDomain_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRRuntimeHost_GetCurrentAppDomainId_Proxy( + ICLRRuntimeHost * This, + /* [out] */ DWORD *pdwAppDomainId); + + +void __RPC_STUB ICLRRuntimeHost_GetCurrentAppDomainId_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRRuntimeHost_ExecuteApplication_Proxy( + ICLRRuntimeHost * This, + /* [in] */ LPCWSTR pwzAppFullName, + /* [in] */ DWORD dwManifestPaths, + /* [in] */ LPCWSTR *ppwzManifestPaths, + /* [in] */ DWORD dwActivationData, + /* [in] */ LPCWSTR *ppwzActivationData, + /* [out] */ int *pReturnValue); + + +void __RPC_STUB ICLRRuntimeHost_ExecuteApplication_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRRuntimeHost_ExecuteInDefaultAppDomain_Proxy( + ICLRRuntimeHost * This, + /* [in] */ LPCWSTR pwzAssemblyPath, + /* [in] */ LPCWSTR pwzTypeName, + /* [in] */ LPCWSTR pwzMethodName, + /* [in] */ LPCWSTR pwzArgument, + /* [out] */ DWORD *pReturnValue); + + +void __RPC_STUB ICLRRuntimeHost_ExecuteInDefaultAppDomain_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLRRuntimeHost_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0167 */ +/* [local] */ + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_mscoree_0167_0001 + { eNoChecks = 0, + eSynchronization = 0x1, + eSharedState = 0x2, + eExternalProcessMgmt = 0x4, + eSelfAffectingProcessMgmt = 0x8, + eExternalThreading = 0x10, + eSelfAffectingThreading = 0x20, + eSecurityInfrastructure = 0x40, + eUI = 0x80, + eMayLeakOnAbort = 0x100, + eAll = 0x1ff + } EApiCategories; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0167_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0167_v0_0_s_ifspec; + +#ifndef __ICLRHostProtectionManager_INTERFACE_DEFINED__ +#define __ICLRHostProtectionManager_INTERFACE_DEFINED__ + +/* interface ICLRHostProtectionManager */ +/* [unique][helpstring][uuid][object] */ + + +EXTERN_C const IID IID_ICLRHostProtectionManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("89F25F5C-CEEF-43e1-9CFA-A68CE863AAAC") + ICLRHostProtectionManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetProtectedCategories( + /* [in] */ EApiCategories categories) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetEagerSerializeGrantSets( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICLRHostProtectionManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRHostProtectionManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRHostProtectionManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRHostProtectionManager * This); + + HRESULT ( STDMETHODCALLTYPE *SetProtectedCategories )( + ICLRHostProtectionManager * This, + /* [in] */ EApiCategories categories); + + HRESULT ( STDMETHODCALLTYPE *SetEagerSerializeGrantSets )( + ICLRHostProtectionManager * This); + + END_INTERFACE + } ICLRHostProtectionManagerVtbl; + + interface ICLRHostProtectionManager + { + CONST_VTBL struct ICLRHostProtectionManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRHostProtectionManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICLRHostProtectionManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICLRHostProtectionManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICLRHostProtectionManager_SetProtectedCategories(This,categories) \ + (This)->lpVtbl -> SetProtectedCategories(This,categories) + +#define ICLRHostProtectionManager_SetEagerSerializeGrantSets(This) \ + (This)->lpVtbl -> SetEagerSerializeGrantSets(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICLRHostProtectionManager_SetProtectedCategories_Proxy( + ICLRHostProtectionManager * This, + /* [in] */ EApiCategories categories); + + +void __RPC_STUB ICLRHostProtectionManager_SetProtectedCategories_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICLRHostProtectionManager_SetEagerSerializeGrantSets_Proxy( + ICLRHostProtectionManager * This); + + +void __RPC_STUB ICLRHostProtectionManager_SetEagerSerializeGrantSets_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICLRHostProtectionManager_INTERFACE_DEFINED__ */ + + + +#ifndef __mscoree_LIBRARY_DEFINED__ +#define __mscoree_LIBRARY_DEFINED__ + +/* library mscoree */ +/* [helpstring][version][uuid] */ + + +EXTERN_C const IID LIBID_mscoree; + +#ifndef __ITypeName_INTERFACE_DEFINED__ +#define __ITypeName_INTERFACE_DEFINED__ + +/* interface ITypeName */ +/* [unique][helpstring][uuid][oleautomation][object] */ + + +EXTERN_C const IID IID_ITypeName; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B81FF171-20F3-11d2-8DCC-00A0C9B00522") + ITypeName : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetNameCount( + /* [retval][out] */ DWORD *pCount) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNames( + /* [in] */ DWORD count, + /* [out] */ BSTR *rgbszNames, + /* [retval][out] */ DWORD *pCount) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTypeArgumentCount( + /* [retval][out] */ DWORD *pCount) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTypeArguments( + /* [in] */ DWORD count, + /* [out] */ ITypeName **rgpArguments, + /* [retval][out] */ DWORD *pCount) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetModifierLength( + /* [retval][out] */ DWORD *pCount) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetModifiers( + /* [in] */ DWORD count, + /* [out] */ DWORD *rgModifiers, + /* [retval][out] */ DWORD *pCount) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAssemblyName( + /* [retval][out] */ BSTR *rgbszAssemblyNames) = 0; + + }; + +#else /* C style interface */ + + typedef struct ITypeNameVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ITypeName * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ITypeName * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ITypeName * This); + + HRESULT ( STDMETHODCALLTYPE *GetNameCount )( + ITypeName * This, + /* [retval][out] */ DWORD *pCount); + + HRESULT ( STDMETHODCALLTYPE *GetNames )( + ITypeName * This, + /* [in] */ DWORD count, + /* [out] */ BSTR *rgbszNames, + /* [retval][out] */ DWORD *pCount); + + HRESULT ( STDMETHODCALLTYPE *GetTypeArgumentCount )( + ITypeName * This, + /* [retval][out] */ DWORD *pCount); + + HRESULT ( STDMETHODCALLTYPE *GetTypeArguments )( + ITypeName * This, + /* [in] */ DWORD count, + /* [out] */ ITypeName **rgpArguments, + /* [retval][out] */ DWORD *pCount); + + HRESULT ( STDMETHODCALLTYPE *GetModifierLength )( + ITypeName * This, + /* [retval][out] */ DWORD *pCount); + + HRESULT ( STDMETHODCALLTYPE *GetModifiers )( + ITypeName * This, + /* [in] */ DWORD count, + /* [out] */ DWORD *rgModifiers, + /* [retval][out] */ DWORD *pCount); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyName )( + ITypeName * This, + /* [retval][out] */ BSTR *rgbszAssemblyNames); + + END_INTERFACE + } ITypeNameVtbl; + + interface ITypeName + { + CONST_VTBL struct ITypeNameVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ITypeName_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ITypeName_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ITypeName_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ITypeName_GetNameCount(This,pCount) \ + (This)->lpVtbl -> GetNameCount(This,pCount) + +#define ITypeName_GetNames(This,count,rgbszNames,pCount) \ + (This)->lpVtbl -> GetNames(This,count,rgbszNames,pCount) + +#define ITypeName_GetTypeArgumentCount(This,pCount) \ + (This)->lpVtbl -> GetTypeArgumentCount(This,pCount) + +#define ITypeName_GetTypeArguments(This,count,rgpArguments,pCount) \ + (This)->lpVtbl -> GetTypeArguments(This,count,rgpArguments,pCount) + +#define ITypeName_GetModifierLength(This,pCount) \ + (This)->lpVtbl -> GetModifierLength(This,pCount) + +#define ITypeName_GetModifiers(This,count,rgModifiers,pCount) \ + (This)->lpVtbl -> GetModifiers(This,count,rgModifiers,pCount) + +#define ITypeName_GetAssemblyName(This,rgbszAssemblyNames) \ + (This)->lpVtbl -> GetAssemblyName(This,rgbszAssemblyNames) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ITypeName_GetNameCount_Proxy( + ITypeName * This, + /* [retval][out] */ DWORD *pCount); + + +void __RPC_STUB ITypeName_GetNameCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeName_GetNames_Proxy( + ITypeName * This, + /* [in] */ DWORD count, + /* [out] */ BSTR *rgbszNames, + /* [retval][out] */ DWORD *pCount); + + +void __RPC_STUB ITypeName_GetNames_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeName_GetTypeArgumentCount_Proxy( + ITypeName * This, + /* [retval][out] */ DWORD *pCount); + + +void __RPC_STUB ITypeName_GetTypeArgumentCount_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeName_GetTypeArguments_Proxy( + ITypeName * This, + /* [in] */ DWORD count, + /* [out] */ ITypeName **rgpArguments, + /* [retval][out] */ DWORD *pCount); + + +void __RPC_STUB ITypeName_GetTypeArguments_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeName_GetModifierLength_Proxy( + ITypeName * This, + /* [retval][out] */ DWORD *pCount); + + +void __RPC_STUB ITypeName_GetModifierLength_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeName_GetModifiers_Proxy( + ITypeName * This, + /* [in] */ DWORD count, + /* [out] */ DWORD *rgModifiers, + /* [retval][out] */ DWORD *pCount); + + +void __RPC_STUB ITypeName_GetModifiers_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeName_GetAssemblyName_Proxy( + ITypeName * This, + /* [retval][out] */ BSTR *rgbszAssemblyNames); + + +void __RPC_STUB ITypeName_GetAssemblyName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ITypeName_INTERFACE_DEFINED__ */ + + +#ifndef __ITypeNameBuilder_INTERFACE_DEFINED__ +#define __ITypeNameBuilder_INTERFACE_DEFINED__ + +/* interface ITypeNameBuilder */ +/* [unique][helpstring][uuid][oleautomation][object] */ + + +EXTERN_C const IID IID_ITypeNameBuilder; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B81FF171-20F3-11d2-8DCC-00A0C9B00523") + ITypeNameBuilder : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE OpenGenericArguments( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE CloseGenericArguments( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE OpenGenericArgument( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE CloseGenericArgument( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE AddName( + /* [in] */ LPCWSTR szName) = 0; + + virtual HRESULT STDMETHODCALLTYPE AddPointer( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE AddByRef( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE AddSzArray( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE AddArray( + /* [in] */ DWORD rank) = 0; + + virtual HRESULT STDMETHODCALLTYPE AddAssemblySpec( + /* [in] */ LPCWSTR szAssemblySpec) = 0; + + virtual HRESULT STDMETHODCALLTYPE ToString( + /* [retval][out] */ BSTR *pszStringRepresentation) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clear( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct ITypeNameBuilderVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ITypeNameBuilder * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ITypeNameBuilder * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ITypeNameBuilder * This); + + HRESULT ( STDMETHODCALLTYPE *OpenGenericArguments )( + ITypeNameBuilder * This); + + HRESULT ( STDMETHODCALLTYPE *CloseGenericArguments )( + ITypeNameBuilder * This); + + HRESULT ( STDMETHODCALLTYPE *OpenGenericArgument )( + ITypeNameBuilder * This); + + HRESULT ( STDMETHODCALLTYPE *CloseGenericArgument )( + ITypeNameBuilder * This); + + HRESULT ( STDMETHODCALLTYPE *AddName )( + ITypeNameBuilder * This, + /* [in] */ LPCWSTR szName); + + HRESULT ( STDMETHODCALLTYPE *AddPointer )( + ITypeNameBuilder * This); + + HRESULT ( STDMETHODCALLTYPE *AddByRef )( + ITypeNameBuilder * This); + + HRESULT ( STDMETHODCALLTYPE *AddSzArray )( + ITypeNameBuilder * This); + + HRESULT ( STDMETHODCALLTYPE *AddArray )( + ITypeNameBuilder * This, + /* [in] */ DWORD rank); + + HRESULT ( STDMETHODCALLTYPE *AddAssemblySpec )( + ITypeNameBuilder * This, + /* [in] */ LPCWSTR szAssemblySpec); + + HRESULT ( STDMETHODCALLTYPE *ToString )( + ITypeNameBuilder * This, + /* [retval][out] */ BSTR *pszStringRepresentation); + + HRESULT ( STDMETHODCALLTYPE *Clear )( + ITypeNameBuilder * This); + + END_INTERFACE + } ITypeNameBuilderVtbl; + + interface ITypeNameBuilder + { + CONST_VTBL struct ITypeNameBuilderVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ITypeNameBuilder_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ITypeNameBuilder_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ITypeNameBuilder_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ITypeNameBuilder_OpenGenericArguments(This) \ + (This)->lpVtbl -> OpenGenericArguments(This) + +#define ITypeNameBuilder_CloseGenericArguments(This) \ + (This)->lpVtbl -> CloseGenericArguments(This) + +#define ITypeNameBuilder_OpenGenericArgument(This) \ + (This)->lpVtbl -> OpenGenericArgument(This) + +#define ITypeNameBuilder_CloseGenericArgument(This) \ + (This)->lpVtbl -> CloseGenericArgument(This) + +#define ITypeNameBuilder_AddName(This,szName) \ + (This)->lpVtbl -> AddName(This,szName) + +#define ITypeNameBuilder_AddPointer(This) \ + (This)->lpVtbl -> AddPointer(This) + +#define ITypeNameBuilder_AddByRef(This) \ + (This)->lpVtbl -> AddByRef(This) + +#define ITypeNameBuilder_AddSzArray(This) \ + (This)->lpVtbl -> AddSzArray(This) + +#define ITypeNameBuilder_AddArray(This,rank) \ + (This)->lpVtbl -> AddArray(This,rank) + +#define ITypeNameBuilder_AddAssemblySpec(This,szAssemblySpec) \ + (This)->lpVtbl -> AddAssemblySpec(This,szAssemblySpec) + +#define ITypeNameBuilder_ToString(This,pszStringRepresentation) \ + (This)->lpVtbl -> ToString(This,pszStringRepresentation) + +#define ITypeNameBuilder_Clear(This) \ + (This)->lpVtbl -> Clear(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ITypeNameBuilder_OpenGenericArguments_Proxy( + ITypeNameBuilder * This); + + +void __RPC_STUB ITypeNameBuilder_OpenGenericArguments_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeNameBuilder_CloseGenericArguments_Proxy( + ITypeNameBuilder * This); + + +void __RPC_STUB ITypeNameBuilder_CloseGenericArguments_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeNameBuilder_OpenGenericArgument_Proxy( + ITypeNameBuilder * This); + + +void __RPC_STUB ITypeNameBuilder_OpenGenericArgument_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeNameBuilder_CloseGenericArgument_Proxy( + ITypeNameBuilder * This); + + +void __RPC_STUB ITypeNameBuilder_CloseGenericArgument_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeNameBuilder_AddName_Proxy( + ITypeNameBuilder * This, + /* [in] */ LPCWSTR szName); + + +void __RPC_STUB ITypeNameBuilder_AddName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeNameBuilder_AddPointer_Proxy( + ITypeNameBuilder * This); + + +void __RPC_STUB ITypeNameBuilder_AddPointer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeNameBuilder_AddByRef_Proxy( + ITypeNameBuilder * This); + + +void __RPC_STUB ITypeNameBuilder_AddByRef_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeNameBuilder_AddSzArray_Proxy( + ITypeNameBuilder * This); + + +void __RPC_STUB ITypeNameBuilder_AddSzArray_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeNameBuilder_AddArray_Proxy( + ITypeNameBuilder * This, + /* [in] */ DWORD rank); + + +void __RPC_STUB ITypeNameBuilder_AddArray_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeNameBuilder_AddAssemblySpec_Proxy( + ITypeNameBuilder * This, + /* [in] */ LPCWSTR szAssemblySpec); + + +void __RPC_STUB ITypeNameBuilder_AddAssemblySpec_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeNameBuilder_ToString_Proxy( + ITypeNameBuilder * This, + /* [retval][out] */ BSTR *pszStringRepresentation); + + +void __RPC_STUB ITypeNameBuilder_ToString_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeNameBuilder_Clear_Proxy( + ITypeNameBuilder * This); + + +void __RPC_STUB ITypeNameBuilder_Clear_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ITypeNameBuilder_INTERFACE_DEFINED__ */ + + +#ifndef __ITypeNameFactory_INTERFACE_DEFINED__ +#define __ITypeNameFactory_INTERFACE_DEFINED__ + +/* interface ITypeNameFactory */ +/* [unique][helpstring][uuid][oleautomation][object] */ + + +EXTERN_C const IID IID_ITypeNameFactory; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B81FF171-20F3-11d2-8DCC-00A0C9B00521") + ITypeNameFactory : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE ParseTypeName( + /* [in] */ LPCWSTR szName, + /* [out] */ DWORD *pError, + /* [retval][out] */ ITypeName **ppTypeName) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTypeNameBuilder( + /* [retval][out] */ ITypeNameBuilder **ppTypeBuilder) = 0; + + }; + +#else /* C style interface */ + + typedef struct ITypeNameFactoryVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ITypeNameFactory * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ITypeNameFactory * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ITypeNameFactory * This); + + HRESULT ( STDMETHODCALLTYPE *ParseTypeName )( + ITypeNameFactory * This, + /* [in] */ LPCWSTR szName, + /* [out] */ DWORD *pError, + /* [retval][out] */ ITypeName **ppTypeName); + + HRESULT ( STDMETHODCALLTYPE *GetTypeNameBuilder )( + ITypeNameFactory * This, + /* [retval][out] */ ITypeNameBuilder **ppTypeBuilder); + + END_INTERFACE + } ITypeNameFactoryVtbl; + + interface ITypeNameFactory + { + CONST_VTBL struct ITypeNameFactoryVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ITypeNameFactory_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ITypeNameFactory_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ITypeNameFactory_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ITypeNameFactory_ParseTypeName(This,szName,pError,ppTypeName) \ + (This)->lpVtbl -> ParseTypeName(This,szName,pError,ppTypeName) + +#define ITypeNameFactory_GetTypeNameBuilder(This,ppTypeBuilder) \ + (This)->lpVtbl -> GetTypeNameBuilder(This,ppTypeBuilder) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ITypeNameFactory_ParseTypeName_Proxy( + ITypeNameFactory * This, + /* [in] */ LPCWSTR szName, + /* [out] */ DWORD *pError, + /* [retval][out] */ ITypeName **ppTypeName); + + +void __RPC_STUB ITypeNameFactory_ParseTypeName_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ITypeNameFactory_GetTypeNameBuilder_Proxy( + ITypeNameFactory * This, + /* [retval][out] */ ITypeNameBuilder **ppTypeBuilder); + + +void __RPC_STUB ITypeNameFactory_GetTypeNameBuilder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ITypeNameFactory_INTERFACE_DEFINED__ */ + + +#ifndef __IApartmentCallback_INTERFACE_DEFINED__ +#define __IApartmentCallback_INTERFACE_DEFINED__ + +/* interface IApartmentCallback */ +/* [unique][helpstring][uuid][oleautomation][object] */ + + +EXTERN_C const IID IID_IApartmentCallback; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("178E5337-1528-4591-B1C9-1C6E484686D8") + IApartmentCallback : public IUnknown + { + public: + virtual HRESULT __stdcall DoCallback( + /* [in] */ SIZE_T pFunc, + /* [in] */ SIZE_T pData) = 0; + + }; + +#else /* C style interface */ + + typedef struct IApartmentCallbackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IApartmentCallback * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IApartmentCallback * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IApartmentCallback * This); + + HRESULT ( __stdcall *DoCallback )( + IApartmentCallback * This, + /* [in] */ SIZE_T pFunc, + /* [in] */ SIZE_T pData); + + END_INTERFACE + } IApartmentCallbackVtbl; + + interface IApartmentCallback + { + CONST_VTBL struct IApartmentCallbackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IApartmentCallback_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IApartmentCallback_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IApartmentCallback_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IApartmentCallback_DoCallback(This,pFunc,pData) \ + (This)->lpVtbl -> DoCallback(This,pFunc,pData) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT __stdcall IApartmentCallback_DoCallback_Proxy( + IApartmentCallback * This, + /* [in] */ SIZE_T pFunc, + /* [in] */ SIZE_T pData); + + +void __RPC_STUB IApartmentCallback_DoCallback_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IApartmentCallback_INTERFACE_DEFINED__ */ + + +#ifndef __IManagedObject_INTERFACE_DEFINED__ +#define __IManagedObject_INTERFACE_DEFINED__ + +/* interface IManagedObject */ +/* [unique][helpstring][uuid][oleautomation][object] */ + + +EXTERN_C const IID IID_IManagedObject; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("C3FCC19E-A970-11d2-8B5A-00A0C9B7C9C4") + IManagedObject : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetSerializedBuffer( + /* [out] */ BSTR *pBSTR) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetObjectIdentity( + /* [out] */ BSTR *pBSTRGUID, + /* [out] */ int *AppDomainID, + /* [out] */ int *pCCW) = 0; + + }; + +#else /* C style interface */ + + typedef struct IManagedObjectVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IManagedObject * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IManagedObject * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IManagedObject * This); + + HRESULT ( STDMETHODCALLTYPE *GetSerializedBuffer )( + IManagedObject * This, + /* [out] */ BSTR *pBSTR); + + HRESULT ( STDMETHODCALLTYPE *GetObjectIdentity )( + IManagedObject * This, + /* [out] */ BSTR *pBSTRGUID, + /* [out] */ int *AppDomainID, + /* [out] */ int *pCCW); + + END_INTERFACE + } IManagedObjectVtbl; + + interface IManagedObject + { + CONST_VTBL struct IManagedObjectVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IManagedObject_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IManagedObject_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IManagedObject_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IManagedObject_GetSerializedBuffer(This,pBSTR) \ + (This)->lpVtbl -> GetSerializedBuffer(This,pBSTR) + +#define IManagedObject_GetObjectIdentity(This,pBSTRGUID,AppDomainID,pCCW) \ + (This)->lpVtbl -> GetObjectIdentity(This,pBSTRGUID,AppDomainID,pCCW) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IManagedObject_GetSerializedBuffer_Proxy( + IManagedObject * This, + /* [out] */ BSTR *pBSTR); + + +void __RPC_STUB IManagedObject_GetSerializedBuffer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IManagedObject_GetObjectIdentity_Proxy( + IManagedObject * This, + /* [out] */ BSTR *pBSTRGUID, + /* [out] */ int *AppDomainID, + /* [out] */ int *pCCW); + + +void __RPC_STUB IManagedObject_GetObjectIdentity_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IManagedObject_INTERFACE_DEFINED__ */ + + +#ifndef __ICatalogServices_INTERFACE_DEFINED__ +#define __ICatalogServices_INTERFACE_DEFINED__ + +/* interface ICatalogServices */ +/* [unique][helpstring][uuid][oleautomation][object] */ + + +EXTERN_C const IID IID_ICatalogServices; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("04C6BE1E-1DB1-4058-AB7A-700CCCFBF254") + ICatalogServices : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Autodone( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE NotAutodone( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICatalogServicesVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICatalogServices * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICatalogServices * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICatalogServices * This); + + HRESULT ( STDMETHODCALLTYPE *Autodone )( + ICatalogServices * This); + + HRESULT ( STDMETHODCALLTYPE *NotAutodone )( + ICatalogServices * This); + + END_INTERFACE + } ICatalogServicesVtbl; + + interface ICatalogServices + { + CONST_VTBL struct ICatalogServicesVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICatalogServices_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICatalogServices_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICatalogServices_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICatalogServices_Autodone(This) \ + (This)->lpVtbl -> Autodone(This) + +#define ICatalogServices_NotAutodone(This) \ + (This)->lpVtbl -> NotAutodone(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICatalogServices_Autodone_Proxy( + ICatalogServices * This); + + +void __RPC_STUB ICatalogServices_Autodone_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICatalogServices_NotAutodone_Proxy( + ICatalogServices * This); + + +void __RPC_STUB ICatalogServices_NotAutodone_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICatalogServices_INTERFACE_DEFINED__ */ + + +EXTERN_C const CLSID CLSID_ComCallUnmarshal; + +#ifdef __cplusplus + +class DECLSPEC_UUID("3F281000-E95A-11d2-886B-00C04F869F04") +ComCallUnmarshal; +#endif + +EXTERN_C const CLSID CLSID_CorRuntimeHost; + +#ifdef __cplusplus + +class DECLSPEC_UUID("CB2F6723-AB3A-11d2-9C40-00C04FA30A3E") +CorRuntimeHost; +#endif + +EXTERN_C const CLSID CLSID_CLRRuntimeHost; + +#ifdef __cplusplus + +class DECLSPEC_UUID("90F1A06E-7712-4762-86B5-7A5EBA6BDB02") +CLRRuntimeHost; +#endif + +EXTERN_C const CLSID CLSID_TypeNameFactory; + +#ifdef __cplusplus + +class DECLSPEC_UUID("B81FF171-20F3-11d2-8DCC-00A0C9B00525") +TypeNameFactory; +#endif +#endif /* __mscoree_LIBRARY_DEFINED__ */ + +/* interface __MIDL_itf_mscoree_0174 */ +/* [local] */ + +typedef /* [public][public][public] */ +enum __MIDL___MIDL_itf_mscoree_0174_0001 + { eCurrentContext = 0, + eRestrictedContext = 0x1 + } EContextType; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0174_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0174_v0_0_s_ifspec; + +#ifndef __IHostSecurityContext_INTERFACE_DEFINED__ +#define __IHostSecurityContext_INTERFACE_DEFINED__ + +/* interface IHostSecurityContext */ +/* [local][unique][helpstring][uuid][version][object] */ + + +EXTERN_C const IID IID_IHostSecurityContext; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("7E573CE4-0343-4423-98D7-6318348A1D3C") + IHostSecurityContext : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Capture( + /* [out] */ IHostSecurityContext **ppClonedContext) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostSecurityContextVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostSecurityContext * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostSecurityContext * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostSecurityContext * This); + + HRESULT ( STDMETHODCALLTYPE *Capture )( + IHostSecurityContext * This, + /* [out] */ IHostSecurityContext **ppClonedContext); + + END_INTERFACE + } IHostSecurityContextVtbl; + + interface IHostSecurityContext + { + CONST_VTBL struct IHostSecurityContextVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostSecurityContext_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostSecurityContext_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostSecurityContext_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostSecurityContext_Capture(This,ppClonedContext) \ + (This)->lpVtbl -> Capture(This,ppClonedContext) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostSecurityContext_Capture_Proxy( + IHostSecurityContext * This, + /* [out] */ IHostSecurityContext **ppClonedContext); + + +void __RPC_STUB IHostSecurityContext_Capture_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostSecurityContext_INTERFACE_DEFINED__ */ + + +#ifndef __IHostSecurityManager_INTERFACE_DEFINED__ +#define __IHostSecurityManager_INTERFACE_DEFINED__ + +/* interface IHostSecurityManager */ +/* [local][unique][helpstring][uuid][version][object] */ + + +EXTERN_C const IID IID_IHostSecurityManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("75ad2468-a349-4d02-a764-76a68aee0c4f") + IHostSecurityManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE ImpersonateLoggedOnUser( + /* [in] */ HANDLE hToken) = 0; + + virtual HRESULT STDMETHODCALLTYPE RevertToSelf( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE OpenThreadToken( + /* [in] */ DWORD dwDesiredAccess, + /* [in] */ BOOL bOpenAsSelf, + /* [out] */ HANDLE *phThreadToken) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetThreadToken( + /* [in] */ HANDLE hToken) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSecurityContext( + /* [in] */ EContextType eContextType, + /* [out] */ IHostSecurityContext **ppSecurityContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetSecurityContext( + /* [in] */ EContextType eContextType, + /* [in] */ IHostSecurityContext *pSecurityContext) = 0; + + }; + +#else /* C style interface */ + + typedef struct IHostSecurityManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IHostSecurityManager * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IHostSecurityManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IHostSecurityManager * This); + + HRESULT ( STDMETHODCALLTYPE *ImpersonateLoggedOnUser )( + IHostSecurityManager * This, + /* [in] */ HANDLE hToken); + + HRESULT ( STDMETHODCALLTYPE *RevertToSelf )( + IHostSecurityManager * This); + + HRESULT ( STDMETHODCALLTYPE *OpenThreadToken )( + IHostSecurityManager * This, + /* [in] */ DWORD dwDesiredAccess, + /* [in] */ BOOL bOpenAsSelf, + /* [out] */ HANDLE *phThreadToken); + + HRESULT ( STDMETHODCALLTYPE *SetThreadToken )( + IHostSecurityManager * This, + /* [in] */ HANDLE hToken); + + HRESULT ( STDMETHODCALLTYPE *GetSecurityContext )( + IHostSecurityManager * This, + /* [in] */ EContextType eContextType, + /* [out] */ IHostSecurityContext **ppSecurityContext); + + HRESULT ( STDMETHODCALLTYPE *SetSecurityContext )( + IHostSecurityManager * This, + /* [in] */ EContextType eContextType, + /* [in] */ IHostSecurityContext *pSecurityContext); + + END_INTERFACE + } IHostSecurityManagerVtbl; + + interface IHostSecurityManager + { + CONST_VTBL struct IHostSecurityManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IHostSecurityManager_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IHostSecurityManager_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IHostSecurityManager_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IHostSecurityManager_ImpersonateLoggedOnUser(This,hToken) \ + (This)->lpVtbl -> ImpersonateLoggedOnUser(This,hToken) + +#define IHostSecurityManager_RevertToSelf(This) \ + (This)->lpVtbl -> RevertToSelf(This) + +#define IHostSecurityManager_OpenThreadToken(This,dwDesiredAccess,bOpenAsSelf,phThreadToken) \ + (This)->lpVtbl -> OpenThreadToken(This,dwDesiredAccess,bOpenAsSelf,phThreadToken) + +#define IHostSecurityManager_SetThreadToken(This,hToken) \ + (This)->lpVtbl -> SetThreadToken(This,hToken) + +#define IHostSecurityManager_GetSecurityContext(This,eContextType,ppSecurityContext) \ + (This)->lpVtbl -> GetSecurityContext(This,eContextType,ppSecurityContext) + +#define IHostSecurityManager_SetSecurityContext(This,eContextType,pSecurityContext) \ + (This)->lpVtbl -> SetSecurityContext(This,eContextType,pSecurityContext) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IHostSecurityManager_ImpersonateLoggedOnUser_Proxy( + IHostSecurityManager * This, + /* [in] */ HANDLE hToken); + + +void __RPC_STUB IHostSecurityManager_ImpersonateLoggedOnUser_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostSecurityManager_RevertToSelf_Proxy( + IHostSecurityManager * This); + + +void __RPC_STUB IHostSecurityManager_RevertToSelf_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostSecurityManager_OpenThreadToken_Proxy( + IHostSecurityManager * This, + /* [in] */ DWORD dwDesiredAccess, + /* [in] */ BOOL bOpenAsSelf, + /* [out] */ HANDLE *phThreadToken); + + +void __RPC_STUB IHostSecurityManager_OpenThreadToken_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostSecurityManager_SetThreadToken_Proxy( + IHostSecurityManager * This, + /* [in] */ HANDLE hToken); + + +void __RPC_STUB IHostSecurityManager_SetThreadToken_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostSecurityManager_GetSecurityContext_Proxy( + IHostSecurityManager * This, + /* [in] */ EContextType eContextType, + /* [out] */ IHostSecurityContext **ppSecurityContext); + + +void __RPC_STUB IHostSecurityManager_GetSecurityContext_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IHostSecurityManager_SetSecurityContext_Proxy( + IHostSecurityManager * This, + /* [in] */ EContextType eContextType, + /* [in] */ IHostSecurityContext *pSecurityContext); + + +void __RPC_STUB IHostSecurityManager_SetSecurityContext_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IHostSecurityManager_INTERFACE_DEFINED__ */ + + +/* Additional Prototypes for ALL interfaces */ + +unsigned long __RPC_USER VARIANT_UserSize( unsigned long *, unsigned long , VARIANT * ); +unsigned char * __RPC_USER VARIANT_UserMarshal( unsigned long *, unsigned char *, VARIANT * ); +unsigned char * __RPC_USER VARIANT_UserUnmarshal(unsigned long *, unsigned char *, VARIANT * ); +void __RPC_USER VARIANT_UserFree( unsigned long *, VARIANT * ); + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/third/Blackbone/src/3rd_party/rewolf-wow64ext/.gitignore b/third/Blackbone/src/3rd_party/rewolf-wow64ext/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b463f9ec72ca652738232528952b51148db29ade --- /dev/null +++ b/third/Blackbone/src/3rd_party/rewolf-wow64ext/.gitignore @@ -0,0 +1,14 @@ +*.opensdf +*.sdf +*.suo +*.obj +*.ilk +*.db +*.user +*.opendb +*.pdb +src/Release/* +src/Debug/* +sample/*.exe +sample/*.dll +sample/*.lib \ No newline at end of file diff --git a/third/Blackbone/src/3rd_party/rewolf-wow64ext/.hgignore b/third/Blackbone/src/3rd_party/rewolf-wow64ext/.hgignore new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/third/Blackbone/src/3rd_party/rewolf-wow64ext/README.md b/third/Blackbone/src/3rd_party/rewolf-wow64ext/README.md new file mode 100644 index 0000000000000000000000000000000000000000..0c7a47bcf7e4bbd01f00cfbb872ebef9a441c7d2 --- /dev/null +++ b/third/Blackbone/src/3rd_party/rewolf-wow64ext/README.md @@ -0,0 +1,2 @@ +# rewolf-wow64ext +WOW64Ext is a helper library for x86 programs that runs under WOW64 layer on x64 versions of Microsoft Windows operating systems. It enables x86 applications to read, write and enumerate memory of a native x64 applications. There is also possibility to call any x64 function from 64-bits version of NTDLL through a special function called X64Call(). As a bonus, wow64ext.h contains definitions of some structures that might be useful for programs that want to access PEB, TEB, TIB etc. diff --git a/third/Blackbone/src/3rd_party/rewolf-wow64ext/doc/wow64ext.txt b/third/Blackbone/src/3rd_party/rewolf-wow64ext/doc/wow64ext.txt new file mode 100644 index 0000000000000000000000000000000000000000..aae43fb09f750ae2a2b9dd5d59d0a96b420b711a --- /dev/null +++ b/third/Blackbone/src/3rd_party/rewolf-wow64ext/doc/wow64ext.txt @@ -0,0 +1,180 @@ +-------------------------------------------------------------------------------- +Name....: WOW64Ext Library +Author..: ReWolf +Rel.Date: 12.I.2012 +Update..: 18.I.2017 +Version.: 1.0.0.9 + + +e.mail..: rewolf@rewolf.pl +www.....: http://blog.rewolf.pl +-------------------------------------------------------------------------------- + +WOW64Ext is a helper library for x86 programs that runs under WOW64 layer on +x64 versions of Microsoft Windows operating systems. It enables x86 applications +to read, write and enumerate memory of a native x64 applications. There is also +possibility to call any x64 function from 64-bits version of NTDLL through +a special function called X64Call(). As a bonus, wow64ext.h contains definitions +of some structures that might be useful for programs that want to access PEB, +TEB, TIB etc. + +Sample application that uses this library can be found in \sample\ directory, it +is simple memory dumper. + +-------------------------------------------------------------------------------- + +Functions: + +-------------------------------------------------------------------------------- + +DWORD64 X64Call(DWORD64 func, int argC, ...); + +Low level function that can call any x64 API from NTDLL. + +func - address of x64 function, can be obtained by GetProcAddress64() +argC - number of arguments that will be passed to the 'func' +... - rest of arguments for 'func', all values should be casted to DWORD64 + +-------------------------------------------------------------------------------- + +DWORD64 GetModuleHandle64(wchar_t* lpModuleName); + +Behaviour similar to x86 version of GetModuleHandle, but it looks for the module +name in the list of loaded x64 libraries. Usually x86 processes under WOW64 +layer have four x64 libraries: ntdll.dll, wow64.dll, wow64cpu.dll and +wow64win.dll + +lpModuleName - unicode string that represents module name + +-------------------------------------------------------------------------------- + +DWORD64 GetProcAddress64(DWORD64 hModule, char* funcName); + +Behaviour similar to x86 version of GetProcAddress(), internally it uses x64 +version of LdrGetProcedureAddress() from NTDLL. + +hModule - base of x64 module +funcName - function name + +-------------------------------------------------------------------------------- + +SIZE_T VirtualQueryEx64(HANDLE hProcess, DWORD64 lpAddress, + MEMORY_BASIC_INFORMATION64* lpBuffer, SIZE_T dwLength) + +Behaviour similar to x86 version of VirtualQueryEx(), internally it uses x64 +version of NtQueryVirtualMemory() from NTDLL. + +hProcess - handle of the process, can be obtained by standard x86 version of + OpenProcess() function +lpAddress - base address of the region of pages to be queried +lpBuffer - a pointer to a MEMORY_BASIC_INFORMATION64 structure, it is defined + in the standard SDK headers +dwLength - size of the buffer pointed to by the lpBuffer parameter + +-------------------------------------------------------------------------------- + +DWORD64 VirtualAllocEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, + DWORD flAllocationType, DWORD flProtect) + +Behaviour similar to x86 version of VirtualAllocEx64(), internally it uses x64 +version of NtAllocateVirtualMemory() from NTDLL. + +hProcess - handle of the process, can be obtained by standard x86 + version of OpenProcess() function +lpAddress - desired base address of the region that will be allocated +dwSize - size of the region that will be allocated +flAllocationType - type of memory allocation +flProtect - memory protection for the region + +-------------------------------------------------------------------------------- + +BOOL VirtualFreeEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, + DWORD dwFreeType) + +Behaviour similar to x86 version of VirtualFreeEx64(), internally it uses x64 +version of NtFreeVirtualMemory() from NTDLL. + +hProcess - handle of the process, can be obtained by standard x86 version of + OpenProcess() function +lpAddress - base address of the memory region to free +dwSize - size (in bytes) of the memory region to free +dwFreeType - type of free operation (MEM_RELEASE, MEM_DECOMMIT) + +-------------------------------------------------------------------------------- + +BOOL VirtualProtectEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, + DWORD flNewProtect, DWORD* lpflOldProtect); + +Behaviour similar to x86 version of VirtualProtectEx64(), internally it uses +x64 version of NtProtectVirtualMemory() from NTDLL. + +hProcess - handle of the process, can be obtained by standard x86 + version of OpenProcess() function +lpAddress - base address of the memory region that will have changed + protection +dwSize - size (in bytes) of the memory region that will have changed + protection +flNewProtect - the memory protection option (see MSDN) +lpflOldProtect - pointer to the variable that receives old protection value + +-------------------------------------------------------------------------------- + +BOOL ReadProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, + LPVOID lpBuffer, SIZE_T nSize, + SIZE_T *lpNumberOfBytesRead); + +Behaviour similar to x86 version of ReadProcessMemory(), internally it uses x64 +version of NtReadVirtualMemory() from NTDLL. + +hProcess - handle of the process, can be obtained by standard x86 + version of OpenProcess() function +lpBaseAddress - base address of the region that will be read +lpBuffer - output memory buffer for the read data +nSize - number of bytes to be read +lpNumberOfBytesRead - pointer to a variable that receives number of read bytes + +-------------------------------------------------------------------------------- + +BOOL WriteProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, + LPVOID lpBuffer, SIZE_T nSize, + SIZE_T *lpNumberOfBytesWritten); + +Behaviour similar to x86 version of WriteProcessMemory(), internally it uses x64 +version of NtWriteVirtualMemory() from NTDLL. + +hProcess - handle of the process, can be obtained by standard x86 + version of OpenProcess() function +lpBaseAddress - base address of the region that will be written +lpBuffer - input memory buffer with the data to write +nSize - number of bytes that will be written +lpNumberOfBytesRead - pointer to variable that receives number of written bytes + +-------------------------------------------------------------------------------- + +BOOL GetThreadContext64(HANDLE hThread, _CONTEXT64* lpContext); + +Behaviour similar to x86 version of GetThreadContext(), internally it uses x64 +version of NtGetContextThread() from NTDLL. Definition of _CONTEXT64 can be +found in wow64ext.h file. + +hThread - handle of the process, can be obtained by standard x86 + version of OpenProcess() function +lpContext - A pointer to a _CONTEXT64 structure that will receive + context data from specified thread. Structure will be + filled according to ContextFlags field. + +-------------------------------------------------------------------------------- + +BOOL SetThreadContext64(HANDLE hThread, _CONTEXT64* lpContext); + +Behaviour similar to x86 version of SetThreadContext(), internally it uses x64 +version of NtSetContextThread() from NTDLL. Definition of _CONTEXT64 can be +found in wow64ext.h file. + +hThread - handle of the process, can be obtained by standard x86 + version of OpenProcess() function +lpContext - A pointer to a _CONTEXT64 structure that will be used + to fill context data in specified thread. Structure will + use only fields defined by ContextFlags. + +-------------------------------------------------------------------------------- \ No newline at end of file diff --git a/third/Blackbone/src/3rd_party/rewolf-wow64ext/lgpl-3.0.txt b/third/Blackbone/src/3rd_party/rewolf-wow64ext/lgpl-3.0.txt new file mode 100644 index 0000000000000000000000000000000000000000..65c5ca88a67c30becee01c5a8816d964b03862f9 --- /dev/null +++ b/third/Blackbone/src/3rd_party/rewolf-wow64ext/lgpl-3.0.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/third/Blackbone/src/3rd_party/rewolf-wow64ext/sample/build.bat b/third/Blackbone/src/3rd_party/rewolf-wow64ext/sample/build.bat new file mode 100644 index 0000000000000000000000000000000000000000..fea402803a203ba6a6e21b7dbe43e9a9d0045d6a --- /dev/null +++ b/third/Blackbone/src/3rd_party/rewolf-wow64ext/sample/build.bat @@ -0,0 +1 @@ +cl /Zi /D "UNICODE" ../bin/wow64ext.lib main.cpp diff --git a/third/Blackbone/src/3rd_party/rewolf-wow64ext/sample/main.cpp b/third/Blackbone/src/3rd_party/rewolf-wow64ext/sample/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..26efd2af9fcbee361a7f82ef1fa5d7da2dacb406 --- /dev/null +++ b/third/Blackbone/src/3rd_party/rewolf-wow64ext/sample/main.cpp @@ -0,0 +1,168 @@ +#include +#include +#include +#include "../src/wow64ext.h" + +#define FNFAIL(a) printf(a " failed\n") + +void AllocTest(HANDLE hProcess) +{ + static const size_t TEST_SIZE = 0x2000; + printf("Requesting 0x%08X bytes of memory at 0x70000020000 ...\n", TEST_SIZE); + DWORD64 mem = VirtualAllocEx64(hProcess, 0x70000020000, TEST_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if (0 == mem) + { + printf("VirtualAllocEx64 failed.\n"); + return; + } + printf("Memory allocated at: %016I64X\n", mem); + + MEMORY_BASIC_INFORMATION64 mbi64 = { 0 }; + VirtualQueryEx64(hProcess, mem, &mbi64, sizeof(mbi64)); + printf("Query memory: %016I64X %016I64X %08X %08X %08X\n", mbi64.BaseAddress, mbi64.RegionSize, mbi64.Protect, mbi64.Type, mbi64.State); + printf("Changing protection from %08X to %08X...\n", PAGE_READWRITE, PAGE_EXECUTE_READWRITE); + DWORD oldProtect = 0; + VirtualProtectEx64(hProcess, mem, mbi64.RegionSize, PAGE_EXECUTE_READWRITE, &oldProtect); + VirtualQueryEx64(hProcess, mem, &mbi64, sizeof(mbi64)); + printf("Query memory: %016I64X %016I64X %08X %08X %08X\n", mbi64.BaseAddress, mbi64.RegionSize, mbi64.Protect, mbi64.Type, mbi64.State); + + printf("WriteProcessMemory64 test: "); + BYTE testBuf[TEST_SIZE]; + for (int i = 0; i < TEST_SIZE; i++) + testBuf[i] = (BYTE)i; + + SIZE_T wrSz = 0; + if (!WriteProcessMemory64(hProcess, mem, testBuf, TEST_SIZE, &wrSz) || (wrSz != TEST_SIZE)) + { + printf("FAILED on WriteProcessMemory64\n"); + } + else + { + BYTE cmpBuf[TEST_SIZE]; + if (!ReadProcessMemory64(hProcess, mem, cmpBuf, TEST_SIZE, &wrSz) || (wrSz != TEST_SIZE)) + printf("FAILED on ReadProcessMemory64\n"); + else + { + if (0 == memcmp(testBuf, cmpBuf, TEST_SIZE)) + printf("SUCCESS\n"); + else + printf("FAILED on memcmp.\n"); + } + } + + printf("Freeing memory: %s\n", VirtualFreeEx64(hProcess, mem, 0, MEM_RELEASE) ? "success" : "failure"); + VirtualQueryEx64(hProcess, mem, &mbi64, sizeof(mbi64)); + printf("Query memory: %016I64X %016I64X %08X %08X %08X\n", mbi64.BaseAddress, mbi64.RegionSize, mbi64.Protect, mbi64.Type, mbi64.State); +} + +int main (int argc, char* argv[]) +{ + DWORD64 s = GetProcAddress64(GetModuleHandle64(L"wow64cpu.dll"),"TurboDispatchJumpAddressStart"); + printf("tt: %016I64X\n", s); + + if (2 != argc) + { + printf("Usage:\n\t%s hex_process_ID\n", argv[0]); + return 0; + } + + DWORD procID = 0; + if (1 != sscanf_s(argv[1], "%X", &procID)) + { + printf("Invalid process ID.\n"); + return 0; + } + + printf("Process ID: %08X\n", procID); + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID); + if (0 == hProcess) + { + printf("Can't open process %08X.\n", procID); + return 0; + } + + MEMORY_BASIC_INFORMATION64 mbi64 = { 0 }; + DWORD64 crAddr = 0; + bool printMemMap = true; + while (VirtualQueryEx64(hProcess, crAddr, &mbi64, sizeof(mbi64))) + { + if (mbi64.Protect && !(mbi64.Protect & (PAGE_NOACCESS | PAGE_GUARD))) + { + if (printMemMap) + printf("[D] : "); + + BYTE* mem = (BYTE*)VirtualAlloc(0, (SIZE_T)mbi64.RegionSize, MEM_COMMIT, PAGE_READWRITE); + if (mem == 0) + { + FNFAIL("VirtualAlloc"); + crAddr = crAddr + mbi64.RegionSize; + continue; + } + SIZE_T rdPM = 0; + if ((0 == ReadProcessMemory64(hProcess, mbi64.BaseAddress, mem, (SIZE_T)mbi64.RegionSize, &rdPM)) || (rdPM != mbi64.RegionSize)) + { + if (printMemMap) + printf("%016I64X : %016I64X : %08X : ", mbi64.BaseAddress, mbi64.RegionSize, mbi64.Protect); + FNFAIL("ReadProcessMemory"); + VirtualFree(mem, 0, MEM_RELEASE); + crAddr = crAddr + mbi64.RegionSize; + continue; + } + + wchar_t fName[0x200]; + swprintf_s(fName, L"%08X_%016I64X_%08X.bin", procID, mbi64.BaseAddress, mbi64.Protect); + HANDLE hFile = CreateFile(fName, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + DWORD tmp = 0; + WriteFile(hFile, mem, (DWORD)mbi64.RegionSize, &tmp, 0); + CloseHandle(hFile); + + VirtualFree(mem, 0, MEM_RELEASE); + } + else + { + if (printMemMap) + printf("[ ] : "); + } + + if (printMemMap) + printf("%016I64X : %016I64X : %08X\n", mbi64.BaseAddress, mbi64.RegionSize, mbi64.Protect); + crAddr = crAddr + mbi64.RegionSize; + } + + DWORD64 ntdll64 = GetModuleHandle64(L"ntdll.dll"); + printf("\nNTDLL64: %016I64X\n\n", ntdll64); + + DWORD64 rtlcrc32 = GetProcAddress64(ntdll64, "RtlComputeCrc32"); + printf("RtlComputeCrc32 address: %016I64X\n", rtlcrc32); + + if (0 != rtlcrc32) + { + DWORD64 ret = X64Call(rtlcrc32, 3, (DWORD64)0, (DWORD64)"ReWolf", (DWORD64)6); + printf("CRC32(\"ReWolf\") = %016I64X\n\n", ret); + } + + printf("Alloc/Protect/Write/Free test:\n"); + AllocTest(hProcess); + + printf("\nAlloc/Protect/Write/Free over 4GB inside WoW64 test:\n"); + AllocTest(GetCurrentProcess()); + + printf("\n\nGet/Set Context test:\n"); + + _CONTEXT64 ctx = { 0 }; + ctx.ContextFlags = CONTEXT64_ALL; + GetThreadContext64(GetCurrentThread(), &ctx); + + printf("rsp: %016I64X\n", ctx.Rsp); + printf("rip: %016I64X\n", ctx.Rip); + printf("r8 : %016I64X\n", ctx.R8); + printf("r9 : %016I64X\n", ctx.R9); + printf("r12: %016I64X\n", ctx.R12); + + //below code will crash application, it is sufficient prove that SetThreadContext64 is working fine :) + //ctx.Rip = 0; + //SetThreadContext64(GetCurrentThread(), &ctx); + + CloseHandle(hProcess); + return 0; +} diff --git a/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/CMemPtr.h b/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/CMemPtr.h new file mode 100644 index 0000000000000000000000000000000000000000..fc7252fe1426e3e30b92025bc411e5102e02a211 --- /dev/null +++ b/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/CMemPtr.h @@ -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 . + * + */ +#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() diff --git a/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/internal.h b/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/internal.h new file mode 100644 index 0000000000000000000000000000000000000000..b439881a08b19765d070b21e327e172fc03a6e1a --- /dev/null +++ b/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/internal.h @@ -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 . + * + */ +#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]; +}; diff --git a/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/resource.h b/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/resource.h new file mode 100644 index 0000000000000000000000000000000000000000..e27a81bb871dc74e7b2b8e6095740452bcd21d06 --- /dev/null +++ b/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/resource.h @@ -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 diff --git a/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/wow64ext.cpp b/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/wow64ext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29213232b81b578e172e1cf3ffc72b3eebd5a771 --- /dev/null +++ b/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/wow64ext.cpp @@ -0,0 +1,601 @@ +/** + * + * 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 . + * + */ + +#include +#include +#include "internal.h" +#include "wow64ext.h" +#include "CMemPtr.h" + +//HANDLE g_heap; +BOOL g_isWow64 = TRUE; + +/*void* malloc(size_t size) +{ + return HeapAlloc(g_heap, 0, size); +} + +void free(void* ptr) +{ + if (nullptr != ptr) + HeapFree(g_heap, 0, ptr); +} + +int _wcsicmp(const wchar_t *string1, const wchar_t *string2) +{ + wchar_t c1; + wchar_t c2; + int i = 0; + do + { + c1 = string1[i]; + if (c1 >= 'A' && c1 <= 'Z') + c1 += 0x20; + + c2 = string2[i]; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 0x20; + + i++; + } while (c1 && c1 == c2); + return c1 - c2; +}*/ + +/*BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + if (DLL_PROCESS_ATTACH == fdwReason) + { + IsWow64Process(GetCurrentProcess(), &g_isWow64); + g_heap = GetProcessHeap(); + } + return TRUE; +}*/ + +#pragma warning(push) +#pragma warning(disable : 4409) +extern "C" DWORD64 __cdecl X64Call(DWORD64 func, int argC, ...) +{ + if (!g_isWow64) + return 0; + + va_list args; + va_start(args, argC); + reg64 _rcx = { (argC > 0) ? argC--, va_arg(args, DWORD64) : 0 }; + reg64 _rdx = { (argC > 0) ? argC--, va_arg(args, DWORD64) : 0 }; + reg64 _r8 = { (argC > 0) ? argC--, va_arg(args, DWORD64) : 0 }; + reg64 _r9 = { (argC > 0) ? argC--, va_arg(args, DWORD64) : 0 }; + reg64 _rax = { 0 }; + + reg64 restArgs = { (DWORD64)&va_arg(args, DWORD64) }; + + // conversion to QWORD for easier use in inline assembly +#ifdef _M_IX86 + reg64 _argC = { (DWORD64)argC }; + DWORD back_esp = 0; + WORD back_fs = 0; + __asm + { + ;// reset FS segment, to properly handle RFG + mov back_fs, fs + mov eax, 0x2B + mov fs, ax + + ;// keep original esp in back_esp variable + mov back_esp, esp + + ;// align esp to 0x10, without aligned stack some syscalls may return errors ! + ;// (actually, for syscalls it is sufficient to align to 8, but SSE opcodes + ;// requires 0x10 alignment), it will be further adjusted according to the + ;// number of arguments above 4 + and esp, 0xFFFFFFF0 + + X64_Start(); + + ;// below code is compiled as x86 inline asm, but it is executed as x64 code + ;// that's why it need sometimes REX_W() macro, right column contains detailed + ;// transcription how it will be interpreted by CPU + + ;// fill first four arguments + REX_W mov ecx, _rcx.dw[0] ;// mov rcx, qword ptr [_rcx] + REX_W mov edx, _rdx.dw[0] ;// mov rdx, qword ptr [_rdx] + push _r8.v ;// push qword ptr [_r8] + X64_Pop(_R8); ;// pop r8 + push _r9.v ;// push qword ptr [_r9] + X64_Pop(_R9); ;// pop r9 + ;// + REX_W mov eax, _argC.dw[0] ;// mov rax, qword ptr [_argC] + ;// + ;// final stack adjustment, according to the ;// + ;// number of arguments above 4 ;// + test al, 1 ;// test al, 1 + jnz _no_adjust ;// jnz _no_adjust + sub esp, 8 ;// sub rsp, 8 +_no_adjust: ;// + ;// + push edi ;// push rdi + REX_W mov edi, restArgs.dw[0] ;// mov rdi, qword ptr [restArgs] + ;// + ;// put rest of arguments on the stack ;// + REX_W test eax, eax ;// test rax, rax + jz _ls_e ;// je _ls_e + REX_W lea edi, dword ptr [edi + 8*eax - 8] ;// lea rdi, [rdi + rax*8 - 8] + ;// +_ls: ;// + REX_W test eax, eax ;// test rax, rax + jz _ls_e ;// je _ls_e + push dword ptr [edi] ;// push qword ptr [rdi] + REX_W sub edi, 8 ;// sub rdi, 8 + REX_W sub eax, 1 ;// sub rax, 1 + jmp _ls ;// jmp _ls +_ls_e: ;// + ;// + ;// create stack space for spilling registers ;// + REX_W sub esp, 0x20 ;// sub rsp, 20h + ;// + call func ;// call qword ptr [func] + ;// + ;// cleanup stack ;// + REX_W mov ecx, _argC.dw[0] ;// mov rcx, qword ptr [_argC] + REX_W lea esp, dword ptr [esp + 8*ecx + 0x20] ;// lea rsp, [rsp + rcx*8 + 20h] + ;// + pop edi ;// pop rdi + ;// + // set return value ;// + REX_W mov _rax.dw[0], eax ;// mov qword ptr [_rax], rax + + X64_End(); + + mov ax, ds + mov ss, ax + mov esp, back_esp + + ;// restore FS segment + mov ax, back_fs + mov fs, ax + } +#endif // _M_IX86 + + return _rax.v; +} +#pragma warning(pop) + +void getMem64(void* dstMem, DWORD64 srcMem, size_t sz) +{ + if ((nullptr == dstMem) || (0 == srcMem) || (0 == sz)) + return; + + reg64 _src = { srcMem }; +#ifdef _M_IX86 + __asm + { + X64_Start(); + + ;// below code is compiled as x86 inline asm, but it is executed as x64 code + ;// that's why it need sometimes REX_W() macro, right column contains detailed + ;// transcription how it will be interpreted by CPU + + push edi ;// push rdi + push esi ;// push rsi + ;// + mov edi, dstMem ;// mov edi, dword ptr [dstMem] ; high part of RDI is zeroed + REX_W mov esi, _src.dw[0] ;// mov rsi, qword ptr [_src] + mov ecx, sz ;// mov ecx, dword ptr [sz] ; high part of RCX is zeroed + ;// + mov eax, ecx ;// mov eax, ecx + and eax, 3 ;// and eax, 3 + shr ecx, 2 ;// shr ecx, 2 + ;// + rep movsd ;// rep movs dword ptr [rdi], dword ptr [rsi] + ;// + test eax, eax ;// test eax, eax + je _move_0 ;// je _move_0 + cmp eax, 1 ;// cmp eax, 1 + je _move_1 ;// je _move_1 + ;// + movsw ;// movs word ptr [rdi], word ptr [rsi] + cmp eax, 2 ;// cmp eax, 2 + je _move_0 ;// je _move_0 + ;// +_move_1: ;// + movsb ;// movs byte ptr [rdi], byte ptr [rsi] + ;// +_move_0: ;// + pop esi ;// pop rsi + pop edi ;// pop rdi + + X64_End(); + } +#endif +} + +bool cmpMem64(void* dstMem, DWORD64 srcMem, size_t sz) +{ + if ((nullptr == dstMem) || (0 == srcMem) || (0 == sz)) + return false; + + bool result = false; + reg64 _src = { srcMem }; +#ifdef _M_IX86 + __asm + { + X64_Start(); + + ;// below code is compiled as x86 inline asm, but it is executed as x64 code + ;// that's why it need sometimes REX_W() macro, right column contains detailed + ;// transcription how it will be interpreted by CPU + + push edi ;// push rdi + push esi ;// push rsi + ;// + mov edi, dstMem ;// mov edi, dword ptr [dstMem] ; high part of RDI is zeroed + REX_W mov esi, _src.dw[0] ;// mov rsi, qword ptr [_src] + mov ecx, sz ;// mov ecx, dword ptr [sz] ; high part of RCX is zeroed + ;// + mov eax, ecx ;// mov eax, ecx + and eax, 3 ;// and eax, 3 + shr ecx, 2 ;// shr ecx, 2 + ;// + repe cmpsd ;// repe cmps dword ptr [rsi], dword ptr [rdi] + jnz _ret_false ;// jnz _ret_false + ;// + test eax, eax ;// test eax, eax + je _move_0 ;// je _move_0 + cmp eax, 1 ;// cmp eax, 1 + je _move_1 ;// je _move_1 + ;// + cmpsw ;// cmps word ptr [rsi], word ptr [rdi] + jnz _ret_false ;// jnz _ret_false + cmp eax, 2 ;// cmp eax, 2 + je _move_0 ;// je _move_0 + ;// +_move_1: ;// + cmpsb ;// cmps byte ptr [rsi], byte ptr [rdi] + jnz _ret_false ;// jnz _ret_false + ;// +_move_0: ;// + mov result, 1 ;// mov byte ptr [result], 1 + ;// +_ret_false: ;// + pop esi ;// pop rsi + pop edi ;// pop rdi + + X64_End(); + } +#endif + return result; +} + +DWORD64 getTEB64() +{ + reg64 reg; + reg.v = 0; +#ifdef _M_IX86 + X64_Start(); + // R12 register should always contain pointer to TEB64 in WoW64 processes + X64_Push(_R12); + // below pop will pop QWORD from stack, as we're in x64 mode now + __asm pop reg.dw[0] + X64_End(); +#endif + return reg.v; +} + +extern "C" DWORD64 __cdecl GetModuleHandle64(wchar_t* lpModuleName) +{ + if (!g_isWow64) + return 0; + + TEB64 teb64; + getMem64(&teb64, getTEB64(), sizeof(TEB64)); + + PEB64 peb64; + getMem64(&peb64, teb64.ProcessEnvironmentBlock, sizeof(PEB64)); + PEB_LDR_DATA64 ldr; + getMem64(&ldr, peb64.Ldr, sizeof(PEB_LDR_DATA64)); + + DWORD64 LastEntry = peb64.Ldr + offsetof(PEB_LDR_DATA64, InLoadOrderModuleList); + LDR_DATA_TABLE_ENTRY64 head; + head.InLoadOrderLinks.Flink = ldr.InLoadOrderModuleList.Flink; + do + { + getMem64(&head, head.InLoadOrderLinks.Flink, sizeof(LDR_DATA_TABLE_ENTRY64)); + + wchar_t* tempBuf = (wchar_t*)malloc(head.BaseDllName.MaximumLength); + if (nullptr == tempBuf) + return 0; + WATCH(tempBuf); + getMem64(tempBuf, head.BaseDllName.Buffer, head.BaseDllName.MaximumLength); + + if (0 == _wcsicmp(lpModuleName, tempBuf)) + return head.DllBase; + } + while (head.InLoadOrderLinks.Flink != LastEntry); + + return 0; +} + +DWORD64 getNTDLL64() +{ + static DWORD64 ntdll64 = 0; + if (0 != ntdll64) + return ntdll64; + + ntdll64 = GetModuleHandle64(L"ntdll.dll"); + return ntdll64; +} + +DWORD64 getLdrGetProcedureAddress() +{ + DWORD64 modBase = getNTDLL64(); + if (0 == modBase) + return 0; + + IMAGE_DOS_HEADER idh; + getMem64(&idh, modBase, sizeof(idh)); + + IMAGE_NT_HEADERS64 inh; + getMem64(&inh, modBase + idh.e_lfanew, sizeof(IMAGE_NT_HEADERS64)); + + IMAGE_DATA_DIRECTORY& idd = inh.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; + + if (0 == idd.VirtualAddress) + return 0; + + IMAGE_EXPORT_DIRECTORY ied; + getMem64(&ied, modBase + idd.VirtualAddress, sizeof(ied)); + + DWORD* rvaTable = (DWORD*)malloc(sizeof(DWORD)*ied.NumberOfFunctions); + if (nullptr == rvaTable) + return 0; + WATCH(rvaTable); + getMem64(rvaTable, modBase + ied.AddressOfFunctions, sizeof(DWORD)*ied.NumberOfFunctions); + + WORD* ordTable = (WORD*)malloc(sizeof(WORD)*ied.NumberOfFunctions); + if (nullptr == ordTable) + return 0; + WATCH(ordTable); + getMem64(ordTable, modBase + ied.AddressOfNameOrdinals, sizeof(WORD)*ied.NumberOfFunctions); + + DWORD* nameTable = (DWORD*)malloc(sizeof(DWORD)*ied.NumberOfNames); + if (nullptr == nameTable) + return 0; + WATCH(nameTable); + getMem64(nameTable, modBase + ied.AddressOfNames, sizeof(DWORD)*ied.NumberOfNames); + + // lazy search, there is no need to use binsearch for just one function + for (DWORD i = 0; i < ied.NumberOfFunctions; i++) + { + if (!cmpMem64("LdrGetProcedureAddress", modBase + nameTable[i], sizeof("LdrGetProcedureAddress"))) + continue; + else + return modBase + rvaTable[ordTable[i]]; + } + return 0; +} + +extern "C" VOID __cdecl SetLastErrorFromX64Call(DWORD64 status) +{ + typedef ULONG (WINAPI *RtlNtStatusToDosError_t)(NTSTATUS Status); + typedef ULONG (WINAPI *RtlSetLastWin32Error_t)(NTSTATUS Status); + + static RtlNtStatusToDosError_t RtlNtStatusToDosError = nullptr; + static RtlSetLastWin32Error_t RtlSetLastWin32Error = nullptr; + + if ((nullptr == RtlNtStatusToDosError) || (nullptr == RtlSetLastWin32Error)) + { + HMODULE ntdll = GetModuleHandleW(L"ntdll.dll"); + RtlNtStatusToDosError = (RtlNtStatusToDosError_t)GetProcAddress(ntdll, "RtlNtStatusToDosError"); + RtlSetLastWin32Error = (RtlSetLastWin32Error_t)GetProcAddress(ntdll, "RtlSetLastWin32Error"); + } + + if ((nullptr != RtlNtStatusToDosError) && (nullptr != RtlSetLastWin32Error)) + { + RtlSetLastWin32Error(RtlNtStatusToDosError((DWORD)status)); + } +} + +extern "C" DWORD64 __cdecl GetProcAddress64(DWORD64 hModule, char* funcName) +{ + static DWORD64 _LdrGetProcedureAddress = 0; + if (0 == _LdrGetProcedureAddress) + { + _LdrGetProcedureAddress = getLdrGetProcedureAddress(); + if (0 == _LdrGetProcedureAddress) + return 0; + } + + _UNICODE_STRING_T fName = { 0 }; + fName.Buffer = (DWORD64)funcName; + fName.Length = (WORD)strlen(funcName); + fName.MaximumLength = fName.Length + 1; + DWORD64 funcRet = 0; + X64Call(_LdrGetProcedureAddress, 4, (DWORD64)hModule, (DWORD64)&fName, (DWORD64)0, (DWORD64)&funcRet); + return funcRet; +} + +extern "C" SIZE_T __cdecl VirtualQueryEx64(HANDLE hProcess, DWORD64 lpAddress, MEMORY_BASIC_INFORMATION64* lpBuffer, SIZE_T dwLength) +{ + static DWORD64 ntqvm = 0; + if (0 == ntqvm) + { + ntqvm = GetProcAddress64(getNTDLL64(), "NtQueryVirtualMemory"); + if (0 == ntqvm) + return 0; + } + DWORD64 ret = 0; + DWORD64 status = X64Call(ntqvm, 6, (DWORD64)hProcess, lpAddress, (DWORD64)0, (DWORD64)lpBuffer, (DWORD64)dwLength, (DWORD64)&ret); + if (STATUS_SUCCESS != status) + SetLastErrorFromX64Call(status); + return (SIZE_T)ret; +} + +extern "C" DWORD64 __cdecl VirtualAllocEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) +{ + static DWORD64 ntavm = 0; + if (0 == ntavm) + { + ntavm = GetProcAddress64(getNTDLL64(), "NtAllocateVirtualMemory"); + if (0 == ntavm) + return 0; + } + + DWORD64 tmpAddr = lpAddress; + DWORD64 tmpSize = dwSize; + DWORD64 ret = X64Call(ntavm, 6, (DWORD64)hProcess, (DWORD64)&tmpAddr, (DWORD64)0, (DWORD64)&tmpSize, (DWORD64)flAllocationType, (DWORD64)flProtect); + if (STATUS_SUCCESS != ret) + { + SetLastErrorFromX64Call(ret); + return FALSE; + } + else + return tmpAddr; +} + +extern "C" BOOL __cdecl VirtualFreeEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD dwFreeType) +{ + static DWORD64 ntfvm = 0; + if (0 == ntfvm) + { + ntfvm = GetProcAddress64(getNTDLL64(), "NtFreeVirtualMemory"); + if (0 == ntfvm) + return 0; + } + + DWORD64 tmpAddr = lpAddress; + DWORD64 tmpSize = dwSize; + DWORD64 ret = X64Call(ntfvm, 4, (DWORD64)hProcess, (DWORD64)&tmpAddr, (DWORD64)&tmpSize, (DWORD64)dwFreeType); + if (STATUS_SUCCESS != ret) + { + SetLastErrorFromX64Call(ret); + return FALSE; + } + else + return TRUE; +} + +extern "C" BOOL __cdecl VirtualProtectEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* lpflOldProtect) +{ + static DWORD64 ntpvm = 0; + if (0 == ntpvm) + { + ntpvm = GetProcAddress64(getNTDLL64(), "NtProtectVirtualMemory"); + if (0 == ntpvm) + return 0; + } + + DWORD64 tmpAddr = lpAddress; + DWORD64 tmpSize = dwSize; + DWORD64 ret = X64Call(ntpvm, 5, (DWORD64)hProcess, (DWORD64)&tmpAddr, (DWORD64)&tmpSize, (DWORD64)flNewProtect, (DWORD64)lpflOldProtect); + if (STATUS_SUCCESS != ret) + { + SetLastErrorFromX64Call(ret); + return FALSE; + } + else + return TRUE; +} + +extern "C" BOOL __cdecl ReadProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead) +{ + static DWORD64 nrvm = 0; + if (0 == nrvm) + { + nrvm = GetProcAddress64(getNTDLL64(), "NtReadVirtualMemory"); + if (0 == nrvm) + return 0; + } + DWORD64 numOfBytes = lpNumberOfBytesRead ? *lpNumberOfBytesRead : 0; + DWORD64 ret = X64Call(nrvm, 5, (DWORD64)hProcess, lpBaseAddress, (DWORD64)lpBuffer, (DWORD64)nSize, (DWORD64)&numOfBytes); + if (STATUS_SUCCESS != ret) + { + SetLastErrorFromX64Call(ret); + return FALSE; + } + else + { + if (lpNumberOfBytesRead) + *lpNumberOfBytesRead = (SIZE_T)numOfBytes; + return TRUE; + } +} + +extern "C" BOOL __cdecl WriteProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten) +{ + static DWORD64 nrvm = 0; + if (0 == nrvm) + { + nrvm = GetProcAddress64(getNTDLL64(), "NtWriteVirtualMemory"); + if (0 == nrvm) + return 0; + } + DWORD64 numOfBytes = lpNumberOfBytesWritten ? *lpNumberOfBytesWritten : 0; + DWORD64 ret = X64Call(nrvm, 5, (DWORD64)hProcess, lpBaseAddress, (DWORD64)lpBuffer, (DWORD64)nSize, (DWORD64)&numOfBytes); + if (STATUS_SUCCESS != ret) + { + SetLastErrorFromX64Call(ret); + return FALSE; + } + else + { + if (lpNumberOfBytesWritten) + *lpNumberOfBytesWritten = (SIZE_T)numOfBytes; + return TRUE; + } +} + +extern "C" BOOL __cdecl GetThreadContext64(HANDLE hThread, _CONTEXT64_2* lpContext) +{ + static DWORD64 gtc = 0; + if (0 == gtc) + { + gtc = GetProcAddress64(getNTDLL64(), "NtGetContextThread"); + if (0 == gtc) + return 0; + } + DWORD64 ret = X64Call(gtc, 2, (DWORD64)hThread, (DWORD64)lpContext); + if(STATUS_SUCCESS != ret) + { + SetLastErrorFromX64Call(ret); + return FALSE; + } + else + return TRUE; +} + +extern "C" BOOL __cdecl SetThreadContext64(HANDLE hThread, _CONTEXT64_2* lpContext) +{ + static DWORD64 stc = 0; + if (0 == stc) + { + stc = GetProcAddress64(getNTDLL64(), "NtSetContextThread"); + if (0 == stc) + return 0; + } + DWORD64 ret = X64Call(stc, 2, (DWORD64)hThread, (DWORD64)lpContext); + if (STATUS_SUCCESS != ret) + { + SetLastErrorFromX64Call(ret); + return FALSE; + } + else + return TRUE; +} diff --git a/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/wow64ext.h b/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/wow64ext.h new file mode 100644 index 0000000000000000000000000000000000000000..278d6c4bfda8f3ba522c6ea0b812c8ee5d928920 --- /dev/null +++ b/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/wow64ext.h @@ -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 . + * + */ +#pragma once + +#include + +#ifndef STATUS_SUCCESS +# define STATUS_SUCCESS 0 +#endif + +#pragma warning(disable : 4201) +#pragma pack(push) +#pragma pack(1) +template +struct _LIST_ENTRY_T +{ + T Flink; + T Blink; +}; + +template +struct _UNICODE_STRING_T +{ + union + { + struct + { + WORD Length; + WORD MaximumLength; + }; + T dummy; + }; + T Buffer; +}; + +template +struct _NT_TIB_T +{ + T ExceptionList; + T StackBase; + T StackLimit; + T SubSystemTib; + T FiberData; + T ArbitraryUserPointer; + T Self; +}; + +template +struct _CLIENT_ID_T +{ + T UniqueProcess; + T UniqueThread; +}; + +template +struct _TEB_T_ +{ + _NT_TIB_T NtTib; + T EnvironmentPointer; + _CLIENT_ID_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 +struct _LDR_DATA_TABLE_ENTRY_T +{ + _LIST_ENTRY_T InLoadOrderLinks; + _LIST_ENTRY_T InMemoryOrderLinks; + _LIST_ENTRY_T InInitializationOrderLinks; + T DllBase; + T EntryPoint; + union + { + DWORD SizeOfImage; + T dummy01; + }; + _UNICODE_STRING_T FullDllName; + _UNICODE_STRING_T BaseDllName; + DWORD Flags; + WORD LoadCount; + WORD TlsIndex; + union + { + _LIST_ENTRY_T HashLinks; + struct + { + T SectionPointer; + T CheckSum; + }; + }; + union + { + T LoadedImports; + DWORD TimeDateStamp; + }; + T EntryPointActivationContext; + T PatchInformation; + _LIST_ENTRY_T ForwarderLinks; + _LIST_ENTRY_T ServiceTagLinks; + _LIST_ENTRY_T StaticLinks; + T ContextInformation; + T OriginalBase; + _LARGE_INTEGER LoadTime; +}; + +template +struct _PEB_LDR_DATA_T +{ + DWORD Length; + DWORD Initialized; + T SsHandle; + _LIST_ENTRY_T InLoadOrderModuleList; + _LIST_ENTRY_T InMemoryOrderModuleList; + _LIST_ENTRY_T InInitializationOrderModuleList; + T EntryInProgress; + DWORD ShutdownInProgress; + T ShutdownThreadId; + +}; + +template +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 CSDVersion; + T ActivationContextData; + T ProcessAssemblyStorageMap; + T SystemDefaultActivationContextData; + T SystemAssemblyStorageMap; + T MinimumStackCommit; + T FlsCallback; + _LIST_ENTRY_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 LDR_DATA_TABLE_ENTRY32; +typedef _LDR_DATA_TABLE_ENTRY_T LDR_DATA_TABLE_ENTRY64; + +typedef _TEB_T_ TEB32; +typedef _TEB_T_ TEB64; + +typedef _PEB_LDR_DATA_T PEB_LDR_DATA32; +typedef _PEB_LDR_DATA_T PEB_LDR_DATA64; + +typedef _PEB_T PEB32; +typedef _PEB_T 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(wchar_t* lpModuleName); + DWORD64 __cdecl getNTDLL64(); + DWORD64 __cdecl GetProcAddress64(DWORD64 hModule, 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); +} diff --git a/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/wow64ext.rc b/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/wow64ext.rc new file mode 100644 index 0000000000000000000000000000000000000000..03c37d2a54f938e414d296f6a577019cfc5fa536 Binary files /dev/null and b/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/wow64ext.rc differ diff --git a/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/wow64ext.sln b/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/wow64ext.sln new file mode 100644 index 0000000000000000000000000000000000000000..a2d24957add5cdb1f0f6f6541254dc1f2db25fe0 --- /dev/null +++ b/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/wow64ext.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wow64ext", "wow64ext.vcxproj", "{9DA7F232-0096-45BC-A452-24C7F3AFA0F8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9DA7F232-0096-45BC-A452-24C7F3AFA0F8}.Debug|Win32.ActiveCfg = Debug|Win32 + {9DA7F232-0096-45BC-A452-24C7F3AFA0F8}.Debug|Win32.Build.0 = Debug|Win32 + {9DA7F232-0096-45BC-A452-24C7F3AFA0F8}.Release|Win32.ActiveCfg = Release|Win32 + {9DA7F232-0096-45BC-A452-24C7F3AFA0F8}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/wow64ext.vcxproj b/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/wow64ext.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..5794e2563daf5728464e10e2cf876c2ca7a46d06 --- /dev/null +++ b/third/Blackbone/src/3rd_party/rewolf-wow64ext/src/wow64ext.vcxproj @@ -0,0 +1,104 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {9DA7F232-0096-45BC-A452-24C7F3AFA0F8} + Win32Proj + wow64ext + 8.1 + + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + false + true + Unicode + v140 + + + + + + + + + + + + + true + + + false + $(WindowsSDK_MetadataPath); + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;WOW64EXT_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;WOW64EXT_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + false + false + false + + + Windows + DebugFastLink + true + true + true + kernel32.lib + DllMain + true + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/third/Blackbone/src/3rd_party/winapifamily.h b/third/Blackbone/src/3rd_party/winapifamily.h new file mode 100644 index 0000000000000000000000000000000000000000..1fac1d4eeb6b606223060b6294331a630e0f1cd6 --- /dev/null +++ b/third/Blackbone/src/3rd_party/winapifamily.h @@ -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 + +/* + * 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 */ diff --git a/third/Blackbone/src/3rd_party/winpackagefamily.h b/third/Blackbone/src/3rd_party/winpackagefamily.h new file mode 100644 index 0000000000000000000000000000000000000000..ee691f9c25198e31a2f1ab9682a34f0e441db15d --- /dev/null +++ b/third/Blackbone/src/3rd_party/winpackagefamily.h @@ -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 */ diff --git a/third/Blackbone/src/BlackBone/Asm/AsmFactory.h b/third/Blackbone/src/BlackBone/Asm/AsmFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..07dc6e760ee5cb16945beaf1afc955f44dc07bf8 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Asm/AsmFactory.h @@ -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; + +/// +/// Get suitable asm generator +/// +class AsmFactory +{ +public: + enum eAsmArch + { + asm32, // x86 + asm64 // x86_64 + }; + + /// + /// Get suitable asm generator + /// + /// Desired CPU architecture + /// AsmHelperBase interface + static AsmHelperPtr GetAssembler( eAsmArch arch ) + { + switch (arch) + { + case asm32: + return std::make_unique(); + case asm64: + return std::make_unique(); + default: + return nullptr; + } + } + + /// + /// Get suitable asm generator + /// + /// Desired PE module architecture + /// AsmHelperBase interface + 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; + } + } + + /// + /// Get suitable asm generator + /// + /// Target process CPU architecture + /// AsmHelperBase interface + static AsmHelperPtr GetAssembler( bool wow64process ) + { + return GetAssembler( wow64process ? asm32 : asm64 ); + } + + + /// + /// Get default asm generator + /// + /// + static AsmHelperPtr GetAssembler() + { +#ifdef USE64 + return std::make_unique(); +#else + return std::make_unique(); +#endif + } +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Asm/AsmHelper32.cpp b/third/Blackbone/src/BlackBone/Asm/AsmHelper32.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ab8eccc818ab09cad8ca0f1c140e247aaa87f9fe --- /dev/null +++ b/third/Blackbone/src/BlackBone/Asm/AsmHelper32.cpp @@ -0,0 +1,277 @@ +#include "AsmHelper32.h" + +#include +#include + +namespace blackbone +{ + +AsmHelper32::AsmHelper32( ) + : IAsmHelper( asmjit::kArchX86 ) +{ +} + +AsmHelper32::~AsmHelper32( void ) +{ +} + +/// +/// Generate function prologue code +/// +/// Unused +void AsmHelper32::GenPrologue( bool switchMode /*= false*/ ) +{ + if(switchMode == true) + { + IAsmHelper::SwitchTo64(); + } + else + { + _assembler.push( asmjit::host::ebp ); + _assembler.mov( asmjit::host::ebp, asmjit::host::esp ); + } +} + +/// +/// Generate function epilogue code +/// +/// Unused +/// Stack change value +void AsmHelper32::GenEpilogue( bool switchMode /*= false*/ , int retSize /*= -1 */ ) +{ + if (switchMode == true) + { + IAsmHelper::SwitchTo86(); + } + else + { + _assembler.mov( asmjit::host::esp, asmjit::host::ebp ); + _assembler.pop( asmjit::host::ebp ); + } + + if (retSize == -1) + _assembler.ret(); + else + _assembler.ret( retSize ); +} + +/// +/// Generate function call +/// +/// Function pointer +/// Function arguments +/// Calling convention +void AsmHelper32::GenCall( const AsmFunctionPtr& pFN, const std::vector& args, eCalligConvention cc /*= CC_stdcall*/ ) +{ + std::set passedIdx; + + // Pass arguments in registers + // 64bit arguments are never passed in registers + if ((cc == cc_thiscall || cc == cc_fastcall) && !args.empty()) + for (int i = 0, j = 0; i < static_cast(args.size()) && (j < ((cc == cc_fastcall) ? 2 : 1)); i++) + if (args[i].reg86Compatible()) + { + PushArg( args[i], (eArgType)j ); + passedIdx.emplace( i ); + j++; + } + + // Push args on stack + for (int i = (int)args.size() - 1; i >= 0; i--) + { + // Skip arguments passed in registers + if (passedIdx.count( i ) == 0) + PushArg( args[i] ); + } + + // Direct pointer + if(pFN.type == AsmVariant::imm) + { + assert( pFN.imm_val64 <= std::numeric_limits::max() ); + _assembler.mov( asmjit::host::eax, pFN.imm_val ); + _assembler.call( asmjit::host::eax ); + } + // Already in register + else if (pFN.type == AsmVariant::reg) + { + _assembler.call( pFN.reg_val ); + } + else + { + assert( "Invalid function pointer type" && false ); + } + + // Adjust stack ptr + if (cc == cc_cdecl) + { + size_t argsize = 0; + + for (auto& arg : args) + { + if (arg.type != AsmVariant::dataPtr) + argsize += arg.size; + else + argsize += sizeof( uint32_t ); + } + + _assembler.add( asmjit::host::esp, argsize ); + } + +} + +/// +/// Save eax value and terminate current thread +/// +/// NtTerminateThread address +/// Memory where eax value will be saved +void AsmHelper32::ExitThreadWithStatus( uint64_t pExitThread, uint64_t resultPtr ) +{ + if (resultPtr != 0) + { + _assembler.mov( asmjit::host::edx, resultPtr ); + _assembler.mov( asmjit::host::dword_ptr( asmjit::host::edx ), asmjit::host::eax ); + } + + // NtTerminateThread( NULL, eax ); + _assembler.push( asmjit::host::eax ); + _assembler.push( 0 ); + _assembler.mov( asmjit::host::eax, pExitThread ); + _assembler.call( asmjit::host::eax ); + + _assembler.ret(); +} + +/// +/// Save return value and signal thread return event +/// +/// NtSetEvent address +/// Result value memory location +/// Event memory location +/// Error code memory location +/// Return type +void AsmHelper32::SaveRetValAndSignalEvent( + uint64_t pSetEvent, + uint64_t ResultPtr, + uint64_t EventPtr, + uint64_t errPtr, + eReturnType rtype /*= rt_int32*/ + ) +{ + _assembler.mov( asmjit::host::ecx, ResultPtr ); + + // Return 64bit value + if (rtype == rt_int64) + { + _assembler.mov( asmjit::host::dword_ptr( asmjit::host::ecx, 4 ), asmjit::host::eax ); + _assembler.mov( asmjit::host::dword_ptr( asmjit::host::ecx ), asmjit::host::edx ); + } + else if (rtype == rt_int32) + _assembler.mov( asmjit::host::dword_ptr( asmjit::host::ecx ), asmjit::host::eax ); + + // Save last NT status + _assembler.mov( asmjit::host::edx, asmjit::host::dword_ptr_abs( 0x18 ).setSegment( asmjit::host::fs ) ); + _assembler.add( asmjit::host::edx, 0x598 + 0x197 * sizeof( uint32_t ) ); + _assembler.mov( asmjit::host::edx, asmjit::host::dword_ptr( asmjit::host::edx ) ); + _assembler.mov( asmjit::host::eax, errPtr ); + _assembler.mov( asmjit::host::dword_ptr( asmjit::host::eax ), asmjit::host::edx ); + + // SetEvent(hEvent) + // NtSetEvent(hEvent, NULL) + _assembler.push( 0 ); + _assembler.mov( asmjit::host::eax, EventPtr ); + _assembler.mov( asmjit::host::eax, asmjit::host::dword_ptr( asmjit::host::eax ) ); + _assembler.push( asmjit::host::eax ); + _assembler.mov( asmjit::host::eax, pSetEvent ); + _assembler.call( asmjit::host::eax ); +} + +/// +/// Push function argument +/// +/// Argument. +/// Push type(register or stack) +void AsmHelper32::PushArg( const AsmVariant& arg, eArgType regidx /*= AT_stack*/ ) +{ + switch (arg.type) + { + case AsmVariant::imm: + case AsmVariant::structRet: + // TODO: resolve 64bit imm values instead of ignoring high bits + PushArgp( arg.imm_val, regidx ); + break; + + case AsmVariant::dataPtr: + PushArgp( arg.new_imm_val != 0 ? arg.new_imm_val : arg.imm_val, regidx ); + break; + + // Copy argument onto stack + case AsmVariant::dataStruct: + { + // Ensure stack remain aligned on word size + size_t realSize = Align( arg.size, sizeof( uint32_t ) ); + _assembler.sub( asmjit::host::esp, realSize ); + _assembler.mov( asmjit::host::esi, arg.new_imm_val ); + _assembler.mov( asmjit::host::edi, asmjit::host::esp); + + // Preserve ecx value, may be __thiscall or __fastcall function + _assembler.mov( asmjit::host::eax, asmjit::host::ecx ); + + _assembler.mov( asmjit::host::ecx, arg.size ); + _assembler.rep_movsb(); + + // Restore registers + _assembler.mov( asmjit::host::ecx, asmjit::host::eax ); + } + break; + + case AsmVariant::imm_double: + { + ULARGE_INTEGER li; + li.QuadPart = arg.getImm_double(); + + PushArgp( static_cast(li.HighPart), regidx ); + PushArgp( static_cast(li.LowPart), regidx ); + } + break; + + case AsmVariant::imm_float: + PushArgp( arg.getImm_float(), regidx ); + break; + + case AsmVariant::mem_ptr: + _assembler.lea( asmjit::host::eax, arg.mem_val ); + PushArgp( asmjit::host::eax, regidx ); + break; + + case AsmVariant::mem: + PushArgp( arg.mem_val, regidx ); + break; + + case AsmVariant::reg: + PushArgp( arg.reg_val, regidx ); + break; + + default: + assert( "Invalid argument type" && false ); + break; + } +} + +/// +/// Push argument into function +/// +/// Argument +/// Argument location +template +void AsmHelper32::PushArgp( _Type arg, eArgType index ) +{ + static const asmjit::GpReg regs[] = { asmjit::host::ecx, asmjit::host::edx }; + + // for __fastcall and __thiscall + if (index < at_stack) + _assembler.mov( regs[index], arg ); + else + _assembler.push( arg ); +} + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Asm/AsmHelper32.h b/third/Blackbone/src/BlackBone/Asm/AsmHelper32.h new file mode 100644 index 0000000000000000000000000000000000000000..7fcb7b7a653f9f6cb8da0b273560da429e83d523 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Asm/AsmHelper32.h @@ -0,0 +1,88 @@ +#pragma once + +#include "IAsmHelper.h" + +namespace blackbone +{ + +/// +/// 32 bit assembler helper +/// +class AsmHelper32 : public IAsmHelper +{ +public: + BLACKBONE_API AsmHelper32( ); + BLACKBONE_API ~AsmHelper32( void ); + + /// + /// Generate function prologue code + /// + /// Unused + virtual void GenPrologue( bool switchMode = false ); + + /// + /// Generate function epilogue code + /// + /// Unused + /// Stack change value + virtual void GenEpilogue( bool switchMode = false, int retSize = -1 ); + + /// + /// Generate function call + /// + /// Function pointer + /// Function arguments + /// Calling convention + virtual void GenCall( const AsmFunctionPtr& pFN, const std::vector& args, eCalligConvention cc = cc_stdcall ); + + /// + /// Save eax value and terminate current thread + /// + /// NtTerminateThread address + /// Memory where eax value will be saved + virtual void ExitThreadWithStatus( uint64_t pExitThread, uint64_t resultPtr ); + + /// + /// Save return value and signal thread return event + /// + /// NtSetEvent address + /// Result value memory location + /// Event memory location + /// Error code memory location + /// Return type + virtual void SaveRetValAndSignalEvent( + uint64_t pSetEvent, + uint64_t ResultPtr, + uint64_t EventPtr, + uint64_t errPtr, + eReturnType rtype = rt_int32 + ); + + /// + /// Does nothing under x86 + /// + /// Unused + virtual void EnableX64CallStack( bool ) { } + +private: + AsmHelper32( const AsmHelper32& ) = delete; + AsmHelper32& operator = (const AsmHelper32&) = delete; + + /// + /// Push function argument + /// + /// Argument. + /// Push type(register or stack) + void PushArg( const AsmVariant& arg, eArgType regidx = at_stack ); + + /// + /// Push argument into function + /// + /// Argument + /// Argument location + template + void PushArgp( _Type arg, eArgType index ); +}; + +} + diff --git a/third/Blackbone/src/BlackBone/Asm/AsmHelper64.cpp b/third/Blackbone/src/BlackBone/Asm/AsmHelper64.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a08e561a4195b8b7a35f7331e77d567f444ba65 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Asm/AsmHelper64.cpp @@ -0,0 +1,253 @@ +#include "AsmHelper64.h" + +#include + +namespace blackbone +{ + +AsmHelper64::AsmHelper64( ) + : IAsmHelper( asmjit::kArchX64 ) + ,_stackEnabled( true ) +{ +} + +AsmHelper64::~AsmHelper64( void ) +{ +} + +/// +/// Generate function prologue code +/// +/// true if execution must be swithed to x64 mode +void AsmHelper64::GenPrologue( bool switchMode /*= false*/ ) +{ + // If switch is required, function was called from x86 mode, + // so arguments can't be saved in x64 way, because there is no shadow space on the stack + if (switchMode) + { + SwitchTo64(); + + // Align stack + _assembler.and_( _assembler.zsp, 0xFFFFFFFFFFFFFFF0 ); + } + else + { + _assembler.mov( asmjit::host::qword_ptr( asmjit::host::rsp, 1 * sizeof( uint64_t ) ), asmjit::host::rcx ); + _assembler.mov( asmjit::host::qword_ptr( asmjit::host::rsp, 2 * sizeof( uint64_t ) ), asmjit::host::rdx ); + _assembler.mov( asmjit::host::qword_ptr( asmjit::host::rsp, 3 * sizeof( uint64_t ) ), asmjit::host::r8 ); + _assembler.mov( asmjit::host::qword_ptr( asmjit::host::rsp, 4 * sizeof( uint64_t ) ), asmjit::host::r9 ); + } +} + +/// +/// Generate function epilogue code +/// +/// true if execution must be swithed to x86 mode +/// Stack change value +void AsmHelper64::GenEpilogue( bool switchMode /*= false*/, int /*retSize = 0*/ ) +{ + if (switchMode) + { + SwitchTo86(); + } + else + { + _assembler.mov( asmjit::host::rcx, asmjit::host::qword_ptr( asmjit::host::rsp, 1 * sizeof( uint64_t ) ) ); + _assembler.mov( asmjit::host::rdx, asmjit::host::qword_ptr( asmjit::host::rsp, 2 * sizeof( uint64_t ) ) ); + _assembler.mov( asmjit::host::r8, asmjit::host::qword_ptr( asmjit::host::rsp, 3 * sizeof( uint64_t ) ) ); + _assembler.mov( asmjit::host::r9, asmjit::host::qword_ptr( asmjit::host::rsp, 4 * sizeof( uint64_t ) ) ); + } + + _assembler.ret(); +} + +/// +/// Generate function call +/// +/// Function pointer +/// Function arguments +/// Ignored +void AsmHelper64::GenCall( const AsmFunctionPtr& pFN, const std::vector& args, eCalligConvention /*cc = CC_stdcall*/ ) +{ + // + // reserve stack size (0x28 - minimal size for 4 registers and return address) + // after call, stack must be aligned on 16 bytes boundary + // + size_t rsp_dif = (args.size() > 4) ? args.size() * sizeof( uint64_t ) : 0x28; + + // align on (16 bytes - sizeof(return address)) + rsp_dif = Align( rsp_dif, 0x10 ); + + if (_stackEnabled) + _assembler.sub( asmjit::host::rsp, rsp_dif + 8 ); + + // Set args + for (int32_t i = 0; i < static_cast(args.size()); i++) + PushArg( args[i], i ); + + if (pFN.type == AsmVariant::imm) + { + _assembler.mov( asmjit::host::rax, pFN.imm_val64 ); + _assembler.call( asmjit::host::rax ); + } + else if (pFN.type == AsmVariant::reg) + { + _assembler.call( pFN.reg_val ); + } + else + assert("Invalid function pointer type" && false ); + + if (_stackEnabled) + _assembler.add( asmjit::host::rsp, rsp_dif + 8 ); +} + +/// +/// Save rax value and terminate current thread +/// +/// NtTerminateThread address +/// Memory where rax value will be saved +void AsmHelper64::ExitThreadWithStatus( uint64_t pExitThread, uint64_t resultPtr ) +{ + if (resultPtr != 0) + { + _assembler.mov( asmjit::host::rdx, resultPtr ); + _assembler.mov( asmjit::host::dword_ptr( asmjit::host::rdx ), asmjit::host::rax ); + } + + _assembler.mov( asmjit::host::rdx, asmjit::host::rax ); + _assembler.mov( asmjit::host::rcx, 0 ); + _assembler.mov( asmjit::host::rax, pExitThread ); + _assembler.call( asmjit::host::rax ); +} + +/// +/// Save return value and signal thread return event +/// +/// NtSetEvent address +/// Result value memory location +/// Event memory location +/// Error code memory location +/// Return type +void AsmHelper64::SaveRetValAndSignalEvent( + uint64_t pSetEvent, + uint64_t ResultPtr, + uint64_t EventPtr, + uint64_t lastStatusPtr, + eReturnType rtype /*= rt_int32*/ + ) +{ + _assembler.mov( asmjit::host::rcx, ResultPtr ); + + // FPU value has been already saved + if (rtype == rt_int64 || rtype == rt_int32) + _assembler.mov( asmjit::host::dword_ptr( asmjit::host::rcx ), asmjit::host::rax ); + + // Save last NT status + _assembler.mov( asmjit::host::rdx, asmjit::host::dword_ptr_abs( 0x30 ).setSegment( asmjit::host::gs ) ); // TEB ptr + _assembler.add( asmjit::host::rdx, 0x598 + 0x197 * sizeof( uint64_t ) ); + _assembler.mov( asmjit::host::rdx, asmjit::host::dword_ptr( asmjit::host::rdx ) ); + _assembler.mov( asmjit::host::rax, lastStatusPtr ); + _assembler.mov( asmjit::host::dword_ptr( asmjit::host::rax ), asmjit::host::rdx ); + + // NtSetEvent(hEvent, NULL) + _assembler.mov( asmjit::host::rax, EventPtr ); + _assembler.mov( asmjit::host::rcx, asmjit::host::dword_ptr( asmjit::host::rax ) ); + _assembler.mov( asmjit::host::rdx, 0 ); + _assembler.mov( asmjit::host::rax, pSetEvent ); + _assembler.call( asmjit::host::rax ); +} + + +/// +/// Set stack reservation policy on call generation +/// +/// +/// If true - stack space will be reserved during each call generation +/// If false - no automatic stack reservation, user must allocate stack by hand +/// +void AsmHelper64::EnableX64CallStack( bool state ) +{ + _stackEnabled = state; +} + +/// +/// Push function argument +/// +/// Argument. +/// Push type(register or stack) +void AsmHelper64::PushArg( const AsmVariant& arg, int32_t index ) +{ + switch (arg.type) + { + + case AsmVariant::imm: + case AsmVariant::structRet: + PushArgp( arg.imm_val64, index ); + break; + + case AsmVariant::dataPtr: + case AsmVariant::dataStruct: + // Use new_imm_val when available. It's populated by remote call engine. + PushArgp( arg.new_imm_val != 0 ? arg.new_imm_val : arg.imm_val64, index ); + break; + + case AsmVariant::imm_double: + PushArgp( arg.getImm_double(), index, true ); + break; + + case AsmVariant::imm_float: + PushArgp( arg.getImm_float(), index, true ); + break; + + case AsmVariant::mem_ptr: + _assembler.lea( asmjit::host::rax, arg.mem_val ); + PushArgp( asmjit::host::rax, index ); + break; + + case AsmVariant::mem: + PushArgp( arg.mem_val, index ); + break; + + case AsmVariant::reg: + PushArgp( arg.reg_val, index ); + break; + + default: + assert( "Invalid argument type" && false ); + break; + } +} + +/// +/// Push function argument +/// +/// Argument +/// Argument index +/// true if argument is a floating point value +template +void AsmHelper64::PushArgp( const _Type& arg, int32_t index, bool fpu /*= false*/ ) +{ + static const asmjit::GpReg regs[] = { asmjit::host::rcx, asmjit::host::rdx, asmjit::host::r8, asmjit::host::r9 }; + static const asmjit::XmmReg xregs[] = { asmjit::host::xmm0, asmjit::host::xmm1, asmjit::host::xmm2, asmjit::host::xmm3 }; + + // Pass via register + if (index < 4) + { + // Use XMM register + if (fpu) + { + _assembler.mov( asmjit::host::rax, arg ); + _assembler.movq( xregs[index], asmjit::host::rax ); + } + else + _assembler.mov( regs[index], arg ); + } + // Pass on stack + else + { + _assembler.mov( asmjit::host::rax, arg ); + _assembler.mov( asmjit::host::qword_ptr( asmjit::host::rsp, index * sizeof( uint64_t ) ), asmjit::host::rax ); + } +} + +} diff --git a/third/Blackbone/src/BlackBone/Asm/AsmHelper64.h b/third/Blackbone/src/BlackBone/Asm/AsmHelper64.h new file mode 100644 index 0000000000000000000000000000000000000000..cd8b73598f83b1d5d4b42f1b8040052a36373c36 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Asm/AsmHelper64.h @@ -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 ); + + /// + /// Generate function prologue code + /// + /// true if execution must be swithed to x64 mode + virtual void GenPrologue( bool switchMode = false ); + + /// + /// Generate function epilogue code + /// + /// true if execution must be swithed to x86 mode + /// Stack change value + virtual void GenEpilogue( bool switchMode = false, int retSize = -1 ); + + /// + /// Generate function call + /// + /// Function pointer + /// Function arguments + /// Ignored + virtual void GenCall( const AsmFunctionPtr& pFN, const std::vector& args, eCalligConvention cc = cc_stdcall ); + + /// + /// Save rax value and terminate current thread + /// + /// NtTerminateThread address + /// Memory where rax value will be saved + virtual void ExitThreadWithStatus( uint64_t pExitThread, uint64_t resultPtr ); + + /// + /// Save return value and signal thread return event + /// + /// NtSetEvent address + /// Result value memory location + /// Event memory location + /// Error code memory location + /// Return type + virtual void SaveRetValAndSignalEvent( + uint64_t pSetEvent, + uint64_t ResultPtr, + uint64_t EventPtr, + uint64_t lastStatusPtr, + eReturnType rtype = rt_int32 + ); + + /// + /// Set stack reservation policy on call generation + /// + /// + /// If true - stack space will be reserved during each call generation + /// If false - no automatic stack reservation, user must allocate stack by hand + /// + virtual void EnableX64CallStack( bool state ); + +private: + AsmHelper64( const AsmHelper64& ) = delete; + AsmHelper64& operator = (const AsmHelper64&) = delete; + + /// + /// Push function argument + /// + /// Argument. + /// Push type(register or stack) + void PushArg( const AsmVariant& arg, int32_t index ); + + /// + /// Push function argument + /// + /// Argument + /// Argument index + /// true if argument is a floating point value + template + void PushArgp( const _Type& arg, int32_t index, bool fpu = false ); + +private: + bool _stackEnabled; // if true - GenCall will allocate shadow stack space +}; + +} diff --git a/third/Blackbone/src/BlackBone/Asm/AsmStack.hpp b/third/Blackbone/src/BlackBone/Asm/AsmStack.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d0e2dd1c356398acb3712bdca1587a8b46f30322 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Asm/AsmStack.hpp @@ -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 + +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 ) ) + { + } + + /// + /// Allocate stack variable + /// + /// Variable size + /// Variable memory object + BLACKBONE_API asmjit::Mem AllocVar( int32_t size ) + { + bool x64 = _pAsm->getArch() == asmjit::kArch::kArchX64; + + // Align on word length + size = static_cast(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; + } + + /// + /// Allocate array of stack variables + /// + /// Output array + /// Array elements count. + /// Element size. + /// true on success + 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; + } + + /// + /// Get total size of all stack variables + /// + /// + 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) ); + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Asm/AsmVariant.hpp b/third/Blackbone/src/BlackBone/Asm/AsmVariant.hpp new file mode 100644 index 0000000000000000000000000000000000000000..118edb52f1730838eefe1dd9b70d1882331259a8 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Asm/AsmVariant.hpp @@ -0,0 +1,227 @@ +#pragma once + + +#include "../Config.h" +#pragma warning(disable : 4100) +#include "../../3rd_party/AsmJit/AsmJit.h" +#pragma warning(default : 4100) + +#include + + +namespace blackbone +{ +/// +/// General purpose assembly variable +/// +struct AsmVariant +{ + template + using cleanup_t = std::remove_cv_t>; + + template + static constexpr bool is_string_ptr = (std::is_pointer_v && std::is_same_v, S>); + + template + static constexpr bool is_number = (std::is_integral_v || std::is_enum_v); + + template + static constexpr bool is_void_ptr = (std::is_pointer_v && std::is_void_v>); + + 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 + AsmVariant( T&& arg ) + { + using RAW_T = std::decay_t; + constexpr size_t argSize = sizeof( RAW_T ); + + // bool, short, int, unsigned long long, etc. + if constexpr (is_number) + { + set( imm, argSize, static_cast(arg) ); + } + // Array of elements + else if constexpr(std::is_array_v>) + { + set( dataPtr, sizeof( arg ), reinterpret_cast(arg) ); + } + // char*, const char*, etc. + else if constexpr(is_string_ptr) + { + set( dataPtr, strlen( arg ) + 1, reinterpret_cast(arg) ); + } + // wchar_t*, const wchar_t*, etc. + else if constexpr(is_string_ptr) + { + set( dataPtr, (wcslen( arg ) + 1) * sizeof( wchar_t ), reinterpret_cast(arg) ); + } + // void*, const void*, etc. + else if constexpr(is_void_ptr) + { + set( imm, argSize, reinterpret_cast(arg) ); + } + // dirty hack to threat HWND as a simple pointer + else if constexpr(std::is_same_v) + { + set( imm, argSize, reinterpret_cast(arg) ); + } + // Function pointer + else if constexpr(std::is_function_v>) + { + set( imm, argSize, reinterpret_cast(arg) ); + } + // Arbitrary pointer + else if constexpr(std::is_pointer_v) + { + set( dataPtr, sizeof( cleanup_t ), reinterpret_cast(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(buf.data()) ); + memcpy( buf.data(), &arg, argSize ); + } + } + + // Custom size pointer + template + explicit AsmVariant( T* ptr, size_t size_ ) + : type( dataPtr ) + , size( size_ ) + , imm_val64( reinterpret_cast(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(_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(&imm_float_val)); } + BLACKBONE_API inline uint64_t getImm_double() const { return *(reinterpret_cast(&imm_double_val)); } + + /// + /// Check if argument can be passed in x86 register + /// + /// true if can + 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 buf; // Value buffer +}; + +/// +/// Remote function pointer +/// +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(ptr) ) { } + + AsmFunctionPtr( const void* ptr ) + : AsmVariant( reinterpret_cast(ptr) ) { } + + AsmFunctionPtr( asmjit::GpReg reg_ ) + : AsmVariant( reg_ ) { } +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Asm/IAsmHelper.h b/third/Blackbone/src/BlackBone/Asm/IAsmHelper.h new file mode 100644 index 0000000000000000000000000000000000000000..1edf40df3cbe70377aa8eaaa06bc7659ca855b80 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Asm/IAsmHelper.h @@ -0,0 +1,101 @@ +#pragma once + +#include "AsmVariant.hpp" +#include "AsmStack.hpp" +#include "../Include/Macro.h" + +#include +#include + +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 + }; + + + /// + /// Assembly generation helper + /// + 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& 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; + + /// + /// Switch processor into WOW64 emulation mode + /// + 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 + } + + /// + /// Switch processor into x64 mode (long mode) + /// + 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; + }; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Asm/LDasm.c b/third/Blackbone/src/BlackBone/Asm/LDasm.c new file mode 100644 index 0000000000000000000000000000000000000000..f9c288cb7fb02d17d4f4245d834fd994537e6081 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Asm/LDasm.c @@ -0,0 +1,823 @@ +/* +* +* Copyright (c) 2009-2011 +* vol4ok PGP KEY ID: 26EC143CCDC61C9D +* + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +*/ + +#include "LDasm.h" + +/* + Instruction format: + + | prefix | REX | opcode | modR/M | SIB | disp8/16/32 | imm8/16/32/64 | + + */ + +#define OP_NONE 0x00 +#define OP_INVALID 0x80 + +#define OP_DATA_I8 0x01 +#define OP_DATA_I16 0x02 +#define OP_DATA_I16_I32 0x04 +#define OP_DATA_I16_I32_I64 0x08 +#define OP_EXTENDED 0x10 +#define OP_RELATIVE 0x20 +#define OP_MODRM 0x40 +#define OP_PREFIX 0x80 + + +static unsigned char flags_table[256] = +{ + /* 00 */ OP_MODRM, + /* 01 */ OP_MODRM, + /* 02 */ OP_MODRM, + /* 03 */ OP_MODRM, + /* 04 */ OP_DATA_I8, + /* 05 */ OP_DATA_I16_I32, + /* 06 */ OP_NONE, + /* 07 */ OP_NONE, + /* 08 */ OP_MODRM, + /* 09 */ OP_MODRM, + /* 0A */ OP_MODRM, + /* 0B */ OP_MODRM, + /* 0C */ OP_DATA_I8, + /* 0D */ OP_DATA_I16_I32, + /* 0E */ OP_NONE, + /* 0F */ OP_NONE, + + /* 10 */ OP_MODRM, + /* 11 */ OP_MODRM, + /* 12 */ OP_MODRM, + /* 13 */ OP_MODRM, + /* 14 */ OP_DATA_I8, + /* 15 */ OP_DATA_I16_I32, + /* 16 */ OP_NONE, + /* 17 */ OP_NONE, + /* 18 */ OP_MODRM, + /* 19 */ OP_MODRM, + /* 1A */ OP_MODRM, + /* 1B */ OP_MODRM, + /* 1C */ OP_DATA_I8, + /* 1D */ OP_DATA_I16_I32, + /* 1E */ OP_NONE, + /* 1F */ OP_NONE, + + /* 20 */ OP_MODRM, + /* 21 */ OP_MODRM, + /* 22 */ OP_MODRM, + /* 23 */ OP_MODRM, + /* 24 */ OP_DATA_I8, + /* 25 */ OP_DATA_I16_I32, + /* 26 */ OP_PREFIX, + /* 27 */ OP_NONE, + /* 28 */ OP_MODRM, + /* 29 */ OP_MODRM, + /* 2A */ OP_MODRM, + /* 2B */ OP_MODRM, + /* 2C */ OP_DATA_I8, + /* 2D */ OP_DATA_I16_I32, + /* 2E */ OP_PREFIX, + /* 2F */ OP_NONE, + + /* 30 */ OP_MODRM, + /* 31 */ OP_MODRM, + /* 32 */ OP_MODRM, + /* 33 */ OP_MODRM, + /* 34 */ OP_DATA_I8, + /* 35 */ OP_DATA_I16_I32, + /* 36 */ OP_PREFIX, + /* 37 */ OP_NONE, + /* 38 */ OP_MODRM, + /* 39 */ OP_MODRM, + /* 3A */ OP_MODRM, + /* 3B */ OP_MODRM, + /* 3C */ OP_DATA_I8, + /* 3D */ OP_DATA_I16_I32, + /* 3E */ OP_PREFIX, + /* 3F */ OP_NONE, + + /* 40 */ OP_NONE, + /* 41 */ OP_NONE, + /* 42 */ OP_NONE, + /* 43 */ OP_NONE, + /* 44 */ OP_NONE, + /* 45 */ OP_NONE, + /* 46 */ OP_NONE, + /* 47 */ OP_NONE, + /* 48 */ OP_NONE, + /* 49 */ OP_NONE, + /* 4A */ OP_NONE, + /* 4B */ OP_NONE, + /* 4C */ OP_NONE, + /* 4D */ OP_NONE, + /* 4E */ OP_NONE, + /* 4F */ OP_NONE, + + /* 50 */ OP_NONE, + /* 51 */ OP_NONE, + /* 52 */ OP_NONE, + /* 53 */ OP_NONE, + /* 54 */ OP_NONE, + /* 55 */ OP_NONE, + /* 56 */ OP_NONE, + /* 57 */ OP_NONE, + /* 58 */ OP_NONE, + /* 59 */ OP_NONE, + /* 5A */ OP_NONE, + /* 5B */ OP_NONE, + /* 5C */ OP_NONE, + /* 5D */ OP_NONE, + /* 5E */ OP_NONE, + /* 5F */ OP_NONE, + /* 60 */ OP_NONE, + + /* 61 */ OP_NONE, + /* 62 */ OP_MODRM, + /* 63 */ OP_MODRM, + /* 64 */ OP_PREFIX, + /* 65 */ OP_PREFIX, + /* 66 */ OP_PREFIX, + /* 67 */ OP_PREFIX, + /* 68 */ OP_DATA_I16_I32, + /* 69 */ OP_MODRM | OP_DATA_I16_I32, + /* 6A */ OP_DATA_I8, + /* 6B */ OP_MODRM | OP_DATA_I8, + /* 6C */ OP_NONE, + /* 6D */ OP_NONE, + /* 6E */ OP_NONE, + /* 6F */ OP_NONE, + + /* 70 */ OP_RELATIVE | OP_DATA_I8, + /* 71 */ OP_RELATIVE | OP_DATA_I8, + /* 72 */ OP_RELATIVE | OP_DATA_I8, + /* 73 */ OP_RELATIVE | OP_DATA_I8, + /* 74 */ OP_RELATIVE | OP_DATA_I8, + /* 75 */ OP_RELATIVE | OP_DATA_I8, + /* 76 */ OP_RELATIVE | OP_DATA_I8, + /* 77 */ OP_RELATIVE | OP_DATA_I8, + /* 78 */ OP_RELATIVE | OP_DATA_I8, + /* 79 */ OP_RELATIVE | OP_DATA_I8, + /* 7A */ OP_RELATIVE | OP_DATA_I8, + /* 7B */ OP_RELATIVE | OP_DATA_I8, + /* 7C */ OP_RELATIVE | OP_DATA_I8, + /* 7D */ OP_RELATIVE | OP_DATA_I8, + /* 7E */ OP_RELATIVE | OP_DATA_I8, + /* 7F */ OP_RELATIVE | OP_DATA_I8, + + /* 80 */ OP_MODRM | OP_DATA_I8, + /* 81 */ OP_MODRM | OP_DATA_I16_I32, + /* 82 */ OP_MODRM | OP_DATA_I8, + /* 83 */ OP_MODRM | OP_DATA_I8, + /* 84 */ OP_MODRM, + /* 85 */ OP_MODRM, + /* 86 */ OP_MODRM, + /* 87 */ OP_MODRM, + /* 88 */ OP_MODRM, + /* 89 */ OP_MODRM, + /* 8A */ OP_MODRM, + /* 8B */ OP_MODRM, + /* 8C */ OP_MODRM, + /* 8D */ OP_MODRM, + /* 8E */ OP_MODRM, + /* 8F */ OP_MODRM, + + /* 90 */ OP_NONE, + /* 91 */ OP_NONE, + /* 92 */ OP_NONE, + /* 93 */ OP_NONE, + /* 94 */ OP_NONE, + /* 95 */ OP_NONE, + /* 96 */ OP_NONE, + /* 97 */ OP_NONE, + /* 98 */ OP_NONE, + /* 99 */ OP_NONE, + /* 9A */ OP_DATA_I16 | OP_DATA_I16_I32, + /* 9B */ OP_NONE, + /* 9C */ OP_NONE, + /* 9D */ OP_NONE, + /* 9E */ OP_NONE, + /* 9F */ OP_NONE, + + /* A0 */ OP_DATA_I8, + /* A1 */ OP_DATA_I16_I32_I64, + /* A2 */ OP_DATA_I8, + /* A3 */ OP_DATA_I16_I32_I64, + /* A4 */ OP_NONE, + /* A5 */ OP_NONE, + /* A6 */ OP_NONE, + /* A7 */ OP_NONE, + /* A8 */ OP_DATA_I8, + /* A9 */ OP_DATA_I16_I32, + /* AA */ OP_NONE, + /* AB */ OP_NONE, + /* AC */ OP_NONE, + /* AD */ OP_NONE, + /* AE */ OP_NONE, + /* AF */ OP_NONE, + + /* B0 */ OP_DATA_I8, + /* B1 */ OP_DATA_I8, + /* B2 */ OP_DATA_I8, + /* B3 */ OP_DATA_I8, + /* B4 */ OP_DATA_I8, + /* B5 */ OP_DATA_I8, + /* B6 */ OP_DATA_I8, + /* B7 */ OP_DATA_I8, + /* B8 */ OP_DATA_I16_I32_I64, + /* B9 */ OP_DATA_I16_I32_I64, + /* BA */ OP_DATA_I16_I32_I64, + /* BB */ OP_DATA_I16_I32_I64, + /* BC */ OP_DATA_I16_I32_I64, + /* BD */ OP_DATA_I16_I32_I64, + /* BE */ OP_DATA_I16_I32_I64, + /* BF */ OP_DATA_I16_I32_I64, + + /* C0 */ OP_MODRM | OP_DATA_I8, + /* C1 */ OP_MODRM | OP_DATA_I8, + /* C2 */ OP_DATA_I16, + /* C3 */ OP_NONE, + /* C4 */ OP_MODRM, + /* C5 */ OP_MODRM, + /* C6 */ OP_MODRM | OP_DATA_I8, + /* C7 */ OP_MODRM | OP_DATA_I16_I32, + /* C8 */ OP_DATA_I8 | OP_DATA_I16, + /* C9 */ OP_NONE, + /* CA */ OP_DATA_I16, + /* CB */ OP_NONE, + /* CC */ OP_NONE, + /* CD */ OP_DATA_I8, + /* CE */ OP_NONE, + /* CF */ OP_NONE, + + /* D0 */ OP_MODRM, + /* D1 */ OP_MODRM, + /* D2 */ OP_MODRM, + /* D3 */ OP_MODRM, + /* D4 */ OP_DATA_I8, + /* D5 */ OP_DATA_I8, + /* D6 */ OP_NONE, + /* D7 */ OP_NONE, + /* D8 */ OP_MODRM, + /* D9 */ OP_MODRM, + /* DA */ OP_MODRM, + /* DB */ OP_MODRM, + /* DC */ OP_MODRM, + /* DD */ OP_MODRM, + /* DE */ OP_MODRM, + /* DF */ OP_MODRM, + + /* E0 */ OP_RELATIVE | OP_DATA_I8, + /* E1 */ OP_RELATIVE | OP_DATA_I8, + /* E2 */ OP_RELATIVE | OP_DATA_I8, + /* E3 */ OP_RELATIVE | OP_DATA_I8, + /* E4 */ OP_DATA_I8, + /* E5 */ OP_DATA_I8, + /* E6 */ OP_DATA_I8, + /* E7 */ OP_DATA_I8, + /* E8 */ OP_RELATIVE | OP_DATA_I16_I32, + /* E9 */ OP_RELATIVE | OP_DATA_I16_I32, + /* EA */ OP_DATA_I16 | OP_DATA_I16_I32, + /* EB */ OP_RELATIVE | OP_DATA_I8, + /* EC */ OP_NONE, + /* ED */ OP_NONE, + /* EE */ OP_NONE, + /* EF */ OP_NONE, + + /* F0 */ OP_PREFIX, + /* F1 */ OP_NONE, + /* F2 */ OP_PREFIX, + /* F3 */ OP_PREFIX, + /* F4 */ OP_NONE, + /* F5 */ OP_NONE, + /* F6 */ OP_MODRM, + /* F7 */ OP_MODRM, + /* F8 */ OP_NONE, + /* F9 */ OP_NONE, + /* FA */ OP_NONE, + /* FB */ OP_NONE, + /* FC */ OP_NONE, + /* FD */ OP_NONE, + /* FE */ OP_MODRM, + /* FF */ OP_MODRM +}; + +static unsigned char flags_table_ex[256] = +{ + /* 0F00 */ OP_MODRM, + /* 0F01 */ OP_MODRM, + /* 0F02 */ OP_MODRM, + /* 0F03 */ OP_MODRM, + /* 0F04 */ OP_INVALID, + /* 0F05 */ OP_NONE, + /* 0F06 */ OP_NONE, + /* 0F07 */ OP_NONE, + /* 0F08 */ OP_NONE, + /* 0F09 */ OP_NONE, + /* 0F0A */ OP_INVALID, + /* 0F0B */ OP_NONE, + /* 0F0C */ OP_INVALID, + /* 0F0D */ OP_MODRM, + /* 0F0E */ OP_INVALID, + /* 0F0F */ OP_MODRM | OP_DATA_I8, //3Dnow + + /* 0F10 */ OP_MODRM, + /* 0F11 */ OP_MODRM, + /* 0F12 */ OP_MODRM, + /* 0F13 */ OP_MODRM, + /* 0F14 */ OP_MODRM, + /* 0F15 */ OP_MODRM, + /* 0F16 */ OP_MODRM, + /* 0F17 */ OP_MODRM, + /* 0F18 */ OP_MODRM, + /* 0F19 */ OP_INVALID, + /* 0F1A */ OP_INVALID, + /* 0F1B */ OP_INVALID, + /* 0F1C */ OP_INVALID, + /* 0F1D */ OP_INVALID, + /* 0F1E */ OP_INVALID, + /* 0F1F */ OP_NONE, + + /* 0F20 */ OP_MODRM, + /* 0F21 */ OP_MODRM, + /* 0F22 */ OP_MODRM, + /* 0F23 */ OP_MODRM, + /* 0F24 */ OP_MODRM | OP_EXTENDED, //SSE5 + /* 0F25 */ OP_INVALID, + /* 0F26 */ OP_MODRM, + /* 0F27 */ OP_INVALID, + /* 0F28 */ OP_MODRM, + /* 0F29 */ OP_MODRM, + /* 0F2A */ OP_MODRM, + /* 0F2B */ OP_MODRM, + /* 0F2C */ OP_MODRM, + /* 0F2D */ OP_MODRM, + /* 0F2E */ OP_MODRM, + /* 0F2F */ OP_MODRM, + + /* 0F30 */ OP_NONE, + /* 0F31 */ OP_NONE, + /* 0F32 */ OP_NONE, + /* 0F33 */ OP_NONE, + /* 0F34 */ OP_NONE, + /* 0F35 */ OP_NONE, + /* 0F36 */ OP_INVALID, + /* 0F37 */ OP_NONE, + /* 0F38 */ OP_MODRM | OP_EXTENDED, + /* 0F39 */ OP_INVALID, + /* 0F3A */ OP_MODRM | OP_EXTENDED | OP_DATA_I8, + /* 0F3B */ OP_INVALID, + /* 0F3C */ OP_INVALID, + /* 0F3D */ OP_INVALID, + /* 0F3E */ OP_INVALID, + /* 0F3F */ OP_INVALID, + + /* 0F40 */ OP_MODRM, + /* 0F41 */ OP_MODRM, + /* 0F42 */ OP_MODRM, + /* 0F43 */ OP_MODRM, + /* 0F44 */ OP_MODRM, + /* 0F45 */ OP_MODRM, + /* 0F46 */ OP_MODRM, + /* 0F47 */ OP_MODRM, + /* 0F48 */ OP_MODRM, + /* 0F49 */ OP_MODRM, + /* 0F4A */ OP_MODRM, + /* 0F4B */ OP_MODRM, + /* 0F4C */ OP_MODRM, + /* 0F4D */ OP_MODRM, + /* 0F4E */ OP_MODRM, + /* 0F4F */ OP_MODRM, + + /* 0F50 */ OP_MODRM, + /* 0F51 */ OP_MODRM, + /* 0F52 */ OP_MODRM, + /* 0F53 */ OP_MODRM, + /* 0F54 */ OP_MODRM, + /* 0F55 */ OP_MODRM, + /* 0F56 */ OP_MODRM, + /* 0F57 */ OP_MODRM, + /* 0F58 */ OP_MODRM, + /* 0F59 */ OP_MODRM, + /* 0F5A */ OP_MODRM, + /* 0F5B */ OP_MODRM, + /* 0F5C */ OP_MODRM, + /* 0F5D */ OP_MODRM, + /* 0F5E */ OP_MODRM, + /* 0F5F */ OP_MODRM, + + /* 0F60 */ OP_MODRM, + /* 0F61 */ OP_MODRM, + /* 0F62 */ OP_MODRM, + /* 0F63 */ OP_MODRM, + /* 0F64 */ OP_MODRM, + /* 0F65 */ OP_MODRM, + /* 0F66 */ OP_MODRM, + /* 0F67 */ OP_MODRM, + /* 0F68 */ OP_MODRM, + /* 0F69 */ OP_MODRM, + /* 0F6A */ OP_MODRM, + /* 0F6B */ OP_MODRM, + /* 0F6C */ OP_MODRM, + /* 0F6D */ OP_MODRM, + /* 0F6E */ OP_MODRM, + /* 0F6F */ OP_MODRM, + + /* 0F70 */ OP_MODRM | OP_DATA_I8, + /* 0F71 */ OP_MODRM | OP_DATA_I8, + /* 0F72 */ OP_MODRM | OP_DATA_I8, + /* 0F73 */ OP_MODRM | OP_DATA_I8, + /* 0F74 */ OP_MODRM, + /* 0F75 */ OP_MODRM, + /* 0F76 */ OP_MODRM, + /* 0F77 */ OP_NONE, + /* 0F78 */ OP_MODRM, + /* 0F79 */ OP_MODRM, + /* 0F7A */ OP_INVALID, + /* 0F7B */ OP_INVALID, + /* 0F7C */ OP_MODRM, + /* 0F7D */ OP_MODRM, + /* 0F7E */ OP_MODRM, + /* 0F7F */ OP_MODRM, + + /* 0F80 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F81 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F82 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F83 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F84 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F85 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F86 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F87 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F88 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F89 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8A */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8B */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8C */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8D */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8E */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8F */ OP_RELATIVE | OP_DATA_I16_I32, + + /* 0F90 */ OP_MODRM, + /* 0F91 */ OP_MODRM, + /* 0F92 */ OP_MODRM, + /* 0F93 */ OP_MODRM, + /* 0F94 */ OP_MODRM, + /* 0F95 */ OP_MODRM, + /* 0F96 */ OP_MODRM, + /* 0F97 */ OP_MODRM, + /* 0F98 */ OP_MODRM, + /* 0F99 */ OP_MODRM, + /* 0F9A */ OP_MODRM, + /* 0F9B */ OP_MODRM, + /* 0F9C */ OP_MODRM, + /* 0F9D */ OP_MODRM, + /* 0F9E */ OP_MODRM, + /* 0F9F */ OP_MODRM, + + /* 0FA0 */ OP_NONE, + /* 0FA1 */ OP_NONE, + /* 0FA2 */ OP_NONE, + /* 0FA3 */ OP_MODRM, + /* 0FA4 */ OP_MODRM | OP_DATA_I8, + /* 0FA5 */ OP_MODRM, + /* 0FA6 */ OP_INVALID, + /* 0FA7 */ OP_INVALID, + /* 0FA8 */ OP_NONE, + /* 0FA9 */ OP_NONE, + /* 0FAA */ OP_NONE, + /* 0FAB */ OP_MODRM, + /* 0FAC */ OP_MODRM | OP_DATA_I8, + /* 0FAD */ OP_MODRM, + /* 0FAE */ OP_MODRM, + /* 0FAF */ OP_MODRM, + + /* 0FB0 */ OP_MODRM, + /* 0FB1 */ OP_MODRM, + /* 0FB2 */ OP_MODRM, + /* 0FB3 */ OP_MODRM, + /* 0FB4 */ OP_MODRM, + /* 0FB5 */ OP_MODRM, + /* 0FB6 */ OP_MODRM, + /* 0FB7 */ OP_MODRM, + /* 0FB8 */ OP_MODRM, + /* 0FB9 */ OP_MODRM, + /* 0FBA */ OP_MODRM | OP_DATA_I8, + /* 0FBB */ OP_MODRM, + /* 0FBC */ OP_MODRM, + /* 0FBD */ OP_MODRM, + /* 0FBE */ OP_MODRM, + /* 0FBF */ OP_MODRM, + + /* 0FC0 */ OP_MODRM, + /* 0FC1 */ OP_MODRM, + /* 0FC2 */ OP_MODRM | OP_DATA_I8, + /* 0FC3 */ OP_MODRM, + /* 0FC4 */ OP_MODRM | OP_DATA_I8, + /* 0FC5 */ OP_MODRM | OP_DATA_I8, + /* 0FC6 */ OP_MODRM | OP_DATA_I8, + /* 0FC7 */ OP_MODRM, + /* 0FC8 */ OP_NONE, + /* 0FC9 */ OP_NONE, + /* 0FCA */ OP_NONE, + /* 0FCB */ OP_NONE, + /* 0FCC */ OP_NONE, + /* 0FCD */ OP_NONE, + /* 0FCE */ OP_NONE, + /* 0FCF */ OP_NONE, + + /* 0FD0 */ OP_MODRM, + /* 0FD1 */ OP_MODRM, + /* 0FD2 */ OP_MODRM, + /* 0FD3 */ OP_MODRM, + /* 0FD4 */ OP_MODRM, + /* 0FD5 */ OP_MODRM, + /* 0FD6 */ OP_MODRM, + /* 0FD7 */ OP_MODRM, + /* 0FD8 */ OP_MODRM, + /* 0FD9 */ OP_MODRM, + /* 0FDA */ OP_MODRM, + /* 0FDB */ OP_MODRM, + /* 0FDC */ OP_MODRM, + /* 0FDD */ OP_MODRM, + /* 0FDE */ OP_MODRM, + /* 0FDF */ OP_MODRM, + + /* 0FE0 */ OP_MODRM, + /* 0FE1 */ OP_MODRM, + /* 0FE2 */ OP_MODRM, + /* 0FE3 */ OP_MODRM, + /* 0FE4 */ OP_MODRM, + /* 0FE5 */ OP_MODRM, + /* 0FE6 */ OP_MODRM, + /* 0FE7 */ OP_MODRM, + /* 0FE8 */ OP_MODRM, + /* 0FE9 */ OP_MODRM, + /* 0FEA */ OP_MODRM, + /* 0FEB */ OP_MODRM, + /* 0FEC */ OP_MODRM, + /* 0FED */ OP_MODRM, + /* 0FEE */ OP_MODRM, + /* 0FEF */ OP_MODRM, + + /* 0FF0 */ OP_MODRM, + /* 0FF1 */ OP_MODRM, + /* 0FF2 */ OP_MODRM, + /* 0FF3 */ OP_MODRM, + /* 0FF4 */ OP_MODRM, + /* 0FF5 */ OP_MODRM, + /* 0FF6 */ OP_MODRM, + /* 0FF7 */ OP_MODRM, + /* 0FF8 */ OP_MODRM, + /* 0FF9 */ OP_MODRM, + /* 0FFA */ OP_MODRM, + /* 0FFB */ OP_MODRM, + /* 0FFC */ OP_MODRM, + /* 0FFD */ OP_MODRM, + /* 0FFE */ OP_MODRM, + /* 0FFF */ OP_INVALID, +}; + +unsigned char cflags( uint8_t op ) +{ + return flags_table[op]; +} + + +unsigned char cflags_ex( uint8_t op ) +{ + return flags_table_ex[op]; +} + +unsigned int __fastcall ldasm( void *code, ldasm_data *ld, uint32_t is64 ) +/* + Description: + Disassemble one instruction + + Arguments: + code - pointer to the code for disassemble + ld - pointer to structure ldasm_data + is64 - set this flag for 64-bit code, and clear for 32-bit + + Return: + length of instruction + */ +{ + uint8_t *p = (uint8_t*)code; + uint8_t s,op,f; + uint8_t rexw,pr_66,pr_67; + + s = rexw = pr_66 = pr_67 = 0; + + /* dummy check */ + if (!code || !ld) + return 0; + + /* init output data */ + memset( ld, 0, sizeof(ldasm_data) ); + + /* phase 1: parse prefixies */ + while (cflags(*p) & OP_PREFIX) { + if (*p == 0x66) + pr_66 = 1; + if (*p == 0x67) + pr_67 = 1; + p++; s++; + ld->flags |= F_PREFIX; + if (s == 15) { + ld->flags |= F_INVALID; + return s; + } + } + + /* parse REX prefix */ + if (is64 && *p >> 4 == 4) { + ld->rex = *p; + rexw = (ld->rex >> 3) & 1; + ld->flags |= F_REX; + p++; s++; + } + + /* can be only one REX prefix */ + if (is64 && *p >> 4 == 4) { + ld->flags |= F_INVALID; + s++; + return s; + } + + /* phase 2: parse opcode */ + ld->opcd_offset = (uint8_t)(p - (uint8_t*)code); + ld->opcd_size = 1; + op = *p++; s++; + + /* is 2 byte opcode? */ + if (op == 0x0F) { + op = *p++; s++; + ld->opcd_size++; + f = cflags_ex(op); + if (f & OP_INVALID){ + ld->flags |= F_INVALID; + return s; + } + /* for SSE instructions */ + if (f & OP_EXTENDED) { + op = *p++; s++; + ld->opcd_size++; + } + } else { + f = cflags(op); + /* pr_66 = pr_67 for opcodes A0-A3 */ + if (op >= 0xA0 && op <= 0xA3) + pr_66 = pr_67; + } + + /* phase 3: parse ModR/M, SIB and DISP */ + if (f & OP_MODRM) { + uint8_t mod = (*p >> 6); + uint8_t ro = (*p & 0x38) >> 3; + uint8_t rm = (*p & 7); + + ld->modrm = *p++; s++; + ld->flags |= F_MODRM; + + /* in F6,F7 opcodes immediate data present if R/O == 0 */ + if (op == 0xF6 && (ro == 0 || ro == 1)) + f |= OP_DATA_I8; + if (op == 0xF7 && (ro == 0 || ro == 1)) + f |= OP_DATA_I16_I32_I64; + + /* is SIB byte exist? */ + if (mod != 3 && rm == 4 && !(!is64 && pr_67)) { + ld->sib = *p++; s++; + ld->flags |= F_SIB; + + /* if base == 5 and mod == 0 */ + if ((ld->sib & 7) == 5 && mod == 0) { + ld->disp_size = 4; + } + } + + switch (mod) { + case 0: + if (is64) { + if (rm == 5) { + ld->disp_size = 4; + if (is64) + ld->flags |= F_RELATIVE; + } + } else if (pr_67) { + if (rm == 6) + ld->disp_size = 2; + } else { + if (rm == 5) + ld->disp_size = 4; + } + break; + case 1: + ld->disp_size = 1; + break; + case 2: + if (is64) + ld->disp_size = 4; + else if (pr_67) + ld->disp_size = 2; + else + ld->disp_size = 4; + break; + } + + if (ld->disp_size) { + ld->disp_offset = (uint8_t)(p - (uint8_t *)code); + p += ld->disp_size; + s += ld->disp_size; + ld->flags |= F_DISP; + } + } + + /* phase 4: parse immediate data */ + if (rexw && f & OP_DATA_I16_I32_I64) + ld->imm_size = 8; + else if (f & OP_DATA_I16_I32 || f & OP_DATA_I16_I32_I64) + ld->imm_size = 4 - (pr_66 << 1); + + /* if exist, add OP_DATA_I16 and OP_DATA_I8 size */ + ld->imm_size += f & 3; + + if (ld->imm_size) { + s += ld->imm_size; + ld->imm_offset = (uint8_t)(p - (uint8_t *)code); + ld->flags |= F_IMM; + if (f & OP_RELATIVE) + ld->flags |= F_RELATIVE; + } + + /* instruction is too long */ + if (s > 15) + ld->flags |= F_INVALID; + + return s; +} + +// Get function size +unsigned long __fastcall SizeOfProc( void *Proc ) +{ + uint32_t Length; + uint8_t* pOpcode; + uint32_t Result = 0; + ldasm_data data = {0}; + + do + { + Length = ldasm((uint8_t*)Proc, &data, is_x64); + + pOpcode = (uint8_t*)Proc + data.opcd_offset; + Result += Length; + + if ((Length == 1) && (*pOpcode == 0xCC)) + break; + + /*if ((Length == 1) && (*pOpcode == 0xC3)) + break; + + if ((Length == 3) && (*pOpcode == 0xC2)) + break;*/ + + Proc = (void*)((size_t)Proc + Length); + + } while (Length); + + return Result; +} + +// If function address is jmp - get jmp destination +void* __fastcall ResolveJmp( void *Proc ) +{ + uint32_t Length; + uint8_t* pOpcode; + ldasm_data data = { 0 }; + + Length = ldasm( (uint8_t*)Proc, &data, is_x64 ); + pOpcode = (uint8_t*)Proc + data.opcd_offset; + + // Recursive unwind + if (Length == 5 && data.opcd_size == 1 && *pOpcode == 0xE9) + { + uint32_t delta = *(int32_t*)((uintptr_t)Proc + data.opcd_size); + return ResolveJmp( (void*)((uintptr_t)Proc + delta + Length) ); + } + + return Proc; +} diff --git a/third/Blackbone/src/BlackBone/Asm/LDasm.h b/third/Blackbone/src/BlackBone/Asm/LDasm.h new file mode 100644 index 0000000000000000000000000000000000000000..72ad4cefff7c4d3162d7e5baeb36a064019af467 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Asm/LDasm.h @@ -0,0 +1,50 @@ +#ifndef _LDASM_ +#define _LDASM_ + +#include "../Config.h" +#include +#include + +#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_ \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/BlackBone.vcxproj b/third/Blackbone/src/BlackBone/BlackBone.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..40e23e907d94d570c8e07e51acc874e77c93ef52 --- /dev/null +++ b/third/Blackbone/src/BlackBone/BlackBone.vcxproj @@ -0,0 +1,866 @@ + + + + + Debug(DLL) + Win32 + + + Debug(DLL) + x64 + + + Debug(XP) + Win32 + + + Debug(XP) + x64 + + + Debug + Win32 + + + Debug + x64 + + + Release(DLL) + Win32 + + + Release(DLL) + x64 + + + Release(XP) + Win32 + + + Release(XP) + x64 + + + Release + Win32 + + + Release + x64 + + + + {A2C53563-46F5-4D87-903F-3F1F2FDB2DEB} + Win32Proj + Xantos + BlackBone + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + true + v141_xp + Unicode + + + DynamicLibrary + true + v141 + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + true + v141_xp + Unicode + + + DynamicLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + false + v141_xp + true + Unicode + + + DynamicLibrary + false + v141 + true + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + false + v141_xp + true + Unicode + + + DynamicLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + true + C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Team Tools\Static Analysis Tools\Rule Sets\NativeRecommendedRules.ruleset + false + + + true + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + true + C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Team Tools\Static Analysis Tools\Rule Sets\NativeRecommendedRules.ruleset + false + + + true + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + $(LibraryPath) + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + + + + Level4 + Disabled + WIN32;_DEBUG;CONSOLE_TRACE;%(PreprocessorDefinitions) + true + UninitializedLocalUsageCheck + ProgramDatabase + 4100 + false + stdcpplatest + true + false + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + true + + + true + + + $(ProjectDir)..\3rd_party\DIA\lib;%(AdditionalLibraryDirectories) + diaguids.lib;Ole32.lib;%(AdditionalDependencies) + + + xcopy "$(ProjectDir)..\..\DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y +xcopy "$(ProjectDir)..\..\DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y + + + + + + + Level4 + Disabled + WIN32;_DEBUG;CONSOLE_TRACE;XP_BUILD;%(PreprocessorDefinitions) + true + UninitializedLocalUsageCheck + ProgramDatabase + 4100 + stdcpplatest + true + false + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + true + + + true + + + $(ProjectDir)..\3rd_party\DIA\lib;%(AdditionalLibraryDirectories) + diaguids.lib;Ole32.lib;%(AdditionalDependencies) + + + xcopy "$(ProjectDir)..\..\DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y +xcopy "$(ProjectDir)..\..\DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y + + + + + + + Level4 + Disabled + WIN32;_DEBUG;_DLL;CONSOLE_TRACE;BLACKBONE_EXPORTS;%(PreprocessorDefinitions) + true + UninitializedLocalUsageCheck + ProgramDatabase + 4100 + stdcpplatest + true + false + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Windows + true + diaguids.lib;Ole32.lib;$(ProjectDir)..\3rd_party\BeaEngine\Win32\Dll\BeaEngineCheetah.lib;%(AdditionalDependencies) + + + $(ProjectDir)..\3rd_party\DIA\lib;%(AdditionalLibraryDirectories) + Exports.def + + + true + + + xcopy "$(ProjectDir)..\..\DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y +xcopy "$(ProjectDir)..\..\DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y + + + + + + + Level4 + Disabled + WIN32;_DEBUG;CONSOLE_TRACE;%(PreprocessorDefinitions) + true + 4100 + ProgramDatabase + false + stdcpplatest + true + false + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + true + + + true + + + $(ProjectDir)..\3rd_party\DIA\lib\amd64;%(AdditionalLibraryDirectories) + diaguids.lib;Ole32.lib;%(AdditionalDependencies) + + + xcopy "$(ProjectDir)..\..\DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y +xcopy "$(ProjectDir)..\..\DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y + + + + + + + Level4 + Disabled + WIN32;_DEBUG;CONSOLE_TRACE;XP_BUILD;%(PreprocessorDefinitions) + true + 4100 + stdcpplatest + true + false + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + true + + + true + + + $(ProjectDir)..\3rd_party\DIA\lib\amd64;%(AdditionalLibraryDirectories) + diaguids.lib;Ole32.lib;%(AdditionalDependencies) + + + xcopy "$(ProjectDir)..\..\DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y +xcopy "$(ProjectDir)..\..\DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y + + + + + + + Level4 + Disabled + WIN32;_DEBUG;_DLL;CONSOLE_TRACE;BLACKBONE_EXPORTS;%(PreprocessorDefinitions) + true + 4100 + stdcpplatest + true + false + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Windows + true + diaguids.lib;Ole32.lib;$(ProjectDir)..\3rd_party\BeaEngine\Win64\Dll\BeaEngineCheetah64.lib;%(AdditionalDependencies) + $(ProjectDir)..\3rd_party\DIA\lib\amd64;%(AdditionalLibraryDirectories) + Exports.def + + + true + + + xcopy "$(ProjectDir)..\..\DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y +xcopy "$(ProjectDir)..\..\DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y + + + + + Level3 + + + Full + true + true + WIN32;NDEBUG;BLACKBONE_NO_TRACE;%(PreprocessorDefinitions) + + + MultiThreaded + AnySuitable + Speed + false + 4100 + stdcpplatest + true + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + true + true + true + + + true + + + $(ProjectDir)..\3rd_party\DIA\lib;%(AdditionalLibraryDirectories) + diaguids.lib;Ole32.lib;%(AdditionalDependencies) + + + xcopy "$(ProjectDir)..\..\DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y +xcopy "$(ProjectDir)..\..\DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y + + + + + Level3 + + + Full + true + true + WIN32;NDEBUG;BLACKBONE_NO_TRACE;XP_BUILD;%(PreprocessorDefinitions) + + + MultiThreaded + AnySuitable + Speed + false + 4100 + stdcpplatest + true + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + true + true + true + + + true + + + $(ProjectDir)..\3rd_party\DIA\lib;%(AdditionalLibraryDirectories) + diaguids.lib;Ole32.lib;%(AdditionalDependencies) + + + xcopy "$(ProjectDir)..\..\DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y +xcopy "$(ProjectDir)..\..\DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y + + + + + Level3 + + + Full + true + true + WIN32;NDEBUG;_DLL;BLACKBONE_NO_TRACE;BLACKBONE_EXPORTS;%(PreprocessorDefinitions) + + + MultiThreadedDLL + AnySuitable + Speed + false + 4100 + stdcpplatest + true + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + diaguids.lib;Ole32.lib;$(ProjectDir)..\3rd_party\BeaEngine\Win32\Dll\BeaEngineCheetah.lib;%(AdditionalDependencies) + NotSet + + + $(ProjectDir)..\3rd_party\DIA\lib;%(AdditionalLibraryDirectories) + Exports.def + + + true + + + xcopy "$(ProjectDir)..\..\DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y +xcopy "$(ProjectDir)..\..\DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;BLACKBONE_NO_TRACE;%(PreprocessorDefinitions) + true + MultiThreaded + 4100 + stdcpplatest + true + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + true + true + true + + + true + + + $(ProjectDir)..\3rd_party\DIA\lib\amd64;%(AdditionalLibraryDirectories) + diaguids.lib;Ole32.lib;%(AdditionalDependencies) + + + xcopy "$(ProjectDir)..\..\DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y +xcopy "$(ProjectDir)..\..\DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;BLACKBONE_NO_TRACE;XP_BUILD;%(PreprocessorDefinitions) + true + MultiThreaded + 4100 + stdcpplatest + true + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + true + true + true + + + true + + + $(ProjectDir)..\3rd_party\DIA\lib\amd64;%(AdditionalLibraryDirectories) + diaguids.lib;Ole32.lib;%(AdditionalDependencies) + + + xcopy "$(ProjectDir)..\..\DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y +xcopy "$(ProjectDir)..\..\DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_DLL;BLACKBONE_NO_TRACE;BLACKBONE_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreadedDLL + 4100 + stdcpplatest + true + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + diaguids.lib;Ole32.lib;$(ProjectDir)..\3rd_party\BeaEngine\Win64\Dll\BeaEngineCheetah64.lib;%(AdditionalDependencies) + $(ProjectDir)..\3rd_party\DIA\lib\amd64;%(AdditionalLibraryDirectories) + Exports.def + + + true + + + xcopy "$(ProjectDir)..\..\DIA\$(Platform)\msdia140.dll" "$(TargetDir)" /Y +xcopy "$(ProjectDir)..\..\DIA\$(Platform)\symsrv.dll" "$(TargetDir)" /Y + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + true + true + true + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + + + + + + + \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/BlackBone.vcxproj.filters b/third/Blackbone/src/BlackBone/BlackBone.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..6cb2f9d33eb9046646438f8f147b4c4125607e9f --- /dev/null +++ b/third/Blackbone/src/BlackBone/BlackBone.vcxproj.filters @@ -0,0 +1,502 @@ + + + + + {8d39d5e3-9347-4412-9a68-95b90cc7654a} + + + {9f7d218c-4abc-47f0-ab3c-2c6f37bb9d04} + + + {9c7a518e-ce73-4f5b-b7cd-9bf492b33049} + + + {f8083125-f26d-4616-ad96-953138aa082d} + + + {c2a29073-8ede-457a-aa0e-144361cafe47} + + + {84d4abb7-680c-40f6-a060-d57309a17b7c} + + + {2a23b60b-d2f9-4865-be48-004c57a2f7bd} + + + {ed49eaa5-5d59-4422-9da7-4e68f2e82774} + + + {400c27bd-fb7a-4125-abf2-90a4bdb04f09} + + + {e856edb5-6e81-44c0-a687-1901b1cc2c3d} + + + {d8e1ddde-63c1-40a4-b8c6-5285e4fad4ba} + + + {3ed75fd0-62a1-4a6a-a158-6749fb3f3d90} + + + {84644925-22dd-4022-be68-30ddf267b977} + + + {f688ae04-991b-40b2-9243-89e38275be42} + + + {7eb59189-daeb-47d1-9fa8-c9e246b22039} + + + {e666a795-e3de-4277-9223-b220c8d109ed} + + + {8ce61b72-1088-4cd7-b7a9-e7cdb027304e} + + + + + Subsystem + + + Subsystem + + + Subsystem + + + Process + + + Process + + + Process + + + Process + + + Process + + + Process\Threads + + + Process\Threads + + + Process\Remote + + + Process\Remote + + + PE + + + Patterns + + + Misc + + + Misc + + + ManualMap + + + ManualMap + + + ManualMap\Native + + + LocalHook + + + LocalHook + + + DriverControl + + + Process\Remote + + + AsmJit\Helpers + + + AsmJit\Helpers + + + AsmJit\Helpers + + + PE + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + Process\Remote + + + Misc + + + Subsystem + + + + Symbols + + + Symbols + + + Symbols + + + Symbols + + + + + + Subsystem + + + Subsystem + + + Subsystem + + + Process + + + Process + + + Process + + + Process + + + Process + + + Process\Threads + + + Process\Threads + + + Process\Remote + + + Process\Remote + + + Process\Remote + + + Process\Remote + + + PE + + + Patterns + + + Misc + + + Misc + + + Misc + + + Misc + + + ManualMap + + + ManualMap + + + ManualMap\Native + + + LocalHook + + + LocalHook + + + LocalHook + + + LocalHook + + + LocalHook + + + LocalHook + + + LocalHook + + + LocalHook + + + LocalHook + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + Include + + + DriverControl + + + Process\Remote + + + AsmJit\Helpers + + + AsmJit\Helpers + + + AsmJit\Helpers + + + AsmJit\Helpers + + + AsmJit\Helpers + + + PE + + + Misc + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + AsmJit\Core + + + Process\Remote + + + Include + + + Include + + + Process + + + Misc + + + Subsystem + + + Include + + + AsmJit\Helpers + + + AsmJit\Helpers + + + Include + + + Include + + + Symbols + + + Symbols + + + Symbols + + + Symbols + + + Syscalls + + + + + Syscalls + + + Syscalls + + + + + + \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/CMakeLists.txt b/third/Blackbone/src/BlackBone/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..42e05f88f0086405896ef1f738a76c9900d6ee2e --- /dev/null +++ b/third/Blackbone/src/BlackBone/CMakeLists.txt @@ -0,0 +1,280 @@ +cmake_minimum_required (VERSION 3.13) +project (BlackBoneLib) + +if(CMAKE_CL_64) +enable_language(ASM_MASM) +endif() + +include_directories(..) + +########################################################## +set(SOURCE_ASMJIT ../3rd_party/asmjit/base/assembler.cpp + ../3rd_party/Asmjit/base/codegen.cpp + ../3rd_party/Asmjit/base/constpool.cpp + ../3rd_party/Asmjit/base/containers.cpp + ../3rd_party/Asmjit/base/cpuinfo.cpp + ../3rd_party/Asmjit/base/cputicks.cpp + ../3rd_party/Asmjit/base/error.cpp + ../3rd_party/Asmjit/base/globals.cpp + ../3rd_party/Asmjit/base/operand.cpp + ../3rd_party/Asmjit/base/runtime.cpp + ../3rd_party/Asmjit/base/string.cpp + ../3rd_party/Asmjit/base/vmem.cpp + ../3rd_party/Asmjit/base/zone.cpp + ../3rd_party/Asmjit/x86/x86assembler.cpp + ../3rd_party/Asmjit/x86/x86cpuinfo.cpp + ../3rd_party/Asmjit/x86/x86inst.cpp + ../3rd_party/Asmjit/x86/x86operand.cpp + ../3rd_party/Asmjit/x86/x86operand_regs.cpp) + +set (HEADER_ASMJIT ../3rd_party/Asmjit/apibegin.h + ../3rd_party/Asmjit/apiend.h + ../3rd_party/Asmjit/asmjit.h + ../3rd_party/Asmjit/base.h + ../3rd_party/Asmjit/build.h + ../3rd_party/Asmjit/config.h + ../3rd_party/Asmjit/host.h + ../3rd_party/Asmjit/x86.h + ../3rd_party/Asmjit/base/assembler.h + ../3rd_party/Asmjit/base/codegen.h + ../3rd_party/Asmjit/base/compiler.h + ../3rd_party/Asmjit/base/constpool.h + ../3rd_party/Asmjit/base/containers.h + ../3rd_party/Asmjit/base/context_p.h + ../3rd_party/Asmjit/base/cpuinfo.h + ../3rd_party/Asmjit/base/cputicks.h + ../3rd_party/Asmjit/base/error.h + ../3rd_party/Asmjit/base/globals.h + ../3rd_party/Asmjit/base/intutil.h + ../3rd_party/Asmjit/base/lock.h + ../3rd_party/Asmjit/base/logger.h + ../3rd_party/Asmjit/base/operand.h + ../3rd_party/Asmjit/base/runtime.h + ../3rd_party/Asmjit/base/string.h + ../3rd_party/Asmjit/base/vectypes.h + ../3rd_party/Asmjit/base/vmem.h + ../3rd_party/Asmjit/base/zone.h + ../3rd_party/Asmjit/x86/x86assembler.h + ../3rd_party/Asmjit/x86/x86compiler.h + ../3rd_party/Asmjit/x86/x86context_p.h + ../3rd_party/Asmjit/x86/x86cpuinfo.h + ../3rd_party/Asmjit/x86/x86inst.h + ../3rd_party/Asmjit/x86/x86operand.h + ../3rd_party/Asmjit/x86/x86scheduler_p.h) + +FILE(GLOB AsmJit ${SOURCE_ASMJIT} ${HEADER_ASMJIT}) +source_group(AsmJit\\Core FILES ${AsmJit}) + +########################################################## +set(SOURCE_HELPERS Asm/AsmHelper32.cpp + Asm/AsmHelper64.cpp + Asm/LDasm.c) + +set(HEADER_HELPERS Asm/AsmFactory.h + Asm/AsmHelper32.h + Asm/AsmHelper64.h + Asm/IAsmHelper.h + Asm/AsmStack.hpp + Asm/AsmVariant.hpp + Asm/LDasm.h) + +FILE(GLOB AsmJitHelpers ${SOURCE_HELPERS} ${HEADER_HELPERS}) +source_group(AsmJit\\Helpers FILES ${AsmJitHelpers}) + +########################################################## +set(SOURCE_DRV DriverControl/DriverControl.cpp) +set(HEADER_DRV DriverControl/DriverControl.h) + +FILE(GLOB DriverControl ${SOURCE_DRV} ${HEADER_DRV}) +source_group(DriverControl FILES ${DriverControl}) + +########################################################## +set(HEADER_INCLUDE Include/ApiSet.h + Include/CallResult.h + Include/FunctionTypes.h + Include/HandleGuard.h + Include/Macro.h + Include/NativeStructures.h + Include/Types.h + Include/Win7Specific.h + Include/Win8Specific.h + Include/Winheaders.h + Include/WinXPSpecific.h) + +FILE(GLOB Include ${HEADER_INCLUDE}) +source_group(Include FILES ${Include}) + +########################################################## +set(SOURCE_LOCALHK LocalHook/LocalHookBase.cpp + LocalHook/TraceHook.cpp) + +set(HEADER_LOCALHK LocalHook/HookHandlerCdecl.h + LocalHook/HookHandlerFastcall.h + LocalHook/HookHandlers.h + LocalHook/HookHandlerStdcall.h + LocalHook/HookHandlerThiscall.h + LocalHook/LocalHook.hpp + LocalHook/LocalHookBase.h + LocalHook/TraceHook.h + LocalHook/VTableHook.hpp) + +FILE(GLOB LocalHook ${SOURCE_LOCALHK} ${HEADER_LOCALHK}) +source_group(LocalHook FILES ${LocalHook}) + +########################################################## +set(SOURCE_MMAP ManualMap/MExcept.cpp + ManualMap/MMap.cpp + ManualMap/Native/NtLoader.cpp) + +set(HEADER_MMAP ManualMap/MExcept.h + ManualMap/MMap.h + ManualMap/Native/NtLoader.h) + +FILE(GLOB ManualMap ${SOURCE_MMAP} ${HEADER_MMAP}) +source_group(ManualMap FILES ${ManualMap}) + +########################################################## +set(SOURCE_MISC Misc/InitOnce.cpp + Misc/NameResolve.cpp + Misc/Utils.cpp) + +set(HEADER_MISC Misc/DynImport.h + Misc/InitOnce.h + Misc/NameResolve.h + Misc/Thunk.hpp + Misc/Trace.hpp + Misc/Utils.h) + +FILE(GLOB Misc ${SOURCE_MISC} ${HEADER_MISC}) +source_group(Misc FILES ${Misc}) + +########################################################## +set(SOURCE_PATTERN Patterns/PatternSearch.cpp) +set(HEADER_PATTERN Patterns/PatternSearch.h) + +FILE(GLOB Patterns ${SOURCE_PATTERN} ${HEADER_PATTERN}) +source_group(Patterns FILES ${Patterns}) + +########################################################## +set(SOURCE_PE PE/ImageNET.cpp PE/PEImage.cpp) +set(HEADER_PE PE/ImageNET.h PE/PEImage.h) + +FILE(GLOB PE ${SOURCE_PE} ${HEADER_PE}) +source_group(PE FILES ${PE}) + +########################################################## +set(SOURCE_PROCESS Process/MemBlock.cpp + Process/Process.cpp + Process/ProcessCore.cpp + Process/ProcessMemory.cpp + Process/ProcessModules.cpp) + +set(HEADER_PROCESS Process/MemBlock.h + Process/Process.h + Process/ProcessCore.h + Process/ProcessMemory.h + Process/ProcessModules.h) + +FILE(GLOB Process ${SOURCE_PROCESS} ${HEADER_PROCESS}) +source_group(Process FILES ${Process}) + +########################################################## +set(SOURCE_RPC Process/RPC/RemoteExec.cpp + Process/RPC/RemoteHook.cpp + Process/RPC/RemoteLocalHook.cpp + Process/RPC/RemoteMemory.cpp) + +set(HEADER_RPC Process/RPC/RemoteContext.hpp + Process/RPC/RemoteExec.h + Process/RPC/RemoteFunction.hpp + Process/RPC/RemoteHook.h + Process/RPC/RemoteLocalHook.h + Process/RPC/RemoteMemory.h) + +FILE(GLOB RPC ${SOURCE_RPC} ${HEADER_RPC}) +source_group(Process\\Remote FILES ${RPC}) + +########################################################## +set(SOURCE_THREADS Process/Threads/Thread.cpp Process/Threads/Threads.cpp) +set(HEADER_THREADS Process/Threads/Thread.h Process/Threads/Threads.h) + +FILE(GLOB Threads ${SOURCE_THREADS} ${HEADER_THREADS}) +source_group(Process\\Threads FILES ${Threads}) + +########################################################## +set(SOURCE_SUB Subsystem/NativeSubsystem.cpp + Subsystem/Wow64Subsystem.cpp + Subsystem/x86Subsystem.cpp + ../3rd_party/rewolf-wow64ext/src/wow64ext.cpp) + +set(HEADER_SUB Subsystem/NativeSubsystem.h + Subsystem/Wow64Subsystem.h + Subsystem/x86Subsystem.h + ../3rd_party/rewolf-wow64ext/src/wow64ext.h) + +FILE(GLOB Subsystem ${SOURCE_SUB} ${HEADER_SUB}) +source_group(Subsystem FILES ${Subsystem}) + +########################################################## +set(SOURCE_SYMBOLS Symbols/PatternLoader.cpp + Symbols/PDBHelper.cpp + Symbols/SymbolData.cpp + Symbols/SymbolLoader.cpp) + +set(HEADER_SYMBOLS Symbols/PatternLoader.h + Symbols/PDBHelper.h + Symbols/SymbolData.h + Symbols/SymbolLoader.h) + +FILE(GLOB Symbols ${SOURCE_SYMBOLS} ${HEADER_SYMBOLS}) +source_group(Symbols FILES ${Symbols}) + +########################################################## +if(CMAKE_SIZEOF_VOID_P EQUAL 8) +set(SOURCE_SYSCALL Syscalls/Syscall64.asm) +else() +set(SOURCE_SYSCALL Syscalls/Syscall32.asm) +endif() + +set(HEADER_SYSCALL Syscalls/Syscall.h) + +FILE(GLOB Syscalls ${SOURCE_SYSCALL} ${HEADER_SYSCALL}) +source_group(Syscalls FILES ${Syscalls}) + +########################################################## +set (HEADER_MAIN Config.h ) + +########################################################## +set(SOURCE_LIB ${SOURCE_ASMJIT} + ${SOURCE_HELPERS} + ${SOURCE_DRV} + ${SOURCE_LOCALHK} + ${SOURCE_MMAP} + ${SOURCE_MISC} + ${SOURCE_PATTERN} + ${SOURCE_PE} + ${SOURCE_PROCESS} + ${SOURCE_RPC} + ${SOURCE_THREADS} + ${SOURCE_SUB} + ${SOURCE_SYMBOLS} + ${SOURCE_SYSCALL}) + +set(HEADER_LIB ${HEADER_ASMJIT} + ${HEADER_HELPERS} + ${HEADER_DRV} + ${HEADER_INCLUDE} + ${HEADER_LOCALHK} + ${HEADER_MMAP} + ${HEADER_MISC} + ${HEADER_PATTERN} + ${HEADER_PE} + ${HEADER_PROCESS} + ${HEADER_RPC} + ${HEADER_THREADS} + ${HEADER_SUB} + ${HEADER_SYMBOLS} + ${HEADER_SYSCALL} + ${HEADER_MAIN}) + +add_library(BlackBone STATIC ${SOURCE_LIB} ${HEADER_LIB}) \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Config.h b/third/Blackbone/src/BlackBone/Config.h new file mode 100644 index 0000000000000000000000000000000000000000..079ca92688a9751e059b2892f7bb14fba95cf35b --- /dev/null +++ b/third/Blackbone/src/BlackBone/Config.h @@ -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 + + diff --git a/third/Blackbone/src/BlackBone/DllMain.cpp b/third/Blackbone/src/BlackBone/DllMain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2ba92b4e1459521784173b110b0e62bcd9bba6de --- /dev/null +++ b/third/Blackbone/src/BlackBone/DllMain.cpp @@ -0,0 +1,16 @@ +#include "Config.h" +#include "Include/Winheaders.h" + +DWORD WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved ) +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + case DLL_PROCESS_DETACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + } + + return TRUE; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/DriverControl/DriverControl.cpp b/third/Blackbone/src/BlackBone/DriverControl/DriverControl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..edf8e072be32968202ddfeb6d2ad523f9f358340 --- /dev/null +++ b/third/Blackbone/src/BlackBone/DriverControl/DriverControl.cpp @@ -0,0 +1,842 @@ +#include "DriverControl.h" +#include "../Misc/Utils.h" +#include "../Misc/Trace.hpp" +#include "../Misc/DynImport.h" + +#include <3rd_party/VersionApi.h> + +namespace blackbone +{ + +#define DRIVER_SVC_NAME L"BlackBone" + +DriverControl::DriverControl() +{ +} + +DriverControl::~DriverControl() +{ + //Unload(); +} + +DriverControl& DriverControl::Instance() +{ + static DriverControl instance; + return instance; +} + +/// +/// Try to load driver if it isn't loaded +/// +/// Path to the driver file +/// Status code +NTSTATUS DriverControl::EnsureLoaded( const std::wstring& path /*= L"" */ ) +{ + // Already open + if (_hDriver) + return STATUS_SUCCESS; + + // Try to open handle to existing driver + _hDriver = CreateFileW( + BLACKBONE_DEVICE_FILE, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL + ); + + if (_hDriver) + return _loadStatus = STATUS_SUCCESS; + + // Start new instance + return Reload( path ); +} + +/// +/// Reload driver +/// +/// Path to the driver file +/// Status code +NTSTATUS DriverControl::Reload( std::wstring path /*= L"" */ ) +{ + Unload(); + + // Use default path + if (path.empty()) + { + const wchar_t* filename = nullptr; + + if (IsWindows10OrGreater()) + filename = BLACKBONE_FILE_NAME_10; + else if (IsWindows8Point1OrGreater()) + filename = BLACKBONE_FILE_NAME_81; + else if (IsWindows8OrGreater()) + filename = BLACKBONE_FILE_NAME_8; + else if (IsWindows7OrGreater()) + filename = BLACKBONE_FILE_NAME_7; + else + filename = BLACKBONE_FILE_NAME; + + path = Utils::GetExeDirectory() + L"\\" + filename; + } + + _loadStatus = LoadDriver( DRIVER_SVC_NAME, path ); + if (!NT_SUCCESS( _loadStatus )) + { + BLACKBONE_TRACE( L"Failed to load driver %ls. Status 0x%X", path.c_str(), _loadStatus ); + return _loadStatus; + } + + _hDriver = CreateFileW( + BLACKBONE_DEVICE_FILE, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL + ); + + if (!_hDriver) + { + _loadStatus = LastNtStatus(); + BLACKBONE_TRACE( L"Failed to open driver handle. Status 0x%X", _loadStatus ); + return _loadStatus; + } + + return _loadStatus; +} + +/// +/// Unload driver +/// +/// Status code +NTSTATUS DriverControl::Unload() +{ + _hDriver.reset(); + return UnloadDriver( DRIVER_SVC_NAME ); +} + + +/// +/// Maps target process memory into current process +/// +/// Target PID +/// Pipe name to use for hook data transfer +/// The map sections. +/// Results +/// Status code +NTSTATUS DriverControl::MapMemory( DWORD pid, const std::wstring& pipeName, bool mapSections, MapMemoryResult& result ) +{ + MAP_MEMORY data = { 0 }; + DWORD bytes = 0; + ULONG sizeRequired = 0; + data.pid = pid; + data.mapSections = mapSections; + + // Not loaded + if (_hDriver == INVALID_HANDLE_VALUE) + return STATUS_DEVICE_DOES_NOT_EXIST; + + wcscpy_s( data.pipeName, pipeName.c_str() ); + + BOOL res = DeviceIoControl( _hDriver, IOCTL_BLACKBONE_MAP_MEMORY, &data, sizeof( data ), &sizeRequired, sizeof( sizeRequired ), &bytes, NULL ); + if (res != FALSE && bytes == 4) + { + MAP_MEMORY_RESULT* pResult = (MAP_MEMORY_RESULT*)malloc( sizeRequired ); + + if (DeviceIoControl( _hDriver, IOCTL_BLACKBONE_MAP_MEMORY, &data, sizeof( data ), pResult, sizeRequired, &bytes, NULL )) + { + for (ULONG i = 0; i < pResult->count; i++) + result.regions.emplace( std::make_pair( std::make_pair( pResult->entries[i].originalPtr, pResult->entries[i].size ), + pResult->entries[i].newPtr ) ); + + result.hostSharedPage = pResult->hostPage; + result.targetSharedPage = pResult->targetPage; + result.targetPipe = (HANDLE)pResult->pipeHandle; + + free( pResult ); + return STATUS_SUCCESS; + } + } + + return LastNtStatus(); +} + +/// +/// Maps single memory region into current process +/// +/// Target PID +/// Region base address +/// Region size +/// Mapped region info +/// Status code +NTSTATUS DriverControl::MapMemoryRegion( DWORD pid, ptr_t base, uint32_t size, MapMemoryRegionResult& result ) +{ + MAP_MEMORY_REGION data = { 0 }; + MAP_MEMORY_REGION_RESULT mapResult = { 0 }; + DWORD bytes = 0; + + // Not loaded + if (_hDriver == INVALID_HANDLE_VALUE) + return STATUS_DEVICE_DOES_NOT_EXIST; + + data.pid = pid; + data.base = base; + data.size = size; + + if (DeviceIoControl( _hDriver, IOCTL_BLACKBONE_MAP_REGION, &data, sizeof( data ), &mapResult, sizeof( mapResult ), &bytes, NULL )) + { + result.newPtr = mapResult.newPtr; + result.originalPtr = mapResult.originalPtr; + result.removedPtr = mapResult.removedPtr; + result.removedSize = mapResult.removedSize; + result.size = mapResult.size; + + return STATUS_SUCCESS; + } + + return LastNtStatus(); +} + +/// +/// Unmap memory of the target process from current +/// +/// Target PID +/// Status code +NTSTATUS DriverControl::UnmapMemory( DWORD pid ) +{ + UNMAP_MEMORY data = { pid }; + DWORD bytes = 0; + + // Not loaded + if (_hDriver == INVALID_HANDLE_VALUE) + return STATUS_DEVICE_DOES_NOT_EXIST; + + if (DeviceIoControl( _hDriver, IOCTL_BLACKBONE_UNMAP_MEMORY, &data, sizeof( data ), NULL, 0, &bytes, NULL )) + return STATUS_SUCCESS; + + return LastNtStatus(); +} + +/// +/// 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 +/// +/// Target PID +/// Region base +/// Region size +/// Unampped region info +/// Status code +NTSTATUS DriverControl::UnmapMemoryRegion( DWORD pid, ptr_t base, uint32_t size ) +{ + UNMAP_MEMORY_REGION data = { 0 }; + DWORD bytes = 0; + + data.pid = pid; + data.base = base; + data.size = size; + + // Not loaded + if (_hDriver == INVALID_HANDLE_VALUE) + return STATUS_DEVICE_DOES_NOT_EXIST; + + if (!DeviceIoControl( _hDriver, IOCTL_BLACKBONE_UNMAP_REGION, &data, sizeof( data ), NULL, 0, &bytes, NULL )) + return LastNtStatus(); + + return STATUS_SUCCESS; +} + + +/// +/// Disable DEP for process +/// Has no effect on native x64 processes +/// +/// Target PID +/// Status code +NTSTATUS DriverControl::DisableDEP( DWORD pid ) +{ + DWORD bytes = 0; + DISABLE_DEP disableDep = { pid }; + + // Not loaded + if (_hDriver == INVALID_HANDLE_VALUE) + return STATUS_DEVICE_DOES_NOT_EXIST; + + if (!DeviceIoControl( _hDriver, IOCTL_BLACKBONE_DISABLE_DEP, &disableDep, sizeof( disableDep ), nullptr, 0, &bytes, NULL )) + return LastNtStatus(); + + return STATUS_SUCCESS; +} + +/// +/// Change process protection flag +/// +/// Target PID +/// Process protection policy +/// Prohibit dynamic code +/// Prohibit loading non-microsoft dlls +/// Status code +NTSTATUS DriverControl::ProtectProcess( + DWORD pid, + PolicyOpt protection, + PolicyOpt dynamicCode /*= Policy_Keep*/, + PolicyOpt binarySignature /*= Policy_Keep*/ + ) +{ + DWORD bytes = 0; + SET_PROC_PROTECTION setProt = { pid, protection, dynamicCode, binarySignature }; + + // Not loaded + if (_hDriver == INVALID_HANDLE_VALUE) + return STATUS_DEVICE_DOES_NOT_EXIST; + + if (!DeviceIoControl( _hDriver, IOCTL_BLACKBONE_SET_PROTECTION, &setProt, sizeof( setProt ), nullptr, 0, &bytes, NULL )) + return LastNtStatus(); + + return STATUS_SUCCESS; +} + +/// +/// Change handle access rights +/// +/// Target PID. +/// Handle +/// New access +/// Status code +NTSTATUS DriverControl::PromoteHandle( DWORD pid, HANDLE handle, DWORD access ) +{ + DWORD bytes = 0; + HANDLE_GRANT_ACCESS grantAccess = { 0 }; + + grantAccess.pid = pid; + grantAccess.handle = (ULONGLONG)handle; + grantAccess.access = access; + + // Not loaded + if (_hDriver == INVALID_HANDLE_VALUE) + return STATUS_DEVICE_DOES_NOT_EXIST; + + if (!DeviceIoControl( _hDriver, IOCTL_BLACKBONE_GRANT_ACCESS, &grantAccess, sizeof( grantAccess ), nullptr, 0, &bytes, NULL )) + return LastNtStatus(); + + return STATUS_SUCCESS; +} + +/// +/// Allocate virtual memory +/// +/// Tarhet PID +/// Desired base. If 0 address is chosed by the system +/// Region size +/// Allocation type - MEM_RESERVE/MEM_COMMIT +/// Memory protection +/// Status code +NTSTATUS DriverControl::AllocateMem( DWORD pid, ptr_t& base, ptr_t& size, DWORD type, DWORD protection, bool physical /*= false*/ ) +{ + DWORD bytes = 0; + ALLOCATE_FREE_MEMORY allocMem = { 0 }; + ALLOCATE_FREE_MEMORY_RESULT result = { 0 }; + + allocMem.pid = pid; + allocMem.base = base; + allocMem.size = size; + allocMem.type = type; + allocMem.protection = protection; + allocMem.allocate = TRUE; + allocMem.physical = physical; + + // Not loaded + if (_hDriver == INVALID_HANDLE_VALUE) + return STATUS_DEVICE_DOES_NOT_EXIST; + + if (!DeviceIoControl( + _hDriver, IOCTL_BLACKBONE_ALLOCATE_FREE_MEMORY, + &allocMem, sizeof( allocMem ), + &result, sizeof( result ), &bytes, NULL + )) + { + size = base = 0; + return LastNtStatus(); + } + + base = result.address; + size = result.size; + + return STATUS_SUCCESS; +} + +/// +/// Free virtual memory +/// +/// Tarhet PID +/// Desired base. If 0 address is chosed by the system +/// Region size +/// Free type - MEM_RELEASE/MEM_DECOMMIT +/// Status code +NTSTATUS DriverControl::FreeMem( DWORD pid, ptr_t base, ptr_t size, DWORD type ) +{ + DWORD bytes = 0; + ALLOCATE_FREE_MEMORY freeMem = { 0 }; + ALLOCATE_FREE_MEMORY_RESULT result = { 0 }; + + freeMem.pid = pid; + freeMem.base = base; + freeMem.size = size; + freeMem.type = type; + freeMem.allocate = FALSE; + freeMem.physical = FALSE; + + // Not loaded + if (_hDriver == INVALID_HANDLE_VALUE) + return STATUS_DEVICE_DOES_NOT_EXIST; + + if (!DeviceIoControl( + _hDriver, IOCTL_BLACKBONE_ALLOCATE_FREE_MEMORY, + &freeMem, sizeof( freeMem ), + &result, sizeof( result ), &bytes, NULL + )) + { + return LastNtStatus(); + } + + return STATUS_SUCCESS; +} + +/// +/// Read process memory +/// +/// Target PID +/// Target base +/// Data size +/// Buffer address +/// Status code +NTSTATUS DriverControl::ReadMem( DWORD pid, ptr_t base, ptr_t size, PVOID buffer ) +{ + DWORD bytes = 0; + COPY_MEMORY copyMem = { 0 }; + + copyMem.pid = pid; + copyMem.targetPtr = base; + copyMem.localbuf = (ULONGLONG)buffer; + copyMem.size = size; + copyMem.write = FALSE; + + // Not loaded + if (_hDriver == INVALID_HANDLE_VALUE) + return STATUS_DEVICE_DOES_NOT_EXIST; + + if (!DeviceIoControl( _hDriver, IOCTL_BLACKBONE_COPY_MEMORY, ©Mem, sizeof( copyMem ), nullptr, 0, &bytes, NULL )) + return LastNtStatus(); + + return STATUS_SUCCESS; +} + +/// +/// Write process memory +/// +/// Target PID +/// Target base +/// Data size +/// Buffer address +/// Status code +NTSTATUS DriverControl::WriteMem( DWORD pid, ptr_t base, ptr_t size, PVOID buffer ) +{ + DWORD bytes = 0; + COPY_MEMORY copyMem = { 0 }; + + copyMem.pid = pid; + copyMem.targetPtr = base; + copyMem.localbuf = (ULONGLONG)buffer; + copyMem.size = size; + copyMem.write = TRUE; + + // Not loaded + if (_hDriver == INVALID_HANDLE_VALUE) + return STATUS_DEVICE_DOES_NOT_EXIST; + + if (!DeviceIoControl( _hDriver, IOCTL_BLACKBONE_COPY_MEMORY, ©Mem, sizeof( copyMem ), nullptr, 0, &bytes, NULL )) + return LastNtStatus(); + + return STATUS_SUCCESS; +} + +/// +/// Change memory protection +/// +/// Target PID. +/// Regiod base address +/// Region size +/// New protection +/// Status code +NTSTATUS DriverControl::ProtectMem( DWORD pid, ptr_t base, ptr_t size, DWORD protection ) +{ + DWORD bytes = 0; + PROTECT_MEMORY protectMem = { 0 }; + + protectMem.pid = pid; + protectMem.base = base; + protectMem.size = size; + protectMem.newProtection = protection; + + // Not loaded + if (_hDriver == INVALID_HANDLE_VALUE) + return STATUS_DEVICE_DOES_NOT_EXIST; + + if (!DeviceIoControl( _hDriver, IOCTL_BLACKBONE_PROTECT_MEMORY, &protectMem, sizeof( protectMem ), nullptr, 0, &bytes, NULL )) + return LastNtStatus(); + + return STATUS_SUCCESS; +} + +/// +/// Inject DLL into arbitrary process +/// +/// Target PID +/// Full qualified dll path +/// Injection type +/// Init routine RVA +/// Init routine argument +/// Unlink module after injection +/// Erase PE headers after injection +/// Wait for injection +/// Status code +NTSTATUS DriverControl::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*/ + ) +{ + DWORD bytes = 0; + INJECT_DLL data = { IT_Thread }; + + // Not loaded + if (_hDriver == INVALID_HANDLE_VALUE) + return STATUS_DEVICE_DOES_NOT_EXIST; + + wcscpy_s( data.FullDllPath, path.c_str() ); + wcscpy_s( data.initArg, initArg.c_str() ); + data.type = itype; + data.pid = pid; + data.initRVA = initRVA; + data.wait = wait; + data.unlink = unlink; + data.erasePE = erasePE; + + if (!DeviceIoControl( _hDriver, IOCTL_BLACKBONE_INJECT_DLL, &data, sizeof( data ), nullptr, 0, &bytes, NULL )) + return LastNtStatus(); + + return STATUS_SUCCESS; +} + +/// +/// Manually map PE image +/// +/// Target PID +/// Full qualified image path +/// Mapping flags +/// Init routine RVA +/// Init routine argument +/// Status code +NTSTATUS DriverControl::MmapDll( + DWORD pid, + const std::wstring& path, + KMmapFlags flags, + uint32_t initRVA /*= 0*/, + const std::wstring& initArg /*= L"" */ + ) +{ + DWORD bytes = 0; + INJECT_DLL data = { IT_MMap }; + UNICODE_STRING ustr = { 0 }; + + // Convert path to native format + SAFE_NATIVE_CALL( RtlDosPathNameToNtPathName_U, path.c_str(), &ustr, nullptr, nullptr ); + wcscpy_s( data.FullDllPath, ustr.Buffer ); + SAFE_CALL( RtlFreeUnicodeString, &ustr ); + + wcscpy_s( data.initArg, initArg.c_str() ); + + data.pid = pid; + data.initRVA = initRVA; + data.wait = true; + data.unlink = false; + data.erasePE = false; + data.flags = flags; + data.imageBase = 0; + data.imageSize = 0; + data.asImage = false; + + if (!DeviceIoControl( _hDriver, IOCTL_BLACKBONE_INJECT_DLL, &data, sizeof( data ), nullptr, 0, &bytes, NULL )) + return LastNtStatus(); + + return STATUS_SUCCESS; +} + +/// +/// Manually map PE image +/// +/// Target PID +/// Memory location of the image to map +/// Image size +/// Memory chunk has image layout +/// Mapping flags +/// Init routine RVA +/// Init routine argument +/// Status code +NTSTATUS DriverControl::MmapDll( + DWORD pid, + void* address, + uint32_t size, + bool asImage, + KMmapFlags flags, + uint32_t initRVA /*= 0*/, + const std::wstring& initArg /*= L"" */ + ) +{ + DWORD bytes = 0; + INJECT_DLL data = { IT_MMap }; + + memset( data.FullDllPath, 0, sizeof( data.FullDllPath ) ); + wcscpy_s( data.initArg, initArg.c_str() ); + + data.pid = pid; + data.initRVA = initRVA; + data.wait = true; + data.unlink = false; + data.erasePE = false; + data.flags = flags; + data.imageBase = (ULONGLONG)address; + data.imageSize = size; + data.asImage = asImage; + + if (!DeviceIoControl( _hDriver, IOCTL_BLACKBONE_INJECT_DLL, &data, sizeof( data ), nullptr, 0, &bytes, NULL )) + return LastNtStatus(); + + return STATUS_SUCCESS; +} + + +/// +/// Manually map another system driver into system space +/// +/// Fully quialified path to the drver +/// Status code +NTSTATUS DriverControl::MMapDriver( const std::wstring& path ) +{ + DWORD bytes = 0; + MMAP_DRIVER data = { { 0 } }; + UNICODE_STRING ustr = { 0 }; + + // Not loaded + if (_hDriver == INVALID_HANDLE_VALUE) + return STATUS_DEVICE_DOES_NOT_EXIST; + + // Convert path to native format + SAFE_NATIVE_CALL( RtlDosPathNameToNtPathName_U, path.c_str(), &ustr, nullptr, nullptr); + wcscpy_s( data.FullPath, ustr.Buffer ); + SAFE_CALL( RtlFreeUnicodeString, &ustr); + + if (!DeviceIoControl( _hDriver, IOCTL_BLACKBONE_MAP_DRIVER, &data, sizeof( data ), nullptr, 0, &bytes, NULL )) + return LastNtStatus(); + + return STATUS_SUCCESS; +} + + +/// +/// Make VAD region appear as PAGE_NO_ACESS to NtQueryVirtualMemory +/// +/// Target process ID +/// Region base +/// Region size +/// Status code +NTSTATUS DriverControl::ConcealVAD( DWORD pid, ptr_t base, uint32_t size ) +{ + DWORD bytes = 0; + HIDE_VAD hideVAD = { 0 }; + + hideVAD.base = base; + hideVAD.size = size; + hideVAD.pid = pid; + + // Not loaded + if (_hDriver == INVALID_HANDLE_VALUE) + return STATUS_DEVICE_DOES_NOT_EXIST; + + if (!DeviceIoControl( _hDriver, IOCTL_BLACKBONE_HIDE_VAD, &hideVAD, sizeof( hideVAD ), nullptr, 0, &bytes, NULL )) + return LastNtStatus(); + + return STATUS_SUCCESS; +} + +/// +/// Unlink process handle table from HandleListHead +/// +/// Target process ID +/// Status code +NTSTATUS DriverControl::UnlinkHandleTable( DWORD pid ) +{ + DWORD bytes = 0; + UNLINK_HTABLE unlink = { pid }; + + // Not loaded + if (_hDriver == INVALID_HANDLE_VALUE) + return STATUS_DEVICE_DOES_NOT_EXIST; + + if (!DeviceIoControl( _hDriver, IOCTL_BLACKBONE_UNLINK_HTABLE, &unlink, sizeof( unlink ), nullptr, 0, &bytes, NULL )) + return LastNtStatus(); + + return STATUS_SUCCESS; +} + +/// +/// Enumerate committed, accessible, non-guarded memory regions +/// +/// Target process ID +/// Found regions +/// Status code +NTSTATUS DriverControl::EnumMemoryRegions( DWORD pid, std::vector& regions ) +{ + // Not loaded + if (_hDriver == INVALID_HANDLE_VALUE) + { + return STATUS_DEVICE_DOES_NOT_EXIST; + } + + DWORD bytes = 0; + ENUM_REGIONS data = { 0 }; + DWORD size = sizeof( ENUM_REGIONS_RESULT ); + auto result = reinterpret_cast(malloc( size )); + + data.pid = pid; + result->count = 0; + + DeviceIoControl( _hDriver, IOCTL_BLACKBONE_ENUM_REGIONS, &data, sizeof( data ), result, size, &bytes, NULL ); + + result->count += 100; + size = static_cast(result->count * sizeof( result->regions[0] ) + sizeof( result->count )); + result = reinterpret_cast(realloc( result, size )); + + if (!DeviceIoControl( _hDriver, IOCTL_BLACKBONE_ENUM_REGIONS, &data, sizeof( data ), result, size, &bytes, NULL )) + { + free( result ); + return LastNtStatus(); + } + + regions.resize( static_cast(result->count) ); + for (uint32_t i = 0; i < result->count; i++) + { + regions[i].AllocationBase = result->regions[i].AllocationBase; + regions[i].AllocationProtect = result->regions[i].AllocationProtect; + regions[i].BaseAddress = result->regions[i].BaseAddress; + regions[i].Protect = result->regions[i].Protect; + regions[i].RegionSize = result->regions[i].RegionSize; + regions[i].State = result->regions[i].State; + regions[i].Type = result->regions[i].Type; + } + + free( result ); + return STATUS_SUCCESS; +} + + + + +/// +/// Load arbitrary driver +/// +/// Driver service name +/// Driver file path +/// Status +NTSTATUS DriverControl::LoadDriver( const std::wstring& svcName, const std::wstring& path ) +{ + UNICODE_STRING Ustr; + + // If no file provided, try to start existing service + if (!path.empty() && PrepareDriverRegEntry( svcName, path ) != 0) + return LastNtStatus(); + + std::wstring regPath = L"\\registry\\machine\\SYSTEM\\CurrentControlSet\\Services\\" + svcName; + SAFE_CALL( RtlInitUnicodeString, &Ustr, regPath.c_str() ); + + return SAFE_NATIVE_CALL( NtLoadDriver, &Ustr ); +} + + +/// +/// Unload arbitrary driver +/// +/// Driver service name +/// Status +NTSTATUS DriverControl::UnloadDriver( const std::wstring& svcName ) +{ + UNICODE_STRING Ustr = { 0 }; + + std::wstring regPath = L"\\registry\\machine\\SYSTEM\\CurrentControlSet\\Services\\" + svcName; + SAFE_CALL( RtlInitUnicodeString, &Ustr, regPath.c_str() ); + + // Remove previously loaded instance, if any + NTSTATUS status = SAFE_NATIVE_CALL( NtUnloadDriver, &Ustr ); + SHDeleteKeyW( HKEY_LOCAL_MACHINE, (L"SYSTEM\\CurrentControlSet\\Services\\" + svcName).c_str() ); + + return status; +} + +/// +/// Fill minimal required driver registry entry +/// +/// Driver service name +/// Driver path +/// Status code +LSTATUS DriverControl::PrepareDriverRegEntry( const std::wstring& svcName, const std::wstring& path ) +{ + HKEY key1, key2; + DWORD dwType = 1; + LSTATUS status = 0; + WCHAR wszLocalPath[MAX_PATH] = { 0 }; + + swprintf_s( wszLocalPath, ARRAYSIZE( wszLocalPath ), L"\\??\\%s", path.c_str() ); + + status = RegOpenKeyW( HKEY_LOCAL_MACHINE, L"system\\CurrentControlSet\\Services", &key1 ); + if (status) + return status; + + status = RegCreateKeyW( key1, svcName.c_str(), &key2 ); + if (status) + { + RegCloseKey( key1 ); + return status; + } + + status = RegSetValueExW( + key2, L"ImagePath", 0, REG_SZ, + reinterpret_cast(wszLocalPath), + static_cast(sizeof( WCHAR )* (wcslen( wszLocalPath ) + 1)) + ); + + if (status) + { + RegCloseKey( key2 ); + RegCloseKey( key1 ); + return status; + } + + status = RegSetValueExW( key2, L"Type", 0, REG_DWORD, reinterpret_cast(&dwType), sizeof( dwType ) ); + if (status) + { + RegCloseKey( key2 ); + RegCloseKey( key1 ); + return status; + } + + RegCloseKey( key2 ); + RegCloseKey( key1 ); + + return status; +} + + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/DriverControl/DriverControl.h b/third/Blackbone/src/BlackBone/DriverControl/DriverControl.h new file mode 100644 index 0000000000000000000000000000000000000000..7bebe607e8f3a1275d0a3ee055a8060849e33678 --- /dev/null +++ b/third/Blackbone/src/BlackBone/DriverControl/DriverControl.h @@ -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 +#include +#include + +ENUM_OPS( KMmapFlags ); + +namespace blackbone +{ +// [Original ptr, size] <--> [Mapped ptr] +using mapMemoryMap = std::map, 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(); + + /// + /// Try to load driver if it isn't loaded + /// + /// Path to the driver file + /// Status code + BLACKBONE_API NTSTATUS EnsureLoaded( const std::wstring& path = L"" ); + + /// + /// Reload driver + /// + /// Path to the driver file + /// Status code + BLACKBONE_API NTSTATUS Reload( std::wstring path = L"" ); + + /// + /// Unload driver + /// + /// Status code + BLACKBONE_API NTSTATUS Unload(); + + /// + /// Disable DEP for process + /// Has no effect on native x64 processes + /// + /// Target PID + /// Status code + BLACKBONE_API NTSTATUS DisableDEP( DWORD pid ); + + /// + /// Change process protection flag + /// + /// Target PID + /// Process protection policy + /// Prohibit dynamic code + /// Prohibit loading non-microsoft dlls + /// Status code + BLACKBONE_API NTSTATUS ProtectProcess( + DWORD pid, + PolicyOpt protection, + PolicyOpt dynamicCode = Policy_Keep, + PolicyOpt binarySignature = Policy_Keep + ); + + /// + /// Change handle access rights + /// + /// Target PID. + /// Handle + /// New access + /// Status code + BLACKBONE_API NTSTATUS PromoteHandle( DWORD pid, HANDLE handle, DWORD access ); + + /// + /// Allocate virtual memory + /// + /// Tarhet PID + /// Desired base. If 0 address is chosed by the system + /// Region size + /// Allocation type - MEM_RESERVE/MEM_COMMIT + /// Memory protection + /// Status code + BLACKBONE_API NTSTATUS AllocateMem( DWORD pid, ptr_t& base, ptr_t& size, DWORD type, DWORD protection, bool physical = false ); + + /// + /// Free virtual memory + /// + /// Tarhet PID + /// Desired base. If 0 address is chosed by the system + /// Region size + /// Free type - MEM_RELEASE/MEM_DECOMMIT + /// Status code + BLACKBONE_API NTSTATUS FreeMem( DWORD pid, ptr_t base, ptr_t size, DWORD type ); + + /// + /// Read process memory + /// + /// Target PID + /// Target base + /// Data size + /// Buffer address + /// Status code + BLACKBONE_API NTSTATUS ReadMem( DWORD pid, ptr_t base, ptr_t size, PVOID buffer ); + + /// + /// Write process memory + /// + /// Target PID + /// Target base + /// Data size + /// Buffer address + /// Status code + BLACKBONE_API NTSTATUS WriteMem( DWORD pid, ptr_t base, ptr_t size, PVOID buffer ); + + /// + /// Change memory protection + /// + /// Target PID. + /// Regiod base address + /// Region size + /// New protection + /// Status code + BLACKBONE_API NTSTATUS ProtectMem( DWORD pid, ptr_t base, ptr_t size, DWORD protection ); + + /// + /// Maps target process memory into current process + /// + /// Target PID + /// Pipe name to use for hook data transfer + /// The map sections. + /// Results + /// Status code + BLACKBONE_API NTSTATUS MapMemory( DWORD pid, const std::wstring& pipeName, bool mapSections, MapMemoryResult& result ); + + /// + /// Maps single memory region into current process + /// + /// Target PID + /// Region base address + /// Region size + /// Mapped region info + /// Status code + BLACKBONE_API NTSTATUS MapMemoryRegion( DWORD pid, ptr_t base, uint32_t size, MapMemoryRegionResult& result ); + + /// + /// Unmap memory of the target process from current + /// + /// Target PID + /// Status code + BLACKBONE_API NTSTATUS UnmapMemory( DWORD pid ); + + /// + /// 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 + /// + /// Target PID + /// Region base + /// Region size + /// Unampped region info + /// Status code + BLACKBONE_API NTSTATUS UnmapMemoryRegion( DWORD pid, ptr_t base, uint32_t size ); + + /// + /// Inject DLL into arbitrary process + /// + /// Target PID. + /// Full qualified dll path. + /// Injection type + /// Init routine RVA + /// Init routine argument + /// Unlink module after injection + /// Erase PE headers after injection + /// Wait for injection + /// Status code + 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 + ); + + /// + /// Manually map PE image + /// + /// Target PID + /// Full qualified image path + /// Mapping flags + /// Init routine RVA + /// Init routine argument + /// Status code + BLACKBONE_API NTSTATUS MmapDll( + DWORD pid, + const std::wstring& path, + KMmapFlags flags, + uint32_t initRVA = 0, + const std::wstring& initArg = L"" + ); + + /// + /// Manually map PE image + /// + /// Target PID + /// Memory location of the image to map + /// Image size + /// Memory chunk has image layout + /// Mapping flags + /// Init routine RVA + /// Init routine argument + /// Status code + BLACKBONE_API NTSTATUS MmapDll( + DWORD pid, + void* address, + uint32_t size, + bool asImage, + KMmapFlags flags, + uint32_t initRVA = 0, + const std::wstring& initArg = L"" + ); + + /// + /// Manually map another system driver into system space + /// + /// Fully quialified path to the drver + /// Status code + BLACKBONE_API NTSTATUS MMapDriver( const std::wstring& path ); + + /// + /// Make VAD region appear as PAGE_NO_ACESS to NtQueryVirtualMemory + /// + /// Target process ID + /// Region base + /// Region size + /// Status code + BLACKBONE_API NTSTATUS ConcealVAD( DWORD pid, ptr_t base, uint32_t size ); + + /// + /// Unlink process handle table from HandleListHead + /// + /// Target process ID + /// Status code + BLACKBONE_API NTSTATUS UnlinkHandleTable( DWORD pid ); + + /// + /// Enumerate committed, accessible, non-guarded memory regions + /// + /// Target process ID + /// Found regions + /// Status code + BLACKBONE_API NTSTATUS EnumMemoryRegions( DWORD pid, std::vector& regions ); + + /// + /// Check if driver is loaded + /// + /// + BLACKBONE_API inline bool loaded() const { return _hDriver != INVALID_HANDLE_VALUE; } + BLACKBONE_API inline NTSTATUS status() const { return _loadStatus; } + +private: + DriverControl( const DriverControl& ) = delete; + DriverControl& operator = (const DriverControl&) = delete; + + /// + /// Load arbitrary driver + /// + /// Driver service name + /// Driver file path + /// Status + NTSTATUS LoadDriver( const std::wstring& svcName, const std::wstring& path ); + + /// + /// Unload arbitrary driver + /// + /// Driver service name + /// Status + NTSTATUS UnloadDriver( const std::wstring& svcName ); + + /// + /// Fill minimum driver registry entry + /// + /// Driver service name + /// Driver path + /// Status code + LSTATUS PrepareDriverRegEntry( const std::wstring& svcName, const std::wstring& path ); +private: + FileHandle _hDriver; + NTSTATUS _loadStatus = STATUS_NOT_FOUND; +}; + +// Syntax sugar +inline DriverControl& Driver() { return DriverControl::Instance(); } + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Exports.def b/third/Blackbone/src/BlackBone/Exports.def new file mode 100644 index 0000000000000000000000000000000000000000..be6723eb59bb54b44cf442720cc34b5490d5b6e9 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Exports.def @@ -0,0 +1,2 @@ +EXPORTS + syscall_stub \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Include/ApiSet.h b/third/Blackbone/src/BlackBone/Include/ApiSet.h new file mode 100644 index 0000000000000000000000000000000000000000..0280e1314d7aeac7b1de3426784b25a06c528f63 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Include/ApiSet.h @@ -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; \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Include/CallResult.h b/third/Blackbone/src/BlackBone/Include/CallResult.h new file mode 100644 index 0000000000000000000000000000000000000000..3a5c88e5c9dec3a8221b3d69b0a08df4cbe36aa7 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Include/CallResult.h @@ -0,0 +1,99 @@ +#pragma once +#if _MSC_VER >= 1910 + +#include +#include + +namespace blackbone +{ +/// +/// Function result or failure status +/// +template +struct call_result_t +{ + NTSTATUS status = STATUS_UNSUCCESSFUL; // Execution status + std::optional 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 +#include + +namespace blackbone +{ + /// + /// Function result or failure status + /// + template + struct call_result_t + { + NTSTATUS status = STATUS_UNSUCCESSFUL; // Execution status + std::unique_ptr result_data; // Returned value + + call_result_t() = default; + + call_result_t(T result_, NTSTATUS status_ = STATUS_SUCCESS) + : status(status_) + , result_data(std::make_unique(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 \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Include/FunctionTypes.h b/third/Blackbone/src/BlackBone/Include/FunctionTypes.h new file mode 100644 index 0000000000000000000000000000000000000000..64eee568d8be5c7297d61724981a47e710afb5d4 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Include/FunctionTypes.h @@ -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* Tree, + _RTL_BALANCED_NODE* Parent, + BOOLEAN Right, + _RTL_BALANCED_NODE * 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* Tree, + _RTL_BALANCED_NODE* 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 + ); + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Include/HandleGuard.h b/third/Blackbone/src/BlackBone/Include/HandleGuard.h new file mode 100644 index 0000000000000000000000000000000000000000..0cccf185e5469cf48ab5183cce02228b8dd9f1e4 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Include/HandleGuard.h @@ -0,0 +1,90 @@ +#pragma once +#include "Winheaders.h" + +namespace blackbone +{ + +/// +/// Strong exception guarantee +/// +template +class HandleGuard +{ +public: + explicit HandleGuard( handle_t handle = zero_handle ) noexcept + : _handle( handle ) + { + } + + HandleGuard( HandleGuard&& rhs ) noexcept + : _handle( rhs._handle ) + { + rhs._handle = zero_handle; + } + + ~HandleGuard() + { + if (_handle != zero_handle) + close_fn( _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 (_handle != zero_handle) + close_fn( _handle ); + + _handle = handle; + } + + handle_t release() noexcept + { + auto tmp = _handle; + _handle = zero_handle; + return tmp; + } + + inline handle_t get() const noexcept { return _handle; } + + inline operator handle_t() const noexcept { return _handle; } + inline explicit operator bool() const noexcept { return _handle != zero_handle; } + + inline handle_t* operator &() noexcept { return &_handle; } + + inline bool operator ==( const HandleGuard& rhs ) const noexcept { return _handle == rhs._handle; } + inline bool operator <( const HandleGuard& rhs ) const noexcept { return _handle < rhs._handle; } + +private: + handle_t _handle; +}; + +using Handle = HandleGuard; +using FileHandle = HandleGuard; +using ACtxHandle = HandleGuard; +using FileMapHandle = HandleGuard; +using SnapHandle = FileHandle; +using RegHandle = HandleGuard; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Include/Macro.h b/third/Blackbone/src/BlackBone/Include/Macro.h new file mode 100644 index 0000000000000000000000000000000000000000..d8d70b5313389c30549e43711e5d2f5a6b45b6f0 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Include/Macro.h @@ -0,0 +1,138 @@ +#pragma once +#include "../Config.h" +#include + +// Architecture-dependent pointer size +#define WordSize 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(__VA_ARGS__) : f(__VA_ARGS__)) +#define FIELD_PTR_64_86(b, e, t, f) (b ? fieldPtr( e, &t::f ) : fieldPtr( e, &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(static_cast(a1) | static_cast(a2)); \ + } \ + \ + inline e operator |= (e& a1, e a2) { \ + return a1 = a1 | a2; \ + } \ + \ + inline e operator &(e a1, e a2) { \ + return static_cast(static_cast(a1)& static_cast(a2)); \ + } \ + \ + inline e operator &= (e& a1, e a2) { \ + return a1 = a1 & a2; \ + } \ + \ + inline e operator ~(e a1) { \ + return static_cast(~static_cast(a1)); \ + } + + +template +struct CompileTimeSizeOf; + +// offsetof alternative +template +constexpr size_t offsetOf( U T::*member ) +{ + return reinterpret_cast(&(reinterpret_cast(nullptr)->*member)); +} + +template +constexpr uint64_t fieldPtr( uint64_t base, U T::*member ) +{ + return base + offsetOf( member ); +} + +// CONTAINING_RECORD alternative +template +constexpr uint64_t structBase( uint64_t ptr, U T::*member ) +{ + return ptr - offsetOf( member ); +} + +// Type-unsafe cast. +template +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 * WordSize) + +using NTSTATUS = long; + +/// +/// Get last NT status +/// +/// +inline NTSTATUS LastNtStatus() +{ + return *(NTSTATUS*)((unsigned char*)NtCurrentTeb() + LAST_STATUS_OFS); +} + +/// +/// Set last NT status +/// +/// The status. +/// +inline NTSTATUS SetLastNtStatus( NTSTATUS status ) +{ + return *(NTSTATUS*)((unsigned char*)NtCurrentTeb() + LAST_STATUS_OFS) = status; +} + +#define SharedUserData32 ((KUSER_SHARED_DATA* const)0x7FFE0000) diff --git a/third/Blackbone/src/BlackBone/Include/NativeEnums.h b/third/Blackbone/src/BlackBone/Include/NativeEnums.h new file mode 100644 index 0000000000000000000000000000000000000000..c7f8f52d30bf506b466975ea1ea1b061b21c8605 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Include/NativeEnums.h @@ -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 +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Include/NativeStructures.h b/third/Blackbone/src/BlackBone/Include/NativeStructures.h new file mode 100644 index 0000000000000000000000000000000000000000..b8852461f3f6db59657f8d533f855b70f7a83ef2 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Include/NativeStructures.h @@ -0,0 +1,818 @@ +#pragma once + +#include "../Config.h" +#include "NativeEnums.h" + +#include "Winheaders.h" +#include + +#include + +namespace blackbone +{ + + +template +using const_int = std::integral_constant; + +template +constexpr bool is32bit = std::is_same_v; + +template +using type_32_64 = std::conditional_t, T32, T64>; + +template +constexpr int int_32_64 = std::conditional_t, const_int, const_int>::value; + +// nonstandard extension used : nameless struct/union +#pragma warning(disable : 4201) + +template +struct _LIST_ENTRY_T +{ + T Flink; + T Blink; +}; + +template +struct _UNICODE_STRING_T +{ + using type = T; + + uint16_t Length; + uint16_t MaximumLength; + T Buffer; +}; + +template +struct _NT_TIB_T +{ + T ExceptionList; + T StackBase; + T StackLimit; + T SubSystemTib; + T FiberData; + T ArbitraryUserPointer; + T Self; +}; + +template +struct _CLIENT_ID_T +{ + T UniqueProcess; + T UniqueThread; +}; + +template +struct _GDI_TEB_BATCH_T +{ + uint32_t Offset; + T HDC; + uint32_t Buffer[310]; +}; + +template +struct _ACTIVATION_CONTEXT_STACK_T +{ + T ActiveFrame; + _LIST_ENTRY_T FrameListCache; + uint32_t Flags; + uint32_t NextCookieSequenceNumber; + uint32_t StackId; +}; + +template +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 NtTib; + T EnvironmentPointer; + _CLIENT_ID_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]; + uint8_t PlaceholderCompatibilityMode; + uint8_t PlaceholderReserved[11]; + uint32_t ProxiedProcessId; + _ACTIVATION_CONTEXT_STACK_T ActivationStack; + uint8_t WorkingOnBehalfTicket[8]; + uint32_t ExceptionCode; + T ActivationContextStackPointer; + T InstrumentationCallbackSp; + T InstrumentationCallbackPreviousPc; + T InstrumentationCallbackPreviousSp; + type_32_64 spec1; + _GDI_TEB_BATCH_T GdiTebBatch; + _CLIENT_ID_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 StaticUnicodeString; + wchar_t StaticUnicodeBuffer[261]; + T DeallocationStack; + T TlsSlots[64]; + _LIST_ENTRY_T TlsLinks; + T Vdm; + T ReservedForNtRpc; + T DbgSsReserved[2]; + uint32_t HardErrorMode; + T Instrumentation[int_32_64]; + 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 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 +struct _PEB_T +{ + static_assert( std::is_same_v || std::is_same_v, "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 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 CSDVersion; + T ActivationContextData; + T ProcessAssemblyStorageMap; + T SystemDefaultActivationContextData; + T SystemAssemblyStorageMap; + T MinimumStackCommit; + T FlsCallback; + _LIST_ENTRY_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 +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 +struct _PROCESS_BASIC_INFORMATION_T +{ + NTSTATUS ExitStatus; + uint32_t Reserved0; + T PebBaseAddress; + T AffinityMask; + LONG BasePriority; + ULONG Reserved1; + T uUniqueProcessId; + T uInheritedFromUniqueProcessId; +}; + +template +struct _SECTION_BASIC_INFORMATION_T +{ + T Base; + uint32_t Attributes; + LARGE_INTEGER Size; +}; + +template +struct _PROCESS_EXTENDED_BASIC_INFORMATION_T +{ + T Size; // Must be set to structure size on input + _PROCESS_BASIC_INFORMATION_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 +struct _THREAD_BASIC_INFORMATION_T +{ + NTSTATUS ExitStatus; + T TebBaseAddress; + _CLIENT_ID_T ClientID; + T AffinityMask; + LONG Priority; + LONG BasePriority; +}; + +template +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 +struct _SYSTEM_THREAD_INFORMATION_T +{ + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER CreateTime; + uint32_t WaitTime; + T StartAddress; + _CLIENT_ID_T ClientId; + LONG Priority; + LONG BasePriority; + uint32_t ContextSwitches; + uint32_t ThreadState; + uint32_t WaitReason; +}; + +template +struct _SYSTEM_EXTENDED_THREAD_INFORMATION_T +{ + _SYSTEM_THREAD_INFORMATION_T ThreadInfo; + T StackBase; + T StackLimit; + T Win32StartAddress; + T TebBase; + T Reserved[3]; +}; + +template +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 ImageName; + LONG BasePriority; + T UniqueProcessId; + T InheritedFromUniqueProcessId; + uint32_t HandleCount; + uint32_t SessionId; + T UniqueProcessKey; + _VM_COUNTERS_T VmCounters; + T PrivatePageCount; + IO_COUNTERS IoCounters; + _SYSTEM_EXTENDED_THREAD_INFORMATION_T Threads[1]; +}; + +template +struct _SYSTEM_HANDLE_T +{ + uint32_t ProcessId; + uint8_t ObjectTypeNumber; + uint8_t Flags; + uint16_t Handle; + T Object; + ACCESS_MASK GrantedAccess; +}; + +template +struct _SYSTEM_HANDLE_INFORMATION_T +{ + uint32_t HandleCount; + _SYSTEM_HANDLE_T Handles[1]; +}; + +template +struct _OBJECT_TYPE_INFORMATION_T +{ + _UNICODE_STRING_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 +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 +struct _CONTEXT_T; + +template<> +struct _CONTEXT_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 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& FromCtx32( const _CONTEXT_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(ctx32.SegGs); + SegFs = static_cast(ctx32.SegFs); + SegEs = static_cast(ctx32.SegEs); + SegDs = static_cast(ctx32.SegDs); + SegCs = static_cast(ctx32.SegCs); + SegSs = static_cast(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 +struct _PEB_LDR_DATA2_T +{ + uint32_t Length; + uint8_t Initialized; + T SsHandle; + _LIST_ENTRY_T InLoadOrderModuleList; + _LIST_ENTRY_T InMemoryOrderModuleList; + _LIST_ENTRY_T InInitializationOrderModuleList; + T EntryInProgress; + uint8_t ShutdownInProgress; + T ShutdownThreadId; +}; + +template +struct _LDR_DATA_TABLE_ENTRY_BASE_T +{ + _LIST_ENTRY_T InLoadOrderLinks; + _LIST_ENTRY_T InMemoryOrderLinks; + _LIST_ENTRY_T InInitializationOrderLinks; + T DllBase; + T EntryPoint; + uint32_t SizeOfImage; + _UNICODE_STRING_T FullDllName; + _UNICODE_STRING_T BaseDllName; + uint32_t Flags; + uint16_t LoadCount; + uint16_t TlsIndex; + _LIST_ENTRY_T HashLinks; + uint32_t TimeDateStamp; + T EntryPointActivationContext; + T PatchInformation; +}; + +template +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; +using _UNICODE_STRING64 = _UNICODE_STRING_T; +using UNICODE_STRING_T = _UNICODE_STRING_T; + +using _PEB32 = _PEB_T; +using _PEB64 = _PEB_T; +using PEB_T = _PEB_T; + +using _TEB32 = _TEB_T; +using _TEB64 = _TEB_T; +using TEB_T = _TEB_T; + +using _PEB_LDR_DATA232 = _PEB_LDR_DATA2_T; +using _PEB_LDR_DATA264 = _PEB_LDR_DATA2_T; +using PEB_LDR_DATA_T = _PEB_LDR_DATA2_T; + +using _LDR_DATA_TABLE_ENTRY_BASE32 = _LDR_DATA_TABLE_ENTRY_BASE_T; +using _LDR_DATA_TABLE_ENTRY_BASE64 = _LDR_DATA_TABLE_ENTRY_BASE_T; +using LDR_DATA_TABLE_ENTRY_BASE_T = _LDR_DATA_TABLE_ENTRY_BASE_T; + +using _CONTEXT32 = _CONTEXT_T; +using _CONTEXT64 = _CONTEXT_T; +using CONTEXT_T = _CONTEXT_T; + +using _SECTION_BASIC_INFORMATION32 = _SECTION_BASIC_INFORMATION_T; +using _SECTION_BASIC_INFORMATION64 = _SECTION_BASIC_INFORMATION_T; +using SECTION_BASIC_INFORMATION_T = _SECTION_BASIC_INFORMATION_T; + +using _SYSTEM_HANDLE_INFORMATION32 = _SYSTEM_HANDLE_INFORMATION_T; +using _SYSTEM_HANDLE_INFORMATION64 = _SYSTEM_HANDLE_INFORMATION_T; +using SYSTEM_HANDLE_INFORMATION_T = _SYSTEM_HANDLE_INFORMATION_T; + +using _OBJECT_TYPE_INFORMATION32 = _OBJECT_TYPE_INFORMATION_T; +using _OBJECT_TYPE_INFORMATION64 = _OBJECT_TYPE_INFORMATION_T; +using OBJECT_TYPE_INFORMATION_T = _OBJECT_TYPE_INFORMATION_T; + +using _OBJECT_ATTRIBUTES32 = _OBJECT_ATTRIBUTES_T; +using _OBJECT_ATTRIBUTES64 = _OBJECT_ATTRIBUTES_T; +using OBJECT_ATTRIBUTES_T = _OBJECT_ATTRIBUTES_T; + +using _ACTCTXW32 = _ACTCTXW_T; +using _ACTCTXW64 = _ACTCTXW_T; +using ACTCTXW_T = _ACTCTXW_T; +} + +#include "ApiSet.h" + +// OS specific structures +#include "Win7Specific.h" +#include "Win8Specific.h" + +#ifdef XP_BUILD +#include "WinXPSpecific.h" +#endif diff --git a/third/Blackbone/src/BlackBone/Include/Types.h b/third/Blackbone/src/BlackBone/Include/Types.h new file mode 100644 index 0000000000000000000000000000000000000000..6d9ca098a9ab2fef3f81074fef59f9b4ef3f9bf6 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Include/Types.h @@ -0,0 +1,84 @@ +#pragma once + +#include "NativeStructures.h" +#include "FunctionTypes.h" + +#include +#include +#include + +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, // 64 bit module + mt_mod64, // 32 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; + +} diff --git a/third/Blackbone/src/BlackBone/Include/Win7Specific.h b/third/Blackbone/src/BlackBone/Include/Win7Specific.h new file mode 100644 index 0000000000000000000000000000000000000000..6f0ad5c6dff24ca550ed3d7d6dd4d5bc456a5bff --- /dev/null +++ b/third/Blackbone/src/BlackBone/Include/Win7Specific.h @@ -0,0 +1,27 @@ +#pragma once + +#include "Winheaders.h" + +namespace blackbone +{ +template +struct _LDR_DATA_TABLE_ENTRY_W7 : _LDR_DATA_TABLE_ENTRY_BASE_T +{ + _LIST_ENTRY_T ForwarderLinks; + _LIST_ENTRY_T ServiceTagLinks; + _LIST_ENTRY_T StaticLinks; + T ContextInformation; + uint32_t OriginalBase; + LARGE_INTEGER LoadTime; +}; + +template +struct _RTL_INVERTED_FUNCTION_TABLE7 +{ + uint32_t Count; + uint32_t MaxCount; + uint32_t Epoch; + _RTL_INVERTED_FUNCTION_TABLE_ENTRY Entries[0x200]; +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Include/Win8Specific.h b/third/Blackbone/src/BlackBone/Include/Win8Specific.h new file mode 100644 index 0000000000000000000000000000000000000000..ca4d802cfc1f78f78ccb99c1bdea7005b4393248 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Include/Win8Specific.h @@ -0,0 +1,74 @@ +#pragma once + +#include "Winheaders.h" + +namespace blackbone +{ + +template +struct _RTL_RB_TREE +{ + T Root; + T Min; +}; + +template +struct _RTL_BALANCED_NODE +{ + T Left; + T Right; + T ParentValue; +}; + +template +struct _LDR_DDAG_NODE +{ + _LIST_ENTRY_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 +struct _LDR_DATA_TABLE_ENTRY_W8 : _LDR_DATA_TABLE_ENTRY_BASE_T +{ + T DdagNode; // _LDR_DDAG_NODE* + _LIST_ENTRY_T NodeModuleLink; + T SnapContext; + T ParentDllBase; + T SwitchBackContext; + _RTL_BALANCED_NODE BaseAddressIndexNode; + _RTL_BALANCED_NODE MappingInfoIndexNode; + T OriginalBase; + LARGE_INTEGER LoadTime; + uint32_t BaseNameHashValue; + _LDR_DLL_LOAD_REASON LoadReason; + uint32_t ImplicitPathOptions; +}; + +template +struct _RTL_INVERTED_FUNCTION_TABLE8 +{ + ULONG Count; + ULONG MaxCount; + ULONG Epoch; + UCHAR Overflow; + _RTL_INVERTED_FUNCTION_TABLE_ENTRY Entries[0x200]; +}; + +using _LDR_DATA_TABLE_ENTRY_W832 = _LDR_DATA_TABLE_ENTRY_W8; +using _LDR_DATA_TABLE_ENTRY_W864 = _LDR_DATA_TABLE_ENTRY_W8; +using LDR_DATA_TABLE_ENTRY_W8T = _LDR_DATA_TABLE_ENTRY_W8; + +using _LDR_DDAG_NODE_32 = _LDR_DDAG_NODE; +using _LDR_DDAG_NODE_64 = _LDR_DDAG_NODE; +using LDR_DDAG_NODE_T = _LDR_DDAG_NODE; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Include/WinXPSpecific.h b/third/Blackbone/src/BlackBone/Include/WinXPSpecific.h new file mode 100644 index 0000000000000000000000000000000000000000..82bc30af26a8c02e52f56b9dcfaa9979b289ff98 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Include/WinXPSpecific.h @@ -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; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Include/Winheaders.h b/third/Blackbone/src/BlackBone/Include/Winheaders.h new file mode 100644 index 0000000000000000000000000000000000000000..deb0274959b0a09442e1059fd0c50fbcad68e533 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Include/Winheaders.h @@ -0,0 +1,16 @@ +#pragma once + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include +#include +#include +#include +#include + +#pragma warning(push) +#pragma warning(disable : 4005) +#include +#pragma warning(pop) \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/LocalHook/HookHandlerCdecl.h b/third/Blackbone/src/BlackBone/LocalHook/HookHandlerCdecl.h new file mode 100644 index 0000000000000000000000000000000000000000..463f4e5bc8064b45b686a4d1c54c2e3beb1fa3fe --- /dev/null +++ b/third/Blackbone/src/BlackBone/LocalHook/HookHandlerCdecl.h @@ -0,0 +1,69 @@ +#pragma once + +namespace blackbone +{ + +template +struct HookHandler : public DetourBase +{ + using ReturnType = std::conditional_t, 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 )... ); + } + + ReturnType HandlerP( Args&&... args ) + { + ReturnType val_new, val_original; + + DisableHook(); + + if (_order == CallOrder::HookFirst) + { + val_new = CallCallback( std::forward( args )... ); + val_original = CallOriginal( std::forward( args )... ); + } + else if (_order == CallOrder::HookLast) + { + val_original = CallOriginal( std::forward( args )... ); + val_new = CallCallback( std::forward( args )... ); + } + else + { + val_original = val_new = CallCallback( std::forward( args )... ); + } + + if (this->_hooked) + EnableHook(); + + return (_retType == ReturnMethod::UseOriginal ? val_original : val_new); + } + + inline ReturnType CallOriginal( Args&&... args ) + { + return (reinterpret_cast(_callOriginal))(args...); + } + + inline ReturnType CallCallback( Args&&... args ) + { + if (_callbackClass != nullptr) + return (reinterpret_cast(_callbackClass)->*brutal_cast(_callback))(args...); + else + return (reinterpret_cast(_callback))(args...); + } +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/LocalHook/HookHandlerFastcall.h b/third/Blackbone/src/BlackBone/LocalHook/HookHandlerFastcall.h new file mode 100644 index 0000000000000000000000000000000000000000..fc234328f5344e43c6bbe9f17fb6c3844ce91872 --- /dev/null +++ b/third/Blackbone/src/BlackBone/LocalHook/HookHandlerFastcall.h @@ -0,0 +1,69 @@ +#pragma once + +namespace blackbone +{ + +template +struct HookHandler : public DetourBase +{ + using ReturnType = std::conditional_t, 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 )... ); + } + + ReturnType HandlerP( Args&&... args ) + { + ReturnType val_new, val_original; + + DisableHook(); + + if (_order == CallOrder::HookFirst) + { + val_new = CallCallback( std::forward( args )... ); + val_original = CallOriginal( std::forward( args )... ); + } + else if (_order == CallOrder::HookLast) + { + val_original = CallOriginal( std::forward( args )... ); + val_new = CallCallback( std::forward( args )... ); + } + else + { + val_original = val_new = CallCallback( std::forward( args )... ); + } + + if (this->_hooked) + EnableHook(); + + return (_retType == ReturnMethod::UseOriginal ? val_original : val_new); + } + + inline ReturnType CallOriginal( Args&&... args ) + { + return (reinterpret_cast(_callOriginal))(args...); + } + + inline ReturnType CallCallback( Args&&... args ) + { + if (_callbackClass != nullptr) + return ((C*)_callbackClass->*brutal_cast(_callback))(args...); + else + return (reinterpret_cast(_callback))(args...); + } +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/LocalHook/HookHandlerStdcall.h b/third/Blackbone/src/BlackBone/LocalHook/HookHandlerStdcall.h new file mode 100644 index 0000000000000000000000000000000000000000..323880c6ee1f4311e78f6f5c7b5c1b686cd084d4 --- /dev/null +++ b/third/Blackbone/src/BlackBone/LocalHook/HookHandlerStdcall.h @@ -0,0 +1,69 @@ +#pragma once + +namespace blackbone +{ + +template +struct HookHandler : public DetourBase +{ + using ReturnType = std::conditional_t, 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 )... ); + } + + ReturnType HandlerP( Args&&... args ) + { + ReturnType val_new, val_original; + + DisableHook(); + + if (_order == CallOrder::HookFirst) + { + val_new = CallCallback( std::forward( args )... ); + val_original = CallOriginal( std::forward( args )... ); + } + else if (_order == CallOrder::HookLast) + { + val_original = CallOriginal( std::forward( args )... ); + val_new = CallCallback( std::forward( args )... ); + } + else + { + val_original = val_new = CallCallback( std::forward( args )... ); + } + + if (this->_hooked) + EnableHook(); + + return (_retType == ReturnMethod::UseOriginal ? val_original : val_new); + } + + inline ReturnType CallOriginal( Args&&... args ) + { + return (reinterpret_cast(_callOriginal))(args...); + } + + inline ReturnType CallCallback( Args&&... args ) + { + if (_callbackClass != nullptr) + return ((C*)_callbackClass->*brutal_cast(_callback))(args...); + else + return (reinterpret_cast(_callback))(args...); + } +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/LocalHook/HookHandlerThiscall.h b/third/Blackbone/src/BlackBone/LocalHook/HookHandlerThiscall.h new file mode 100644 index 0000000000000000000000000000000000000000..3cd502ee65af4d647b38e78ff66dfa96e3650f98 --- /dev/null +++ b/third/Blackbone/src/BlackBone/LocalHook/HookHandlerThiscall.h @@ -0,0 +1,69 @@ +#pragma once + +namespace blackbone +{ + +template +struct HookHandler : public DetourBase +{ + using ReturnType = std::conditional_t, 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 )... ); + } + + ReturnType HandlerP( Args&&... args ) + { + ReturnType val_new, val_original; + + DisableHook(); + + if (_order == CallOrder::HookFirst) + { + val_new = CallCallback( std::forward( args )... ); + val_original = CallOriginal( std::forward( args )... ); + } + else if (_order == CallOrder::HookLast) + { + val_original = CallOriginal( std::forward( args )... ); + val_new = CallCallback( std::forward( args )... ); + } + else + { + val_original = val_new = CallCallback( std::forward( args )... ); + } + + if (this->_hooked) + EnableHook(); + + return (_retType == ReturnMethod::UseOriginal ? val_original : val_new); + } + + inline ReturnType CallOriginal( Args&&... args ) + { + return (reinterpret_cast(_callOriginal))( args...); + } + + inline ReturnType CallCallback( Args&&... args ) + { + if (_callbackClass != nullptr) + return ((C*)_callbackClass->*brutal_cast(_callback))( args...); + else + return (reinterpret_cast(_callback))( args...); + } +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/LocalHook/HookHandlers.h b/third/Blackbone/src/BlackBone/LocalHook/HookHandlers.h new file mode 100644 index 0000000000000000000000000000000000000000..ad90a004a60585764b8182919ad33c3ffeb38e88 --- /dev/null +++ b/third/Blackbone/src/BlackBone/LocalHook/HookHandlers.h @@ -0,0 +1,19 @@ +#pragma once + +#include "LocalHookBase.h" + +namespace blackbone +{ + class BLACKBONE_API NoClass { }; + + template + struct HookHandler; +} + +#include "HookHandlerCdecl.h" + +#ifndef USE64 +#include "HookHandlerStdcall.h" +#include "HookHandlerThiscall.h" +#include "HookHandlerFastcall.h" +#endif \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/LocalHook/LocalHook.hpp b/third/Blackbone/src/BlackBone/LocalHook/LocalHook.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8aad7227fcb1c3907e55a4d49328fa06fc3171ab --- /dev/null +++ b/third/Blackbone/src/BlackBone/LocalHook/LocalHook.hpp @@ -0,0 +1,252 @@ +#pragma once + +#include "HookHandlers.h" +#include "../Process/Process.h" + +namespace blackbone +{ + +template +class Detour: public HookHandler +{ +public: + using type = typename HookHandler::type; + using hktype = typename HookHandler::hktype; + using hktypeC = typename HookHandler::hktypeC; + +public: + Detour() + { + this->_internalHandler = &HookHandler::Handler; + } + + ~Detour() + { + Restore(); + } + + /// + /// Hook function + /// + /// Target function address + /// Hook function address + /// Hooking method + /// Call order. Hook before original or vice versa + /// Return value. Use origianl or value from hook + /// true on success + 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(ptr) )) + return false; + + switch (this->_type) + { + case HookType::Inline: + return HookInline(); + + case HookType::Int3: + return HookInt3(); + + case HookType::HWBP: + return HookHWBP(); + + default: + return false; + } + } + + /// + /// Hook function + /// + /// Target function address + /// Hook class member address + /// Hook class address + /// Hooking method + /// Call order. Hook before original or vice versa + /// Return value. Use origianl or value from hook + /// true on success + 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(hkPtr), type, order, retType ); + } + + + /// + /// Restore hooked function + /// + /// true on success, false if not hooked + 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(this->_original) ); + + this->_hwbpIdx.clear(); + } + break; + + default: + break; + } + + this->_hooked = false; + return true; + } + +private: + + /// + /// Perform inline hook + /// + /// true on success + 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::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; + } + + /// + /// Perform int3 hook + /// + /// true on success + 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; + } + + /// + /// Perform hardware breakpoint hook + /// + /// true on success + 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(this->_original), hwbp_execute, hwbp_1 ).result(); + + return this->_hooked = true; + } +}; + +} diff --git a/third/Blackbone/src/BlackBone/LocalHook/LocalHookBase.cpp b/third/Blackbone/src/BlackBone/LocalHook/LocalHookBase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e3c99863915ae9ea58b125387cbf1e6630c903b8 --- /dev/null +++ b/third/Blackbone/src/BlackBone/LocalHook/LocalHookBase.cpp @@ -0,0 +1,260 @@ +#include "LocalHookBase.h" + +namespace blackbone +{ +std::unordered_map DetourBase::_breakpoints; +void* DetourBase::_vecHandler = nullptr; + +DetourBase::DetourBase() +{ +} + +DetourBase::~DetourBase() +{ + VirtualFree( _buf, 0, MEM_RELEASE ); +} + +/// +/// Allocate detour buffer as close to target as possible +/// +/// Target address +/// true on success +bool DetourBase::AllocateBuffer( uint8_t* nearest ) +{ + if (_buf != nullptr) + return true; + + MEMORY_BASIC_INFORMATION mbi = { 0 }; + for (SIZE_T addr = (SIZE_T)nearest; addr > (SIZE_T)nearest - 0x80000000; addr = (SIZE_T)mbi.BaseAddress - 1) + { + if (!VirtualQuery( (LPCVOID)addr, &mbi, sizeof( mbi ) )) + break; + + if (mbi.State == MEM_FREE) + { + _buf = (uint8_t*)VirtualAlloc( + (uint8_t*)mbi.BaseAddress + mbi.RegionSize - 0x1000, 0x1000, + MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE + ); + + if (_buf) + break; + } + } + + // If allocating a memory page failed, allocate first suitable + if (_buf == nullptr) + _buf = (uint8_t*)VirtualAlloc( nullptr, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + + _origCode = _buf + 0x100; + _origThunk = _buf + 0x200; + _newCode = _buf + 0x300; + + return _buf != nullptr; +} + + +/// +/// Temporarily disable hook +/// +/// true on success +bool DetourBase::DisableHook() +{ + if (_type == HookType::InternalInline || _type == HookType::Int3) + WriteProcessMemory( GetCurrentProcess(), _original, _origCode, _origSize, NULL ); + else if (_type == HookType::HWBP) + ToggleHBP( _hwbpIdx[GetCurrentThreadId()], false ); + + return true; +} + +/// +/// Enable disabled hook +/// +/// true on success +bool DetourBase::EnableHook() +{ + if (_type == HookType::InternalInline || _type == HookType::Int3) + WriteProcessMemory( GetCurrentProcess(), _original, _newCode, _origSize, NULL ); + else if (_type == HookType::HWBP) + ToggleHBP( _hwbpIdx[GetCurrentThreadId()], true ); + + return true; +} + +/// +/// Toggle hardware breakpoint for current thread +/// +/// Breakpoint index ( 0-4 ) +/// true to enable, false to disable +/// true on success +bool DetourBase::ToggleHBP( int index, bool enable ) +{ + CONTEXT context = { 0 }; + context.ContextFlags = CONTEXT_DEBUG_REGISTERS; + + if (GetThreadContext( GetCurrentThread(), &context ) != TRUE) + return FALSE; + + if (enable) + BitTestAndSetT( (LONG_PTR*)&context.Dr7, 2 * index ); + else + BitTestAndResetT( (LONG_PTR*)&context.Dr7, 2 * index ); + + return (SetThreadContext( GetCurrentThread(), &context ) != FALSE); +} + +/// +/// Copy original function bytes +/// +/// Origianl function address +void DetourBase::CopyOldCode( uint8_t* ptr ) +{ + // Store original bytes + uint8_t* src = ptr; + uint8_t* thunk = _origThunk, *original = _origCode; + uint32_t all_len = 0; + ldasm_data ld = { 0 }; + + do + { + uint32_t len = ldasm( src, &ld, is_x64 ); + + // Determine code end + if (ld.flags & F_INVALID + || (len == 1 && (src[ld.opcd_offset] == 0xCC || src[ld.opcd_offset] == 0xC3)) + || (len == 3 && src[ld.opcd_offset] == 0xC2) + || len + all_len > 128) + { + break; + } + + // move instruction + memcpy( original, src, len ); + memcpy( thunk, src, len ); + + // if instruction has relative offset, calculate new offset + if (ld.flags & F_RELATIVE) + { + int32_t diff = 0; + const uintptr_t ofst = (ld.disp_offset != 0 ? ld.disp_offset : ld.imm_offset); + const uintptr_t sz = ld.disp_size != 0 ? ld.disp_size : ld.imm_size; + + memcpy( &diff, src + ofst, sz ); + + #ifdef USE64 + // exit if jump is greater then 2GB + if (_abs64( src + len + diff - thunk ) > INT_MAX) + { + break; + } + else + { + diff += static_cast(src - thunk); + memcpy( thunk + ofst, &diff, sz ); + } + #else + diff += src - thunk; + memcpy( thunk + ofst, &diff, sz ); + #endif + } + + src += len; + thunk += len; + original += len; + all_len += len; + } while (all_len < _origSize); + + // Failed to copy old code, use backup plan + if (all_len < _origSize) + { + _type = HookType::InternalInline; + memcpy( _origCode, ptr, _origSize ); + } + else + { + SET_JUMP( thunk, src ); + _callOriginal = _origThunk; + } +} + + +/// +/// Exception handler +/// +/// Exception information +/// Exception disposition +LONG NTAPI DetourBase::VectoredHandler( PEXCEPTION_POINTERS excpt ) +{ + switch (excpt->ExceptionRecord->ExceptionCode) + { + case static_cast(EXCEPTION_BREAKPOINT): + return Int3Handler( excpt ); + + case static_cast(EXCEPTION_ACCESS_VIOLATION): + return AVHandler( excpt ); + + case static_cast(EXCEPTION_SINGLE_STEP): + return StepHandler( excpt ); + + default: + return EXCEPTION_CONTINUE_SEARCH; + } +} + +/// +/// Int3 exception handler +/// +/// Exception information +/// Exception disposition +LONG NTAPI DetourBase::Int3Handler( PEXCEPTION_POINTERS excpt ) +{ + if (_breakpoints.count( excpt->ExceptionRecord->ExceptionAddress )) + { + DetourBase* pInst = _breakpoints[excpt->ExceptionRecord->ExceptionAddress]; + + ((_NT_TIB*)NtCurrentTeb())->ArbitraryUserPointer = (void*)pInst; + excpt->ContextRecord->NIP = (uintptr_t)pInst->_internalHandler; + + return EXCEPTION_CONTINUE_EXECUTION; + } + + return EXCEPTION_CONTINUE_SEARCH; +} + +/// +/// Access violation handler +/// +/// Exception information +/// Exception disposition +LONG NTAPI DetourBase::AVHandler( PEXCEPTION_POINTERS /*excpt*/ ) +{ + return EXCEPTION_CONTINUE_SEARCH; +} + +/// +/// Single step exception handler +/// +/// Exception information +/// Exception disposition +LONG NTAPI DetourBase::StepHandler( PEXCEPTION_POINTERS excpt ) +{ + DWORD index = 0; + int found = _BitScanForward( &index, static_cast(excpt->ContextRecord->Dr6) ); + + if (found != 0 && index < 4 && _breakpoints.count( excpt->ExceptionRecord->ExceptionAddress )) + { + DetourBase* pInst = _breakpoints[excpt->ExceptionRecord->ExceptionAddress]; + + // Disable breakpoint at current index + BitTestAndResetT( (LONG_PTR*)&excpt->ContextRecord->Dr7, 2 * index ); + + ((_NT_TIB*)NtCurrentTeb())->ArbitraryUserPointer = (void*)pInst; + excpt->ContextRecord->NIP = (uintptr_t)pInst->_internalHandler; + + return EXCEPTION_CONTINUE_EXECUTION; + } + return EXCEPTION_CONTINUE_SEARCH; +} + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/LocalHook/LocalHookBase.h b/third/Blackbone/src/BlackBone/LocalHook/LocalHookBase.h new file mode 100644 index 0000000000000000000000000000000000000000..cb0ee9a46791fe303b458b4e253953f65c75045c --- /dev/null +++ b/third/Blackbone/src/BlackBone/LocalHook/LocalHookBase.h @@ -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 +#include + +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; + +public: + BLACKBONE_API DetourBase(); + BLACKBONE_API ~DetourBase(); + +protected: + + /// + /// Allocate detour buffer as close to target as possible + /// + /// Target address + /// true on success + BLACKBONE_API bool AllocateBuffer( uint8_t* nearest ); + + /// + /// Temporarily disable hook + /// + /// true on success + BLACKBONE_API bool DisableHook(); + + /// + /// Enable disabled hook + /// + /// true on success + BLACKBONE_API bool EnableHook(); + + /// + /// Toggle hardware breakpoint for current thread + /// + /// Breakpoint index ( 0-4 ) + /// true to enable, false to disable + /// true on success + BLACKBONE_API bool ToggleHBP( int index, bool enable ); + + /// + /// Copy original function bytes + /// + /// Origianl function address + BLACKBONE_API void CopyOldCode( uint8_t* Ptr ); + + /// + /// Exception handlers + /// + /// Exception information + /// Exception disposition + 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 _breakpoints; + + // Exception handler + BLACKBONE_API static void* _vecHandler; +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/LocalHook/TraceHook.cpp b/third/Blackbone/src/BlackBone/LocalHook/TraceHook.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d7f71a52d2088928f8308ddc1ca4c9938fd0458f --- /dev/null +++ b/third/Blackbone/src/BlackBone/LocalHook/TraceHook.cpp @@ -0,0 +1,458 @@ +#include "../Config.h" +#include "TraceHook.h" +#include "../Include/Macro.h" + +#define BEA_USE_STDCALL +//#define BEA_ENGINE_STATIC +#include <3rd_party/BeaEngine/headers/BeaEngine.h> + +#include + +#define HIGHEST_BIT_SET (1LL << (sizeof(void*) * 8 - 1)) +#define HIGHEST_BIT_UNSET ~HIGHEST_BIT_SET +#define SingleStep 0x100 + +// Architecture-specific +#ifdef USE64 +#define ADDR_MASK 0xFFFFFFFFFFFFF000 +#else +#define ADDR_MASK 0xFFFFF000 +#endif + +namespace blackbone +{ + +TraceHook::TraceHook() +{ +} + +TraceHook::~TraceHook() +{ + if (_pExptHandler != nullptr) + RemoveVectoredExceptionHandler( _pExptHandler ); +} + +TraceHook& TraceHook::Instance() +{ + static TraceHook instance; + return instance; +} + +/// +/// Setup hook +/// +/// Target function to be hooked +/// New function +/// Address of pointer to destroy +/// Function tracing path +/// Optional. Address of instruction that checks target pointer +/// true on success, false if already hooked +bool TraceHook::ApplyHook( void* targetFunc, + void* hookFunc, + void* ptrAddress, + const HookContext::vecState& tracePath /*= HookContext::vecState()*/, + void* chekcIP /*= 0*/) +{ + // Pointer already present + if (_contexts.count( (uintptr_t)ptrAddress )) + { + HookContext& ctx = _contexts[(uintptr_t)ptrAddress]; + + // Already hooked + if (ctx.hooks.count( (uintptr_t)targetFunc )) + return false; + else + ctx.hooks.emplace( (uintptr_t)targetFunc, std::make_pair( (uintptr_t)hookFunc, false ) ); + } + // Create new context + else + { + HookContext ctx; + + // Setup context + ctx.targetPtr = (uintptr_t)ptrAddress; + ctx.checkIP = (uintptr_t)chekcIP; + ctx.origPtrVal = *(uintptr_t*)ptrAddress; + ctx.breakValue = _breakPtr; + ctx.tracePath = tracePath; + + ctx.hooks.emplace( (uintptr_t)targetFunc, std::make_pair( (uintptr_t)hookFunc, false ) ); + _contexts.emplace( (uintptr_t)ptrAddress, std::move( ctx ) ); + + if (_pExptHandler == nullptr) + _pExptHandler = AddVectoredExceptionHandler( 0, &TraceHook::VecHandler ); + + // Setup exception + *(uintptr_t*)ptrAddress = ctx.breakValue; + _breakPtr += 0x10; + } + + return true; +} + +/// +/// Remove existing hook +/// +/// Target function ptr +/// true on success, false if not found +bool TraceHook::RemoveHook( void* targetFunc ) +{ + auto findfn = [targetFunc]( const mapContext::value_type& val ) { + return val.second.hooks.count( (uintptr_t)targetFunc ); + }; + + // Get context containing target function + auto iter = std::find_if( _contexts.begin(), _contexts.end(), findfn ); + + if (iter != _contexts.end()) + { + auto& ctx = iter->second; + + // Remove function from list + ctx.hooks.erase( (uintptr_t)targetFunc ); + + if (ctx.hooks.empty()) + { + // Remove hook itself + *(uintptr_t*)ctx.targetPtr = ctx.origPtrVal; + _contexts.erase( iter ); + } + + // Before handler is removed we need to make sure no thread will + // generate exception again + Sleep( 10 ); + + // Remove exception handler + if (_contexts.empty() && _pExptHandler != nullptr) + { + RemoveVectoredExceptionHandler( _pExptHandler ); + _pExptHandler = nullptr; + } + + return true; + } + + return false; +} + + +/// +/// Exception handler +/// +/// The exception information +/// Handling status +LONG __stdcall TraceHook::VecHandler( PEXCEPTION_POINTERS ExceptionInfo ) +{ + return Instance().VecHandlerP( ExceptionInfo ); +} + +/// +/// Exception handler +/// +/// The exception information +/// Handling status +LONG TraceHook::VecHandlerP( PEXCEPTION_POINTERS ExceptionInfo ) +{ + auto exptContex = ExceptionInfo->ContextRecord; + auto exptRecord = ExceptionInfo->ExceptionRecord; + auto exptCode = exptRecord->ExceptionCode; + + // TODO: Somehow determine current hook context + HookContext* ctx = &_contexts.begin()->second; + + // Check if exception should be handled + if (exptCode != EXCEPTION_SINGLE_STEP && exptCode != EXCEPTION_ACCESS_VIOLATION) + { + return EXCEPTION_CONTINUE_SEARCH; + } + else if (exptCode == EXCEPTION_ACCESS_VIOLATION && (ctx->state == TS_Step || ctx->state == TS_StepInto)) + { + if ((exptRecord->ExceptionInformation[1] & ADDR_MASK) != (ctx->breakValue & ADDR_MASK)) + return EXCEPTION_CONTINUE_SEARCH; + + // Pointer accessed by non-target address + if (ctx->checkIP != 0 && exptContex->NIP != ctx->checkIP) + { + exptContex->EFlags |= SingleStep; + + RestorePtr( *ctx, ExceptionInfo ); + return EXCEPTION_CONTINUE_EXECUTION; + } + } + + switch (ctx->state) + { + // Start of tracing + case TS_Start: + { + ctx->state = ctx->tracePath[ctx->stateIdx].action; + + RestorePtr( *ctx, ExceptionInfo ); + return VecHandlerP( ExceptionInfo ); + } + break; + + // Single step + case TS_Step: + { + // Function call occurred. Queue break on return. + if (CheckBranching( *ctx, exptContex->NIP, exptContex->NSP )) + { + // Target function reached + if (ctx->hooks.count( exptContex->NIP )) + { + HandleBranch( *ctx, exptContex ); + return EXCEPTION_CONTINUE_EXECUTION; + } + else + { + ctx->state = TS_WaitReturn; + BreakOnReturn( exptContex->NSP ); + } + } + // Step further + else + exptContex->EFlags |= SingleStep; + } + break; + + // Step out from function + case TS_StepOut: + { + // Get current stack frame + vecStackFrames frames; + StackBacktrace( exptContex->NIP, exptContex->NSP, frames, 1 ); + + if (frames.size() > 1) + { + ctx->stateIdx++; + ctx->state = TS_WaitReturn; + BreakOnReturn( frames.back().first ); + } + } + break; + + // Step into specific function + case TS_StepInto: + { + // Check if step into path function has occurred + if (CheckBranching( *ctx, exptContex->NIP, exptContex->NSP )) + { + if (exptContex->NIP == ctx->tracePath[ctx->stateIdx].arg) + { + ctx->stateIdx++; + ctx->state = ctx->tracePath[ctx->stateIdx].action; + } + } + + exptContex->EFlags |= SingleStep; + } + break; + + // Break on 'ret' instruction + case TS_WaitReturn: + { + exptContex->NIP &= HIGHEST_BIT_UNSET; + + // Restore stack for x64 + #ifdef USE64 + *(uintptr_t*)exptContex->NSP &= HIGHEST_BIT_UNSET; + #endif // USE64 + + // Continue stepping + exptContex->EFlags |= SingleStep; + ctx->state = ctx->tracePath[ctx->stateIdx].action; + } + break; + + default: + break; + } + + ctx->lastIP = exptContex->NIP; + ctx->lastSP = exptContex->NSP; + + return EXCEPTION_CONTINUE_EXECUTION; +} + + +/// +/// Check if last instruction caused branching +/// +/// Current hook info +/// Instruction pointer +/// Stack pointer +/// True if branching has occurred +bool TraceHook::CheckBranching( const HookContext& ctx, uintptr_t ip, uintptr_t sp ) +{ + // Not yet initialized + if (ctx.lastIP == 0 || ctx.lastSP == 0) + return false; + + // Difference in instruction pointer more than possible 'call' length + // Stack pointer changed + if (ip - ctx.lastIP >= 8 && sp != ctx.lastSP) + { + DISASM info = { 0 }; + info.EIP = ctx.lastIP; + + #ifdef USE64 + info.Archi = 64; + #endif + + // FIXME: Alternateve for MinGW +#ifdef COMPILER_MSVC + // Double-check call instruction using disasm + if (Disasm( &info ) > 0 && info.Instruction.BranchType == CallType) + return true; +#endif //COMPILER_MSVC + } + + return false; +} + +/// +/// Handle branching +/// +/// Current hook context +/// Thread context +void TraceHook::HandleBranch( HookContext& ctx, PCONTEXT exptContex ) +{ + // Mark this hook as called + ctx.hooks[exptContex->NIP].second = true; + + // Reset tracing state if all hooks were called + auto iter = std::find_if( ctx.hooks.begin(), ctx.hooks.end(), + []( const decltype(ctx.hooks)::value_type& val ){ return (val.second.second == false); } ); + + // Break after hook execution + if (iter != ctx.hooks.end()) + { + ctx.state = TS_WaitReturn; + BreakOnReturn( exptContex->NSP ); + } + // Reset state + else + ctx.reset(); + + // Reroute to hook function + exptContex->NIP = ctx.hooks[exptContex->NIP].first; +} + + +/// +/// Setup exception upon function return +/// +/// The exception information +inline void TraceHook::BreakOnReturn( uintptr_t sp ) +{ + *(DWORD_PTR*)sp |= HIGHEST_BIT_SET; +} + +/// +/// Restore original pointer value +/// +/// The CTX. +/// The exception information +/// true on success, false if no invalid register was found +bool TraceHook::RestorePtr( const HookContext& ctx, PEXCEPTION_POINTERS ExceptionInfo ) +{ + bool found = false; + auto expCtx = ExceptionInfo->ContextRecord; + + // Exception on execute + if (ExceptionInfo->ExceptionRecord->ExceptionInformation[0] == 8) + { + expCtx->NIP = ctx.origPtrVal; + return true; + } + + // Exception on read/write +#ifdef USE64 + for (DWORD_PTR* pRegVal = &expCtx->Rax; pRegVal <= &expCtx->R15; pRegVal++) +#else + for (DWORD_PTR* pRegVal = &expCtx->NDI; pRegVal <= &expCtx->NAX; pRegVal++) +#endif + { + // Compare high address parts + if ((*pRegVal & ADDR_MASK) == (ExceptionInfo->ExceptionRecord->ExceptionInformation[1] & ADDR_MASK)) + { + *pRegVal = ctx.origPtrVal; + found = true; + } + } + + return found; +} + +/// +/// Capture stack frames +/// +/// Current instruction pointer +/// Current stack pointer +/// Found frames. +/// Frame depth limit +/// Number of found frames +size_t TraceHook::StackBacktrace( uintptr_t ip, uintptr_t sp, vecStackFrames& results, uintptr_t depth /*= 10 */ ) +{ + SYSTEM_INFO sysinfo = {}; + uintptr_t stack_base = (uintptr_t)((PNT_TIB)NtCurrentTeb())->StackBase; + + GetNativeSystemInfo( &sysinfo ); + + // Store exception address + results.emplace_back( 0, ip ); + + // Walk stack + for (uintptr_t stackPtr = sp; stackPtr < stack_base && results.size() <= depth; stackPtr += sizeof(void*)) + { + uintptr_t stack_val = *(uintptr_t*)stackPtr; + MEMORY_BASIC_INFORMATION meminfo = { 0 }; + + // Decode value + uintptr_t original = stack_val & HIGHEST_BIT_UNSET; + + // Invalid value + if ( original < (uintptr_t)sysinfo.lpMinimumApplicationAddress || + original > (uintptr_t)sysinfo.lpMaximumApplicationAddress) + { + continue; + } + + // Check if memory is executable + if (VirtualQuery( (LPVOID)original, &meminfo, sizeof(meminfo) ) != sizeof(meminfo)) + continue; + + if ( meminfo.Protect != PAGE_EXECUTE_READ && + meminfo.Protect != PAGE_EXECUTE_WRITECOPY && + meminfo.Protect != PAGE_EXECUTE_READWRITE) + { + continue; + } + + // Detect 'call' instruction + for (uintptr_t j = 1; j < 8; j++) + { + DISASM info = { 0 }; + info.EIP = original - j; + + #ifdef USE64 + info.Archi = 64; + #endif + + // FIXME: Alternative for MinGW +#ifdef COMPILER_MSVC + if (Disasm( &info ) > 0 && info.Instruction.BranchType == CallType) + { + results.emplace_back( stackPtr, stack_val ); + break; + } +#endif // COMPILER_MSVC + } + + } + + return results.size(); +} + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/LocalHook/TraceHook.h b/third/Blackbone/src/BlackBone/LocalHook/TraceHook.h new file mode 100644 index 0000000000000000000000000000000000000000..5da37bbbe9fc143ff205bcdf86540215bd892d8f --- /dev/null +++ b/third/Blackbone/src/BlackBone/LocalHook/TraceHook.h @@ -0,0 +1,161 @@ +#pragma once + +#include "../Include/WinHeaders.h" + +#include +#include +#include +#include + +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 ) { } +}; + + +/// +/// Hook-related data +/// +struct HookContext +{ + using mapHooks = std::unordered_map>; + using vecState = std::vector; + + 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 + + + /// + /// Reset tracing state + /// + 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; + using vecStackFrames = std::vector >; + +public: + ~TraceHook(); + BLACKBONE_API static TraceHook& Instance(); + + /// + /// Setup hook + /// + /// Target function to be hooked + /// New function + /// Address of pointer to destroy + /// Function tracing path + /// Optional. Address of instruction that checks target pointer + /// true on success, false if already hooked + BLACKBONE_API bool ApplyHook( void* targetFunc, + void* hookFunc, + void* ptrAddress, + const HookContext::vecState& tracePath = HookContext::vecState(), + void* checkIP = 0 ); + + /// + /// Remove existing hook + /// + /// Target function ptr + /// true on success, false if not found + 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 ); + + /// + /// Capture stack frames + /// + /// Current instruction pointer + /// Current stack pointer + /// Found frames. + /// Frame depth limit + /// Number of found frames + size_t StackBacktrace( uintptr_t ip, uintptr_t sp, vecStackFrames& results, uintptr_t depth = 10 ); + + /// + /// Setup exception upon function return + /// + /// The exception information + inline void BreakOnReturn( uintptr_t sp ); + + /// + /// Check if last instruction caused branching + /// + /// Current hook info + /// Instruction pointer + /// Stack pointer + /// True if branching has occurred + bool CheckBranching( const HookContext& ctx, uintptr_t ip, uintptr_t sp ); + + /// + /// Handle branching + /// + /// Current hook context + /// Thread context + void HandleBranch( HookContext& ctx, PCONTEXT exptContex ); + + /// + /// Restore original pointer value + /// + /// The CTX. + /// The exception information + /// true on success, false if no invalid register was found + 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 +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/LocalHook/VTableHook.hpp b/third/Blackbone/src/BlackBone/LocalHook/VTableHook.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fdc2f9e2d0a3b1dea1ef10627e087f6a38a7d5c2 --- /dev/null +++ b/third/Blackbone/src/BlackBone/LocalHook/VTableHook.hpp @@ -0,0 +1,182 @@ +#pragma once + +#include "LocalHook.hpp" +#include "../Misc/DynImport.h" + +namespace blackbone +{ + +template +class VTableDetour : public Detour +{ +public: + using type = typename HookHandler::type; + using hktype = typename HookHandler::hktype; + using hktypeC = typename HookHandler::hktypeC; + +public: + VTableDetour() + { + DetourBase::AllocateBuffer( nullptr ); + } + + ~VTableDetour() + { + Restore(); + } + + /// + /// Hook function in vtable + /// + /// Pointer to vtable pointer + /// Function index + /// Hook function address + /// Call order. Hook before original or vice versa + /// Return value. Use origianl or value from hook + /// if true, vtable will be copied and edited, otherwise existing vtable will be edited + /// Optional. Valid only when copyVtable is true. Number of function in vtable. + /// Used to determine number of function to copy + /// true on success + 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::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(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); + } + + /// + /// Hooks function in vtable + /// + /// Pointer to vtable pointer + /// Function index + /// Hook class member address + /// Hook class address + /// Call order. Hook before original or vice versa + /// Return value. Use origianl or value from hook + /// if true, vtable will be copied and edited, otherwise existing vtable will be edited + /// Optional. Valid only when copyVtable is true. Number of function in vtable. + /// Used to determine number of function to copy + /// true on success + 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(hkPtr), order, retType, copyVtable, vtableLen ); + } + + /// + /// Restore hooked function + /// + /// true on success, false if not hooked + 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 +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/ManualMap/MExcept.cpp b/third/Blackbone/src/BlackBone/ManualMap/MExcept.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e78e811089192df6df3c95d88557077cdd4f65f2 --- /dev/null +++ b/third/Blackbone/src/BlackBone/ManualMap/MExcept.cpp @@ -0,0 +1,362 @@ +#include "MExcept.h" +#include "../Process/Process.h" +#include "../Include/Macro.h" +#include "../Misc/Trace.hpp" +#include "../Symbols/SymbolData.h" +#include "../Asm/LDasm.h" + +namespace blackbone +{ + +// taken from CRT include +#define EH_MAGIC_NUMBER1 0x19930520 +#define EH_PURE_MAGIC_NUMBER1 0x01994000 +#define EH_EXCEPTION_NUMBER ('msc' | 0xE0000000) + +/* +LONG __declspec(naked) CALLBACK VectoredHandler( PEXCEPTION_POINTERS / *ExceptionInfo* / ) +{ + PEXCEPTION_REGISTRATION_RECORD pFs; + PRTL_INVERTED_FUNCTION_TABLE7 pTable;// = (PRTL_INVERTED_FUNCTION_TABLE7)0x777dc2b0; + PRTL_INVERTED_FUNCTION_TABLE_ENTRY pEntries; + void( __stdcall* LdrProtectMrdata )(BOOL a); + PDWORD pDec, pStart; + DWORD verMajor, verMinor, tmp; + PEB_T* peb; + bool newHandler, useNewTable; + + __asm + { + push ebp + mov ebp, esp + sub esp, __LOCAL_SIZE + pushad + mov eax, 0xDEADDA7A + mov pTable, eax + mov eax, 0xDEADC0D2 + mov LdrProtectMrdata, eax + } + + pFs = reinterpret_cast(__readfsdword( 0 )); + + // Get OS version + peb = reinterpret_cast(__readfsdword( 0x30 )); + verMajor = peb->OSMajorVersion; + verMinor = peb->OSMinorVersion; + + useNewTable = (verMajor >= 6 && verMinor >= 2) || verMajor >= 10; + + if (useNewTable) + pEntries = reinterpret_cast(GET_FIELD_PTR( reinterpret_cast(pTable), Entries )); + else + pEntries = reinterpret_cast(GET_FIELD_PTR( pTable, Entries )); + + + //LdrProtectMrdata = (decltype(LdrProtectMrdata))0x777043aa; + if (LdrProtectMrdata) + LdrProtectMrdata( FALSE ); + + // + // Add each handler to LdrpInvertedFunctionTable + // + for (; pFs && pFs != reinterpret_cast(0xffffffff) + && pFs->Next != reinterpret_cast(0xffffffff); + pFs = pFs->Next) + { + // Find image for handler + for (ULONG imageIndex = 0; imageIndex < pTable->Count; imageIndex++) + { + if (reinterpret_cast(pFs->Handler) >= reinterpret_cast(pEntries[imageIndex].ImageBase) && + reinterpret_cast(pFs->Handler) <= reinterpret_cast(pEntries[imageIndex].ImageBase) + + pEntries[imageIndex].ImageSize) + { + newHandler = false; + + // Win8+ always has ntdll.dll as first image, so we can safely skip its handlers. + // Also ntdll.dll ExceptionDirectory isn't Encoded via RtlEncodeSystemPointer (it's plain address) + if (useNewTable && imageIndex == 0) + break; + + //pStart = (DWORD*)DecodeSystemPointer( pEntries[imageIndex].ExceptionDirectory ); + pStart = (DWORD*)((int( __stdcall* )(PVOID))0xDEADC0DE)(pEntries[imageIndex].ExceptionDirectory); + + // + // Add handler as fake SAFESEH record + // + for (pDec = pStart; pDec != nullptr && pDec < pStart + 0x100; pDec++) + { + if (*pDec == 0) + { + *pDec = reinterpret_cast(pFs->Handler) - reinterpret_cast(pEntries[imageIndex].ImageBase); + pEntries[imageIndex].SizeOfTable++; + newHandler = true; + + break; + } + // Already in table + else if ((*pDec + reinterpret_cast(pEntries[imageIndex].ImageBase)) == reinterpret_cast(pFs->Handler)) + break; + } + + // Sort handler addresses + if (newHandler) + for (ULONG i = 0; i < pEntries[imageIndex].SizeOfTable; i++) + for (ULONG j = pEntries[imageIndex].SizeOfTable - 1; j > i; j--) + if (pStart[j - 1] > pStart[j]) + { + tmp = pStart[j - 1]; + pStart[j - 1] = pStart[j]; + pStart[j] = tmp; + } + } + } + } + + if (LdrProtectMrdata) + LdrProtectMrdata( TRUE ); + + // Return control to SEH + //return EXCEPTION_CONTINUE_SEARCH; + __asm + { + popad + mov esp, ebp + pop ebp + + mov eax, EXCEPTION_CONTINUE_SEARCH + ret 4 + } +} +*/ +uint8_t MExcept::_handler32[]= +{ + 0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x18, 0x60, 0xB8, 0x7A, 0xDA, 0xAD, 0xDE, 0x89, 0x45, 0xF4, 0xB8, + 0xD2, 0xC0, 0xAD, 0xDE, 0x89, 0x45, 0xEC, 0x64, 0x8B, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x64, 0x8B, + 0x0D, 0x30, 0x00, 0x00, 0x00, 0x89, 0x5D, 0xF8, 0x8B, 0x81, 0xA4, 0x00, 0x00, 0x00, 0x83, 0xF8, + 0x06, 0x72, 0x09, 0x83, 0xB9, 0xA8, 0x00, 0x00, 0x00, 0x02, 0x73, 0x11, 0x83, 0xF8, 0x0A, 0x73, + 0x0C, 0x8B, 0x7D, 0xF4, 0xC6, 0x45, 0xFF, 0x00, 0x83, 0xC7, 0x0C, 0xEB, 0x0A, 0x8B, 0x7D, 0xF4, + 0xC6, 0x45, 0xFF, 0x01, 0x83, 0xC7, 0x10, 0x8B, 0x45, 0xEC, 0x89, 0x7D, 0xE8, 0x85, 0xC0, 0x74, + 0x07, 0x6A, 0x00, 0xFF, 0xD0, 0x8B, 0x45, 0xEC, 0x85, 0xDB, 0x0F, 0x84, 0xEA, 0x00, 0x00, 0x00, + 0x83, 0xFB, 0xFF, 0x0F, 0x84, 0xDE, 0x00, 0x00, 0x00, 0x83, 0x3B, 0xFF, 0x0F, 0x84, 0xD5, 0x00, + 0x00, 0x00, 0x8B, 0x45, 0xF4, 0x33, 0xF6, 0x89, 0x75, 0xF0, 0x39, 0x30, 0x0F, 0x86, 0xB5, 0x00, + 0x00, 0x00, 0x83, 0xC7, 0x04, 0x8B, 0x4B, 0x04, 0x8B, 0x17, 0x3B, 0xCA, 0x0F, 0x82, 0x8E, 0x00, + 0x00, 0x00, 0x8B, 0x47, 0x04, 0x03, 0xC2, 0x3B, 0xC8, 0x0F, 0x87, 0x81, 0x00, 0x00, 0x00, 0x80, + 0x7D, 0xFF, 0x00, 0x74, 0x08, 0x85, 0xF6, 0x0F, 0x84, 0x8A, 0x00, 0x00, 0x00, 0xFF, 0x77, 0xFC, + 0xB8, 0xDE, 0xC0, 0xAD, 0xDE, 0xFF, 0xD0, 0x8B, 0xD8, 0x8B, 0xCB, 0x85, 0xDB, 0x74, 0x5E, 0x8D, + 0xB3, 0x00, 0x04, 0x00, 0x00, 0x3B, 0xCE, 0x73, 0x54, 0x8B, 0x11, 0x85, 0xD2, 0x74, 0x13, 0x8B, + 0x07, 0x03, 0xC2, 0x8B, 0x55, 0xF8, 0x3B, 0x42, 0x04, 0x74, 0x42, 0x83, 0xC1, 0x04, 0x75, 0xE5, + 0xEB, 0x3B, 0x8B, 0x45, 0xF8, 0x8B, 0x40, 0x04, 0x2B, 0x07, 0x89, 0x01, 0xB9, 0x00, 0x00, 0x00, + 0x00, 0x83, 0x47, 0x08, 0x01, 0x74, 0x26, 0x8B, 0x47, 0x08, 0x48, 0x3B, 0xC1, 0x76, 0x18, 0x90, + 0x8B, 0x74, 0x83, 0xFC, 0x8B, 0x14, 0x83, 0x3B, 0xF2, 0x76, 0x07, 0x89, 0x54, 0x83, 0xFC, 0x89, + 0x34, 0x83, 0x48, 0x3B, 0xC1, 0x77, 0xE9, 0x41, 0x3B, 0x4F, 0x08, 0x72, 0xDA, 0x8B, 0x5D, 0xF8, + 0x8B, 0x4D, 0xF0, 0x83, 0xC7, 0x10, 0x8B, 0x45, 0xF4, 0x41, 0x89, 0x4D, 0xF0, 0x8B, 0xF1, 0x3B, + 0x08, 0x0F, 0x82, 0x4E, 0xFF, 0xFF, 0xFF, 0x8B, 0x1B, 0x8B, 0x7D, 0xE8, 0x89, 0x5D, 0xF8, 0x85, + 0xDB, 0x0F, 0x85, 0x19, 0xFF, 0xFF, 0xFF, 0x8B, 0x45, 0xEC, 0x85, 0xC0, 0x74, 0x04, 0x6A, 0x01, + 0xFF, 0xD0, 0x61, 0x8B, 0xE5, 0x5D, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x04, 0x00 +}; + +/* +LONG CALLBACK VectoredHandler( PEXCEPTION_POINTERS ExceptionInfo ) +{ + // Check if it's a VC++ exception + // for SEH RtlAddFunctionTable is enough + if (ExceptionInfo->ExceptionRecord->ExceptionCode == EH_EXCEPTION_NUMBER) + { + ModuleTable* pTable = reinterpret_cast(0xDEADBEEFDEADBEEF); + for (ptr_t i = 0; i < pTable->count; i++) + { + // Check exception site image boundaries + if (ExceptionInfo->ExceptionRecord->ExceptionInformation[2] >= pTable->entry[i].base && + ExceptionInfo->ExceptionRecord->ExceptionInformation[2] <= pTable->entry[i].base + pTable->entry[i].size) + { + // Assume that's our exception because ImageBase = 0 and not suitable magic number + if (ExceptionInfo->ExceptionRecord->ExceptionInformation[0] == EH_PURE_MAGIC_NUMBER1 + && ExceptionInfo->ExceptionRecord->ExceptionInformation[3] == 0) + { + // CRT magic number + ExceptionInfo->ExceptionRecord->ExceptionInformation[0] = (ULONG_PTR)EH_MAGIC_NUMBER1; + + // fix exception image base + ExceptionInfo->ExceptionRecord->ExceptionInformation[3] = (ULONG_PTR)pTable->entry[i].base; + } + } + } + } + + return EXCEPTION_CONTINUE_SEARCH; +}*/ +uint8_t MExcept::_handler64[] = +{ + 0x48, 0x83, 0xEC, 0x08, 0x48, 0x8B, 0x01, 0x4C, 0x8B, 0xD9, 0x81, 0x38, 0x63, 0x73, 0x6D, 0xE0, + 0x0F, 0x85, 0x7C, 0x00, 0x00, 0x00, 0x48, 0x89, 0x1C, 0x24, 0x45, 0x33, 0xC9, 0x48, 0xBB, 0xEF, + 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0x4C, 0x39, 0x0B, 0x76, 0x5B, 0x48, 0xB8, 0xF7, 0xBE, + 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4D, 0x8B, 0x03, 0x48, 0x8B, 0x10, 0x4D, 0x8B, 0x50, 0x30, 0x4C, 0x3B, 0xD2, 0x72, 0x2C, 0x48, + 0x03, 0x50, 0x08, 0x4C, 0x3B, 0xD2, 0x77, 0x23, 0x49, 0x81, 0x78, 0x20, 0x00, 0x40, 0x99, 0x01, + 0x75, 0x19, 0x49, 0x83, 0x78, 0x38, 0x00, 0x75, 0x12, 0x49, 0xC7, 0x40, 0x20, 0x20, 0x05, 0x93, + 0x19, 0x49, 0x8B, 0x13, 0x48, 0x8B, 0x08, 0x48, 0x89, 0x4A, 0x38, 0x49, 0xFF, 0xC1, 0x48, 0x83, + 0xC0, 0x10, 0x4C, 0x3B, 0x0B, 0x72, 0xB9, 0x33, 0xC0, 0x48, 0x8B, 0x1C, 0x24, 0x48, 0x83, 0xC4, + 0x08, 0xC3, 0x33, 0xC0, 0x48, 0x83, 0xC4, 0x08, 0xC3 +}; + +/// +/// Inject VEH wrapper into process +/// Used to enable execution of SEH handlers out of image +/// +/// Target process +/// Target module +/// Partial exception support +/// Error code +NTSTATUS MExcept::CreateVEH( Process& proc, ModuleData& mod, bool partial ) +{ + uint64_t result = 0; + auto& mods = proc.modules(); + + if (mod.type == mt_mod64) + { + // Add module to module table + if (!_pModTable.valid()) + { + auto mem = proc.memory().Allocate( 0x1000, PAGE_READWRITE, 0, false ); + if (!mem) + return mem.status; + + _pModTable = std::move( mem.result() ); + } + + ModuleTable table; + _pModTable.Read ( 0, table ); + + // Add new entry to the table + table.entry[table.count].base = mod.baseAddress; + table.entry[table.count].size = mod.size; + table.count++; + + _pModTable.Write( 0, table ); + } + + // No handler required + if (partial) + return STATUS_SUCCESS; + + // VEH codecave + auto mem = proc.memory().Allocate( 0x2000, PAGE_EXECUTE_READWRITE, 0, false ); + if (!mem) + return mem.status; + + _pVEHCode = std::move( mem.result() ); + + BLACKBONE_TRACE( "ManualMap: Vectored hander: 0x%p", _pVEHCode.ptr() ); + + auto replaceStub = []( uint8_t* ptr, size_t size, auto oldVal, auto newVal ) + { + using ValuePtr = std::add_pointer_t; + + for (uint8_t *pData = ptr; pData < ptr + size - sizeof( oldVal ); pData++) + { + if (*reinterpret_cast(pData) == oldVal) + { + *reinterpret_cast(pData) = newVal; + return true; + } + } + + return false; + }; + + uint8_t newHandler[sizeof( _handler32 ) + sizeof( _handler64 )]; + size_t handlerSize = 0; + + if (mod.type == mt_mod64) + { + handlerSize = sizeof( _handler64 ); + memcpy( newHandler, _handler64, handlerSize ); + + replaceStub( newHandler, handlerSize, 0xDEADBEEFDEADBEEF, _pModTable.ptr() ); + replaceStub( newHandler, handlerSize, 0xDEADBEEFDEADBEF7, _pModTable.ptr() + sizeof( ptr_t ) ); + } + else + { + handlerSize = sizeof( _handler32 ); + memcpy( newHandler, _handler32, handlerSize ); + + auto pDecode = mods.GetNtdllExport( "RtlDecodeSystemPointer", mod.type, Sections ); + if (!pDecode) + return pDecode.status; + + replaceStub( newHandler, handlerSize, 0xDEADDA7A, static_cast(g_symbols.LdrpInvertedFunctionTable32) ); + replaceStub( newHandler, handlerSize, 0xDEADC0DE, static_cast(pDecode->procAddress) ); + replaceStub( newHandler, handlerSize, 0xDEADC0D2, static_cast(g_symbols.LdrProtectMrdata) ); + } + + // Write handler data into target process + if (!NT_SUCCESS( _pVEHCode.Write( 0, handlerSize, newHandler ) )) + { + _pVEHCode.Free(); + return LastNtStatus(); + } + + // AddVectoredExceptionHandler(0, pHandler); + auto pAddHandler = mods.GetNtdllExport( "RtlAddVectoredExceptionHandler", mod.type, Sections ); + if (!pAddHandler) + return pAddHandler.status; + + auto a = AsmFactory::GetAssembler( mod.type ); + + a->GenPrologue(); + a->GenCall( pAddHandler->procAddress, { 0, _pVEHCode.ptr() } ); + proc.remote().AddReturnWithEvent( *a, mod.type ); + a->GenEpilogue(); + + NTSTATUS status = proc.remote().ExecInWorkerThread( (*a)->make(), (*a)->getCodeSize(), result ); + if (result != 0) + { + _hVEH = result; + return STATUS_SUCCESS; + } + else + { + status = proc.remote().GetLastStatus(); + return status; + } +} + +/// +/// Removes VEH from target process +/// +/// Target process +/// Partial exception support +/// Mosule type +/// Status code +NTSTATUS MExcept::RemoveVEH( Process& proc, bool partial, eModType mt ) +{ + auto a = AsmFactory::GetAssembler( mt ); + uint64_t result = 0; + + auto& mods = proc.modules(); + auto pRemoveHandler = mods.GetNtdllExport( "RtlRemoveVectoredExceptionHandler", mt ); + if (!pRemoveHandler) + return pRemoveHandler.status; + + a->GenPrologue(); + + // RemoveVectoredExceptionHandler(pHandler); + a->GenCall( pRemoveHandler->procAddress, { _hVEH } ); + + proc.remote().AddReturnWithEvent( *a ); + a->GenEpilogue(); + + // Destroy table and handler + if (!partial) + { + proc.remote().ExecInWorkerThread( (*a)->make(), (*a)->getCodeSize(), result ); + _pVEHCode.Free(); + _hVEH = 0; + + _pModTable.Free(); + } + + return STATUS_SUCCESS; +} + +} diff --git a/third/Blackbone/src/BlackBone/ManualMap/MExcept.h b/third/Blackbone/src/BlackBone/ManualMap/MExcept.h new file mode 100644 index 0000000000000000000000000000000000000000..694f69f69a383fdbcd8644ce944954fdab90ee6c --- /dev/null +++ b/third/Blackbone/src/BlackBone/ManualMap/MExcept.h @@ -0,0 +1,74 @@ +#pragma once + +#include "../Include/Winheaders.h" +#include "../Process/MemBlock.h" + +namespace blackbone +{ + +/// +/// x64 exception module info +/// +struct ExceptionModule +{ + ptr_t base; + ptr_t size; +}; + + +/// +/// x64 module table +/// +struct ModuleTable +{ + ptr_t count; // Number of used entries + ExceptionModule entry[250]; // Module data +}; + +/// +/// Exception handling support for arbitrary code +/// +class MExcept +{ +public: + BLACKBONE_API MExcept() = default; + BLACKBONE_API ~MExcept() = default; + + /// + /// Inject VEH wrapper into process + /// Used to enable execution of SEH handlers out of image + /// + /// Target process + /// Target module + /// Partial exception support + /// Error code + BLACKBONE_API NTSTATUS CreateVEH( class Process& proc, ModuleData& mod, bool partial ); + + /// + /// Removes VEH from target process + /// + /// Target process + /// Partial exception support + /// Mosule type + /// Status code + BLACKBONE_API NTSTATUS RemoveVEH( class Process& proc, bool partial, eModType mt ); + + /// + /// Reset data + /// + BLACKBONE_API inline void reset() { _pModTable.Free(); } + +private: + MExcept( const MExcept& ) = delete; + MExcept& operator =(const MExcept&) = delete; + +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[]; +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/ManualMap/MMap.cpp b/third/Blackbone/src/BlackBone/ManualMap/MMap.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ddebede4a0b255aa5c41432027000d004f8b58b7 --- /dev/null +++ b/third/Blackbone/src/BlackBone/ManualMap/MMap.cpp @@ -0,0 +1,1593 @@ +#include "MMap.h" +#include "../Process/Process.h" +#include "../Misc/NameResolve.h" +#include "../Misc/Utils.h" +#include "../Misc/DynImport.h" +#include "../Misc/Trace.hpp" +#include "../DriverControl/DriverControl.h" + +#include +#include <3rd_party/VersionApi.h> + +#ifndef STATUS_INVALID_EXCEPTION_HANDLER +#define STATUS_INVALID_EXCEPTION_HANDLER ((NTSTATUS)0xC00001A5L) +#endif + +namespace blackbone +{ + +MMap::MMap( Process& proc ) + : _process( proc ) +{ +} + +MMap::~MMap(void) +{ + //UnmapAllModules(); +} + +/// +/// Manually map PE image into underlying target process +/// +/// Image path +/// Image mapping flags +/// Mapping callback. Triggers for each mapped module +/// User-supplied callback context +/// Mapped image info +call_result_t MMap::MapImage( + const std::wstring& path, + eLoadFlags flags /*= NoFlags*/, + MapCallback mapCallback /*= nullptr*/, + void* context /*= nullptr*/, + CustomArgs_t* pCustomArgs /*= nullptr*/ + ) +{ + return MapImageInternal( path, nullptr, 0, false, flags, mapCallback, context, pCustomArgs ); +} + +/// +///Manually map PE image into underlying target process +/// +/// Image data buffer +/// Buffer size. +/// If set to true - buffer has image memory layout +/// Image mapping flags +/// Mapping callback. Triggers for each mapped module +/// User-supplied callback context +/// Mapped image info +call_result_t MMap::MapImage( + size_t size, void* buffer, + bool asImage /*= false*/, + eLoadFlags flags /*= NoFlags*/, + MapCallback mapCallback /*= nullptr*/, + void* context /*= nullptr*/, + CustomArgs_t* pCustomArgs /*= nullptr*/ + ) +{ + // Create fake path + wchar_t path[64]; + wsprintfW( path, L"MemoryImage_0x%p", buffer ); + + return MapImageInternal( path, buffer, size, asImage, flags, mapCallback, context, pCustomArgs ); +} + +/// +/// Manually map PE image into underlying target process +/// +/// Image path +/// Image data buffer +/// Buffer size. +/// If set to true - buffer has image memory layout +/// Image mapping flags +/// Mapping callback. Triggers for each mapped module +/// User-supplied callback context +/// Mapped image info +call_result_t MMap::MapImageInternal( + const std::wstring& path, + void* buffer, size_t size, + bool asImage /*= false*/, + eLoadFlags flags /*= NoFlags*/, + MapCallback mapCallback /*= nullptr*/, + void* context /*= nullptr*/, + CustomArgs_t* pCustomArgs /*= nullptr*/ + ) +{ + if (!(flags & ForceRemap)) + { + // Already loaded + if (auto hMod = _process.modules().GetModule(path)) + return hMod; + } + + // Prepare target process + auto mode = (flags & NoThreads) ? Worker_UseExisting : Worker_CreateNew; + auto status = _process.remote().CreateRPCEnvironment( mode, true ); + if (!NT_SUCCESS( status )) + { + Cleanup(); + return status; + } + + // No need to support exceptions if DEP is disabled + if (_process.core().DEP() == false) + flags |= NoExceptions; + + // Ignore MapInHighMem for native x64 process + if (!_process.core().isWow64()) + flags &= ~MapInHighMem; + + // Set native loader callback + _mapCallback = mapCallback; + _userContext = context; + + BLACKBONE_TRACE( L"ManualMap: Mapping image '%ls' with flags 0x%x", path.c_str(), flags ); + + // Map module and all dependencies + auto mod = FindOrMapModule( path, buffer, size, asImage, flags ); + if (!mod) + { + Cleanup(); + return mod.status; + } + + // Change process base module address if needed + if (flags & RebaseProcess && !_images.empty() && _images.rbegin()->get()->peImage.isExe()) + { + BLACKBONE_TRACE( L"ManualMap: Rebasing process to address 0x%p", (*mod)->baseAddress ); + + // Managed path fix + if (_images.rbegin()->get()->peImage.pureIL() && !path.empty()) + { + CALL_64_86( + (*mod)->type == mt_mod64, + FixManagedPath, + _process.modules().GetMainModule()->baseAddress, + path + ); + } + + // PEB64 + _process.memory().Write( + fieldPtr( _process.core().peb64(), &_PEB64::ImageBaseAddress ), + sizeof( uint64_t ), + &(*mod)->baseAddress + ); + + // PEB32 + if(_process.core().isWow64()) + { + _process.memory().Write( + fieldPtr(_process.core().peb32(), &_PEB32::ImageBaseAddress ), + sizeof( uint32_t ), + &(*mod)->baseAddress + ); + } + } + + auto wipeMemory = []( Process& proc, ImageContext* img, uintptr_t offset, uintptr_t size ) + { + size = Align( size, 0x1000 ); + std::unique_ptr zeroBuf( new uint8_t[size]() ); + + if (img->flags & HideVAD) + { + Driver().WriteMem( proc.pid(), img->imgMem.ptr() + offset, size, zeroBuf.get() ); + } + else + { + img->imgMem.Write( offset, size, zeroBuf.get() ); + proc.memory().Protect( img->imgMem.ptr() + offset, size, PAGE_NOACCESS ); + proc.memory().Free( img->imgMem.ptr() + offset, size, MEM_DECOMMIT ); + } + }; + + // Run initializers + for (auto& img : _images) + { + // Init once + if (!img->initialized) + { + // Hack for IL dlls + if (!img->peImage.isExe() && img->peImage.pureIL()) + { + DWORD flOld = 0; + auto flg = img->imgMem.Read( img->peImage.ilFlagOffset(), 0 ); + img->imgMem.Protect( PAGE_EXECUTE_READWRITE, img->peImage.ilFlagOffset(), sizeof( flg ), &flOld ); + img->imgMem.Write( img->peImage.ilFlagOffset(), flg & ~COMIMAGE_FLAGS_ILONLY ); + img->imgMem.Protect( flOld, img->peImage.ilFlagOffset(), sizeof( flg ), &flOld ); + } + + // Don't run initializer for pure IL dlls + if (!img->peImage.pureIL() || img->peImage.isExe()) + status = RunModuleInitializers( img, DLL_PROCESS_ATTACH, pCustomArgs ).status; + + if (!NT_SUCCESS( status )) + { + BLACKBONE_TRACE( L"ManualMap: ModuleInitializers failed for '%ls', status: 0x%X", img->ldrEntry.name.c_str(), status ); + Cleanup(); + return status; + } + + // Wipe header + if (img->flags & WipeHeader) + wipeMemory( _process, img.get(), 0, img->peImage.headersSize() ); + + // Wipe discardable sections + if(!img->peImage.pureIL()) + { + for (auto& sec : img->peImage.sections()) + if (sec.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) + wipeMemory( _process, img.get(), sec.VirtualAddress, sec.Misc.VirtualSize ); + } + + img->initialized = true; + } + } + + //Cleanup(); + return mod; +} + +/// +/// Fix image path for pure managed mapping +/// +/// Image base +/// New image path +template +void MMap::FixManagedPath( ptr_t base, const std::wstring &path ) +{ + _PEB_T peb = { 0 }; + _PEB_LDR_DATA2_T ldr = { 0 }; + + if (_process.core().peb( &peb ) != 0 && _process.memory().Read( peb.Ldr, sizeof( ldr ), &ldr ) == STATUS_SUCCESS) + { + // Get PEB loader entry + for (auto head = ldr.InLoadOrderModuleList.Flink; + head != fieldPtr( peb.Ldr, &_PEB_LDR_DATA2_T::InLoadOrderModuleList ); + head = _process.memory().Read( head ).result( 0 )) + { + _LDR_DATA_TABLE_ENTRY_BASE_T localdata = { { 0 } }; + + _process.memory().Read( head, sizeof( localdata ), &localdata ); + if (localdata.DllBase == base) + { + auto len = path.length()* sizeof( wchar_t ); + _process.memory().Write( localdata.FullDllName.Buffer, len + 2, path.c_str() ); + _process.memory().Write( + head + FIELD_OFFSET( _LDR_DATA_TABLE_ENTRY_BASE_T, FullDllName.Length ), + static_cast(len) + ); + + return; + } + } + } +} + +/// +/// Get existing module or map it if absent +/// +/// Image path +/// Image data buffer +/// Buffer size. +/// If set to true - buffer has image memory layout +/// Mapping flags +/// Module info +call_result_t MMap::FindOrMapModule( + const std::wstring& path, + void* buffer, size_t size, bool asImage, + eLoadFlags flags /*= NoFlags*/ + ) +{ + NTSTATUS status = STATUS_SUCCESS; + ImageContextPtr pImage( new ImageContext() ); + auto& ldrEntry = pImage->ldrEntry; + + ldrEntry.fullPath = Utils::ToLower( path ); + ldrEntry.name = Utils::StripPath( ldrEntry.fullPath ); + pImage->flags = flags; + + // Load and parse image + status = buffer ? pImage->peImage.Load( buffer, size, !asImage ) : pImage->peImage.Load( path, flags & NoSxS ? true : false ); + if (!NT_SUCCESS( status )) + { + BLACKBONE_TRACE( L"ManualMap: Failed to load image '%ls'/0x%p. Status 0x%X", path.c_str(), buffer, status ); + pImage->peImage.Release(); + return status; + } + + // Check if already loaded, but only if doesn't explicitly excluded + if (!(flags & ForceRemap)) + { + if (auto hMod = _process.modules().GetModule( path, LdrList, pImage->peImage.mType() )) + { + pImage->peImage.Release(); + return hMod; + } + } + + // Check architecture + if (pImage->peImage.mType() == mt_mod32 && !_process.core().isWow64()) + { + BLACKBONE_TRACE( L"ManualMap: Can't map x86 dll '%ls' into native x64 process", path.c_str() ); + pImage->peImage.Release(); + return STATUS_INVALID_IMAGE_WIN_32; + } + + BLACKBONE_TRACE( L"ManualMap: Loading new image '%ls'", path.c_str() ); + + ldrEntry.type = pImage->peImage.mType(); + + // Try to map image in high (>4GB) memory range + if (flags & MapInHighMem) + { + AllocateInHighMem( pImage->imgMem, pImage->peImage.imageSize() ); + } + // Try to map image at it's original ASRL-aware base + else if (flags & HideVAD) + { + ptr_t base = pImage->peImage.imageBase(); + ptr_t image_size = pImage->peImage.imageSize(); + + if (!NT_SUCCESS( Driver().EnsureLoaded() )) + { + pImage->peImage.Release(); + return Driver().status(); + } + + // Allocate as physical at desired base + status = Driver().AllocateMem( _process.pid(), base, image_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE, true ); + + // Allocate at any base + if (!NT_SUCCESS( status )) + { + base = 0; + image_size = pImage->peImage.imageSize(); + status = Driver().AllocateMem( _process.pid(), base, image_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE, true ); + } + + // Store allocated region + if (NT_SUCCESS( status )) + { + pImage->imgMem = MemBlock( &_process.memory(), base, static_cast(image_size), PAGE_EXECUTE_READWRITE, true, true ); + } + // Stop mapping + else + { + //flags &= ~HideVAD; + BLACKBONE_TRACE( L"ManualMap: Failed to allocate physical memory for image, status 0x%X", status ); + pImage->peImage.Release(); + return status; + } + } + + // Allocate normally if something went wrong + if (!pImage->imgMem.valid()) + { + auto mem = _process.memory().Allocate( pImage->peImage.imageSize(), PAGE_EXECUTE_READWRITE, pImage->peImage.imageBase() ); + if (!mem) + { + BLACKBONE_TRACE( L"ManualMap: Failed to allocate memory for image, status 0x%X", status ); + pImage->peImage.Release(); + return mem.status; + } + + pImage->imgMem = std::move( mem.result() ); + } + + ldrEntry.baseAddress = pImage->imgMem.ptr(); + ldrEntry.size = pImage->peImage.imageSize(); + + BLACKBONE_TRACE( L"ManualMap: Image base allocated at 0x%016llx", pImage->imgMem.ptr() ); + + // Create Activation context for SxS + if (pImage->peImage.manifestID() == 0) + flags |= NoSxS; + + if (!(flags & NoSxS)) + { + status = CreateActx( pImage->peImage ); + if (!NT_SUCCESS( status )) + { + pImage->peImage.Release(); + return status; + } + } + + // Core image mapping operations + if (!NT_SUCCESS( status = CopyImage( pImage ) )) + { + pImage->peImage.Release(); + return status; + } + + if (!NT_SUCCESS( status = RelocateImage( pImage ) )) + { + pImage->peImage.Release(); + return status; + } + + auto mt = ldrEntry.type; + ModuleDataPtr pMod; + + if (flags & ForceRemap) + pMod = std::make_shared( _process.modules().Canonicalize( ldrEntry, true ) ); + else + pMod = _process.modules().AddManualModule( ldrEntry ); + + { + // Handle x64 system32 dlls for wow64 process + bool fsRedirect = !(flags & IsDependency) && mt == mt_mod64 && _process.barrier().sourceWow64; + + FsRedirector fsr( fsRedirect ); + + // Import + if (!NT_SUCCESS( status = ResolveImport( pImage ) )) + { + pImage->peImage.Release(); + _process.modules().RemoveManualModule( ldrEntry.name, mt ); + return status; + } + + // Delayed import + if (!(flags & NoDelayLoad) && !NT_SUCCESS( status = ResolveImport( pImage, true ) )) + { + pImage->peImage.Release(); + _process.modules().RemoveManualModule( ldrEntry.name, mt ); + return status; + } + } + + // Apply proper memory protection for sections + if (!(flags & HideVAD)) + ProtectImageMemory( pImage ); + + // Make exception handling possible (C and C++) + if (!(flags & NoExceptions)) + { + if (!NT_SUCCESS( status = EnableExceptions( pImage ) ) && status != STATUS_NOT_FOUND) + { + BLACKBONE_TRACE( L"ManualMap: Failed to enable exception handling for image %ls", ldrEntry.name.c_str() ); + pImage->peImage.Release(); + _process.modules().RemoveManualModule( ldrEntry.name, mt ); + return status; + } + } + + // Initialize security cookie + if (!NT_SUCCESS ( status = InitializeCookie( pImage ) )) + { + BLACKBONE_TRACE( L"ManualMap: Failed to initialize cookie for image %ls", ldrEntry.name.c_str() ); + pImage->peImage.Release(); + _process.modules().RemoveManualModule( ldrEntry.name, mt ); + return status; + } + + // Unlink image from VAD list + if (flags & HideVAD && !NT_SUCCESS( status = ConcealVad( pImage->imgMem ) )) + { + pImage->peImage.Release(); + _process.modules().RemoveManualModule( ldrEntry.name, mt ); + return status; + } + + // Get entry point + pImage->ldrEntry.entryPoint = pImage->peImage.entryPoint( pImage->imgMem.ptr() ); + + // Create reference for native loader functions + pImage->ldrEntry.flags = flags & CreateLdrRef ? Ldr_All : Ldr_None; + if (_mapCallback != nullptr) + { + auto mapData = _mapCallback( PostCallback, _userContext, _process, *pMod ); + if(mapData.ldrFlags != Ldr_Ignore) + pImage->ldrEntry.flags = mapData.ldrFlags; + } + + if (pImage->ldrEntry.flags != Ldr_None) + { + if (!_process.nativeLdr().CreateNTReference( pImage->ldrEntry )) + { + BLACKBONE_TRACE( L"ManualMap: Failed to add loader reference for image %ls", ldrEntry.name.c_str() ); + } + } + + // Static TLS data + if (!(flags & NoTLS) && !NT_SUCCESS( status = InitStaticTLS( pImage ) )) + { + BLACKBONE_TRACE( L"ManualMap: Failed to initialize static TLS for image %ls, status 0x%X", ldrEntry.name.c_str(), status ); + pImage->peImage.Release(); + _process.modules().RemoveManualModule( ldrEntry.name, mt ); + return status; + } + + // Fill TLS callbacks + pImage->peImage.GetTLSCallbacks( pImage->imgMem.ptr(), pImage->tlsCallbacks ); + + // Unload local copy + pImage->peImage.Release(); + + // Release ownership of image memory block + pImage->imgMem.Release(); + + // Store image + _images.emplace_back( std::move( pImage ) ); + return pMod; +} + +/// +/// Unmap all manually mapped modules +/// +/// Status code +NTSTATUS MMap::UnmapAllModules() +{ + for (auto img = _images.rbegin(); img != _images.rend(); ++img) + { + auto pImage = *img; + BLACKBONE_TRACE( L"ManualMap: Unmapping image '%ls'", pImage->ldrEntry.name.c_str() ); + + // Call main + RunModuleInitializers( pImage, DLL_PROCESS_DETACH ); + + // Remove VEH + if (!(pImage->flags & NoExceptions)) + DisableExceptions( pImage ); + + _process.nativeLdr().UnloadTLS( pImage->ldrEntry ); + + // Remove from loader + if (pImage->ldrEntry.flags != Ldr_None) + _process.nativeLdr().Unlink( pImage->ldrEntry ); + + // Free memory + pImage->imgMem.Free(); + + // Remove reference from local modules list + _process.modules().RemoveManualModule( pImage->ldrEntry.name, pImage->peImage.mType() ); + } + + Cleanup(); + return STATUS_SUCCESS; +} + +/// +/// Copies image into target process +/// +/// Image data +/// Status code +NTSTATUS MMap::CopyImage( ImageContextPtr pImage ) +{ + NTSTATUS status = STATUS_SUCCESS; + + BLACKBONE_TRACE( L"ManualMap: Performing image copy" ); + + // offset to first section equals to header size + size_t dwHeaderSize = pImage->peImage.headersSize(); + + // Copy header + if (pImage->flags & HideVAD) + status = Driver().WriteMem( _process.pid(), pImage->imgMem.ptr(), dwHeaderSize, pImage->peImage.base() ); + else + status = pImage->imgMem.Write( 0, dwHeaderSize, pImage->peImage.base() ); + + if (!NT_SUCCESS( status )) + { + BLACKBONE_TRACE( L"ManualMap: Failed to copy image headers. Status = 0x%x", status ); + return status; + } + + // Set header protection + if (!(pImage->flags & HideVAD)) + { + status = pImage->imgMem.Protect( PAGE_READONLY, 0, dwHeaderSize ); + if (!NT_SUCCESS( status )) + { + BLACKBONE_TRACE( L"ManualMap: Failed to set header memory protection. Status = 0x%x", status ); + return status; + } + } + + // Copy sections + for (auto& section : pImage->peImage.sections()) + { + // Skip discardable sections + if (section.Characteristics & (IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE)) + { + if (section.SizeOfRawData == 0) + continue; + + uint8_t* pSource = reinterpret_cast(pImage->peImage.ResolveRVAToVA( section.VirtualAddress )); + + // Copy section data + if (pImage->flags & HideVAD) + { + status = Driver().WriteMem( + _process.pid(), pImage->imgMem.ptr() + section.VirtualAddress, + section.SizeOfRawData, pSource + ); + } + else + { + status = pImage->imgMem.Write( section.VirtualAddress, section.SizeOfRawData, pSource ); + } + + if (!NT_SUCCESS( status )) + { + BLACKBONE_TRACE( + L"ManualMap: Failed to copy image section at offset 0x%x. Status = 0x%x", + section.VirtualAddress, status + ); + + return status; + } + } + } + + return STATUS_SUCCESS; +} + +/// +/// Adjust image memory protection +/// +/// image data +/// Status code +NTSTATUS MMap::ProtectImageMemory( ImageContextPtr pImage ) +{ + // Set section memory protection + for (auto& section : pImage->peImage.sections()) + { + auto prot = GetSectionProt( section.Characteristics ); + if (prot != PAGE_NOACCESS) + { + auto status = pImage->imgMem.Protect( prot, section.VirtualAddress, section.Misc.VirtualSize ); + if (!NT_SUCCESS( status )) + { + BLACKBONE_TRACE( + L"ManualMap: Failed to set section memory protection at offset 0x%x. Status = 0x%x", + section.VirtualAddress, status + ); + + return status; + } + } + // Decommit pages with NO_ACCESS protection + else + { + auto status = _process.memory().Free( pImage->imgMem.ptr() + section.VirtualAddress, section.Misc.VirtualSize, MEM_DECOMMIT ); + if (!NT_SUCCESS( status )) + { + BLACKBONE_TRACE( + L"ManualMap: Failed to set section memory protection at offset 0x%x. Status = 0x%x", + section.VirtualAddress, status + ); + } + } + } + + return STATUS_SUCCESS; +} + +/// +/// Fix relocations if image wasn't loaded at base address +/// +/// image data +/// true on success +NTSTATUS MMap::RelocateImage( ImageContextPtr pImage ) +{ + NTSTATUS status = STATUS_SUCCESS; + BLACKBONE_TRACE( L"ManualMap: Relocating image '%ls'", pImage->ldrEntry.fullPath.c_str() ); + + // Reloc delta + ptr_t Delta = pImage->imgMem.ptr() - pImage->peImage.imageBase(); + + // No need to relocate + if (Delta == 0) + { + BLACKBONE_TRACE( L"ManualMap: No need for relocation" ); + return STATUS_SUCCESS; + } + + // Dll can't be relocated + if (!(pImage->peImage.DllCharacteristics() & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)) + { + BLACKBONE_TRACE( L"ManualMap: Can't relocate image, no relocation flag" ); + return STATUS_INVALID_IMAGE_HASH; + } + + auto start = pImage->peImage.DirectoryAddress( IMAGE_DIRECTORY_ENTRY_BASERELOC ); + auto end = start + pImage->peImage.DirectorySize( IMAGE_DIRECTORY_ENTRY_BASERELOC ); + auto fixrec = reinterpret_cast(start); + + // No relocatable data + if (fixrec == nullptr) + { + BLACKBONE_TRACE( L"ManualMap: Image does not use relocations" ); + return STATUS_SUCCESS; + } + + // Read whole image to process it locally + std::unique_ptr localImage( new uint8_t[pImage->ldrEntry.size] ); + auto pLocal = localImage.get(); + _process.memory().Read( pImage->imgMem.ptr(), pImage->ldrEntry.size, pLocal ); + + while ((uintptr_t)fixrec < end && fixrec->BlockSize) + { + DWORD count = (fixrec->BlockSize - 8) >> 1; // records count + + for (DWORD i = 0; i < count; ++i) + { + WORD fixtype = (fixrec->Item[i].Type); // fixup type + WORD fixoffset = (fixrec->Item[i].Offset) % 4096; // offset in 4K block + + // no fixup required + if (fixtype == IMAGE_REL_BASED_ABSOLUTE) + continue; + + // add delta + if (fixtype == IMAGE_REL_BASED_HIGHLOW || fixtype == IMAGE_REL_BASED_DIR64) + { + uintptr_t fixRVA = fixoffset + fixrec->PageRVA; + if (pImage->ldrEntry.type == mt_mod64) + { + uint64_t val = *reinterpret_cast(pLocal + fixRVA) + Delta; + *reinterpret_cast(pLocal + fixRVA) = val; + } + else + { + uint32_t val = *reinterpret_cast(pLocal + fixRVA) + static_cast(Delta); + *reinterpret_cast(pLocal + fixRVA) = static_cast(val); + } + } + else + { + // TODO: support for all remaining relocations + BLACKBONE_TRACE( L"ManualMap: Abnormal relocation type %d. Aborting", fixtype ); + return STATUS_INVALID_IMAGE_FORMAT; + } + } + + // next reloc entry + fixrec = reinterpret_cast(reinterpret_cast(fixrec) + fixrec->BlockSize); + } + + // Apply relocations, skip header + if (pImage->flags & HideVAD) + status = Driver().WriteMem( _process.pid(), pImage->ldrEntry.baseAddress + 0x1000, pImage->ldrEntry.size - 0x1000, pLocal + 0x1000 ); + else + status = _process.memory().Write( pImage->ldrEntry.baseAddress + 0x1000, pImage->ldrEntry.size - 0x1000, pLocal + 0x1000 ); + + if (!NT_SUCCESS( status )) + { + BLACKBONE_TRACE( L"ManualMap: Failed to apply relocations. Status = 0x%x", status ); + } + + return status; +} + +/// +/// Return existing or load missing dependency +/// +/// Currently napped image data +/// Dependency path +/// +call_result_t MMap::FindOrMapDependency( ImageContextPtr pImage, std::wstring& path ) +{ + // Already loaded + auto hMod = _process.modules().GetModule( path, LdrList, pImage->peImage.mType(), pImage->ldrEntry.fullPath.c_str() ); + if (hMod) + return hMod; + + BLACKBONE_TRACE( L"ManualMap: Loading new dependency '%ls'", path.c_str() ); + + auto flags = NameResolve::EnsureFullPath; + + // Wow64 fs redirection + if (pImage->ldrEntry.type == mt_mod32 && !_process.barrier().sourceWow64) + flags = static_cast(static_cast(flags) | NameResolve::Wow64); + + auto basedir = pImage->peImage.noPhysFile() ? Utils::GetExeDirectory() : Utils::GetParent( pImage->ldrEntry.fullPath ); + auto status = NameResolve::Instance().ResolvePath( + path, + pImage->ldrEntry.name, + basedir, + flags, + _process, + pImage->peImage.actx() + ); + + // Do remote SxS probe + if (status == STATUS_SXS_IDENTITIES_DIFFERENT) + { + status = ProbeRemoteSxS( path ); + } + + if (!NT_SUCCESS( status )) + { + BLACKBONE_TRACE( L"ManualMap: Failed to resolve dependency path '%ls', status 0x%x", path.c_str(), status ); + return status; + } + + BLACKBONE_TRACE( L"ManualMap: Dependency path resolved to '%ls'", path.c_str() ); + + LoadData data; + if (_mapCallback != nullptr) + { + ModuleData tmpData; + tmpData.baseAddress = 0; + tmpData.manual = ((pImage->flags & ManualImports) != 0); + tmpData.fullPath = path; + tmpData.name = Utils::ToLower( Utils::StripPath( path ) ); + tmpData.size = 0; + tmpData.type = pImage->ldrEntry.type; + + data = _mapCallback( PreCallback, _userContext, _process, tmpData ); + } + + // Loading method + if (data.mtype == MT_Manual || (data.mtype == MT_Default && pImage->flags & ManualImports)) + { + return FindOrMapModule( path, nullptr, 0, false, pImage->flags | NoSxS | NoDelayLoad | PartialExcept | IsDependency ); + } + else if (data.mtype != MT_None) + { + return _process.modules().Inject( path ); + } + // Aborted by user + else + { + return STATUS_REQUEST_CANCELED; + } +}; + +/// +/// Resolves image import or delayed image import +/// +/// Image data +/// Resolve delayed import instead +/// Status code +NTSTATUS MMap::ResolveImport( ImageContextPtr pImage, bool useDelayed /*= false */ ) +{ + auto imports = pImage->peImage.GetImports( useDelayed ); + if (imports.empty()) + return STATUS_SUCCESS; + + // Read whole image to process it locally + std::unique_ptr localImage( new uint8_t[pImage->ldrEntry.size] ); + auto pLocal = localImage.get(); + _process.memory().Read( pImage->imgMem.ptr(), pImage->ldrEntry.size, pLocal ); + + // Traverse entries + for (auto& importMod : imports) + { + std::wstring wstrDll = importMod.first; + + // Load dependency if needed + auto hMod = FindOrMapDependency( pImage, wstrDll ); + if (!hMod) + { + BLACKBONE_TRACE( L"ManualMap: Failed to load dependency '%ls'. Status 0x%x", wstrDll.c_str(), hMod.status ); + return hMod.status; + } + + for (auto& importFn : importMod.second) + { + call_result_t expData; + + if (importFn.importByOrd) + expData = _process.modules().GetExport( hMod.result(), reinterpret_cast(importFn.importOrdinal) ); + else + expData = _process.modules().GetExport( hMod.result(), importFn.importName.c_str() ); + + // Still forwarded, load missing modules + while (expData && expData->procAddress && expData->isForwarded) + { + std::wstring wdllpath = expData->forwardModule; + + // Ensure module is loaded + auto hFwdMod = FindOrMapDependency( pImage, wdllpath ); + if (!hFwdMod) + { + BLACKBONE_TRACE( L"ManualMap: Failed to load forwarded dependency '%ls'. Status 0x%x", wstrDll.c_str(), hFwdMod.status ); + return hFwdMod.status; + } + + if (expData->forwardByOrd) + { + expData = _process.modules().GetExport( + hFwdMod.result(), + reinterpret_cast(expData->forwardOrdinal), + wdllpath.c_str() + ); + } + else + expData = _process.modules().GetExport( hFwdMod.result(), expData->forwardName.c_str(), wdllpath.c_str() ); + } + + // Failed to resolve import + if (!expData) + { + if (importFn.importByOrd) + { + BLACKBONE_TRACE( + L"ManualMap: Failed to get import #%d from image '%ls'", + importFn.importOrdinal, + wstrDll.c_str() + ); + } + else + { + BLACKBONE_TRACE( + L"ManualMap: Failed to get import '%ls' from image '%ls'", + Utils::AnsiToWstring( importFn.importName ).c_str(), + wstrDll.c_str() + ); + } + + return expData.status; + } + + if (pImage->ldrEntry.type == mt_mod64) + *reinterpret_cast(pLocal + importFn.ptrRVA) = expData->procAddress; + else + *reinterpret_cast(pLocal + importFn.ptrRVA) = static_cast(expData->procAddress); + } + } + + auto status = STATUS_SUCCESS; + + // Apply imports, skip header + if (pImage->flags & HideVAD) + { + status = Driver().WriteMem( + _process.pid(), + pImage->ldrEntry.baseAddress + 0x1000, + pImage->ldrEntry.size - 0x1000, + pLocal + 0x1000 + ); + } + else + { + status = _process.memory().Write( + pImage->ldrEntry.baseAddress + 0x1000, + pImage->ldrEntry.size - 0x1000, + pLocal + 0x1000 + ); + } + + // Write function address + if (!NT_SUCCESS( status )) + { + BLACKBONE_TRACE( L"ManualMap: Failed to write import function. Status 0x%x", status ); + } + + return status; +} + +/// +/// Set custom exception handler to bypass SafeSEH under DEP +/// +/// image data +/// true on success +NTSTATUS MMap::EnableExceptions( ImageContextPtr pImage ) +{ + BLACKBONE_TRACE( L"ManualMap: Enabling exception support for image '%ls'", pImage->ldrEntry.name.c_str() ); + bool partial = (pImage->flags & PartialExcept) != 0; + bool success = _process.nativeLdr().InsertInvertedFunctionTable( pImage->ldrEntry ); + + if (pImage->ldrEntry.type == mt_mod64) + { + // Try RtlIsertInvertedTable + if (!success) + { + // Retry with documented method + auto expTableRVA = pImage->peImage.DirectoryAddress( IMAGE_DIRECTORY_ENTRY_EXCEPTION, pe::RVA ); + size_t size = pImage->peImage.DirectorySize( IMAGE_DIRECTORY_ENTRY_EXCEPTION ); + + // Invoke RtlAddFunctionTable + if (expTableRVA) + { + auto a = AsmFactory::GetAssembler( pImage->ldrEntry.type ); + uint64_t result = 0; + + pImage->pExpTableAddr = expTableRVA + pImage->imgMem.ptr(); + auto pAddTable = _process.modules().GetNtdllExport( "RtlAddFunctionTable", pImage->ldrEntry.type ); + if (!pAddTable) + return pAddTable.status; + + a->GenPrologue(); + a->GenCall( + pAddTable->procAddress, { + pImage->pExpTableAddr, + size / sizeof( IMAGE_RUNTIME_FUNCTION_ENTRY ), + pImage->imgMem.ptr() } + ); + + _process.remote().AddReturnWithEvent( *a, pImage->ldrEntry.type ); + a->GenEpilogue(); + + auto status = _process.remote().ExecInWorkerThread( (*a)->make(), (*a)->getCodeSize(), result ); + if (!NT_SUCCESS( status )) + return status; + } + // No exception table + else + return STATUS_NOT_FOUND; + } + } + else if (!success) + return STATUS_INVALID_EXCEPTION_HANDLER; + + // Custom handler not required + if (pImage->ldrEntry.safeSEH || (pImage->ldrEntry.type == mt_mod64 && (pImage->flags & CreateLdrRef || success))) + return STATUS_SUCCESS; + + return _expMgr.CreateVEH( _process, pImage->ldrEntry, partial ); +} + +/// +/// Remove custom exception handler +/// +/// image data +/// true on success +NTSTATUS MMap::DisableExceptions( ImageContextPtr pImage ) +{ + BLACKBONE_TRACE( L"ManualMap: Disabling exception support for image '%ls'", pImage->ldrEntry.name.c_str() ); + bool partial = false; + + if (pImage->ldrEntry.type == mt_mod64) + { + if (!pImage->pExpTableAddr) + return STATUS_NOT_FOUND; + + auto a = AsmFactory::GetAssembler( pImage->ldrEntry.type ); + uint64_t result = 0; + + auto pRemoveTable = _process.modules().GetNtdllExport( "RtlDeleteFunctionTable", pImage->ldrEntry.type ); + if (!pRemoveTable) + return pRemoveTable.status; + + a->GenPrologue(); + // RtlDeleteFunctionTable(pExpTable); + a->GenCall(pRemoveTable->procAddress, { pImage->pExpTableAddr } ); + _process.remote().AddReturnWithEvent( *a ); + a->GenEpilogue(); + + auto status = _process.remote().ExecInWorkerThread( (*a)->make(), (*a)->getCodeSize(), result ); + if (!NT_SUCCESS( status )) + return status; + } + + partial = (pImage->flags & PartialExcept) != 0; + return _expMgr.RemoveVEH( _process, partial, pImage->peImage.mType() ); +} + +/// +/// Resolve static TLS storage +/// +/// image data +/// Status code +NTSTATUS MMap::InitStaticTLS( ImageContextPtr pImage ) +{ + auto pTls = reinterpret_cast(pImage->peImage.DirectoryAddress( IMAGE_DIRECTORY_ENTRY_TLS )); + auto rebasedTlsPtr = REBASE( pTls, pImage->peImage.base(), pImage->imgMem.ptr() ); + + // Use native TLS initialization + if (pTls && pTls->AddressOfIndex) + { + BLACKBONE_TRACE( L"ManualMap: Performing static TLS initialization for image '%ls'", pImage->ldrEntry.name.c_str() ); + return _process.nativeLdr().AddStaticTLSEntry( pImage->ldrEntry, rebasedTlsPtr ); + } + + return STATUS_SUCCESS; +} + +/// +/// Calculate and set security cookie +/// +/// image data +/// Status code +NTSTATUS MMap::InitializeCookie( ImageContextPtr pImage ) +{ + auto pLoadConfig32 = reinterpret_cast(pImage->peImage.DirectoryAddress( IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG )); + auto pLoadConfig64 = reinterpret_cast(pLoadConfig32); + if (!pLoadConfig32) + return STATUS_SUCCESS; + + ptr_t pCookie = pLoadConfig32->SecurityCookie; + if (pImage->ldrEntry.type == mt_mod64) + pCookie = pLoadConfig64->SecurityCookie; + + if (!pCookie) + return STATUS_SUCCESS; + + // + // Cookie generation based on MSVC++ compiler + // + BLACKBONE_TRACE( L"ManualMap: Performing security cookie initializtion for image '%ls'", pImage->ldrEntry.name.c_str() ); + + FILETIME systime = { 0 }; + LARGE_INTEGER PerformanceCount = { { 0 } }; + size_t size = sizeof( uint32_t ); + + GetSystemTimeAsFileTime( &systime ); + QueryPerformanceCounter( &PerformanceCount ); + + ptr_t cookie = _process.pid() ^ _process.remote().getExecThread()->id() ^ reinterpret_cast(&cookie); + + if (pImage->ldrEntry.type == mt_mod64) + { + size = sizeof( uint64_t ); + + cookie ^= *reinterpret_cast(&systime); + cookie ^= (PerformanceCount.QuadPart << 32) ^ PerformanceCount.QuadPart; + cookie &= 0xFFFFFFFFFFFF; + + if (cookie == 0x2B992DDFA232) + cookie++; + } + else + { + cookie &= 0xFFFFFFFF; + cookie ^= systime.dwHighDateTime ^ systime.dwLowDateTime; + cookie ^= PerformanceCount.LowPart; + cookie ^= PerformanceCount.HighPart; + + if (cookie == 0xBB40E64E) + cookie++; + else if (!(cookie & 0xFFFF0000)) + cookie |= (cookie | 0x4711) << 16; + } + + return _process.memory().Write( REBASE( pCookie, pImage->peImage.imageBase(), pImage->imgMem.ptr() ), size, &cookie ); +} + +/// +/// Run module initializers(TLS and entry point). +/// +/// Image data +/// one of the following: +/// DLL_PROCESS_ATTACH +/// DLL_THREAD_ATTACH +/// DLL_PROCESS_DETACH +/// DLL_THREAD_DETTACH +/// +/// DllMain result +call_result_t MMap::RunModuleInitializers( ImageContextPtr pImage, DWORD dwReason, CustomArgs_t* pCustomArgs /*= nullptr*/ ) +{ + auto a = AsmFactory::GetAssembler( pImage->ldrEntry.type ); + uint64_t result = 0; + + auto hNtdll = _process.modules().GetModule( L"ntdll.dll", LdrList, pImage->peImage.mType() ); + auto pActivateActx = _process.modules().GetExport( hNtdll, "RtlActivateActivationContext" ); + auto pDeactivateActx = _process.modules().GetExport( hNtdll, "RtlDeactivateActivationContext" ); + + a->GenPrologue(); + + // ActivateActCtx + if (_pAContext.valid() && pActivateActx) + { + (*a)->mov( (*a)->zax, _pAContext.ptr() ); + (*a)->mov( (*a)->zax, asmjit::host::dword_ptr( (*a)->zax ) ); + a->GenCall( pActivateActx->procAddress, { 0, (*a)->zax, _pAContext.ptr() + sizeof( ptr_t ) } ); + } + + // Prepare custom arguments + ptr_t customArgumentsAddress = 0; + if (pCustomArgs) + { + auto memBuf = _process.memory().Allocate( pCustomArgs->size() + sizeof( uint64_t ), PAGE_EXECUTE_READWRITE, 0, false ); + if (!memBuf) + return memBuf.status; + + memBuf->Write( 0, pCustomArgs->size() ); + memBuf->Write( sizeof( uint64_t ), pCustomArgs->size(), pCustomArgs->data() ); + customArgumentsAddress = memBuf->ptr(); + } + + // Function order + // TLS first, entry point last + if (!(pImage->flags & NoTLS)) + { + // PTLS_CALLBACK_FUNCTION(pImage->ImageBase, dwReason, NULL); + for (auto& pCallback : pImage->tlsCallbacks) + { + BLACKBONE_TRACE( + L"ManualMap: Calling TLS callback at 0x%016llx for '%ls', Reason: %d", + pCallback, pImage->ldrEntry.name.c_str(), dwReason + ); + + a->GenCall( pCallback, { pImage->imgMem.ptr(), dwReason, customArgumentsAddress } ); + } + } + + // DllMain + if (pImage->ldrEntry.entryPoint != 0) + { + BLACKBONE_TRACE( L"ManualMap: Calling entry point for '%ls', Reason: %d", pImage->ldrEntry.name.c_str(), dwReason ); + a->GenCall( pImage->ldrEntry.entryPoint, { pImage->imgMem.ptr(), dwReason, customArgumentsAddress } ); + _process.remote().SaveCallResult( *a ); + } + + // DeactivateActCtx + if (_pAContext.valid() && pDeactivateActx) + { + (*a)->mov( (*a)->zax, _pAContext.ptr() + sizeof( ptr_t ) ); + (*a)->mov( (*a)->zax, asmjit::host::dword_ptr( (*a)->zax ) ); + a->GenCall( pDeactivateActx->procAddress, { 0, (*a)->zax } ); + } + + // Set invalid return code offset to preserve one from DllMain + _process.remote().AddReturnWithEvent( *a, pImage->ldrEntry.type, rt_int32, ARGS_OFFSET ); + a->GenEpilogue(); + + NTSTATUS status = _process.remote().ExecInWorkerThread( (*a)->make(), (*a)->getCodeSize(), result ); + if (!NT_SUCCESS( status )) + return status; + + if (pImage->ldrEntry.entryPoint == 0) + return call_result_t( ERROR_SUCCESS, STATUS_SUCCESS ); + + BLACKBONE_TRACE( L"ManualMap: DllMain of '%ls' returned %lld", pImage->ldrEntry.name.c_str(), result ); + return result; +} + + +/// +/// Create activation context +/// Target memory layout: +/// ----------------------------- +/// | hCtx | ACTCTX | file_path | +/// ----------------------------- +/// +/// Source umage +/// true on success +NTSTATUS MMap::CreateActx( const pe::PEImage& image ) +{ + auto a = AsmFactory::GetAssembler( image.mType() ); + + NTSTATUS status = STATUS_SUCCESS; + uint64_t result = 0; + + auto mem = _process.memory().Allocate( 512, PAGE_READWRITE ); + if (!mem) + return mem.status; + + _pAContext = std::move( mem.result() ); + + bool switchMode = image.mType() == mt_mod64 && _process.core().isWow64(); + auto kernel32 = _process.modules().GetModule( L"kernel32.dll" ); + if (!kernel32) + { + BLACKBONE_TRACE( + L"ManualMap: Failed to get kernel32 base, error 0x%08x. Possibly LDR is not available yet", + LastNtStatus() + ); + return LastNtStatus(); + } + + auto pCreateActx = _process.modules().GetExport( kernel32, "CreateActCtxW" ); + if (!pCreateActx) + { + BLACKBONE_TRACE( + L"ManualMap: Failed to create activation context for image '%ls'. 'CreateActCtxW' is absent", + image.manifestFile().c_str() + ); + return STATUS_ORDINAL_NOT_FOUND; + } + + // CreateActCtx(&act) + // Emulate Wow64 + if (switchMode) + { + _ACTCTXW_T act32 = { 0 }; + + act32.cbSize = sizeof(act32); + act32.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID; + act32.lpSource = _pAContext.ptr() + sizeof( ptr_t ) + sizeof( act32 ); + act32.lpResourceName = image.manifestID(); + + (*a)->push( _pAContext.ptr() + static_cast(sizeof( ptr_t )) ); + (*a)->mov( asmjit::host::eax, static_cast(pCreateActx->procAddress) ); + (*a)->call( (*a)->zax ); + (*a)->mov( asmjit::host::edx, _pAContext.ptr() ); + //a->mov( asmjit::host::dword_ptr( asmjit::host::edx ), asmjit::host::eax ); + (*a)->dw( '\x01\x02' ); + + auto pTermThd = _process.modules().GetNtdllExport( "NtTerminateThread", mt_mod32 ); + (*a)->push( (*a)->zax ); + (*a)->push( uint32_t( 0 ) ); + (*a)->mov( asmjit::host::eax, static_cast(pTermThd->procAddress) ); + (*a)->call( (*a)->zax ); + (*a)->ret( 4 ); + + // Write path to file + _pAContext.Write( sizeof( ptr_t ), act32 ); + _pAContext.Write( + sizeof( ptr_t ) + sizeof( act32 ), + (image.manifestFile().length() + 1) * sizeof( wchar_t ), + image.manifestFile().c_str() + ); + + auto pCode = _process.memory().Allocate( 0x1000 ); + if (!pCode) + return pCode.status; + + pCode->Write( 0, (*a)->getCodeSize(), (*a)->make() ); + + result = _process.remote().ExecDirect( pCode->ptr(), _pAContext.ptr() + sizeof( ptr_t ) ); + } + // Native way + else + { + auto fillACTX = [this, &image]( auto act ) + { + memset( &act, 0, sizeof( act ) ); + + act.cbSize = sizeof( act ); + act.lpSource = static_cast(this->_pAContext.ptr() + sizeof( ptr_t ) + sizeof( act )); + + // Ignore some fields for pure manifest file + if (!image.noPhysFile()) + { + act.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID; + act.lpResourceName = static_cast(image.manifestID()); + } + + // Write path to file + NTSTATUS status = this->_pAContext.Write( sizeof( ptr_t ), act ); + status |= this->_pAContext.Write( + sizeof( ptr_t ) + sizeof( act ), + (image.manifestFile().length() + 1) * sizeof( wchar_t ), + image.manifestFile().c_str() + ); + + return status; + }; + + if (_process.core().isWow64()) + status = fillACTX( _ACTCTXW32() ); + else + status = fillACTX( _ACTCTXW64() ); + + a->GenPrologue(); + a->GenCall( pCreateActx->procAddress, { _pAContext.ptr() + sizeof( ptr_t ) } ); + + (*a)->mov( (*a)->zdx, _pAContext.ptr() ); + (*a)->mov( (*a)->intptr_ptr( (*a)->zdx ), (*a)->zax ); + + _process.remote().AddReturnWithEvent( *a, image.mType() ); + a->GenEpilogue(); + + status = _process.remote().ExecInWorkerThread( (*a)->make(), (*a)->getCodeSize(), result ); + if (!NT_SUCCESS( status )) + return status; + } + + + if (reinterpret_cast(result) == INVALID_HANDLE_VALUE) + { + _pAContext.Free(); + + status = _process.remote().GetLastStatus(); + BLACKBONE_TRACE( L"ManualMap: Failed to create activation context for image '%ls'. Status: 0x%x", image.manifestFile().c_str(), status ); + return status; + } + + return STATUS_SUCCESS; +} + +/// +/// Do SxS path probing in the target process +/// +/// Path to probe +/// Status code +NTSTATUS MMap::ProbeRemoteSxS( std::wstring& path ) +{ + NTSTATUS status = STATUS_SUCCESS; + + constexpr uint32_t memSize = 0x1000; + constexpr uint32_t dll1Offset = 0x300; + constexpr uint32_t dll2Offset = 0x600; + constexpr uint32_t pathOffset = 0x800; + constexpr uint32_t strOffset = 0xA00; + constexpr uint16_t strSize = 0x200; + + // No underlying function + auto ProbeFn = _process.modules().GetNtdllExport( "RtlDosApplyFileIsolationRedirection_Ustr" ); + if (!ProbeFn) + return ProbeFn.status; + + auto actx = _pAContext.ptr(); + auto pActivateActx = _process.modules().GetNtdllExport( "RtlActivateActivationContext" ); + auto pDeactivateActx = _process.modules().GetNtdllExport( "RtlDeactivateActivationContext" ); + auto pAsm = AsmFactory::GetAssembler( _process.barrier().targetWow64 ); + auto& a = *pAsm.get(); + + // REmote buffer + auto memBuf = _process.memory().Allocate( memSize, PAGE_READWRITE ); + if (!memBuf) + return memBuf.status; + + // Fill Unicode strings + auto memPtr = memBuf->ptr(); + auto fillStr = [&]( auto&& OriginalName ) + { + std::remove_reference::type DllName1 = { 0 }; + + OriginalName.Length = static_cast(path.length() * sizeof( wchar_t )); + OriginalName.MaximumLength = OriginalName.Length; + OriginalName.Buffer = static_cast(memPtr + sizeof( OriginalName )); + + auto status = _process.memory().Write( memPtr, OriginalName ); + status = _process.memory().Write( memPtr + sizeof( OriginalName ), OriginalName.Length + 2, path.c_str() ); + if (!NT_SUCCESS( status )) + return status; + + DllName1.Length = 0; + DllName1.MaximumLength = strSize; + DllName1.Buffer = static_cast(memPtr + strOffset); + + return _process.memory().Write( memPtr + dll1Offset, DllName1 ); + }; + + if (_process.barrier().targetWow64) + status = fillStr( _UNICODE_STRING_T() ); + else + status = fillStr( _UNICODE_STRING_T() ); + + if (!NT_SUCCESS( status )) + return status; + + a.GenPrologue(); + + // ActivateActCtx + if (actx && pActivateActx) + { + a->mov( a->zax, actx ); + a->mov( a->zax, asmjit::host::dword_ptr( a->zax ) ); + a.GenCall( pActivateActx->procAddress, { 0, a->zax, actx + sizeof( ptr_t ) } ); + } + + // RtlDosApplyFileIsolationRedirection_Ustr + a.GenCall( ProbeFn->procAddress, + { + TRUE, + memPtr + 0, 0, + memPtr + dll1Offset, + memPtr + dll2Offset, + memPtr + pathOffset, + 0, 0, 0 + } ); + + _process.remote().SaveCallResult( a ); + + // DeactivateActCtx + if (actx && pDeactivateActx) + { + a->mov( a->zax, actx + sizeof( ptr_t ) ); + a->mov( a->zax, asmjit::host::dword_ptr( a->zax ) ); + a.GenCall( pDeactivateActx->procAddress, { 0, a->zax } ); + } + + _process.remote().AddReturnWithEvent( a, mt_default, rt_int32, ARGS_OFFSET ); + a.GenEpilogue(); + + uint64_t result = 0; + if (!NT_SUCCESS( status = _process.remote().ExecInWorkerThread( a->make(), a->getCodeSize(), result ) )) + return status; + + status = static_cast(result); + if (NT_SUCCESS( status )) + { + // Read result back + std::unique_ptr localBuf( new uint8_t[memSize] ); + if (NT_SUCCESS( status = memBuf->Read( 0, memSize, localBuf.get() ) )) + path = reinterpret_cast(localBuf.get() + strOffset); + } + + return status; +} + +/// +/// Hide memory VAD node +/// +/// Image to purge +/// Status code +NTSTATUS MMap::ConcealVad( const MemBlock& imageMem) +{ + return Driver().ConcealVAD( _process.pid(), imageMem.ptr(), static_cast(imageMem.size()) ); +} + +/// +/// Allocates memory region beyond 4GB limit +/// +/// Image data +/// Block size +/// Status code +NTSTATUS MMap::AllocateInHighMem( MemBlock& imageMem, size_t size ) +{ + ptr_t ptr = 0; + + // Align on page boundary + size = Align( size, 0x1000 ); + + // + // Get random address + // + bool found = true; + static std::random_device rd; + std::uniform_int_distribution dist( 0x100000, 0x7FFFFFFF ); + + // Make sure address is unused + for (ptr = dist( rd ) * 0x1000; found; ptr = dist( rd ) * 0x1000) + { + found = false; + for (auto& entry : _usedBlocks) + { + if (ptr >= entry.first && ptr < entry.first + entry.second) + { + found = true; + break; + } + } + } + + // Not implemented yet + NTSTATUS status = STATUS_NOT_IMPLEMENTED; + + // Change protection and save address + if (NT_SUCCESS( status )) + { + _usedBlocks.emplace_back( ptr, size ); + + imageMem = MemBlock( &_process.memory(), ptr, size, PAGE_READWRITE, false ); + _process.memory().Protect( ptr, size, PAGE_READWRITE ); + return true; + } + + return status; +} + +/// +/// Remove any traces from remote process +/// +/// +void MMap::Cleanup() +{ + reset(); + _expMgr.reset(); + _process.remote().reset(); +} + + +/// +/// Transform section characteristics into memory protection flags +/// +/// Section characteristics +/// Memory protection value +DWORD MMap::GetSectionProt( DWORD characteristics ) +{ + DWORD dwResult = PAGE_NOACCESS; + + if(characteristics & IMAGE_SCN_MEM_EXECUTE) + { + if(characteristics & IMAGE_SCN_MEM_WRITE) + dwResult = PAGE_EXECUTE_READWRITE; + else if(characteristics & IMAGE_SCN_MEM_READ) + dwResult = PAGE_EXECUTE_READ; + else + dwResult = PAGE_EXECUTE; + } + else + { + if(characteristics & IMAGE_SCN_MEM_WRITE) + dwResult = PAGE_READWRITE; + else if(characteristics & IMAGE_SCN_MEM_READ) + dwResult = PAGE_READONLY; + else + dwResult = PAGE_NOACCESS; + } + + return dwResult; +} + +} diff --git a/third/Blackbone/src/BlackBone/ManualMap/MMap.h b/third/Blackbone/src/BlackBone/ManualMap/MMap.h new file mode 100644 index 0000000000000000000000000000000000000000..df18ad0821bddb21c6a91950d993fb56224b0c27 --- /dev/null +++ b/third/Blackbone/src/BlackBone/ManualMap/MMap.h @@ -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 +#include +#include +#include + +namespace blackbone +{ + +class CustomArgs_t +{ +public: + void push_back( const void* ptr, size_t size ) + { + append( ptr, size ); + } + + template + void push_back( const T* ptr ) + { + append( ptr, sizeof( T ) ); + } + + template + void push_back( const std::basic_string& str ) + { + append( str.data(), str.size() * sizeof( T ) ); + } + + template + void push_back( const std::vector& cVec ) + { + append( cVec.data(), cVec.size() * sizeof( T ) ); + } + + template + void push_back( const std::array& arr ) + { + append( arr.data(), arr.size() * sizeof( T ) ); + } + +#if _MSC_VER >= 1900 + template + void push_back( const std::tuple& tpl ) + { + tuple_detail::copyTuple( tpl, _buffer ); + } +#endif + /// + /// Get raw data size + /// + /// + inline size_t size() const { return _buffer.size(); } + + /// + /// Get raw data + /// + /// Data ptr + inline uint8_t* data() { return _buffer.data(); } + inline const uint8_t* data() const { return _buffer.data(); } + +private: + /// + /// Append buffer from raw memory + /// + /// Raw pointer + /// Data size + 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 _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(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); + + +/// +/// Image data +/// +struct ImageContext +{ + using vecPtr = std::vector; + + 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; +using vecImageCtx = std::vector; + +/// +/// Manual image mapper +/// +class MMap +{ +public: + BLACKBONE_API MMap( class Process& proc ); + BLACKBONE_API ~MMap( void ); + + /// + /// Manually map PE image into underlying target process + /// + /// Image path + /// Image mapping flags + /// Mapping callback. Triggers for each mapped module + /// User-supplied callback context + /// Mapped image info + BLACKBONE_API call_result_t MapImage( + const std::wstring& path, + eLoadFlags flags = NoFlags, + MapCallback mapCallback = nullptr, + void* context = nullptr, + CustomArgs_t* pCustomArgs_t = nullptr + ); + + /// + ///Manually map PE image into underlying target process + /// + /// Image data buffer + /// Buffer size. + /// If set to true - buffer has image memory layout + /// Image mapping flags + /// Mapping callback. Triggers for each mapped module + /// User-supplied callback context + /// Mapped image info + BLACKBONE_API call_result_t MapImage( + size_t size, void* buffer, + bool asImage = false, + eLoadFlags flags = NoFlags, + MapCallback mapCallback = nullptr, + void* context = nullptr, + CustomArgs_t* pCustomArgs_t = nullptr + ); + + /// + /// Unmap all manually mapped modules + /// + /// Status code + BLACKBONE_API NTSTATUS UnmapAllModules(); + + /// + /// Remove any traces from remote process + /// + /// + BLACKBONE_API void Cleanup(); + + /// + /// Reset local data + /// + BLACKBONE_API inline void reset() { _images.clear(); _pAContext.Reset(); _usedBlocks.clear(); } +private: + /// + /// Manually map PE image into underlying target process + /// + /// Image path + /// Image data buffer + /// Buffer size. + /// If set to true - buffer has image memory layout + /// Image mapping flags + /// Mapping callback. Triggers for each mapped module + /// User-supplied callback context + /// Mapped image info + call_result_t 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 + ); + + /// + /// Fix image path for pure managed mapping + /// + /// Image base + /// New image path + template + void FixManagedPath( ptr_t base, const std::wstring &path ); + + /// + /// Get existing module or map it if absent + /// + /// Image path + /// Mapping flags + /// Module info + call_result_t FindOrMapModule( + const std::wstring& path, + void* buffer, size_t size, bool asImage, + eLoadFlags flags = NoFlags + ); + + /// + /// Run module initializers(TLS and entry point). + /// + /// Image data + /// one of the following: + /// DLL_PROCESS_ATTACH + /// DLL_THREAD_ATTACH + /// DLL_PROCESS_DETACH + /// DLL_THREAD_DETTACH + /// + /// DllMain result + call_result_t RunModuleInitializers( ImageContextPtr pImage, DWORD dwReason, CustomArgs_t* pCustomArgs_t = nullptr ); + + /// + /// Copies image into target process + /// + /// Image data + /// Status code + NTSTATUS CopyImage( ImageContextPtr pImage ); + + /// + /// Adjust image memory protection + /// + /// image data + /// Status code + NTSTATUS ProtectImageMemory( ImageContextPtr pImage ); + + /// + /// Fix relocations if image wasn't loaded at base address + /// + /// image data + /// true on success + NTSTATUS RelocateImage( ImageContextPtr pImage ); + + /// + /// Resolves image import or delayed image import + /// + /// Image data + /// Resolve delayed import instead + /// Status code + NTSTATUS ResolveImport( ImageContextPtr pImage, bool useDelayed = false ); + + /// + /// Resolve static TLS storage + /// + /// image data + /// Status code + NTSTATUS InitStaticTLS( ImageContextPtr pImage ); + + /// + /// Set custom exception handler to bypass SafeSEH under DEP + /// + /// image data + /// Status code + NTSTATUS EnableExceptions( ImageContextPtr pImage ); + + /// + /// Remove custom exception handler + /// + /// image data + /// true on success + NTSTATUS DisableExceptions( ImageContextPtr pImage ); + + /// + /// Calculate and set security cookie + /// + /// image data + /// Status code + NTSTATUS InitializeCookie( ImageContextPtr pImage ); + + /// + /// Return existing or load missing dependency + /// + /// Currently mapped image data + /// Dependency path + /// + call_result_t FindOrMapDependency( ImageContextPtr pImage, std::wstring& path ); + + /// + /// Create activation context + /// Target memory layout: + /// ----------------------------- + /// | hCtx | ACTCTX | file_path | + /// ----------------------------- + /// + /// Manifest container path + /// Manifest resource id + /// if true - 'path' points to a valid PE file, otherwise - 'path' points to separate manifest file + /// true on success + NTSTATUS CreateActx( const pe::PEImage& image ); + + /// + /// Do SxS path probing in the target process + /// + /// Path to probe + /// Status code + NTSTATUS ProbeRemoteSxS( std::wstring& path ); + + /// + /// Hide memory VAD node + /// + /// Image to purge + /// Status code + NTSTATUS ConcealVad( const MemBlock& imageMem ); + + /// + /// Allocates memory region beyond 4GB limit + /// + /// Image data + /// Block size + /// Status code + NTSTATUS AllocateInHighMem( MemBlock& imageMem, size_t size ); + + /// + /// Transform section characteristics into memory protection flags + /// + /// Section characteristics + /// Memory protection value + 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> _usedBlocks; // Used memory blocks +}; + +} + diff --git a/third/Blackbone/src/BlackBone/ManualMap/Native/NtLoader.cpp b/third/Blackbone/src/BlackBone/ManualMap/Native/NtLoader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..af18d74e24d14e515ede14587bbfd74ebe8f252a --- /dev/null +++ b/third/Blackbone/src/BlackBone/ManualMap/Native/NtLoader.cpp @@ -0,0 +1,1009 @@ +#include "NtLoader.h" +#include "../../Process/Process.h" +#include "../../Include/Macro.h" +#include "../../Misc/Utils.h" +#include "../../Misc/DynImport.h" +#include "../../Misc/trace.hpp" +#include "../../Symbols/SymbolData.h" + +#include <3rd_party/VersionApi.h> + +namespace blackbone +{ + +NtLdr::NtLdr( Process& proc ) + : _process( proc ) +{ +} + +NtLdr::~NtLdr(void) +{ +} + +/// +/// Initialize some loader stuff +/// +/// Target module type +/// true on success(); + FindLdrpHashTable(); + if (IsWindows8OrGreater()) + FindLdrpModuleIndexBase(); + } + else + { + FindLdrHeap(); + FindLdrpHashTable(); + if (IsWindows8OrGreater()) + FindLdrpModuleIndexBase(); + } + + _nodeMap.clear(); + + // Report errors +#ifndef BLACKBONE_NO_TRACE + if (_LdrHeapBase == 0) + BLACKBONE_TRACE( "NativeLdr: LdrHeapBase not found" ); + if (_LdrpHashTable == 0) + BLACKBONE_TRACE( "NativeLdr: LdrpHashTable not found" ); + if (IsWindows8OrGreater() && _LdrpModuleIndexBase == 0) + BLACKBONE_TRACE( "NativeLdr: LdrpModuleIndexBase not found" ); +#endif + + return true; +} + +/// +/// Add module to some loader structures +/// (LdrpHashTable, LdrpModuleIndex( win8+ only ), InMemoryOrderModuleList( win7 only )) +/// +/// Module data +/// true on success +bool NtLdr::CreateNTReference( NtLdrEntry& mod ) +{ + // Skip + if (mod.flags == Ldr_None) + return true; + + // Check if reinitialization is required + if (_initializedFor != mod.type) + Init( mod.type ); + + bool x64Image = (mod.type == mt_mod64); + bool w8 = IsWindows8OrGreater(); + + // Win 8 and higher + if (w8) + mod.ldrPtr = CALL_64_86( x64Image, InitW8Node, mod ); + // Windows 7 and earlier + else + mod.ldrPtr = CALL_64_86( x64Image, InitW7Node, mod ); + + if (mod.ldrPtr == 0) + return false; + + _nodeMap.emplace( mod.baseAddress, mod.ldrPtr ); + + // Insert into module graph + if (mod.flags & Ldr_ModList && w8) + CALL_64_86( x64Image, InsertTreeNode, mod.ldrPtr, mod ); + + // Insert into LdrpHashTable + if (mod.flags & Ldr_HashTable) + { + auto ptr = FIELD_PTR_64_86( x64Image, mod.ldrPtr, _LDR_DATA_TABLE_ENTRY_BASE_T, HashLinks ); + CALL_64_86( x64Image, InsertHashNode, ptr, mod.hash ); + } + + // Insert into ldr lists + if (mod.flags & Ldr_ThdCall || (!w8 && mod.flags & Ldr_ModList)) + { + _process.memory().Write( FIELD_PTR_64_86( x64Image, mod.ldrPtr, _LDR_DATA_TABLE_ENTRY_BASE_T, Flags ), 0x80004 ); + ptr_t loadPtr = 0, initptr = 0; + + loadPtr = FIELD_PTR_64_86( x64Image, mod.ldrPtr, _LDR_DATA_TABLE_ENTRY_BASE_T, InLoadOrderLinks ); + if(w8) + initptr = FIELD_PTR_64_86( x64Image, mod.ldrPtr, _LDR_DATA_TABLE_ENTRY_BASE_T, InInitializationOrderLinks ); + + CALL_64_86( x64Image, InsertMemModuleNode, 0, loadPtr, initptr ); + } + + return true; +} + +/// +/// Get module native node ptr or create new +/// +/// node pointer (if nullptr - new dummy node is allocated) +/// Module base address +/// Node address +template +ptr_t NtLdr::SetNode( ptr_t ptr, Module pModule ) +{ + if(ptr == 0) + { + auto mem = _process.memory().Allocate( sizeof( T ), PAGE_READWRITE, 0, false ); + if (!mem) + return 0; + + ptr = mem->ptr(); + mem->Write( offsetOf( &T::DllBase ), pModule ); + } + + return ptr; +} + +/// +/// Create thread static TLS array +/// +/// Module data +/// TLS directory of target image +/// Status code +NTSTATUS NtLdr::AddStaticTLSEntry( NtLdrEntry& mod, ptr_t tlsPtr ) +{ + bool wxp = IsWindowsXPOrGreater() && !IsWindowsVistaOrGreater(); + ptr_t pNode = _nodeMap.count( mod.baseAddress ) ? _nodeMap[mod.baseAddress] : 0; + + // Allocate appropriate structure + ptr_t LdrpHandleTlsData = 0; + if (mod.type == mt_mod64) + { + LdrpHandleTlsData = g_symbols.LdrpHandleTlsData64; + pNode = SetNode<_LDR_DATA_TABLE_ENTRY_BASE64>( pNode, mod.baseAddress ); + } + else + { + LdrpHandleTlsData = g_symbols.LdrpHandleTlsData32; + pNode = SetNode<_LDR_DATA_TABLE_ENTRY_BASE32>( pNode, mod.baseAddress ); + } + + if (pNode == 0) + return STATUS_NO_MEMORY; + + // Update ptr + if (mod.ldrPtr == 0) + mod.ldrPtr = pNode; + + // Manually add TLS table + if (wxp && tlsPtr != 0) + { + ptr_t pTeb = 0; + pTeb = _process.remote().getExecThread()->teb( static_cast<_TEB32*>(nullptr) ); + + auto mem = _process.memory().Allocate( 0x1000, PAGE_READWRITE, 0, false ); + if (!mem) + return mem.status; + + auto tlsStore = std::move( mem.result() ); + + IMAGE_TLS_DIRECTORY remoteTls = { 0 }; + _process.memory().Read( tlsPtr, sizeof( remoteTls ), &remoteTls ); + + auto size = remoteTls.EndAddressOfRawData - remoteTls.StartAddressOfRawData; + std::unique_ptr buf( new uint8_t[size]() ); + + _process.memory().Read( remoteTls.StartAddressOfRawData, size, buf.get() ); + + tlsStore.Write( 0, tlsStore.ptr() + 0x800 ); + tlsStore.Write( 0x800, size, buf.get() ); + + return _process.memory().Write( fieldPtr( pTeb, &_TEB32::ThreadLocalStoragePointer ), tlsStore.ptr() ); + } + + // Use native method + if (LdrpHandleTlsData) + { + auto a = AsmFactory::GetAssembler( mod.type ); + uint64_t result = 0; + + a->GenPrologue(); + a->GenCall( LdrpHandleTlsData, { pNode }, IsWindows8Point1OrGreater() ? cc_thiscall : cc_stdcall ); + _process.remote().AddReturnWithEvent( *a ); + a->GenEpilogue(); + + auto status = _process.remote().ExecInWorkerThread( (*a)->make(), (*a)->getCodeSize(), result ); + if (!NT_SUCCESS( status )) + return status; + + return static_cast(result); + } + else + return STATUS_ORDINAL_NOT_FOUND; +} + + +/// +/// Create module record in LdrpInvertedFunctionTable +/// Used to create fake SAFESEH entries +/// +/// Module data +/// true on success +bool NtLdr::InsertInvertedFunctionTable( NtLdrEntry& mod ) +{ + ptr_t RtlInsertInvertedFunctionTable = g_symbols.RtlInsertInvertedFunctionTable64; + ptr_t LdrpInvertedFunctionTable = g_symbols.LdrpInvertedFunctionTable64; + if (mod.type == mt_mod32) + { + RtlInsertInvertedFunctionTable = g_symbols.RtlInsertInvertedFunctionTable32; + LdrpInvertedFunctionTable = g_symbols.LdrpInvertedFunctionTable32; + } + + // Invalid addresses. Probably pattern scan has failed + if (RtlInsertInvertedFunctionTable == 0 || LdrpInvertedFunctionTable == 0) + return false; + + auto InsertP = [&]( auto table ) + { + uint64_t result = 0; + auto a = AsmFactory::GetAssembler( mod.type ); + auto& memory = _process.memory(); + + memory.Read( LdrpInvertedFunctionTable, sizeof( table ), &table ); + for (ULONG i = 0; i < table.Count; i++) + if (table.Entries[i].ImageBase == mod.baseAddress) + return true; + + a->GenPrologue(); + + if (IsWindows8Point1OrGreater()) + a->GenCall( RtlInsertInvertedFunctionTable, { mod.baseAddress, mod.size }, cc_fastcall ); + else if (IsWindows8OrGreater()) + a->GenCall( RtlInsertInvertedFunctionTable, { mod.baseAddress, mod.size } ); + else + a->GenCall( RtlInsertInvertedFunctionTable, { LdrpInvertedFunctionTable, mod.baseAddress, mod.size } ); + + _process.remote().AddReturnWithEvent( *a ); + a->GenEpilogue(); + + _process.remote().ExecInWorkerThread( (*a)->make(), (*a)->getCodeSize(), result ); + memory.Read( LdrpInvertedFunctionTable, sizeof( table ), &table ); + + for (DWORD i = 0; i < table.Count; i++) + { + if (table.Entries[i].ImageBase != mod.baseAddress) + continue; + + // If Image has SAFESEH, RtlInsertInvertedFunctionTable is enough + if (table.Entries[i].SizeOfTable != 0) + return mod.safeSEH = true; + + // + // Create fake Exception directory + // Directory will be filled later, during exception handling + // + + // Allocate memory for 2048 possible handlers + auto mem = memory.Allocate( sizeof( DWORD ) * 0x800, PAGE_READWRITE, 0, false ); + if (!mem) + return false; + + // EncodeSystemPointer( mem->ptr() ) + uint32_t size = 0; + ptr_t pEncoded = 0; + auto cookie = *reinterpret_cast(0x7FFE0330); + if (mod.type == mt_mod64) + { + size = sizeof( uint64_t ); + pEncoded = _rotr64( cookie ^ mem->ptr(), cookie & 0x3F ); + } + else + { + size = sizeof( uint32_t ); + pEncoded = _rotr( cookie ^ mem->ptr(), cookie & 0x1F ); + } + + // m_LdrpInvertedFunctionTable->Entries[i].ExceptionDirectory + uintptr_t field_ofst = reinterpret_cast(&table.Entries[i].ExceptionDirectory) + - reinterpret_cast(&table); + + // In Win10 LdrpInvertedFunctionTable is located in mrdata section + // mrdata is read-only by default + // LdrProtectMrdata is used to make it writable when needed + DWORD flOld = 0; + memory.Protect( LdrpInvertedFunctionTable + field_ofst, sizeof( ptr_t ), PAGE_EXECUTE_READWRITE, &flOld ); + auto status = memory.Write( LdrpInvertedFunctionTable + field_ofst, size, &pEncoded ); + memory.Protect( LdrpInvertedFunctionTable + field_ofst, sizeof( ptr_t ), flOld, &flOld ); + + return NT_SUCCESS( status ); + } + + return false; + }; + + if (IsWindows8OrGreater()) + { + if(mod.type == mt_mod64) + return InsertP( _RTL_INVERTED_FUNCTION_TABLE8() ); + else + return InsertP( _RTL_INVERTED_FUNCTION_TABLE8() ); + } + else + { + if (mod.type == mt_mod64) + return InsertP( _RTL_INVERTED_FUNCTION_TABLE7() ); + else + return InsertP( _RTL_INVERTED_FUNCTION_TABLE7() ); + } +} + +/// +/// Free static TLS +/// +/// Target module +/// Don't create new threads during remote call +/// Status code +NTSTATUS NtLdr::UnloadTLS( const NtLdrEntry& mod, bool noThread /*= false*/ ) +{ + // No loader entry to free + if (mod.ldrPtr == 0) + return STATUS_INVALID_ADDRESS; + + ptr_t LdrpReleaseTlsEntry = g_symbols.LdrpReleaseTlsEntry64; + if (mod.type == mt_mod32) + LdrpReleaseTlsEntry = g_symbols.LdrpReleaseTlsEntry32; + + // Not available + if (LdrpReleaseTlsEntry == 0) + return STATUS_ORDINAL_NOT_FOUND; + + auto a = AsmFactory::GetAssembler( mod.type ); + uint64_t result = 0; + + a->GenPrologue(); + a->GenCall( LdrpReleaseTlsEntry, { mod.ldrPtr, 0 }, IsWindows8Point1OrGreater() ? cc_fastcall : cc_stdcall ); + + _process.remote().AddReturnWithEvent( *a ); + a->GenEpilogue(); + + _process.remote().CreateRPCEnvironment( noThread ? Worker_UseExisting : Worker_CreateNew, true ); + _process.remote().ExecInWorkerThread( (*a)->make(), (*a)->getCodeSize(), result ); + + return STATUS_SUCCESS; +} + +/// +/// Initialize OS-specific module entry +/// +/// Module data +/// Pointer to created entry +template +ptr_t NtLdr::InitBaseNode( NtLdrEntry& mod ) +{ + using EntryType = _LDR_DATA_TABLE_ENTRY_BASE_T; + ptr_t entryPtr = AllocateInHeap( mod.type, sizeof( _LDR_DATA_TABLE_ENTRY_W8 ) ).result( 0 ); + if (entryPtr == 0) + return 0; + + // Allocate space for Unicode string + _UNICODE_STRING_T strLocal = { 0 }; + auto mem = _process.memory().Allocate( 0x1000, PAGE_READWRITE, 0, false ); + if (!mem) + return 0; + + auto StringBuf = std::move( mem.result() ); + + // entryPtr->DllBase = ModuleBase; + _process.memory().Write( fieldPtr( entryPtr, &EntryType::DllBase ), static_cast(mod.baseAddress) ); + + // entryPtr->SizeOfImage = ImageSize; + _process.memory().Write( fieldPtr( entryPtr, &EntryType::SizeOfImage ), mod.size ); + + // entryPtr->EntryPoint = entryPoint; + _process.memory().Write( fieldPtr( entryPtr, &EntryType::EntryPoint ), static_cast(mod.entryPoint) ); + + // Dll name hash + mod.hash = HashString( mod.name ); + + // Dll name + strLocal.Length = static_cast(mod.name.length() * sizeof( wchar_t )); + strLocal.MaximumLength = 0x600; + strLocal.Buffer = StringBuf.ptr(); + StringBuf.Write( 0, strLocal.Length + 2, mod.name.c_str() ); + + // entryPtr->BaseDllName = strLocal; + _process.memory().Write( fieldPtr( entryPtr, &EntryType::BaseDllName ), strLocal ); + + // Dll full path + strLocal.Length = static_cast(mod.fullPath.length() * sizeof( wchar_t )); + strLocal.Buffer = StringBuf.ptr() + 0x800; + StringBuf.Write( 0x800, strLocal.Length + 2, mod.fullPath.c_str() ); + + // entryPtr->FullDllName = strLocal; + _process.memory().Write( fieldPtr( entryPtr, &EntryType::FullDllName ), strLocal ); + + // entryPtr->LoadCount = -1; + _process.memory().Write( fieldPtr( entryPtr, &EntryType::LoadCount ), strLocal ); + + return entryPtr; +} + +/// +/// Initialize OS-specific module entry +/// +/// Module data +/// Pointer to created entry +template +ptr_t NtLdr::InitW8Node( NtLdrEntry& mod ) +{ + using EntryType = _LDR_DATA_TABLE_ENTRY_W8; + using DdagType = _LDR_DDAG_NODE; + + ptr_t entryPtr = InitBaseNode( mod ); + ptr_t DdagNodePtr = AllocateInHeap( mod.type, sizeof( DdagType ) ).result( 0 ); + if (!entryPtr || !DdagNodePtr) + return 0; + + // entryPtr->BaseNameHashValue = hash; + _process.memory().Write( fieldPtr( entryPtr, &EntryType::BaseNameHashValue ), mod.hash ); + + // + // Ddag node + // + + // entryPtr->DdagNode = pDdagNode; + _process.memory().Write( fieldPtr( entryPtr, &EntryType::DdagNode ), static_cast(DdagNodePtr) ); + + // DdagNodePtr->State = LdrModulesReadyToRun; + _process.memory().Write( fieldPtr( DdagNodePtr, &DdagType::State ), LdrModulesReadyToRun ); + + // DdagNodePtr->ReferenceCount = 1; + _process.memory().Write( fieldPtr( DdagNodePtr, &DdagType::ReferenceCount ), 1 ); + + // DdagNodePtr->LoadCount = -1; + _process.memory().Write( fieldPtr( DdagNodePtr, &DdagType::LoadCount ), -1 ); + + return entryPtr; +} + +/// +/// Initialize OS-specific module entry +/// +/// Module data +/// Pointer to created entry +template +ptr_t NtLdr::InitW7Node( NtLdrEntry& mod ) +{ + using EntryType = _LDR_DATA_TABLE_ENTRY_W7; + + ptr_t entryPtr = InitBaseNode( mod ); + if (!entryPtr) + return 0; + + // Forward Links + _process.memory().Write( fieldPtr( entryPtr, &EntryType::ForwarderLinks ), fieldPtr( entryPtr, &EntryType::ForwarderLinks ) ); + _process.memory().Write( fieldPtr( entryPtr, &EntryType::ForwarderLinks ) + sizeof( T ), fieldPtr( entryPtr, &EntryType::ForwarderLinks ) ); + + // Static links + _process.memory().Write( fieldPtr( entryPtr, &EntryType::StaticLinks ), fieldPtr( entryPtr, &EntryType::StaticLinks ) ); + _process.memory().Write( fieldPtr( entryPtr, &EntryType::StaticLinks ) + sizeof( T ), fieldPtr( entryPtr, &EntryType::StaticLinks ) ); + + return entryPtr; +} + +/// +/// Insert entry into win8 module graph +/// +/// Node to insert +/// Module data +template +void NtLdr::InsertTreeNode( ptr_t nodePtr, const NtLdrEntry& mod ) +{ + // + // Win8 module tree + // + auto root = _process.memory().Read( _LdrpModuleIndexBase ); + if (!root) + return; + + auto LdrNodePtr = structBase( root.result(), &_LDR_DATA_TABLE_ENTRY_W8::BaseAddressIndexNode ); + auto LdrNode = _process.memory().Read<_LDR_DATA_TABLE_ENTRY_W8>( LdrNodePtr ).result( _LDR_DATA_TABLE_ENTRY_W8() ); + bool bRight = false; + + // Walk tree + for (;;) + { + if (static_cast(mod.baseAddress) < LdrNode.DllBase) + { + if (LdrNode.BaseAddressIndexNode.Left) + { + LdrNodePtr = structBase( LdrNode.BaseAddressIndexNode.Left, &_LDR_DATA_TABLE_ENTRY_W8::BaseAddressIndexNode ); + _process.memory().Read( LdrNodePtr, sizeof(LdrNode), &LdrNode ); + } + else + break; + } + else if (static_cast(mod.baseAddress) > LdrNode.DllBase) + { + if (LdrNode.BaseAddressIndexNode.Right) + { + LdrNodePtr = structBase( LdrNode.BaseAddressIndexNode.Right, &_LDR_DATA_TABLE_ENTRY_W8::BaseAddressIndexNode ); + _process.memory().Read( LdrNodePtr, sizeof(LdrNode), &LdrNode ); + } + else + { + bRight = true; + break; + } + } + // Already in tree (increase ref counter) + else + { + // pLdrNode->DdagNode->ReferenceCount++; + auto Ddag = _process.memory().Read<_LDR_DDAG_NODE>( LdrNode.DdagNode ); + if (!Ddag) + return; + + Ddag->ReferenceCount++; + _process.memory().Write( LdrNode.DdagNode, Ddag.result() ); + return; + } + } + + // Insert using RtlRbInsertNodeEx + auto a = AsmFactory::GetAssembler( mod.type ); + uint64_t result = 0; + auto RtlRbInsertNodeEx = _process.modules().GetNtdllExport( "RtlRbInsertNodeEx", mod.type ); + if (!RtlRbInsertNodeEx) + return; + + a->GenPrologue(); + a->GenCall( RtlRbInsertNodeEx->procAddress, + { + _LdrpModuleIndexBase, + fieldPtr( LdrNodePtr, &_LDR_DATA_TABLE_ENTRY_W8::BaseAddressIndexNode ), + static_cast(bRight), + fieldPtr( nodePtr, &_LDR_DATA_TABLE_ENTRY_W8::BaseAddressIndexNode ) + } ); + + _process.remote().AddReturnWithEvent( *a, mod.type ); + a->GenEpilogue(); + + _process.remote().ExecInWorkerThread( (*a)->make(), (*a)->getCodeSize(), result ); +} + +/// +/// Insert entry into InLoadOrderModuleList and InMemoryOrderModuleList +/// +/// InMemoryOrderModuleList link of entry to be inserted +/// InLoadOrderModuleList link of entry to be inserted +template +void NtLdr::InsertMemModuleNode( ptr_t pNodeMemoryOrderLink, ptr_t pNodeLoadOrderLink, ptr_t pNodeInitOrderLink ) +{ + ptr_t pPeb = _process.core().peb(); + ptr_t pLdr = 0; + + if (pPeb) + pLdr = _process.memory().Read( fieldPtr( pPeb, &PEB_T::Ldr ) ).result( 0 ); + + if (pLdr) + { + // pLdr->InMemoryOrderModuleList + if (pNodeMemoryOrderLink) + InsertTailList( fieldPtr( pLdr, &_PEB_LDR_DATA2_T::InMemoryOrderModuleList ), pNodeMemoryOrderLink ); + + // pLdr->InLoadOrderModuleList + if (pNodeLoadOrderLink) + InsertTailList( fieldPtr( pLdr, &_PEB_LDR_DATA2_T::InLoadOrderModuleList ), pNodeLoadOrderLink ); + + // pLdr->InInitializationOrderModuleList + if (pNodeInitOrderLink) + InsertTailList( fieldPtr( pLdr, &_PEB_LDR_DATA2_T::InInitializationOrderModuleList ), pNodeInitOrderLink ); + } +} + +/// +/// Insert entry into LdrpHashTable[] +/// +/// Link of entry to be inserted +/// Module hash +template +void NtLdr::InsertHashNode( ptr_t pNodeLink, ULONG hash ) +{ + if(pNodeLink) + { + // LrpHashTable record + auto pHashList = _process.memory().Read( _LdrpHashTable + sizeof( _LIST_ENTRY_T )*(hash & 0x1F) ); + if(pHashList) + InsertTailList( pHashList.result(), pNodeLink ); + } +} + +/// +/// Insert entry into standard double linked list +/// +/// List head pointer +/// Entry list link to be inserted +template +void NtLdr::InsertTailList( ptr_t ListHead, ptr_t Entry ) +{ + // PrevEntry = ListHead->Blink; + auto PrevEntry = _process.memory().Read( fieldPtr( ListHead, &_LIST_ENTRY_T::Blink ) ).result( 0 ); + + // Entry->Flink = ListHead; + // Entry->Blink = PrevEntry; + _process.memory().Write( fieldPtr( Entry, &_LIST_ENTRY_T::Flink ), sizeof(T), &ListHead ); + _process.memory().Write( fieldPtr( Entry, &_LIST_ENTRY_T::Blink ), sizeof( T ), &PrevEntry ); + + // PrevEntry->Flink = Entry; + // ListHead->Blink = Entry; + _process.memory().Write( fieldPtr( PrevEntry, &_LIST_ENTRY_T::Flink ), sizeof( T ), &Entry ); + _process.memory().Write( fieldPtr( ListHead, &_LIST_ENTRY_T::Blink ), sizeof( T ), &Entry ); +} + +/// +/// Hash image name +/// +/// Iamge name +/// Hash +ULONG NtLdr::HashString( const std::wstring& str ) +{ + ULONG hash = 0; + + if (IsWindows8OrGreater()) + { + UNICODE_STRING ustr; + SAFE_CALL( RtlInitUnicodeString, &ustr, str.c_str() ); + SAFE_NATIVE_CALL( RtlHashUnicodeString, &ustr, (BOOLEAN)TRUE, 0, &hash ); + } + else + { + for (auto& ch : str) + hash += 0x1003F * static_cast(SAFE_CALL( RtlUpcaseUnicodeChar, ch )); + } + + return hash; +} + +/// +/// Allocate memory from heap if possible +/// +/// Module type +/// Size to allocate +/// Allocated address +call_result_t NtLdr::AllocateInHeap( eModType mt, size_t size ) +{ + NTSTATUS status = STATUS_SUCCESS; + auto RtlAllocateHeap = _process.modules().GetNtdllExport( "RtlAllocateHeap", mt ); + if (_LdrHeapBase && RtlAllocateHeap) + { + auto a = AsmFactory::GetAssembler( mt ); + + // + // HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); + // + a->GenPrologue(); + a->GenCall( RtlAllocateHeap->procAddress, { _LdrHeapBase, HEAP_ZERO_MEMORY, size } ); + _process.remote().AddReturnWithEvent( (*a), mt ); + a->GenEpilogue(); + + uint64_t result = 0; + status = _process.remote().ExecInWorkerThread( (*a)->make(), (*a)->getCodeSize(), result ); + if (NT_SUCCESS( status )) + return result; + } + else + status = STATUS_ORDINAL_NOT_FOUND; + + if (!NT_SUCCESS( status )) + { + auto mem = _process.memory().Allocate( size, PAGE_READWRITE, 0, false ); + if (!mem) + return mem.status; + + return mem->ptr(); + } + + return STATUS_ILLEGAL_FUNCTION; +} + +/// +/// Find LdrpHashTable[] variable +/// +/// true on success +template +bool NtLdr::FindLdrpHashTable() +{ + _PEB_T Peb = { 0 }; + _process.core().peb( &Peb ); + if (Peb.ImageBaseAddress == 0) + return false; + + auto Ldr = _process.memory().Read<_PEB_LDR_DATA2_T>( Peb.Ldr ); + if (!Ldr) + return false; + + // Get loader entry + _LDR_DATA_TABLE_ENTRY_BASE_T entry = { 0 }; + auto entryPtr = structBase( Ldr->InInitializationOrderModuleList.Flink, &_LDR_DATA_TABLE_ENTRY_BASE_T::InInitializationOrderLinks ); + if (!NT_SUCCESS( _process.memory().Read( entryPtr, entry ) )) + return false; + + wchar_t nameBuf[260] = { 0 }; + if (!NT_SUCCESS( _process.memory().Read( entry.BaseDllName.Buffer, entry.BaseDllName.Length + 2, nameBuf ) )) + return false; + + ULONG NtdllHashIndex = HashString( nameBuf ) & 0x1F; + T NtdllBase = static_cast(entry.DllBase); + T NtdllEndAddress = NtdllBase + entry.SizeOfImage - 1; + + // scan hash list to the head (head is located within ntdll) + T NtdllHashHeadPtr = 0; + _LIST_ENTRY_T hashNode = entry.HashLinks; + + for (auto e = hashNode.Flink; + e != fieldPtr( entryPtr, &_LDR_DATA_TABLE_ENTRY_BASE_T::HashLinks ); + e = hashNode.Flink) + { + if (e >= NtdllBase && e < NtdllEndAddress) + { + NtdllHashHeadPtr = e; + break; + } + + if (!NT_SUCCESS ( _process.memory().Read( hashNode.Flink, hashNode ) )) + return false; + } + + if (NtdllHashHeadPtr != 0) + _LdrpHashTable = NtdllHashHeadPtr - NtdllHashIndex * sizeof( _LIST_ENTRY_T ); + + return _LdrpHashTable != 0; +} + + +/// +/// Find LdrpModuleIndex variable under win8 +/// +/// true on success +template +bool NtLdr::FindLdrpModuleIndexBase() +{ + _PEB_T Peb = { 0 }; + _process.core().peb( &Peb ); + + if (Peb.ImageBaseAddress != 0) + { + T lastNode = 0; + auto Ldr = _process.memory().Read<_PEB_LDR_DATA2_T>( Peb.Ldr ); + if (!Ldr) + return false; + + auto entryPtr = structBase( Ldr->InInitializationOrderModuleList.Flink, &_LDR_DATA_TABLE_ENTRY_W8::InInitializationOrderLinks ); + + _RTL_BALANCED_NODE node = { 0 }; + if (!NT_SUCCESS( _process.memory().Read( fieldPtr( entryPtr, &_LDR_DATA_TABLE_ENTRY_W8::BaseAddressIndexNode ), node ) )) + return false; + + // Get root node + for(; node.ParentValue; ) + { + // Ignore last few bits + lastNode = node.ParentValue & T( -8 ); + if (!NT_SUCCESS( _process.memory().Read( lastNode, node ) )) + return false; + } + + // Get pointer to root + pe::PEImage ntdllPE; + T* pStart = nullptr; + T* pEnd = nullptr; + + auto pNtdll = _process.modules().GetModule( L"ntdll.dll" ); + std::unique_ptr localBuf( new uint8_t[pNtdll->size] ); + _process.memory().Read( pNtdll->baseAddress, pNtdll->size, localBuf.get() ); + + ntdllPE.Parse( localBuf.get() ); + + for (auto& section : ntdllPE.sections()) + if (_stricmp( reinterpret_cast(section.Name), ".data") == 0 ) + { + pStart = reinterpret_cast( localBuf.get() + section.VirtualAddress); + pEnd = reinterpret_cast( localBuf.get() + section.VirtualAddress + section.Misc.VirtualSize); + break; + } + + auto iter = std::find( pStart, pEnd, lastNode ); + if (iter != pEnd) + { + _LdrpModuleIndexBase = REBASE( iter, localBuf.get(), pNtdll->baseAddress ); + return true; + } + } + + return false; +} + +/// +/// Find Loader heap base +/// +/// true on success +template +bool NtLdr::FindLdrHeap() +{ + int32_t retries = 50; + _PEB_T Peb = { 0 }; + + _process.core().peb( &Peb ); + for (; Peb.Ldr == 0 && retries > 0; retries--, Sleep( 10 )) + _process.core().peb( &Peb ); + + if (Peb.Ldr) + { + auto Ldr = _process.memory().Read<_PEB_LDR_DATA2_T>( Peb.Ldr ); + if (!Ldr) + return false; + + for (; Ldr->InMemoryOrderModuleList.Flink == Ldr->InMemoryOrderModuleList.Blink && retries > 0; retries--, Sleep( 10 )) + Ldr = _process.memory().Read<_PEB_LDR_DATA2_T>( Peb.Ldr ); + + MEMORY_BASIC_INFORMATION64 mbi = { 0 }; + auto NtdllEntry = Ldr->InMemoryOrderModuleList.Flink; + if (NT_SUCCESS( _process.core().native()->VirtualQueryExT( NtdllEntry, &mbi ) )) + { + _LdrHeapBase = static_cast(mbi.AllocationBase); + assert( _LdrHeapBase != _process.modules().GetModule( L"ntdll.dll" )->baseAddress ); + return true; + } + } + + return false; +} + +/// +/// Unlink module from Ntdll loader +/// +/// Module data +/// Don't create new threads during unlink +/// true on success +bool NtLdr::Unlink( const ModuleData& mod, bool noThread /*= false*/ ) +{ + ptr_t ldrEntry = 0; + auto x64Image = mod.type == mt_mod64; + + // Reinitialize + if (_initializedFor != mod.type) + Init( mod.type ); + + // Unlink from linked lists + ldrEntry = CALL_64_86( x64Image, UnlinkFromLdr, mod ); + + // Unlink from graph + // TODO: Unlink from _LdrpMappingInfoIndex. Still can't decide if it is required. + if (IsWindows8OrGreater()) + ldrEntry = CALL_64_86( x64Image, UnlinkTreeNode, mod, ldrEntry, noThread ); + + return ldrEntry != 0; +} + +/// +/// Unlink module from PEB_LDR_DATA +/// +/// Module data +/// Address of removed record +template +ptr_t NtLdr::UnlinkFromLdr( const ModuleData& mod ) +{ + auto ldrEntry = mod.ldrPtr; + if (ldrEntry == 0) + ldrEntry = FindLdrEntry( mod.baseAddress ); + + // Unlink from module lists + if (ldrEntry != 0) + { + UnlinkListEntry( fieldPtr( ldrEntry, &_LDR_DATA_TABLE_ENTRY_BASE_T::InLoadOrderLinks ) ); + UnlinkListEntry( fieldPtr( ldrEntry, &_LDR_DATA_TABLE_ENTRY_BASE_T::InMemoryOrderLinks ) ); + UnlinkListEntry( fieldPtr( ldrEntry, &_LDR_DATA_TABLE_ENTRY_BASE_T::InInitializationOrderLinks ) ); + UnlinkListEntry( fieldPtr( ldrEntry, &_LDR_DATA_TABLE_ENTRY_BASE_T::HashLinks ) ); + } + + return ldrEntry; +} + +/// +/// Finds LDR entry for module +/// +/// Target module base +/// Found entry +/// Found LDR entry address +template +ptr_t NtLdr::FindLdrEntry( module_t moduleBase, _LDR_DATA_TABLE_ENTRY_BASE_T* found /*= nullptr*/ ) +{ + auto native = _process.core().native(); + _PEB_T peb = { }; + _PEB_LDR_DATA2_T ldr = { }; + _LDR_DATA_TABLE_ENTRY_BASE_T localEntry = { }; + if (found == nullptr) + found = &localEntry; + + if (native->getPEB( &peb ) != 0 && NT_SUCCESS( native->ReadProcessMemoryT( peb.Ldr, &ldr, sizeof( ldr ) ) )) + { + const auto ofst = offsetOf( &_LDR_DATA_TABLE_ENTRY_BASE_T::InLoadOrderLinks ); + const auto head = fieldPtr( peb.Ldr, &_PEB_LDR_DATA2_T::InLoadOrderModuleList ); + + for (T entry = ldr.InLoadOrderModuleList.Flink; + entry != 0 && entry != head; + native->ReadProcessMemoryT( entry, &entry, sizeof( entry ) ) + ) + { + native->ReadProcessMemoryT( entry - ofst, found, sizeof( *found ) ); + if (found->DllBase == static_cast(moduleBase)) + return entry - ofst; + } + } + + return 0; +} + +/// +/// Remove record from LIST_ENTRY structure +/// +/// Entry link +template +void NtLdr::UnlinkListEntry( ptr_t pListLink ) +{ + T OldFlink = _process.memory().Read( fieldPtr( pListLink, &_LIST_ENTRY_T::Flink ) ).result( 0 ); + T OldBlink = _process.memory().Read( fieldPtr( pListLink, &_LIST_ENTRY_T::Blink ) ).result( 0 ); + + // List is empty + if (OldBlink == 0 || OldFlink == 0 || OldBlink == OldFlink) + return; + + // OldFlink->Blink = OldBlink; + _process.memory().Write( fieldPtr( OldFlink, &_LIST_ENTRY_T::Blink ), OldBlink ); + + // OldBlink->Flink = OldFlink; + _process.memory().Write( fieldPtr( OldBlink, &_LIST_ENTRY_T::Flink ), OldFlink ); +} + +/// +/// Unlink from module graph +/// +/// Module data +/// Module LDR entry +/// Don't create new threads during unlink +/// Address of removed record +template +ptr_t NtLdr::UnlinkTreeNode( const ModuleData& mod, ptr_t ldrEntry, bool noThread /*= false*/ ) +{ + if (ldrEntry == 0) + return ldrEntry; + + auto a = AsmFactory::GetAssembler( mod.type ); + uint64_t result = 0; + + auto RtlRbRemoveNode = _process.modules().GetNtdllExport( "RtlRbRemoveNode" ); + if (!RtlRbRemoveNode) + return 0; + + a->GenPrologue(); + a->GenCall( RtlRbRemoveNode->procAddress, + { + _LdrpModuleIndexBase, + ldrEntry + offsetOf( &_LDR_DATA_TABLE_ENTRY_W8::BaseAddressIndexNode ) + } ); + + _process.remote().AddReturnWithEvent( *a ); + a->GenEpilogue(); + + _process.remote().CreateRPCEnvironment( noThread ? Worker_UseExisting : Worker_CreateNew, true ); + _process.remote().ExecInWorkerThread( (*a)->make(), (*a)->getCodeSize(), result ); + + return ldrEntry; +} + +} diff --git a/third/Blackbone/src/BlackBone/ManualMap/Native/NtLoader.h b/third/Blackbone/src/BlackBone/ManualMap/Native/NtLoader.h new file mode 100644 index 0000000000000000000000000000000000000000..871e588a79406fa8305992a8fc6f0494297163f8 --- /dev/null +++ b/third/Blackbone/src/BlackBone/ManualMap/Native/NtLoader.h @@ -0,0 +1,237 @@ +#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 ); + BLACKBONE_API ~NtLdr( void ); + + /// + /// Initialize some loader stuff + /// + /// Target module type + /// true on success + BLACKBONE_API bool Init( eModType initFor = mt_default ); + + /// + /// Add module to some loader structures + /// (LdrpHashTable, LdrpModuleIndex( win8 only ), InMemoryOrderModuleList( win7 only )) + /// + /// Module data + /// true on success + BLACKBONE_API bool CreateNTReference( NtLdrEntry& mod ); + + /// + /// Create thread static TLS array + /// + /// Module data + /// TLS directory of target image + /// Status code + BLACKBONE_API NTSTATUS AddStaticTLSEntry( NtLdrEntry& mod, ptr_t tlsPtr ); + + /// + /// Create module record in LdrpInvertedFunctionTable + /// Used to create fake SAFESEH entries + /// + /// Module data + /// true on success + BLACKBONE_API bool InsertInvertedFunctionTable( NtLdrEntry& mod ); + + /// + /// Free static TLS + /// + /// Target module + /// Don't create new threads during remote call + /// Status code + BLACKBONE_API NTSTATUS UnloadTLS( const NtLdrEntry& mod, bool noThread = false ); + + /// + /// Unlink module from Ntdll loader + /// + /// Module data + /// Don't create new threads during unlink + /// true on success + BLACKBONE_API bool Unlink( const ModuleData& mod, bool noThread = false ); +private: + + /// + /// Find LdrpHashTable[] variable + /// + /// true on success + template + bool FindLdrpHashTable(); + + /// + /// Find LdrpModuleIndex variable under win8 + /// + /// true on success + template + bool FindLdrpModuleIndexBase(); + + /// + /// Find Loader heap base + /// + /// true on success + template + bool FindLdrHeap(); + + /// + /// Initialize OS-specific module entry + /// + /// Module data + /// Pointer to created entry + template + ptr_t InitBaseNode( NtLdrEntry& mod ); + + /// + /// Initialize OS-specific module entry + /// + /// Module data + /// Pointer to created entry + template + ptr_t InitW8Node( NtLdrEntry& mod ); + + /// + /// Initialize OS-specific module entry + /// + /// Module data + /// Pointer to created entry + template + ptr_t InitW7Node( NtLdrEntry& mod ); + + /// + /// Insert entry into win8 module graph + /// + /// Node to insert + /// Module data + template + void InsertTreeNode( ptr_t nodePtr, const NtLdrEntry& mod ); + + /// + /// Insert entry into LdrpHashTable[] + /// + /// Link of entry to be inserted + /// Module hash + template + void InsertHashNode( ptr_t pNodeLink, ULONG hash ); + + /// + /// Insert entry into InLoadOrderModuleList and InMemoryOrderModuleList + /// + /// InMemoryOrderModuleList link of entry to be inserted + /// InLoadOrderModuleList link of entry to be inserted + template + void InsertMemModuleNode( ptr_t pNodeMemoryOrderLink, ptr_t pNodeLoadOrderLink, ptr_t pNodeInitOrderLink ); + + /// + /// Insert entry into standard double linked list + /// + /// List head pointer + /// Entry list link to be inserted + template + void InsertTailList( ptr_t ListHead, ptr_t Entry ); + + /// + /// Hash image name + /// + /// Iamge name + /// Hash + ULONG HashString( const std::wstring& str ); + + /// + /// Allocate memory from heap if possible + /// + /// Module type + /// Size to allocate + /// Allocated address + call_result_t AllocateInHeap( eModType mt, size_t size ); + + /// + /// Get module native node ptr or create new + /// + /// node pointer (if nullptr - new dummy node is allocated) + /// Module base address + /// Node address + template + ptr_t SetNode( ptr_t ptr, Module pModule ); + + /// + /// Unlink module from PEB_LDR_DATA + /// + /// Module data + /// Address of removed record + template + ptr_t UnlinkFromLdr( const ModuleData& mod ); + + /// + /// Finds LDR entry for module + /// + /// Target module base + /// Found entry + /// Found LDR entry address + template + ptr_t FindLdrEntry( module_t moduleBase, _LDR_DATA_TABLE_ENTRY_BASE_T* found = nullptr ); + + /// + /// Remove record from LIST_ENTRY structure + /// + /// Entry link + template + void UnlinkListEntry( ptr_t pListLink ); + + /// + /// Unlink from module graph + /// + /// Module data + /// Module LDR entry + /// Don't create new threads during unlink + /// Address of removed record + template + 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 _nodeMap; // Allocated native structures +}; + +} + diff --git a/third/Blackbone/src/BlackBone/Misc/DynImport.h b/third/Blackbone/src/BlackBone/Misc/DynImport.h new file mode 100644 index 0000000000000000000000000000000000000000..4b16d7397ea31a6e4e6617e2af604c11264c5dee --- /dev/null +++ b/third/Blackbone/src/BlackBone/Misc/DynImport.h @@ -0,0 +1,118 @@ +#pragma once + +#include "../Include/Types.h" +#include "../Include/Winheaders.h" +#include "Utils.h" +#include "InitOnce.h" + +#include + +namespace blackbone +{ + +/// +/// Dynamic import +/// +class DynImport +{ +public: + BLACKBONE_API static DynImport& Instance() + { + static DynImport instance; + return instance; + } + + DynImport() = default; + DynImport( const DynImport& ) = delete; + + /// + /// Get dll function + /// + /// Function name + /// Function pointer + template + T get( const std::string& name ) + { + InitializeOnce(); + + CSLock lck( _mapGuard ); + + auto iter = _funcs.find( name ); + if (iter != _funcs.end()) + return reinterpret_cast(iter->second); + + return nullptr; + } + + /// + /// Safely call import + /// If import not found - return STATUS_ORDINAL_NOT_FOUND + /// + /// Import name. + /// Function args + /// Function result or STATUS_ORDINAL_NOT_FOUND if import not found + template + NTSTATUS safeNativeCall( const std::string& name, Args&&... args ) + { + auto pfn = DynImport::get( name ); + return pfn ? pfn( std::forward( args )... ) : STATUS_ORDINAL_NOT_FOUND; + } + + /// + /// Safely call import + /// If import not found - return 0 + /// + /// Import name. + /// Function args + /// Function result or 0 if import not found + template + auto safeCall( const std::string& name, Args&&... args ) + { + auto pfn = DynImport::get( name ); + return pfn ? pfn( std::forward( args )... ) : std::invoke_result_t(); + } + + /// + /// Load function into database + /// + /// Function name + /// Module name + /// true on success + BLACKBONE_API FARPROC load( const std::string& name, const std::wstring& module ) + { + auto mod = GetModuleHandleW( module.c_str() ); + return load( name, mod ); + } + + /// + /// Load function into database + /// + /// Function name + /// Module base + /// true on success + 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 _funcs; // function database + CriticalSection _mapGuard; // function database guard +}; + +// Syntax sugar +#define LOAD_IMPORT(name, module) (DynImport::Instance().load( name, module )) +#define GET_IMPORT(name) (DynImport::Instance().get( #name )) +#define SAFE_NATIVE_CALL(name, ...) (DynImport::Instance().safeNativeCall( #name, __VA_ARGS__ )) +#define SAFE_CALL(name, ...) (DynImport::Instance().safeCall( #name, __VA_ARGS__ )) + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Misc/InitOnce.cpp b/third/Blackbone/src/BlackBone/Misc/InitOnce.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9bf4c676a5ac6b4280eea0ab359d072260631753 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Misc/InitOnce.cpp @@ -0,0 +1,135 @@ +#include "InitOnce.h" +#include "../Include/Winheaders.h" +#include "../Include/Macro.h" +#include "../Include/HandleGuard.h" +#include <3rd_party/VersionApi.h> + +#include "DynImport.h" +#include "../Symbols/SymbolLoader.h" +#include "NameResolve.h" + +#include +#include + +namespace blackbone +{ + +class InitOnce +{ +public: + InitOnce() = delete; + InitOnce( const InitOnce& ) = delete; + InitOnce& operator=( const InitOnce& ) = delete; + InitOnce( InitOnce&& ) = delete; + InitOnce& operator=( InitOnce&& ) = delete; + + static bool Exec() + { + if (!_InterlockedCompareExchange( &_done, TRUE, FALSE )) + { + InitVersion(); + + GrantPriviledge( L"SeDebugPrivilege" ); + GrantPriviledge( L"SeLoadDriverPrivilege" ); + LoadFuncs(); + + SymbolLoader sl; + sl.Load( g_symbols ); + + NameResolve::Instance().Initialize(); + } + + return true; + } + + /// + /// Grant current process arbitrary privilege + /// + /// Privilege name + /// Status + static NTSTATUS GrantPriviledge( const std::wstring& name ) + { + TOKEN_PRIVILEGES Priv, PrivOld; + DWORD cbPriv = sizeof( PrivOld ); + Handle token; + + if (!OpenThreadToken( GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, FALSE, &token )) + { + if (GetLastError() != ERROR_NO_TOKEN) + return LastNtStatus(); + + if (!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &token )) + return LastNtStatus(); + } + + Priv.PrivilegeCount = 1; + Priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + LookupPrivilegeValueW( NULL, name.c_str(), &Priv.Privileges[0].Luid ); + + if (!AdjustTokenPrivileges( token, FALSE, &Priv, sizeof( Priv ), &PrivOld, &cbPriv )) + return LastNtStatus(); + + if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) + return LastNtStatus(); + + return STATUS_SUCCESS; + } + + static void LoadFuncs() + { + HMODULE hNtdll = GetModuleHandleW( L"ntdll.dll" ); + HMODULE hKernel32 = GetModuleHandleW( L"kernel32.dll" ); + + LOAD_IMPORT( "NtQuerySystemInformation", hNtdll ); + LOAD_IMPORT( "RtlDosApplyFileIsolationRedirection_Ustr", hNtdll ); + LOAD_IMPORT( "RtlInitUnicodeString", hNtdll ); + LOAD_IMPORT( "RtlFreeUnicodeString", hNtdll ); + LOAD_IMPORT( "RtlHashUnicodeString", hNtdll ); + LOAD_IMPORT( "RtlUpcaseUnicodeChar", hNtdll ); + LOAD_IMPORT( "NtQueryInformationProcess", hNtdll ); + LOAD_IMPORT( "NtSetInformationProcess", hNtdll ); + LOAD_IMPORT( "NtQueryInformationThread", hNtdll ); + LOAD_IMPORT( "NtDuplicateObject", hNtdll ); + LOAD_IMPORT( "NtQueryObject", hNtdll ); + LOAD_IMPORT( "NtQuerySection", hNtdll ); + LOAD_IMPORT( "RtlCreateActivationContext", hNtdll ); + LOAD_IMPORT( "NtQueryVirtualMemory", hNtdll ); + LOAD_IMPORT( "NtCreateThreadEx", hNtdll ); + LOAD_IMPORT( "NtLockVirtualMemory", hNtdll ); + LOAD_IMPORT( "NtSuspendProcess", hNtdll ); + LOAD_IMPORT( "NtResumeProcess", hNtdll ); + LOAD_IMPORT( "RtlImageNtHeader", hNtdll ); + LOAD_IMPORT( "NtLoadDriver", hNtdll ); + LOAD_IMPORT( "NtUnloadDriver", hNtdll ); + LOAD_IMPORT( "RtlDosPathNameToNtPathName_U", hNtdll ); + LOAD_IMPORT( "NtOpenEvent", hNtdll ); + LOAD_IMPORT( "NtCreateEvent", hNtdll ); + LOAD_IMPORT( "NtQueueApcThread", hNtdll ); + LOAD_IMPORT( "RtlEncodeSystemPointer", hNtdll ); + LOAD_IMPORT( "RtlQueueApcWow64Thread", hNtdll ); + LOAD_IMPORT( "NtWow64QueryInformationProcess64", hNtdll ); + LOAD_IMPORT( "NtWow64ReadVirtualMemory64", hNtdll ); + LOAD_IMPORT( "NtWow64WriteVirtualMemory64", hNtdll ); + LOAD_IMPORT( "Wow64GetThreadContext", hKernel32 ); + LOAD_IMPORT( "Wow64SetThreadContext", hKernel32 ); + LOAD_IMPORT( "Wow64SuspendThread", hKernel32 ); + LOAD_IMPORT( "GetProcessDEPPolicy", hKernel32 ); + LOAD_IMPORT( "QueryFullProcessImageNameW", hKernel32 ); + } + +private: + static volatile long _done; +}; + +/// +/// Exported InitOnce wrapper +/// +/// true on initialization completion +bool InitializeOnce() +{ + // Static flag is still unsafe because of magic statics + return InitOnce::Exec(); +} + +volatile long InitOnce::_done = 0; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Misc/InitOnce.h b/third/Blackbone/src/BlackBone/Misc/InitOnce.h new file mode 100644 index 0000000000000000000000000000000000000000..78a6adc92624b41c2197e1c5a7cc9791e397b9ce --- /dev/null +++ b/third/Blackbone/src/BlackBone/Misc/InitOnce.h @@ -0,0 +1,7 @@ +#pragma once +#include "../Config.h" + +namespace blackbone +{ +BLACKBONE_API bool InitializeOnce(); +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Misc/NameResolve.cpp b/third/Blackbone/src/BlackBone/Misc/NameResolve.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f2d84e817d9b494155b21d6b4d37be5547cbb281 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Misc/NameResolve.cpp @@ -0,0 +1,377 @@ +#include "NameResolve.h" +#include "../Include/NativeStructures.h" +#include "../Include/Macro.h" +#include "../Misc/Utils.h" +#include "../Misc/DynImport.h" +#include "../Process/Process.h" + +#include +#include +#include <3rd_party/VersionApi.h> + +namespace blackbone +{ + +NameResolve& NameResolve::Instance() +{ + static NameResolve instance; + return instance; +} + +/// +/// Initialize api set map +/// +/// +bool NameResolve::Initialize() +{ + if (IsWindows10OrGreater()) + return InitializeP< PAPI_SET_NAMESPACE_ARRAY_10, + PAPI_SET_NAMESPACE_ENTRY_10, + PAPI_SET_VALUE_ARRAY_10, + PAPI_SET_VALUE_ENTRY_10 >(); + else if (IsWindows8Point1OrGreater()) + return InitializeP< PAPI_SET_NAMESPACE_ARRAY, + PAPI_SET_NAMESPACE_ENTRY, + PAPI_SET_VALUE_ARRAY, + PAPI_SET_VALUE_ENTRY >(); + else if (IsWindows7OrGreater()) + return InitializeP< PAPI_SET_NAMESPACE_ARRAY_V2, + PAPI_SET_NAMESPACE_ENTRY_V2, + PAPI_SET_VALUE_ARRAY_V2, + PAPI_SET_VALUE_ENTRY_V2 >(); + else + return true; +} + +/// +/// OS dependent api set initialization +/// +/// true on success +template +bool blackbone::NameResolve::InitializeP() +{ + if (!_apiSchema.empty()) + return true; + + PEB_T *ppeb = reinterpret_cast(reinterpret_cast(NtCurrentTeb())->ProcessEnvironmentBlock); + PApiSetMap pSetMap = reinterpret_cast(ppeb->ApiSetMap); + + for (DWORD i = 0; i < pSetMap->Count; i++) + { + PApiSetEntry pDescriptor = pSetMap->entry(i); + + std::vector vhosts; + wchar_t dllName[MAX_PATH] = { 0 }; + + auto nameSize = pSetMap->apiName( pDescriptor, dllName ); + std::transform( dllName, dllName + nameSize / sizeof( wchar_t ), dllName, ::towlower ); + + PHostArray pHostData = pSetMap->valArray( pDescriptor ); + + for (DWORD j = 0; j < pHostData->Count; j++) + { + PHostEntry pHost = pHostData->entry( pSetMap, j ); + std::wstring hostName( + reinterpret_cast(reinterpret_cast(pSetMap) + pHost->ValueOffset), + pHost->ValueLength / sizeof( wchar_t ) + ); + + if (!hostName.empty()) + vhosts.emplace_back( std::move( hostName ) ); + } + + _apiSchema.emplace( dllName, std::move( vhosts ) ); + } + + return true; +} + +/// +/// Resolve image path. +/// +/// Image to resolve +/// Name of parent image. Used only when resolving import images +/// Directory where source image is located +/// Resolve flags +/// Process ID. Used to search process executable directory +/// Activation context +/// Status +NTSTATUS NameResolve::ResolvePath( + std::wstring& path, + const std::wstring& baseName, + const std::wstring& searchDir, + eResolveFlag flags, + Process& proc, + HANDLE actx /*= INVALID_HANDLE_VALUE*/ + ) +{ + NTSTATUS status = STATUS_SUCCESS; + wchar_t tmpPath[4096] = { 0 }; + std::wstring completePath; + + path = Utils::ToLower( std::move( path ) ); + + // Leave only file name + std::wstring filename = Utils::StripPath( path ); + + // 'ext-ms-' are resolved the same way 'api-ms-' are + if (!IsWindows10OrGreater() && filename.find( L"ext-ms-" ) == 0) + filename.erase( 0, 4 ); + + // + // ApiSchema redirection + // + auto iter = std::find_if( _apiSchema.begin(), _apiSchema.end(), [&filename]( const auto& val ) { + return filename.find( val.first.c_str() ) != filename.npos; } ); + + if (iter != _apiSchema.end()) + { + // Select appropriate api host + if (!iter->second.empty()) + path = iter->second.front() != baseName ? iter->second.front() : iter->second.back(); + else + path = baseName; + + status = ProbeSxSRedirect( path, proc, actx ); + if (NT_SUCCESS( status ) || status == STATUS_SXS_IDENTITIES_DIFFERENT) + { + return status; + } + else if (flags & EnsureFullPath) + { + wchar_t sys_path[255] = { 0 }; + GetSystemDirectoryW( sys_path, 255 ); + + path = std::wstring( sys_path ) + L"\\" + path; + } + + return STATUS_SUCCESS; + } + + if (flags & ApiSchemaOnly) + return STATUS_NOT_FOUND; + + // SxS redirection + status = ProbeSxSRedirect( path, proc, actx ); + if (NT_SUCCESS( status ) || status == STATUS_SXS_IDENTITIES_DIFFERENT) + return status; + + if (flags & NoSearch) + return STATUS_NOT_FOUND; + + // Already a full-qualified name + if (Utils::FileExists( path )) + return STATUS_SUCCESS; + + // + // Perform search accordingly to Windows Image loader search order + // 1. KnownDlls + // + HKEY hKey = NULL; + LRESULT res = 0; + res = RegOpenKeyW( HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\KnownDLLs", &hKey ); + + if (res == 0) + { + for (int i = 0; i < 0x1000 && res == ERROR_SUCCESS; i++) + { + wchar_t value_name[255] = { 0 }; + wchar_t value_data[255] = { 0 }; + + DWORD dwSize = 255; + DWORD dwType = 0; + + res = RegEnumValueW( hKey, i, value_name, &dwSize, NULL, &dwType, reinterpret_cast(value_data), &dwSize ); + + if (_wcsicmp( value_data, filename.c_str() ) == 0) + { + wchar_t sys_path[255] = { 0 }; + dwSize = 255; + + // In Win10 DllDirectory value got screwed, so less reliable method is used + if (flags & Wow64) + GetSystemWow64DirectoryW( sys_path, dwSize ); + else + GetSystemDirectoryW( sys_path, dwSize ); + + if (res == ERROR_SUCCESS) + { + path = std::wstring( sys_path ) + L"\\" + value_data; + + RegCloseKey( hKey ); + return STATUS_SUCCESS; + } + } + } + + RegCloseKey( hKey ); + } + + + // + // 2. Parent directory of the image being resolved + // + if (!searchDir.empty()) + { + completePath = searchDir + L"\\" + filename; + if (Utils::FileExists( completePath )) + { + path = completePath; + return STATUS_SUCCESS; + } + } + + // + // 3. The directory from which the application was started. + // + completePath = GetProcessDirectory( proc.core().pid() ) + L"\\" + filename; + + if (Utils::FileExists( completePath )) + { + path = completePath; + return STATUS_SUCCESS; + } + + // + // 4. The system directory + // + if (flags & Wow64) + GetSystemWow64DirectoryW( tmpPath, ARRAYSIZE( tmpPath ) ); + else + GetSystemDirectoryW( tmpPath, ARRAYSIZE( tmpPath ) ); + + completePath = std::wstring( tmpPath ) + L"\\" + filename; + + if (Utils::FileExists( completePath )) + { + path = completePath; + return STATUS_SUCCESS; + } + + // + // 5. The Windows directory + // + GetWindowsDirectoryW( tmpPath, ARRAYSIZE( tmpPath ) ); + + completePath = std::wstring( tmpPath ) + L"\\" + filename; + + if (Utils::FileExists( completePath )) + { + path = completePath; + return STATUS_SUCCESS; + } + + // + // 6. The current directory + // + GetCurrentDirectoryW( ARRAYSIZE( tmpPath ), tmpPath ); + + completePath = std::wstring( tmpPath ) + L"\\" + filename; + + if (Utils::FileExists( completePath )) + { + path = completePath; + return STATUS_SUCCESS; + } + + // + // 7. Directories listed in PATH environment variable + // + GetEnvironmentVariableW( L"PATH", tmpPath, ARRAYSIZE( tmpPath ) ); + wchar_t *pContext; + + for (wchar_t *pDir = wcstok_s( tmpPath, L";", &pContext ); pDir; pDir = wcstok_s( pContext, L";", &pContext )) + { + completePath = std::wstring( pDir ) + L"\\" + filename; + + if (Utils::FileExists( completePath )) + { + path = completePath; + return STATUS_SUCCESS; + } + } + + return STATUS_NOT_FOUND; +} + + +/// +/// Try SxS redirection +/// +/// Image path. +/// Process. Used to search process executable directory +/// Activation context +/// +NTSTATUS NameResolve::ProbeSxSRedirect( std::wstring& path, Process& proc, HANDLE actx /*= INVALID_HANDLE_VALUE*/ ) +{ + UNICODE_STRING OriginalName = { 0 }; + UNICODE_STRING DllName1 = { 0 }; + UNICODE_STRING DllName2 = { 0 }; + PUNICODE_STRING pPath = nullptr; + ULONG_PTR cookie = 0; + wchar_t wBuf[255]; + + // No underlying function + if (GET_IMPORT( RtlDosApplyFileIsolationRedirection_Ustr ) == nullptr) + return STATUS_ORDINAL_NOT_FOUND; + + SAFE_CALL( RtlInitUnicodeString, &OriginalName, path.c_str() ); + + DllName1.Buffer = wBuf; + DllName1.Length = NULL; + DllName1.MaximumLength = sizeof( wBuf ); + + // Use activation context + if (actx != INVALID_HANDLE_VALUE) + ActivateActCtx( actx, &cookie ); + + // SxS resolve + NTSTATUS status = SAFE_NATIVE_CALL( + RtlDosApplyFileIsolationRedirection_Ustr, TRUE, &OriginalName, (PUNICODE_STRING)NULL, + &DllName1, &DllName2, &pPath, + nullptr, nullptr, nullptr + ); + + if (cookie != 0 && actx != INVALID_HANDLE_VALUE) + DeactivateActCtx( 0, cookie ); + + if (status == STATUS_SUCCESS) + { + // Arch mismatch, local SxS redirection is incorrect + if (proc.barrier().mismatch) + return STATUS_SXS_IDENTITIES_DIFFERENT; + else + path = pPath->Buffer; + } + else + { + if (DllName2.Buffer) + SAFE_CALL( RtlFreeUnicodeString, &DllName2); + } + + return status; +} + +/// +/// Gets the process executable directory +/// +/// Process ID +/// Process executable directory +std::wstring NameResolve::GetProcessDirectory( DWORD pid ) +{ + SnapHandle snapshot; + MODULEENTRY32W mod = { sizeof(MODULEENTRY32W), 0 }; + std::wstring path = L""; + + if ((snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, pid )) && + Module32FirstW( snapshot, &mod ) != FALSE + ) + { + path = mod.szExePath; + path = path.substr( 0, path.rfind( L"\\" ) ); + } + + return path; +} + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Misc/NameResolve.h b/third/Blackbone/src/BlackBone/Misc/NameResolve.h new file mode 100644 index 0000000000000000000000000000000000000000..8c1f0580c77de0975fa3f13d616318e904e27f58 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Misc/NameResolve.h @@ -0,0 +1,91 @@ +#pragma once + +#include "../Include/Winheaders.h" +#include "../Include/Types.h" + +#include +#include +#include + +namespace blackbone +{ + +class NameResolve +{ + using mapApiSchema = std::unordered_map>; + +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(); + + /// + /// Initialize api set map + /// + /// + BLACKBONE_API bool Initialize(); + + /// + /// Resolve image path. + /// + /// Image to resolve + /// Name of parent image. Used only when resolving import images + /// Directory where source image is located + /// Resolve flags + /// Process. Used to search process executable directory + /// Activation context + /// Status + 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 + ); + + /// + /// Try SxS redirection + /// + /// Image path. + /// Process. Used to search process executable directory + /// Activation context + /// + 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; + + /// + /// Gets the process executable directory + /// + /// Process ID + /// Process executable directory + std::wstring GetProcessDirectory( DWORD pid ); + + /// + /// OS dependent api set initialization + /// + /// true on success + template + bool InitializeP(); + +private: + mapApiSchema _apiSchema; // Api schema table +}; + + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Misc/Thunk.hpp b/third/Blackbone/src/BlackBone/Misc/Thunk.hpp new file mode 100644 index 0000000000000000000000000000000000000000..cb212011169ee18dd911dda2b6698a214ab0827c --- /dev/null +++ b/third/Blackbone/src/BlackBone/Misc/Thunk.hpp @@ -0,0 +1,97 @@ +#include "../Config.h" +#include +#include + +// 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 +class Win32Thunk; + +template +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 ); + } + + /// + /// Redirect call + /// + /// Arguments + /// Call result + static R __stdcall WrapHandler( Args... args ) + { + auto _this = reinterpret_cast(((PNT_TIB)NtCurrentTeb())->ArbitraryUserPointer); + return (_this->_pInstance->*_this->_pMethod)(args...); + } + + /// + /// Get thunk + /// + /// + TypeFree GetThunk() + { + return reinterpret_cast(&_thunk); + } + +private: + TypeMember _pMethod = nullptr; // Member function to call + C* _pInstance = nullptr; // Bound instance + ThunkData _thunk; // Thunk code +}; \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Misc/Trace.hpp b/third/Blackbone/src/BlackBone/Misc/Trace.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7b6c6fc642b63e7b0002540fcca7a212564b50e1 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Misc/Trace.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include +#include + +#pragma warning(push) +#pragma warning(disable : 4091) +#include +#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 +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 + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Misc/Utils.cpp b/third/Blackbone/src/BlackBone/Misc/Utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d547ba929810df8293ef2f31ff7f71baa1baa5a --- /dev/null +++ b/third/Blackbone/src/BlackBone/Misc/Utils.cpp @@ -0,0 +1,206 @@ +#include "../Config.h" +#include "Utils.h" +#include "DynImport.h" + +#include +#include + +namespace blackbone +{ + +/// +/// Convert UTF-8 string to wide char one +/// +/// UTF-8 string +/// wide char string +std::wstring Utils::UTF8ToWstring( const std::string& str ) +{ + return AnsiToWstring( str, CP_UTF8 ); +} + +/// +/// Convert wide string to UTF-8 +/// +/// Wide char string +/// UTF-8 string +std::string Utils::WstringToUTF8( const std::wstring& str ) +{ + return WstringToAnsi( str, CP_UTF8 ); +} + +/// +/// Convert ANSI string to wide char one +/// +/// ANSI string. +/// String locale +/// wide char string +std::wstring Utils::AnsiToWstring( const std::string& input, DWORD locale /*= CP_ACP*/ ) +{ + wchar_t buf[2048] = { 0 }; + MultiByteToWideChar( locale, 0, input.c_str(), (int)input.length(), buf, ARRAYSIZE( buf ) ); + return buf; +} + +/// +/// Convert wide char string to ANSI one +/// +/// wide char string. +/// String locale +/// ANSI string +std::string Utils::WstringToAnsi( const std::wstring& input, DWORD locale /*= CP_ACP*/ ) +{ + char buf[2048] = { 0 }; + WideCharToMultiByte( locale, 0, input.c_str(), (int)input.length(), buf, ARRAYSIZE( buf ), nullptr, nullptr ); + return buf; +} + +/// +/// Format string +/// +/// Format specifier +/// Arguments +/// Formatted string +std::wstring Utils::FormatString( const wchar_t* fmt, ... ) +{ + wchar_t buf[4096] = { 0 }; + + va_list vl; + va_start( vl, fmt ); + vswprintf_s( buf, fmt, vl ); + va_end( vl ); + + return buf; +} + + +/// +/// Get filename from full-qualified path +/// +/// File path +/// Filename +std::wstring Utils::StripPath( const std::wstring& path ) +{ + if (path.empty()) + return path; + + auto idx = path.rfind( L'\\' ); + if(idx == path.npos) + idx = path.rfind( L'/' ); + + if (idx != path.npos) + return path.substr( idx + 1 ); + else + return path; +} + +/// +/// Get parent directory +/// +/// File path +/// Parent directory +std::wstring Utils::GetParent( const std::wstring& path ) +{ + if (path.empty()) + return path; + + auto idx = path.rfind( L'\\' ); + if (idx == path.npos) + idx = path.rfind( L'/' ); + + if (idx != path.npos) + return path.substr( 0, idx ); + else + return path; +} + +/// +/// Get current process exe file directory +/// +/// Exe directory +std::wstring Utils::GetExeDirectory() +{ + wchar_t imgName[MAX_PATH] = { 0 }; + DWORD len = ARRAYSIZE(imgName); + + auto pFunc = GET_IMPORT( QueryFullProcessImageNameW ); + if (pFunc != nullptr) + pFunc( GetCurrentProcess(), 0, imgName, &len ); + else + GetModuleFileNameW( NULL, imgName, len ); + + return GetParent( imgName ); +} + +/// +/// Generate random alpha-numeric string +/// +/// Desired length. 0 - random length from 5 to 15 +/// Generated string +std::wstring Utils::RandomANString( int length /*= 0*/ ) +{ + static constexpr wchar_t alphabet[] = L"ABCDEFGHIJKLMNOPQRSTUVWXYZbcdefghijklmnopqrstuvwxyz1234567890"; + static std::random_device rd; + static std::uniform_int_distribution<> dist( 0, _countof( alphabet ) - 2 ); + static std::uniform_int_distribution<> dist_len( 5, 15 ); + std::wstring result; + + // Get random string length + if (length == 0) + length = dist_len( rd ); + + for (int i = 0; i < length; i++) + result.push_back( alphabet[dist( rd )] ); + + return result; +} + +/// +/// Cast string characters to lower case +/// +/// Source string. +/// Result string +std::wstring Utils::ToLower( std::wstring str ) +{ + std::transform( str.begin(), str.end(), str.begin(), ::towlower ); + return str; +} + +/// +/// Get system error description +/// +/// The code. +/// Error message +std::wstring Utils::GetErrorDescription( NTSTATUS code ) +{ + LPWSTR lpMsgBuf = nullptr; + + if (FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_FROM_HMODULE | + FORMAT_MESSAGE_IGNORE_INSERTS, + GetModuleHandleW( L"ntdll.dll" ), + code, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), + (LPWSTR)&lpMsgBuf, 0, NULL ) != 0) + { + std::wstring ret( lpMsgBuf ); + + LocalFree( lpMsgBuf ); + return ret; + } + + return L""; +} + +/// +/// Check if file exists +/// +/// Full-qualified file path +/// true if exists +bool Utils::FileExists( const std::wstring& path ) +{ + return (GetFileAttributesW( path.c_str() ) != 0xFFFFFFFF ); +} + + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Misc/Utils.h b/third/Blackbone/src/BlackBone/Misc/Utils.h new file mode 100644 index 0000000000000000000000000000000000000000..aa1c6ed88db998f37a67cd49a598bb50374a79e2 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Misc/Utils.h @@ -0,0 +1,208 @@ +#pragma once + +#include "../Include/Winheaders.h" +#include +#include +#include + +namespace blackbone +{ + +class Utils +{ +public: + /// + /// Convert UTF-8 string to wide char one + /// + /// UTF-8 string + /// wide char string + BLACKBONE_API static std::wstring UTF8ToWstring( const std::string& str ); + + /// + /// Convert wide string to UTF-8 + /// + /// UTF-8 string + /// wide char string + BLACKBONE_API static std::string WstringToUTF8( const std::wstring& str ); + + /// + /// Convert ANSI string to wide char one + /// + /// ANSI string. + /// String locale + /// wide char string + BLACKBONE_API static std::wstring AnsiToWstring( const std::string& input, DWORD locale = CP_ACP ); + + /// + /// Convert wide char string to ANSI one + /// + /// wide char string. + /// String locale + /// ANSI string + BLACKBONE_API static std::string WstringToAnsi( const std::wstring& input, DWORD locale = CP_ACP ); + + /// + /// Format string + /// + /// Format specifier + /// Arguments + /// Formatted string + BLACKBONE_API static std::wstring FormatString( const wchar_t* fmt, ... ); + + /// + /// Get filename from full-qualified path + /// + /// File path + /// Filename + BLACKBONE_API static std::wstring StripPath( const std::wstring& path ); + + /// + /// Get parent directory + /// + /// File path + /// Parent directory + BLACKBONE_API static std::wstring GetParent( const std::wstring& path ); + + /// + /// Get current process exe file directory + /// + /// Exe directory + BLACKBONE_API static std::wstring GetExeDirectory(); + + /// + /// Cast string characters to lower case + /// + /// Source string. + /// Result string + BLACKBONE_API static std::wstring ToLower( std::wstring str ); + + /// + /// Generate random alpha-numeric string + /// + /// Desired length. 0 - random length from 5 to 15 + /// Generated string + BLACKBONE_API static std::wstring RandomANString( int length = 0 ); + + /// + /// Get system error description + /// + /// The code. + /// Error message + BLACKBONE_API static std::wstring GetErrorDescription( NTSTATUS code ); + + /// + /// Check if file exists + /// + /// Full-qualified file path + /// true if exists + BLACKBONE_API static bool FileExists( const std::wstring& path ); +}; + + +/// +/// std::mutex alternative +/// +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; +}; + + +/// +/// std::lock_guard alternative +/// +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; +}; + + +/// +/// System32 helper +/// +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 + void visit_each( T&& t, F f, std::index_sequence ) { auto l = { (f( std::get( t ) ), 0)... }; } + + template + void copyTuple( std::tuple const& from, std::vector& 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() ); + } +} +#endif +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/PE/ImageNET.cpp b/third/Blackbone/src/BlackBone/PE/ImageNET.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f56719e7934a289460b1db9cfdb3a34974acf0ba --- /dev/null +++ b/third/Blackbone/src/BlackBone/PE/ImageNET.cpp @@ -0,0 +1,223 @@ +#include "../Config.h" +#include "ImageNET.h" + +#ifdef COMPILER_MSVC + +#include "mscoree.h" +#include "metahost.h" + +#include + +namespace blackbone +{ + +ImageNET::ImageNET( void ) +{ +} + +ImageNET::~ImageNET(void) +{ + if (!_path.empty()) + CoUninitialize(); +} + +/// +/// Initialize COM classes +/// +/// Image file path +/// true on success +bool ImageNET::Init( const std::wstring& path ) +{ + HRESULT hr; + VARIANT value; + + _path = path; + + if(!_pMetaDisp) + { + if (FAILED( CoInitialize( 0 ) )) + return false; + + hr = CoCreateInstance( + CLSID_CorMetaDataDispenser, NULL, CLSCTX_INPROC_SERVER, + IID_IMetaDataDispenserEx, reinterpret_cast(&_pMetaDisp) + ); + + if (FAILED( hr )) + return false; + } + + // + // Query required interfaces + // + if(!_pMetaImport) + { + hr = _pMetaDisp->OpenScope( _path.c_str(), 0, IID_IMetaDataImport, reinterpret_cast(&_pMetaImport) ); + if (hr == CLDB_E_BADUPDATEMODE) + { + V_VT( &value ) = VT_UI4; + V_UI4( &value ) = MDUpdateIncremental; + + if (FAILED( hr = _pMetaDisp->SetOption( MetaDataSetUpdate, &value ) )) + return false; + + hr = _pMetaDisp->OpenScope( _path.c_str(), 0, IID_IMetaDataImport, reinterpret_cast(&_pMetaImport) ); + } + + if (FAILED( hr )) + return false; + } + + if(!_pAssemblyImport) + { + hr = _pMetaImport->QueryInterface( IID_IMetaDataAssemblyImport, reinterpret_cast(&_pAssemblyImport) ); + if (FAILED( hr )) + return false; + } + + return true; +} + +/// +/// Extract methods from image +/// +/// Found Methods +/// true on success +bool ImageNET::Parse( mapMethodRVA* methods /*= nullptr*/ ) +{ + DWORD dwcTypeDefs, dwTypeDefFlags, dwcTokens, dwSigBlobSize; + + HCORENUM hceTypeDefs = 0; + mdToken tExtends = 0; + HCORENUM hceMethods = 0; + mdTypeRef rTypeDefs[10] = { 0 }; + WCHAR wcName[1024] = { 0 }; + mdToken rTokens[10] = { 0 }; + + while (SUCCEEDED( _pMetaImport->EnumTypeDefs( &hceTypeDefs, rTypeDefs, ARRAYSIZE( rTypeDefs ), &dwcTypeDefs ) ) + && dwcTypeDefs > 0) + { + for (UINT i = 0; i < dwcTypeDefs; i++) + { + HRESULT hr = _pMetaImport->GetTypeDefProps( rTypeDefs[i], wcName, ARRAYSIZE( wcName ), NULL, &dwTypeDefFlags, &tExtends ); + if (FAILED( hr )) + continue; + + while (SUCCEEDED( _pMetaImport->EnumMethods( &hceMethods, rTypeDefs[i], rTokens, ARRAYSIZE( rTokens ), &dwcTokens ) ) + && dwcTokens > 0) + { + DWORD dwCodeRVA, dwAttr; + WCHAR wmName[1024] = { 0 }; + PCCOR_SIGNATURE pbySigBlob = nullptr; + + for (UINT j = 0; j < dwcTokens; j++) + { + // get method information + hr = _pMetaImport->GetMemberProps( + rTokens[j], NULL, wmName, + ARRAYSIZE( wmName ), NULL, + &dwAttr, &pbySigBlob, &dwSigBlobSize, + &dwCodeRVA, NULL, NULL, NULL, NULL + ); + + if (FAILED( hr )) + continue; + + _methods.emplace( std::make_pair( wcName, wmName ), dwCodeRVA ); + } + } + } + } + + if(methods) + *methods = _methods; + + return true; +} + +using fnGetRequestedRuntimeVersion = decltype(&GetRequestedRuntimeVersion); +using fnCLRCreateInstancen = decltype(&CLRCreateInstance); + +/// +/// Get image .NET runtime version +/// +/// runtime version, "n/a" if nothing found +std::wstring ImageNET::GetImageRuntimeVer( const wchar_t* ImagePath ) +{ + std::wstring LatestVersion = L"n/a"; + + CComPtr MetaHost; + + // Check if .NET 4 or higher is present + auto clrCreate = reinterpret_cast( + GetProcAddress( LoadLibraryW( L"mscoree.dll" ), "CLRCreateInstance" )); + + // Legacy runtime. Get exact required version + if(!clrCreate) + { + wchar_t ver[64] = { 0 }; + DWORD bytes = 0; + + auto clrGetVer = reinterpret_cast( + GetProcAddress( GetModuleHandleW( L"mscoree.dll" ), "GetRequestedRuntimeVersion" )); + + clrGetVer( const_cast(ImagePath), ver, 64, &bytes ); + + FreeLibrary( GetModuleHandleW( L"mscoree.dll" ) ); + return ver; + } + // Get highest available + else + { + if (FAILED( clrCreate( CLSID_CLRMetaHost, IID_ICLRMetaHost, reinterpret_cast(&MetaHost) ) )) + return LatestVersion; + + CComPtr Runtimes; + if (FAILED( MetaHost->EnumerateInstalledRuntimes( &Runtimes ) )) + return LatestVersion; + + CComPtr Runtime; + CComPtr Latest; + + while (Runtimes->Next( 1, &Runtime, NULL ) == S_OK) + { + CComPtr Current; + wchar_t tmpString[MAX_PATH]; + DWORD tmp = MAX_PATH * sizeof(wchar_t); + + if (SUCCEEDED( Runtime->QueryInterface( IID_PPV_ARGS( &Current ) ) )) + { + if (!Latest) + { + if (SUCCEEDED( Current->QueryInterface( IID_PPV_ARGS( &Latest ) ) )) + { + Latest->GetVersionString( tmpString, &tmp ); + LatestVersion = tmpString; + } + } + else + { + if (SUCCEEDED( Current->GetVersionString( tmpString, &tmp ) )) + { + std::wstring CurrentVersion = tmpString; + if (CurrentVersion.compare( LatestVersion ) > 0) + { + LatestVersion = CurrentVersion; + Latest.Release(); + Current->QueryInterface( IID_PPV_ARGS( &Latest ) ); + } + } + } + } + + Runtime.Release(); + } + + return LatestVersion; + } + +} + +} + +#endif \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/PE/ImageNET.h b/third/Blackbone/src/BlackBone/PE/ImageNET.h new file mode 100644 index 0000000000000000000000000000000000000000..636d66e44e14be665ab42cd4659438e5d1e94f8d --- /dev/null +++ b/third/Blackbone/src/BlackBone/PE/ImageNET.h @@ -0,0 +1,66 @@ +#pragma once +#include "../Config.h" +#ifdef COMPILER_MSVC + +#include "../Include/Winheaders.h" + +#include + +#if _MSC_VER >= 1920 + #include +#endif + +#pragma warning(push) +#pragma warning(disable : 4091) +#include "cor.h" +#include +#pragma warning(pop) + +namespace blackbone +{ + +/// +/// .NET metadata parser +/// +class ImageNET +{ +public: + using mapMethodRVA = std::map, uintptr_t>; + +public: + BLACKBONE_API ImageNET(void); + BLACKBONE_API ~ImageNET(void); + + /// + /// Initialize COM classes + /// + /// Image file path + /// true on success + BLACKBONE_API bool Init( const std::wstring& path ); + + /// + /// Extract methods from image + /// + /// Found Methods + /// true on success + BLACKBONE_API bool Parse( mapMethodRVA* methods = nullptr ); + + /// + /// Get image .NET runtime version + /// + /// runtime version, "n/a" if nothing found + BLACKBONE_API static std::wstring GetImageRuntimeVer( const wchar_t* ImagePath ); + +private: + std::wstring _path; // Image path + mapMethodRVA _methods; // Image methods + + // COM helpers + CComPtr _pMetaDisp; + CComPtr _pMetaImport; + CComPtr _pAssemblyImport; +}; + +} + +#endif diff --git a/third/Blackbone/src/BlackBone/PE/PEImage.cpp b/third/Blackbone/src/BlackBone/PE/PEImage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4adeed850c6a8582ddd9d1943b52dcf854bdc6ae --- /dev/null +++ b/third/Blackbone/src/BlackBone/PE/PEImage.cpp @@ -0,0 +1,626 @@ +#include "../PE/PEImage.h" +#include "../Include/Macro.h" +#include "../Misc/Utils.h" +#include "../Misc/DynImport.h" + +#include + +#define TLS32(ptr) ((const IMAGE_TLS_DIRECTORY32*)ptr) // TLS directory +#define TLS64(ptr) ((const IMAGE_TLS_DIRECTORY64*)ptr) // TLS directory +#define THK32(ptr) ((const IMAGE_THUNK_DATA32*)ptr) // Import thunk data +#define THK64(ptr) ((const IMAGE_THUNK_DATA64*)ptr) // Import thunk data + +namespace blackbone +{ + +namespace pe +{ + +PEImage::PEImage( void ) +{ +} + +PEImage::~PEImage( void ) +{ + Release(); +} + +/// +/// Load image from file +/// +/// File path +/// If true - do not initialize activation context +/// Status code +NTSTATUS PEImage::Load( const std::wstring& path, bool skipActx /*= false*/ ) +{ + Release( true ); + _imagePath = path; + _noFile = false; + + _hFile = CreateFileW( + path.c_str(), FILE_GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, 0, NULL + ); + + if (_hFile) + { + // Try mapping as image + _hMapping = CreateFileMappingW( _hFile, NULL, SEC_IMAGE | PAGE_READONLY, 0, 0, NULL ); + if (_hMapping) + { + _isPlainData = false; + _pFileBase = MapViewOfFile( _hMapping, FILE_MAP_READ, 0, 0, 0 ); + } + // Map as simple datafile + else + { + _isPlainData = true; + _hMapping = CreateFileMappingW( _hFile, NULL, PAGE_READONLY, 0, 0, NULL ); + + if (_hMapping) + _pFileBase = MapViewOfFile( _hMapping, FILE_MAP_READ, 0, 0, 0 ); + } + + // Mapping failed + if (!_pFileBase) + return LastNtStatus(); + } + else + return LastNtStatus(); + + auto status = Parse(); + if (!NT_SUCCESS( status )) + return status; + + return skipActx ? status : PrepareACTX( _imagePath.c_str() ); +} + +/// +/// Load image from memory location +/// +/// Image data +/// Data size. +/// If false - data has image layout +/// Status code +NTSTATUS PEImage::Load( void* pData, size_t size, bool plainData /*= true */ ) +{ + Release( true ); + + _noFile = true; + _pFileBase = pData; + _isPlainData = plainData; + + auto status = Parse(); + if (!NT_SUCCESS( status )) + return status; + + return PrepareACTX(); +} + +/// +/// Reload closed image +/// +/// Status code +NTSTATUS PEImage::Reload() +{ + return Load( _imagePath ); +} + +/// +/// Release mapping, if any +/// +/// Preserve file paths for file reopening +void PEImage::Release( bool temporary /*= false*/ ) +{ + if (_pFileBase) + { + UnmapViewOfFile( _pFileBase ); + _pFileBase = nullptr; + } + + _hMapping.reset(); + _hFile.reset(); + _hctx.reset(); + + // Reset pointers to data + _pImageHdr32 = nullptr; + _pImageHdr64 = nullptr; + + if(!temporary) + { + _imagePath.clear(); + + // Ensure temporary file is deleted + if (_noFile) + DeleteFileW( _manifestPath.c_str() ); + + _manifestPath.clear(); + } +} + +/// +/// Parses PE image +/// +/// Status code +NTSTATUS PEImage::Parse( void* pImageBase /*= nullptr*/ ) +{ + const IMAGE_DOS_HEADER *pDosHdr = nullptr; + const IMAGE_SECTION_HEADER *pSection = nullptr; + + if (pImageBase != nullptr) + _pFileBase = pImageBase; + + // Something went wrong + if (!_pFileBase) + return STATUS_INVALID_ADDRESS; + + // Get DOS header + pDosHdr = reinterpret_cast(_pFileBase); + + // File not a valid PE file + if (pDosHdr->e_magic != IMAGE_DOS_SIGNATURE) + return STATUS_INVALID_IMAGE_FORMAT; + + // Get image header + _pImageHdr32 = reinterpret_cast(reinterpret_cast(pDosHdr) + pDosHdr->e_lfanew); + _pImageHdr64 = reinterpret_cast(_pImageHdr32); + + // File not a valid PE file + if (_pImageHdr32->Signature != IMAGE_NT_SIGNATURE) + return STATUS_INVALID_IMAGE_FORMAT; + + auto GetHeaderData = [this, &pSection]( auto pImageHeader ) + { + _imgBase = pImageHeader->OptionalHeader.ImageBase; + _imgSize = pImageHeader->OptionalHeader.SizeOfImage; + _hdrSize = pImageHeader->OptionalHeader.SizeOfHeaders; + _epRVA = pImageHeader->OptionalHeader.AddressOfEntryPoint; + _subsystem = pImageHeader->OptionalHeader.Subsystem; + _DllCharacteristics = pImageHeader->OptionalHeader.DllCharacteristics; + + pSection = reinterpret_cast(pImageHeader + 1); + }; + + // Detect x64 image + if (_pImageHdr32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) + { + _is64 = true; + GetHeaderData( _pImageHdr64 ); + } + else + { + _is64 = false; + GetHeaderData( _pImageHdr32 ); + } + + // Exe file + _isExe = !(_pImageHdr32->FileHeader.Characteristics & IMAGE_FILE_DLL); + + // Pure IL image + auto pCorHdr = reinterpret_cast(DirectoryAddress( IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR )); + + _isPureIL = (pCorHdr && (pCorHdr->Flags & COMIMAGE_FLAGS_ILONLY)) ? true : false; + + if (_isPureIL) + { + _ILFlagOffset = static_cast( + reinterpret_cast(pCorHdr) + - reinterpret_cast(_pFileBase) + + static_cast(offsetof( IMAGE_COR20_HEADER, Flags ))); + +#ifdef COMPILER_MSVC + if (_netImage.Init( _imagePath )) + _netImage.Parse(); +#endif + } + + // Sections + for (int i = 0; i < _pImageHdr32->FileHeader.NumberOfSections; ++i, ++pSection) + _sections.emplace_back( *pSection ); + + return STATUS_SUCCESS; +} + +/// +/// Processes image imports +/// +/// Process delayed import instead +/// Import data +mapImports& PEImage::GetImports( bool useDelayed /*= false*/ ) +{ + if(useDelayed) + { + auto pImportTbl = reinterpret_cast(DirectoryAddress( IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT )); + if (!pImportTbl) + return _delayImports; + + // Delayed Imports + for (; pImportTbl->DllNameRVA; ++pImportTbl) + { + uint8_t* pRVA = nullptr; + DWORD IAT_Index = 0; + char *pDllName = reinterpret_cast(ResolveRVAToVA( pImportTbl->DllNameRVA )); + auto dllStr = Utils::AnsiToWstring( pDllName ); + + pRVA = reinterpret_cast(ResolveRVAToVA( pImportTbl->ImportNameTableRVA )); + + while (_is64 ? THK64( pRVA )->u1.AddressOfData : THK32( pRVA )->u1.AddressOfData) + { + uint64_t AddressOfData = _is64 ? THK64( pRVA )->u1.AddressOfData : THK32( pRVA )->u1.AddressOfData; + auto pAddressTable = reinterpret_cast(ResolveRVAToVA( static_cast(AddressOfData) )); + ImportData data; + + // import by name + if (AddressOfData < (_is64 ? IMAGE_ORDINAL_FLAG64 : IMAGE_ORDINAL_FLAG32) && pAddressTable->Name[0]) + { + data.importByOrd = false; + data.importName = reinterpret_cast(pAddressTable->Name); + data.importOrdinal = 0; + } + // import by ordinal + else + { + data.importByOrd = true; + data.importOrdinal = static_cast(AddressOfData & 0xFFFF); + } + + data.ptrRVA = pImportTbl->ImportAddressTableRVA + IAT_Index; + + _delayImports[dllStr].emplace_back( data ); + + // Go to next entry + pRVA += _is64 ? sizeof(IMAGE_THUNK_DATA64) : sizeof(IMAGE_THUNK_DATA32); + IAT_Index += _is64 ? sizeof(uint64_t) : sizeof(uint32_t); + } + } + + return _delayImports; + } + else + { + auto *pImportTbl = reinterpret_cast(DirectoryAddress( IMAGE_DIRECTORY_ENTRY_IMPORT )); + if (!pImportTbl) + return _imports; + + // Imports + for (; pImportTbl->Name; ++pImportTbl) + { + uint8_t* pRVA = nullptr; + DWORD IAT_Index = 0; + char *pDllName = reinterpret_cast(ResolveRVAToVA( pImportTbl->Name )); + auto dllStr = Utils::AnsiToWstring( pDllName ); + + pRVA = reinterpret_cast(ResolveRVAToVA( + pImportTbl->OriginalFirstThunk ? + pImportTbl->OriginalFirstThunk : + pImportTbl->FirstThunk )); + + while (_is64 ? THK64( pRVA )->u1.AddressOfData : THK32( pRVA )->u1.AddressOfData) + { + uint64_t AddressOfData = _is64 ? THK64( pRVA )->u1.AddressOfData : THK32( pRVA )->u1.AddressOfData; + + auto* pAddressTable = reinterpret_cast(ResolveRVAToVA( static_cast(AddressOfData) )); + ImportData data; + + // import by name + if (AddressOfData < (_is64 ? IMAGE_ORDINAL_FLAG64 : IMAGE_ORDINAL_FLAG32) && pAddressTable->Name[0]) + { + data.importByOrd = false; + data.importName = reinterpret_cast(pAddressTable->Name); + data.importOrdinal = 0; + } + // import by ordinal + else + { + data.importByOrd = true; + data.importOrdinal = static_cast(AddressOfData & 0xFFFF); + } + + // Save address to IAT + if (pImportTbl->FirstThunk) + data.ptrRVA = pImportTbl->FirstThunk + IAT_Index; + // Save address to OrigianlFirstThunk + else + data.ptrRVA = static_cast(AddressOfData) - reinterpret_cast(_pFileBase); + + _imports[dllStr].emplace_back( data ); + + // Go to next entry + pRVA += _is64 ? sizeof(IMAGE_THUNK_DATA64) : sizeof(IMAGE_THUNK_DATA32); + IAT_Index += _is64 ? sizeof(uint64_t) : sizeof(uint32_t); + } + } + + return _imports; + + } +} + +/// +/// Retrieve all exported functions with names +/// +/// Found exports +void PEImage::GetExports( vecExports& exports ) +{ + exports.clear(); + Reload(); + + auto pExport = reinterpret_cast(DirectoryAddress( IMAGE_DIRECTORY_ENTRY_EXPORT )); + if (pExport == 0) + return; + + DWORD *pAddressOfNames = reinterpret_cast(pExport->AddressOfNames + reinterpret_cast(_pFileBase)); + DWORD *pAddressOfFuncs = reinterpret_cast(pExport->AddressOfFunctions + reinterpret_cast(_pFileBase)); + WORD *pAddressOfOrds = reinterpret_cast (pExport->AddressOfNameOrdinals + reinterpret_cast(_pFileBase)); + + for (DWORD i = 0; i < pExport->NumberOfNames; ++i) + exports.push_back( ExportData( reinterpret_cast(_pFileBase)+pAddressOfNames[i], pAddressOfFuncs[pAddressOfOrds[i]] ) ); + + std::sort( exports.begin(), exports.end() ); + return Release( true ); +} + +/// +/// Retrieve data directory address +/// +/// Directory index +/// Keep address relative to image base +/// Directory address +uintptr_t PEImage::DirectoryAddress( int index, AddressType type /*= VA*/ ) const +{ + // Sanity check + if (index < 0 || index >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES) + return 0; + + const auto idd = _is64 ? _pImageHdr64->OptionalHeader.DataDirectory : _pImageHdr32->OptionalHeader.DataDirectory; + return idd[index].VirtualAddress == 0 ? 0 : ResolveRVAToVA( idd[index].VirtualAddress, type ); +} + +/// +/// Get data directory size +/// +/// Data directory index +/// Data directory size +size_t PEImage::DirectorySize( int index ) const +{ + // Sanity check + if (index < 0 || index >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES) + return 0; + + const IMAGE_DATA_DIRECTORY* idd = _is64 ? _pImageHdr64->OptionalHeader.DataDirectory : _pImageHdr32->OptionalHeader.DataDirectory; + return idd[index].VirtualAddress != 0 ? static_cast(idd[index].Size) : 0; +} + + +/// +/// Resolve virtual memory address to physical file offset +/// +/// Memory address +/// Keep address relative to file start +/// Resolved address +uintptr_t PEImage::ResolveRVAToVA( uintptr_t Rva, AddressType type /*= VA*/ ) const +{ + switch (type) + { + case blackbone::pe::RVA: + return Rva; + + case blackbone::pe::VA: + case blackbone::pe::RPA: + if (_isPlainData) + { + for (auto& sec : _sections) + { + if (Rva >= sec.VirtualAddress && Rva < sec.VirtualAddress + sec.Misc.VirtualSize) + if (type == VA) + return reinterpret_cast(_pFileBase) + Rva - sec.VirtualAddress + sec.PointerToRawData; + else + return Rva - sec.VirtualAddress + sec.PointerToRawData; + } + + return 0; + } + else + return (type == VA) ? (reinterpret_cast(_pFileBase) + Rva) : Rva; + + default: + return 0; + } + +} + +/// +/// Retrieve image TLS callbacks +/// Callbacks are rebased for target image +/// +/// Target image base +/// Found callbacks +/// Number of TLS callbacks in image +int PEImage::GetTLSCallbacks( module_t targetBase, std::vector& result ) const +{ + uint8_t *pTls = reinterpret_cast(DirectoryAddress( IMAGE_DIRECTORY_ENTRY_TLS )); + uint64_t* pCallback = 0; + if (!pTls) + return 0; + + uint64_t offset = _is64 ? TLS64( pTls )->AddressOfCallBacks : TLS32( pTls )->AddressOfCallBacks; + if (offset == 0) + return 0; + + // Not at base + if (imageBase() != reinterpret_cast(_pFileBase)) + pCallback = reinterpret_cast(ResolveRVAToVA( static_cast(offset - imageBase()) )); + else + pCallback = reinterpret_cast(offset); + + if(_is64) + { + for (; *pCallback; pCallback++) + result.push_back( REBASE( *pCallback, imageBase(), targetBase ) ); + } + else + { + for (uint32_t *pCallback2 = reinterpret_cast(pCallback); *pCallback2; pCallback2++) + result.push_back( REBASE( *pCallback2, imageBase(), targetBase ) ); + } + + return (int)result.size(); +} + +/// +/// Prepare activation context +/// +/// Path to PE file. If nullptr - manifest is extracted from memory to disk +/// Status code +NTSTATUS PEImage::PrepareACTX( const wchar_t* filepath /*= nullptr*/ ) +{ + wchar_t tempPath[256] = { 0 }; + uint32_t manifestSize = 0; + + ACTCTXW act = { 0 }; + act.cbSize = sizeof( act ); + + // No manifest found, skip + auto pManifest = GetManifest( manifestSize, _manifestIdx ); + if (!pManifest) + return STATUS_SUCCESS; + + // + // Dump manifest to TMP folder + // + if (filepath == nullptr) + { + wchar_t tempDir[256] = { 0 }; + + GetTempPathW( ARRAYSIZE( tempDir ), tempDir ); + if (GetTempFileNameW( tempDir, L"ImageManifest", 0, tempPath ) == 0) + return STATUS_SXS_CANT_GEN_ACTCTX; + + auto hTmpFile = FileHandle( CreateFileW( tempPath, FILE_GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL ) ); + if (hTmpFile != INVALID_HANDLE_VALUE) + { + DWORD bytes = 0; + WriteFile( hTmpFile, pManifest, manifestSize, &bytes, NULL ); + hTmpFile.reset(); + + act.lpSource = tempPath; + _manifestPath = tempPath; + } + else + return LastNtStatus(); + } + else + { + act.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID; + act.lpResourceName = MAKEINTRESOURCEW( _manifestIdx ); + act.lpSource = filepath; + + _manifestPath = _imagePath; + } + + // Create ACTX + _hctx = CreateActCtxW( &act ); + + if (_hctx != INVALID_HANDLE_VALUE) + return STATUS_SUCCESS; + + // Return success if current process is protected + if (LastNtStatus() == STATUS_ACCESS_DENIED) + { + _manifestIdx = 0; + return STATUS_SUCCESS; + } + + return LastNtStatus(); +} + +/// +/// Get manifest from image data +/// +/// Manifest size +/// Mmanifest ID +/// Manifest data +void* PEImage::GetManifest( uint32_t& size, int32_t& manifestID ) +{ + // 3 levels of pointers to nodes + const IMAGE_RESOURCE_DIRECTORY_ENTRY *pDirNode1 = nullptr; + const IMAGE_RESOURCE_DIRECTORY_ENTRY *pDirNode2 = nullptr; + const IMAGE_RESOURCE_DIRECTORY_ENTRY *pDirNode3 = nullptr; + + // 3 levels of nodes + const IMAGE_RESOURCE_DIRECTORY *pDirNodePtr1 = nullptr; + const IMAGE_RESOURCE_DIRECTORY *pDirNodePtr2 = nullptr; + const IMAGE_RESOURCE_DIRECTORY *pDirNodePtr3 = nullptr; + + // resource entry data + const IMAGE_RESOURCE_DATA_ENTRY *pDataNode = nullptr; + + size_t ofst_1 = 0; // first level nodes offset + size_t ofst_2 = 0; // second level nodes offset + size_t ofst_3 = 0; // third level nodes offset + + // Get section base + auto secBase = DirectoryAddress( IMAGE_DIRECTORY_ENTRY_RESOURCE ); + if (secBase == 0) + { + size = 0; + manifestID = 0; + return nullptr; + } + + pDirNodePtr1 = reinterpret_cast(secBase); + ofst_1 += sizeof( IMAGE_RESOURCE_DIRECTORY ); + + // first-level nodes + for (int i = 0; i < pDirNodePtr1->NumberOfIdEntries + pDirNodePtr1->NumberOfNamedEntries; ++i) + { + pDirNode1 = reinterpret_cast(secBase + ofst_1); + + // Not a manifest directory + if (!pDirNode1->DataIsDirectory || pDirNode1->Id != 0x18) + { + ofst_1 += sizeof( IMAGE_RESOURCE_DIRECTORY_ENTRY ); + continue; + } + + pDirNodePtr2 = reinterpret_cast(secBase + pDirNode1->OffsetToDirectory); + ofst_2 = pDirNode1->OffsetToDirectory + sizeof( IMAGE_RESOURCE_DIRECTORY ); + + // second-level nodes + for (int j = 0; j < pDirNodePtr2->NumberOfIdEntries + pDirNodePtr2->NumberOfNamedEntries; ++j) + { + pDirNode2 = reinterpret_cast(secBase + ofst_2); + + if (!pDirNode2->DataIsDirectory) + { + ofst_2 += sizeof( IMAGE_RESOURCE_DIRECTORY_ENTRY ); + continue; + } + + // Check if this is a valid manifest resource + if (pDirNode2->Id == 1 || pDirNode2->Id == 2 || pDirNode2->Id == 3) + { + pDirNodePtr3 = reinterpret_cast(secBase + pDirNode2->OffsetToDirectory); + ofst_3 = pDirNode2->OffsetToDirectory + sizeof( IMAGE_RESOURCE_DIRECTORY ); + pDirNode3 = reinterpret_cast(secBase + ofst_3); + pDataNode = reinterpret_cast(secBase + pDirNode3->OffsetToData); + + manifestID = pDirNode2->Id; + size = pDataNode->Size; + + return reinterpret_cast(ResolveRVAToVA( pDataNode->OffsetToData )); + } + + ofst_2 += sizeof( IMAGE_RESOURCE_DIRECTORY_ENTRY ); + } + + ofst_1 += sizeof( IMAGE_RESOURCE_DIRECTORY_ENTRY ); + } + + return nullptr; +} + +} + +} diff --git a/third/Blackbone/src/BlackBone/PE/PEImage.h b/third/Blackbone/src/BlackBone/PE/PEImage.h new file mode 100644 index 0000000000000000000000000000000000000000..9609acb549481da65e775dedac1d2c0fc00f2132 --- /dev/null +++ b/third/Blackbone/src/BlackBone/PE/PEImage.h @@ -0,0 +1,346 @@ +#pragma once + +#include "../Config.h" +#include "../Include/Winheaders.h" +#include "../Include/Types.h" +#include "../Include/HandleGuard.h" +#include "../Misc/Utils.h" + +#ifdef COMPILER_MSVC +#include "ImageNET.h" +#endif // COMPILER_MSVC + +#include +#include +#include +#include +#include +#include +#include + +namespace blackbone +{ + +namespace pe +{ + +enum AddressType +{ + RVA, // Relative virtual + VA, // Absolute virtual + RPA, // Relative physical +}; + +// Relocation block information +struct RelocData +{ + ULONG PageRVA; + ULONG BlockSize; + + struct + { + WORD Offset : 12; + WORD Type : 4; + }Item[1]; +}; + +/// +/// Import information +/// +struct ImportData +{ + std::string importName; // Function name + uintptr_t ptrRVA; // Function pointer RVA in + WORD importOrdinal; // Function ordinal + bool importByOrd; // Function is imported by ordinal +}; + +/// +/// Export function info +/// +struct ExportData +{ + std::string name; + uint32_t RVA = 0; + + ExportData( const std::string& name_, uint32_t rva_ ) + : name( name_ ) + , RVA( rva_ ) { } + + bool operator == (const ExportData& other) + { + return name == other.name; + } + + bool operator < (const ExportData& other) + { + return name < other.name; + } +}; + +// Imports and sections related +using mapImports = std::unordered_map>; +using vecSections = std::vector; +using vecExports = std::vector; + +/// +/// Primitive PE parsing class +/// +class PEImage +{ + using PCHDR32 = const IMAGE_NT_HEADERS32*; + using PCHDR64 = const IMAGE_NT_HEADERS64*; + +public: + BLACKBONE_API PEImage( void ); + BLACKBONE_API ~PEImage( void ); + + /// + /// Load image from file + /// + /// File path + /// If true - do not initialize activation context + /// Status code + BLACKBONE_API NTSTATUS Load( const std::wstring& path, bool skipActx = false ); + + /// + /// Load image from memory location + /// + /// Image data + /// Data size. + /// If false - data has image layout + /// Status code + BLACKBONE_API NTSTATUS Load( void* pData, size_t size, bool plainData = true ); + + /// + /// Reload closed image + /// + /// Status code + BLACKBONE_API NTSTATUS Reload(); + + /// + /// Release mapping, if any + /// + /// Preserve file paths for file reopening + BLACKBONE_API void Release( bool temporary = false ); + + /// + /// Parses PE image + /// + /// Status code + BLACKBONE_API NTSTATUS Parse( void* pImageBase = nullptr ); + + /// + /// Processes image imports + /// + /// Process delayed import instead + /// Import data + BLACKBONE_API mapImports& GetImports( bool useDelayed = false ); + + /// + /// Retrieve all exported functions with names + /// + /// Found exports + BLACKBONE_API void GetExports( vecExports& exports ); + + /// + /// Retrieve image TLS callbacks + /// Callbacks are rebased for target image + /// + /// Target image base + /// Found callbacks + /// Number of TLS callbacks in image + BLACKBONE_API int GetTLSCallbacks( module_t targetBase, std::vector& result ) const; + + /// + /// Retrieve data directory address + /// + /// Directory index + /// Keep address relative to image base + /// Directory address + BLACKBONE_API uintptr_t DirectoryAddress( int index, AddressType type = VA ) const; + + /// + /// Get data directory size + /// + /// Data directory index + /// Data directory size + BLACKBONE_API size_t DirectorySize( int index ) const; + + /// + /// Resolve virtual memory address to physical file offset + /// + /// Memory address + /// Address type to return + /// Resolved address + BLACKBONE_API uintptr_t ResolveRVAToVA( uintptr_t Rva, AddressType type = VA ) const; + + /// + /// Get image path + /// + /// Image path + BLACKBONE_API inline const std::wstring& path() const { return _imagePath; } + + /// + /// Get image name + /// + /// Image name + BLACKBONE_API inline std::wstring name() const { return Utils::StripPath( _imagePath ); } + + /// + /// Get image load address + /// + /// Image base + BLACKBONE_API inline void* base() const { return _pFileBase; } + + /// + /// Get image base address + /// + /// Image base + BLACKBONE_API inline module_t imageBase() const { return _imgBase; } + + /// + /// Get image size in bytes + /// + /// Image size + BLACKBONE_API inline uint32_t imageSize() const { return _imgSize; } + + /// + /// Get size of image headers + /// + /// Size of image headers + BLACKBONE_API inline size_t headersSize() const { return _hdrSize; } + + /// + /// Get image entry point rebased to another image base + /// + /// New image base + /// New entry point address + BLACKBONE_API inline ptr_t entryPoint( module_t base ) const { return ((_epRVA != 0) ? (_epRVA + base) : 0); }; + + /// + /// Get image sections + /// + /// Image sections + BLACKBONE_API inline const vecSections& sections() const { return _sections; } + + /// + /// Check if image is an executable file and not a dll + /// + /// true if image is an *.exe + BLACKBONE_API inline bool isExe() const { return _isExe; } + + /// + /// Check if image is pure IL image + /// + /// true on success + BLACKBONE_API inline bool pureIL() const { return _isPureIL; } + BLACKBONE_API inline int32_t ilFlagOffset() const { return _ILFlagOffset; } + + /// + /// Get image type. 32/64 bit + /// + /// Image type + BLACKBONE_API inline eModType mType() const { return _is64 ? mt_mod64 : mt_mod32; } + + /// + /// Get activation context handle + /// + /// Actx handle + BLACKBONE_API inline HANDLE actx() const { return _hctx; } + + /// + /// true if image is mapped as plain data file + /// + /// true if mapped as plain data file, false if mapped as image + BLACKBONE_API inline bool isPlainData() const { return _isPlainData; } + + /// + /// Get manifest resource ID + /// + /// Manifest resource ID + BLACKBONE_API inline int manifestID() const { return _manifestIdx; } + + /// + /// Get image subsystem + /// + /// Image subsystem + BLACKBONE_API inline uint32_t subsystem() const { return _subsystem; } + + /// + /// Get manifest resource file + /// + /// Manifest resource file + BLACKBONE_API inline const std::wstring& manifestFile() const { return _manifestPath; } + + /// + /// If true - no actual PE file available on disk + /// + /// Flag + BLACKBONE_API inline bool noPhysFile() const { return _noFile; } + + /// + /// DllCharacteristics field of header + /// + /// DllCharacteristics + BLACKBONE_API inline uint32_t DllCharacteristics() const { return _DllCharacteristics; } + +#ifdef COMPILER_MSVC + /// + /// .NET image parser + /// + /// .NET image parser + BLACKBONE_API ImageNET& net() { return _netImage; } +#endif + +private: + /// + /// Prepare activation context + /// + /// Path to PE file. If nullptr - manifest is extracted from memory to disk + /// Status code + NTSTATUS PrepareACTX( const wchar_t* filepath = nullptr ); + + /// + /// Get manifest from image data + /// + /// Manifest size + /// Mmanifest ID + /// Manifest data + void* GetManifest( uint32_t& size, int32_t& manifestID ); + +private: + FileHandle _hFile; // Target file HANDLE + Handle _hMapping; // Memory mapping object + void* _pFileBase = nullptr; // Mapping base + bool _isPlainData = false; // File mapped as plain data file + bool _is64 = false; // Image is 64 bit + bool _isExe = false; // Image is an .exe file + bool _isPureIL = false; // Pure IL image + bool _noFile = false; // Parsed from memory, no underlying PE file available + PCHDR32 _pImageHdr32 = nullptr; // PE header info + PCHDR64 _pImageHdr64 = nullptr; // PE header info + ptr_t _imgBase = 0; // Image base + uint32_t _imgSize = 0; // Image size + uint32_t _epRVA = 0; // Entry point RVA + uint32_t _hdrSize = 0; // Size of headers + ACtxHandle _hctx; // Activation context + int32_t _manifestIdx = 0; // Manifest resource ID + uint32_t _subsystem = 0; // Image subsystem + int32_t _ILFlagOffset = 0; // Offset of pure IL flag + uint32_t _DllCharacteristics = 0; // DllCharacteristics flags + + vecSections _sections; // Section info + mapImports _imports; // Import functions + mapImports _delayImports; // Import functions + + std::wstring _imagePath; // Image path + std::wstring _manifestPath; // Image manifest container + +#ifdef COMPILER_MSVC + ImageNET _netImage; // .net image info +#endif +}; + +} +} diff --git a/third/Blackbone/src/BlackBone/Patterns/PatternSearch.cpp b/third/Blackbone/src/BlackBone/Patterns/PatternSearch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..273f5839a63918ac118e18680f7a50ef08a26e18 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Patterns/PatternSearch.cpp @@ -0,0 +1,251 @@ +#include "PatternSearch.h" +#include "../Include/Macro.h" +#include "../Include/Winheaders.h" +#include "../Process/Process.h" + +#include +#include + +namespace blackbone +{ + +PatternSearch::PatternSearch( const std::vector& pattern ) + : _pattern( pattern ) +{ +} + +PatternSearch::PatternSearch( const std::initializer_list&& pattern ) + : _pattern( pattern ) +{ +} + +PatternSearch::PatternSearch( const std::string& pattern ) + : _pattern( pattern.begin(), pattern.end() ) +{ +} + +PatternSearch::PatternSearch( const char* pattern, size_t len /*= 0*/ ) + : _pattern( pattern, pattern + (len ? len : strlen( pattern )) ) +{ +} + +PatternSearch::PatternSearch( const uint8_t* pattern, size_t len /*= 0*/ ) + : _pattern( pattern, pattern + (len ? len : strlen( (const char*)pattern )) ) +{ +} + +/// +/// Default pattern matching with wildcards. +/// std::search is approximately 2x faster than naive approach. +/// +/// Pattern wildcard +/// Starting address +/// Size of region to scan +/// Found results +/// Value that will be added to resulting addresses +/// Number of found addresses +size_t PatternSearch::Search( + uint8_t wildcard, + void* scanStart, + size_t scanSize, + std::vector& out, + ptr_t value_offset /*= 0*/ + ) const +{ + const uint8_t* cstart = (const uint8_t*)scanStart; + const uint8_t* cend = cstart + scanSize; + + auto comparer = [&wildcard]( uint8_t val1, uint8_t val2 ) + { + return (val1 == val2 || val2 == wildcard); + }; + + for (;;) + { + const uint8_t* res = std::search( cstart, cend, _pattern.begin(), _pattern.end(), comparer ); + if (res >= cend) + break; + + if (value_offset != 0) + out.emplace_back( REBASE( res, scanStart, value_offset ) ); + else + out.emplace_back( reinterpret_cast(res) ); + + cstart = res + _pattern.size(); + } + + return out.size(); +} + +/// +/// Full pattern match, no wildcards. +/// Uses Boyer–Moore–Horspool algorithm. +/// +/// Starting address +/// Size of region to scan +/// Found results +/// Value that will be added to resulting addresses +/// Number of found addresses +size_t PatternSearch::Search( + void* scanStart, + size_t scanSize, + std::vector& out, + ptr_t value_offset /*= 0*/ + ) const +{ + size_t bad_char_skip[UCHAR_MAX + 1]; + + const uint8_t* haystack = reinterpret_cast(scanStart); + const uint8_t* needle = &_pattern[0]; + uintptr_t nlen = _pattern.size(); + uintptr_t scan = 0; + uintptr_t last = nlen - 1; + + // + // Preprocess + // + for (scan = 0; scan <= UCHAR_MAX; ++scan) + bad_char_skip[scan] = nlen; + + for (scan = 0; scan < last; ++scan) + bad_char_skip[needle[scan]] = last - scan; + + // + // Search + // + while (scanSize >= static_cast(nlen)) + { + for (scan = last; haystack[scan] == needle[scan]; --scan) + { + if (scan == 0) + { + if (value_offset != 0) + out.emplace_back( REBASE( haystack, scanStart, value_offset ) ); + else + out.emplace_back( reinterpret_cast(haystack) ); + + break; + } + } + + scanSize -= bad_char_skip[haystack[last]]; + haystack += bad_char_skip[haystack[last]]; + } + + return out.size(); +} + +/// +/// Search pattern in remote process +/// +/// Remote process +/// Pattern wildcard +/// Starting address +/// Size of region to scan +/// Found results +/// Number of found addresses +size_t PatternSearch::SearchRemote( + Process& remote, + uint8_t wildcard, + ptr_t scanStart, + size_t scanSize, + std::vector& out + ) const +{ + uint8_t *pBuffer = reinterpret_cast(VirtualAlloc( NULL, scanSize, MEM_COMMIT, PAGE_READWRITE )); + + if (pBuffer && remote.memory().Read( scanStart, scanSize, pBuffer ) == STATUS_SUCCESS) + Search( wildcard, pBuffer, scanSize, out, scanStart ); + + if (pBuffer) + VirtualFree( pBuffer, 0, MEM_RELEASE ); + + return out.size(); +} + +/// +/// Search pattern in remote process +/// +/// Remote process +/// Starting address +/// Size of region to scan +/// Found results +/// Number of found addresses +size_t PatternSearch::SearchRemote( + Process& remote, + ptr_t scanStart, + size_t scanSize, + std::vector& out + ) const +{ + uint8_t *pBuffer = reinterpret_cast(VirtualAlloc( NULL, scanSize, MEM_COMMIT, PAGE_READWRITE )); + + if (pBuffer && remote.memory().Read( scanStart, scanSize, pBuffer ) == STATUS_SUCCESS) + Search( pBuffer, scanSize, out, scanStart ); + + if (pBuffer) + VirtualFree( pBuffer, 0, MEM_RELEASE ); + + return out.size(); +} + +/// +/// Search pattern in whole address space of remote process +/// +/// Remote process +/// True if pattern contains wildcards +/// Pattern wildcard +/// Found results +/// Number of found addresses +size_t PatternSearch::SearchRemoteWhole( + Process& remote, + bool useWildcard, + uint8_t wildcard, + std::vector& out + ) const +{ + MEMORY_BASIC_INFORMATION64 mbi = { 0 }; + size_t bufsize = 1 * 1024 * 1024; // 1 MB + uint8_t *buf = reinterpret_cast(VirtualAlloc( 0, bufsize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE )); + + out.clear(); + + auto native = remote.core().native(); + + for (ptr_t memptr = native->minAddr(); memptr < native->maxAddr(); memptr = mbi.BaseAddress + mbi.RegionSize) + { + auto status = remote.core().native()->VirtualQueryExT( memptr, &mbi ); + + if (status == STATUS_INVALID_PARAMETER || status == STATUS_ACCESS_DENIED) + break; + else if (status != STATUS_SUCCESS) + continue; + + // Filter regions + if (mbi.State != MEM_COMMIT || mbi.Protect == PAGE_NOACCESS/*|| !(mbi.Protect & PAGE_READWRITE)*/) + continue; + + // Reallocate buffer + if (mbi.RegionSize > bufsize) + { + bufsize = static_cast(mbi.RegionSize); + VirtualFree( buf, 0, MEM_RELEASE ); + buf = reinterpret_cast(VirtualAlloc( 0, bufsize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE )); + } + + if (remote.memory().Read( memptr, static_cast(mbi.RegionSize), buf ) != STATUS_SUCCESS) + continue; + + if (useWildcard) + Search( wildcard, buf, static_cast(mbi.RegionSize), out, memptr ); + else + Search( buf, static_cast(mbi.RegionSize), out, memptr ); + } + + VirtualFree( buf, 0, MEM_RELEASE ); + + return out.size(); +} + + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Patterns/PatternSearch.h b/third/Blackbone/src/BlackBone/Patterns/PatternSearch.h new file mode 100644 index 0000000000000000000000000000000000000000..77ed59dcbd6c7bb045c74ab28f99116f18f4e243 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Patterns/PatternSearch.h @@ -0,0 +1,108 @@ +#pragma once + +#include "../Include/Types.h" + +#include +#include +#include + +namespace blackbone +{ + +class PatternSearch +{ +public: + BLACKBONE_API PatternSearch( const std::vector& pattern ); + BLACKBONE_API PatternSearch( const std::initializer_list&& pattern ); + BLACKBONE_API PatternSearch( const std::string& pattern ); + BLACKBONE_API PatternSearch( const char* pattern, size_t len = 0 ); + BLACKBONE_API PatternSearch( const uint8_t* pattern, size_t len = 0 ); + + BLACKBONE_API ~PatternSearch() = default; + + /// + /// Default pattern matching with wildcards. + /// std::search is approximately 2x faster than naive approach. + /// + /// Pattern wildcard + /// Starting address + /// Size of region to scan + /// Found results + /// Value that will be added to resulting addresses + /// Number of found addresses + BLACKBONE_API size_t Search( + uint8_t wildcard, + void* scanStart, + size_t scanSize, + std::vector& out, + ptr_t value_offset = 0 + ) const; + + /// + /// Full pattern match, no wildcards. + /// Uses Boyer–Moore–Horspool algorithm. + /// + /// Starting address + /// Size of region to scan + /// Found results + /// Value that will be added to resulting addresses + /// Number of found addresses + BLACKBONE_API size_t Search( + void* scanStart, + size_t scanSize, + std::vector& out, + ptr_t value_offset = 0 + ) const; + + /// + /// Search pattern in remote process + /// + /// Remote process + /// Pattern wildcard + /// Starting address + /// Size of region to scan + /// Found results + /// Number of found addresses + BLACKBONE_API size_t SearchRemote( + class Process& remote, + uint8_t wildcard, + ptr_t scanStart, + size_t scanSize, + std::vector& out + ) const; + + /// + /// Search pattern in remote process + /// + /// Remote process + /// Starting address + /// Size of region to scan + /// Found results + /// Number of found addresses + BLACKBONE_API size_t SearchRemote( + class Process& remote, + ptr_t scanStart, + size_t scanSize, + std::vector& out + ) const; + + /// + /// Search pattern in whole address space of remote process + /// + /// Remote process + /// True if pattern contains wildcards + /// Pattern wildcard + /// Found results + /// Number of found addresses + BLACKBONE_API size_t SearchRemoteWhole( + class Process& remote, + bool useWildcard, + uint8_t wildcard, + std::vector& out + ) const; + +private: + std::vector _pattern; // Pattern to search +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/MemBlock.cpp b/third/Blackbone/src/BlackBone/Process/MemBlock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bc48e3942d57073a86ce8365a85d19c4ecfe1c21 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/MemBlock.cpp @@ -0,0 +1,256 @@ +#include "MemBlock.h" +#include "ProcessMemory.h" +#include "ProcessCore.h" +#include "../Subsystem/NativeSubsystem.h" +#include "../Misc/Trace.hpp" + +namespace blackbone +{ +/// +/// MemBlock ctor +/// +/// Process memory routines +/// Memory address +/// Block size +/// Memory protection +/// false if caller will be responsible for block deallocation +MemBlock::MemBlock( + ProcessMemory* mem, + ptr_t ptr, + size_t size, + DWORD prot, + bool own /*= true*/, + bool physical /*= false*/ + ) + : _pImpl( new MemBlockImpl( mem, ptr, size, prot, own, physical ) ) +{ +} + +/// +/// MemBlock_p ctor +/// +/// Process memory routines +/// Memory address +/// Block size +/// Memory protection +/// false if caller will be responsible for block deallocation +MemBlock::MemBlockImpl::MemBlockImpl( + class ProcessMemory* mem, + ptr_t ptr, size_t size, + DWORD prot, + bool own /*= true*/, + bool physical /*= false */ + ) + : _ptr( ptr ) + , _size( size ) + , _protection( prot ) + , _own( own ) + , _physical( physical ) + , _memory( mem ) +{ +} + +/// +/// MemBlock ctor +/// +/// Process memory routines +/// Memory address +/// false if caller will be responsible for block deallocation +MemBlock::MemBlock( ProcessMemory* mem, ptr_t ptr, bool own /*= true*/ ) + : _pImpl( new MemBlockImpl ) +{ + _pImpl->_ptr = ptr; + _pImpl->_own = own; + _pImpl->_memory = mem; + + MEMORY_BASIC_INFORMATION64 mbi = { 0 }; + mem->Query( _pImpl->_ptr, &mbi ); + + _pImpl->_protection = mbi.Protect; + _pImpl->_size = (size_t)mbi.RegionSize; +} + + +/// +/// Allocate new memory block +/// +/// Process memory routines +/// Block size +/// Desired base address of new block +/// Memory protection +/// false if caller will be responsible for block deallocation +/// Memory block. If failed - returned block will be invalid +call_result_t MemBlock::Allocate( + ProcessMemory& process, + size_t size, + ptr_t desired /*= 0*/, + DWORD protection /*= PAGE_EXECUTE_READWRITE */, + bool own /*= true*/ + ) +{ + ptr_t desired64 = desired; + DWORD newProt = CastProtection( protection, process.core().DEP() ); + + NTSTATUS status = process.core().native()->VirtualAllocExT( desired64, size, MEM_RESERVE | MEM_COMMIT, newProt ); + if (!NT_SUCCESS( status )) + { + desired64 = 0; + status = process.core().native()->VirtualAllocExT( desired64, size, MEM_COMMIT, newProt ); + if (NT_SUCCESS( status )) + return call_result_t( MemBlock( &process, desired64, size, protection, own ), STATUS_IMAGE_NOT_AT_BASE ); + else + return status; + } +#ifdef _DEBUG + BLACKBONE_TRACE(L"Allocate: Allocating at address 0x%p (0x%X bytes)", static_cast(desired64), size); +#endif + return MemBlock( &process, desired64, size, protection, own ); +} + +/// +/// Reallocate existing block for new size +/// +/// New block size +/// Desired base address of new block +/// Memory protection +/// New block address +call_result_t MemBlock::Realloc( size_t size, ptr_t desired /*= 0*/, DWORD protection /*= PAGE_EXECUTE_READWRITE*/ ) +{ + if (!_pImpl) + return STATUS_MEMORY_NOT_ALLOCATED; + + ptr_t desired64 = desired; + auto status = _pImpl->_memory->core().native()->VirtualAllocExT( desired64, size, MEM_COMMIT, protection ); + if (!desired64) + { + desired64 = 0; + status = _pImpl->_memory->core().native()->VirtualAllocExT( desired64, size, MEM_COMMIT, protection ); + if (!NT_SUCCESS( status )) + return status; + + status = STATUS_IMAGE_NOT_AT_BASE; + } + + // Replace current instance + if (desired64) + { + Free(); + + _pImpl->_ptr = desired64; + _pImpl->_size = size; + _pImpl->_protection = protection; + } + + return call_result_t( desired64, status ); +} + +/// +/// Change memory protection +/// +/// New protection flags +/// Memory offset in block +/// Block size +/// Old protection flags +/// Status +NTSTATUS MemBlock::Protect( DWORD protection, uintptr_t offset /*= 0*/, size_t size /*= 0*/, DWORD* pOld /*= nullptr */ ) +{ + if (!_pImpl) + return STATUS_MEMORY_NOT_ALLOCATED; + + auto prot = CastProtection( protection, _pImpl->_memory->core().DEP() ); + + if (size == 0) + size = _pImpl->_size; + + return _pImpl->_physical ? Driver().ProtectMem( _pImpl->_memory->core().pid(), _pImpl->_ptr + offset, size, prot ) : + _pImpl->_memory->Protect( _pImpl->_ptr + offset, size, prot, pOld ); +} + +/// +/// Free memory +/// +/// Size of memory chunk to free. If 0 - whole block is freed +NTSTATUS MemBlock::Free( size_t size /*= 0*/ ) +{ + if (!_pImpl) + return STATUS_MEMORY_NOT_ALLOCATED; + + return _pImpl->Free(); +} + +/// +/// Free memory +/// +/// Size of memory chunk to free. If 0 - whole block is freed +NTSTATUS MemBlock::MemBlockImpl::Free( size_t size /*= 0 */ ) +{ + if (_ptr == 0) + return STATUS_MEMORY_NOT_ALLOCATED; + + size = Align( size, 0x1000 ); + + NTSTATUS status = _physical ? Driver().FreeMem( _memory->core().pid(), _ptr, size, MEM_RELEASE ) : + _memory->Free( _ptr, size, size == 0 ? MEM_RELEASE : MEM_DECOMMIT ); + + if (!NT_SUCCESS( status )) + return LastNtStatus(); + + if (size == 0) + { + _ptr = 0; + _size = 0; + _protection = 0; + } + else + { + _ptr += size; + _size -= size; + } + + return STATUS_SUCCESS; +} + +/// +/// Read data +/// +/// Data offset in block +/// Size of data to read +/// Output buffer +/// +/// If true, function will try to read all committed pages in range ignoring uncommitted. +/// Otherwise function will fail if there is at least one non-committed page in region. +/// +/// Status +NTSTATUS MemBlock::Read( uintptr_t offset, size_t size, PVOID pResult, bool handleHoles /*= false*/ ) +{ + if (!_pImpl) + return STATUS_MEMORY_NOT_ALLOCATED; + + return _pImpl->_memory->Read( _pImpl->_ptr + offset, size, pResult, handleHoles ); +} + + +/// +/// Write data +/// +/// Data offset in block +/// Size of data to write +/// Buffer to write +/// Status +NTSTATUS MemBlock::Write( uintptr_t offset, size_t size, const void* pData ) +{ + if (!_pImpl) + return STATUS_MEMORY_NOT_ALLOCATED; + + return _pImpl->_memory->Write( _pImpl->_ptr + offset, size, pData ); +} + +/// +/// Try to free memory and reset pointers +/// +void MemBlock::Reset() +{ + _pImpl.reset(); +} + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/MemBlock.h b/third/Blackbone/src/BlackBone/Process/MemBlock.h new file mode 100644 index 0000000000000000000000000000000000000000..31b0eca889ccb2db839eb3b055bbbade4d84226b --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/MemBlock.h @@ -0,0 +1,265 @@ +#pragma once + +#include "../Include/Winheaders.h" +#include "../Include/Macro.h" +#include "../Include/Types.h" +#include "../Include/CallResult.h" + +#include +#include + +namespace blackbone +{ + +/// +/// Get rid of EXECUTABLE flag if DEP isn't enabled +/// +/// Memory protection flags +/// DEP flag +/// New protection flags +inline DWORD CastProtection( DWORD prot, bool bDEP ) +{ + if (bDEP == true) + { + return prot; + } + else + { + if (prot == PAGE_EXECUTE_READ) + return PAGE_READONLY; + else if (prot == PAGE_EXECUTE_READWRITE) + return PAGE_READWRITE; + else if (prot == PAGE_EXECUTE_WRITECOPY) + return PAGE_WRITECOPY; + else + return prot; + } +} + +class MemBlock +{ +public: + class MemBlockImpl + { + friend class MemBlock; + + public: + MemBlockImpl() = default; + + /// + /// MemBlock_p ctor + /// + /// Process memory routines + /// Memory address + /// Block size + /// Memory protection + /// true if caller will be responsible for block deallocation + MemBlockImpl( class ProcessMemory* mem, ptr_t ptr, size_t size, DWORD prot, bool own = true, bool physical = false ); + + ~MemBlockImpl() + { + if (_own) + Free(); + } + + /// + /// Free memory + /// + /// Size of memory chunk to free. If 0 - whole block is freed + NTSTATUS Free( size_t size = 0 ); + + private: + ptr_t _ptr = 0; // Raw memory pointer + size_t _size = 0; // Region size + DWORD _protection = 0; // Region protection + bool _own = true; // Memory will be freed in destructor + bool _physical = false; // Memory allocated as direct physical + class ProcessMemory* _memory; // Target process routines + }; + +public: + /// + /// MemBlock ctor + /// + BLACKBONE_API MemBlock() = default; + + /// + /// MemBlock ctor + /// + /// Process memory routines + /// Memory address + /// true if caller will be responsible for block deallocation + BLACKBONE_API MemBlock( class ProcessMemory* mem, ptr_t ptr, bool own = true ); + + /// + /// MemBlock ctor + /// + /// Process memory routines + /// Memory address + /// Block size + /// Memory protection + /// true if caller will be responsible for block deallocation + BLACKBONE_API MemBlock( class ProcessMemory* mem, ptr_t ptr, size_t size, DWORD prot, bool own = true, bool physical = false ); + + /// + /// Move ctor + /// + /// Move from + BLACKBONE_API MemBlock( MemBlock&& rhs ) { _pImpl.swap( rhs._pImpl ); } + BLACKBONE_API MemBlock& operator = ( MemBlock&& rhs ) + { + // Self assign + if (_pImpl == rhs._pImpl) + return *this; + + _pImpl.swap( rhs._pImpl ); + return *this; + } + + /// + /// Allocate new memory block + /// + /// Process memory routines + /// Block size + /// Desired base address of new block + /// Win32 Memory protection flags + /// false if caller will be responsible for block deallocation + /// Memory block. If failed - returned block will be invalid + BLACKBONE_API static call_result_t Allocate( + class ProcessMemory& process, + size_t size, + ptr_t desired = 0, + DWORD protection = PAGE_EXECUTE_READWRITE, + bool own = true + ); + + /// + /// Reallocate existing block for new size + /// + /// New block size + /// Desired base address of new block + /// Memory protection + /// New block address + BLACKBONE_API call_result_t Realloc( size_t size, ptr_t desired = 0, DWORD protection = PAGE_EXECUTE_READWRITE ); + + /// + /// Change memory protection + /// + /// New protection flags + /// Memory offset in block + /// Block size + /// Old protection flags + /// Status + BLACKBONE_API NTSTATUS Protect( DWORD protection, uintptr_t offset = 0, size_t size = 0, DWORD* pOld = nullptr ); + + /// + /// Free memory + /// + /// Size of memory chunk to free. If 0 - whole block is freed + BLACKBONE_API NTSTATUS Free( size_t size = 0 ); + + /// + /// Read data + /// + /// Data offset in block + /// Size of data to read + /// Output buffer + /// + /// If true, function will try to read all committed pages in range ignoring uncommitted. + /// Otherwise function will fail if there is at least one non-committed page in region. + /// + /// Status + BLACKBONE_API NTSTATUS Read( uintptr_t offset, size_t size, PVOID pResult, bool handleHoles = false ); + + /// + /// Write data + /// + /// Data offset in block + /// Size of data to write + /// Buffer to write + /// Status + BLACKBONE_API NTSTATUS Write( uintptr_t offset, size_t size, const void* pData ); + + /// + /// Read data + /// + /// Data offset in block + /// Defult return value if read has failed + /// Read data + template + T Read( uintptr_t offset, const T& def_val ) + { + T res = def_val; + Read( offset, sizeof( T ), &res ); + return res; + } + + /// + /// Read data + /// + /// Data offset in block + /// Read data + /// Status code + template + NTSTATUS Read( size_t offset, T& val ) + { + return Read( offset, sizeof( val ), &val ); + } + + /// + /// Write data + /// + /// Offset in block + /// Data to write + /// Status + template + NTSTATUS Write( uintptr_t offset, const T& data ) + { + return Write( offset, sizeof( data ), &data ); + } + + /// + /// Try to free memory and reset pointers + /// + BLACKBONE_API void Reset(); + + /// + /// Memory will not be deallocated upon object destruction + /// + BLACKBONE_API inline void Release() { if (_pImpl) _pImpl->_own = false; } + + /// + /// Get memory pointer + /// + /// Memory pointer + template + inline T ptr() const { return _pImpl ? (T)_pImpl->_ptr : T( 0 ); } + + /// + /// Get block size + /// + /// Block size + BLACKBONE_API inline size_t size() const { return _pImpl ? _pImpl->_size : 0; } + + /// + /// Get block memory protection + /// + /// Memory protection flags + BLACKBONE_API inline DWORD protection() const { return _pImpl ? _pImpl->_protection : 0; } + + /// + /// Validate memory block + /// true if memory pointer isn't 0 + BLACKBONE_API inline bool valid() const { return( _pImpl.get() != nullptr && _pImpl->_ptr != 0); } + + /// + /// Get memory pointer + /// + /// Memory pointer + BLACKBONE_API inline operator ptr_t() const { return _pImpl ? _pImpl->_ptr : 0; } + +private: + std::shared_ptr _pImpl; +}; + +} diff --git a/third/Blackbone/src/BlackBone/Process/MultPtr.hpp b/third/Blackbone/src/BlackBone/Process/MultPtr.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3d3191bd2981eadae5746362a3133329f9e0dc79 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/MultPtr.hpp @@ -0,0 +1,160 @@ +#pragma once +#include "Process.h" +#include "../Misc/Trace.hpp" + +#include +#include +#include + +namespace blackbone +{ + +/// +/// Multi-level pointer wrapper for local process +/// +template +class multi_ptr +{ +public: + using type = std::remove_pointer_t; + using type_ptr = std::add_pointer_t; + using vecOffsets = std::vector; + + constexpr static bool type_is_ptr = std::is_pointer_v; + +public: + multi_ptr() = default; + + multi_ptr( uintptr_t base, const vecOffsets& offsets = vecOffsets() ) + : _base( base ) + , _offsets( offsets ) { } + + /// + /// Object getters + /// + /// Object pointer, if valid + inline type_ptr get() { return read(); } + inline operator type_ptr() { return read(); } + inline type_ptr operator ->() { return read(); } + +protected: + /// + /// Get object pointer from base and offsets + /// + /// Object ptr, if valid + virtual type_ptr read() + { + intptr_t i = -1; + uintptr_t ptr = _base; + + __try + { + if (!ptr) + return _ptr = nullptr; + + ptr = *reinterpret_cast(ptr); + if (!_offsets.empty()) + { + for (i = 0; i < static_cast(_offsets.size()) - 1; i++) + ptr = *reinterpret_cast(ptr + _offsets[i]); + + ptr += _offsets.back(); + if (type_is_ptr) + ptr = *reinterpret_cast(ptr); + } + + return _ptr = reinterpret_cast(ptr); + } + // Invalid address + __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) + { + BLACKBONE_TRACE( + "Invalid pointer derefrence: base 0x%p, offset 0x%08x, target address 0x%p", + _base, (i > 0 ? _offsets[i] : -1), ptr + ); + + return _ptr = nullptr; + } + } + +protected: + uintptr_t _base = 0; + type_ptr _ptr = nullptr; + std::vector _offsets; +}; + +/// +/// Multi-level pointer wrapper for remote process +/// +template +class multi_ptr_ex : public multi_ptr +{ +public: + /// + /// Initializes a new instance of the class. + /// + /// Target process + /// Base address + /// Offsets + multi_ptr_ex( Process* proc, uintptr_t base = 0, const vecOffsets& offsets = vecOffsets() ) + : _proc( proc ) + , multi_ptr( base, offsets ) { } + + /// + /// Commit changed object into process + /// + /// Status code + NTSTATUS commit() + { + auto ptr = get_ptr(); + if (ptr == 0) + return STATUS_ACCESS_VIOLATION; + + return _proc->memory().Write( ptr, sizeof( _data ), &_data ); + } + +private: + /// + /// Read object from pointer + /// + /// Pointer to local copy or nullptr if invalid + virtual type_ptr read() + { + auto ptr = get_ptr(); + if (ptr == 0) + return nullptr; + + return NT_SUCCESS( _proc->memory().Read( ptr, sizeof( _data ), &_data ) ) ? &_data : nullptr; + } + + /// + /// Get target pointer + /// + /// Pointer value or 0 if chain is invalid + uintptr_t get_ptr() + { + uintptr_t ptr = _base; + if (!NT_SUCCESS( _proc->memory().Read( ptr, ptr ) )) + return 0; + + if (!_offsets.empty()) + { + for (intptr_t i = 0; i < static_cast(_offsets.size()) - 1; i++) + if (!NT_SUCCESS( _proc->memory().Read( ptr + _offsets[i], ptr ) )) + return 0; + + ptr += _offsets.back(); + if (type_is_ptr) + if (!NT_SUCCESS( _proc->memory().Read( ptr, ptr ) )) + return 0; + } + + return ptr; + } + + +private: + Process* _proc = nullptr; // Target process + type _data; // Local object copy +}; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/Process.cpp b/third/Blackbone/src/BlackBone/Process/Process.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2b03b68cd16a8637d5f58b3b6a0ede85e498481c --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/Process.cpp @@ -0,0 +1,435 @@ +#include "Process.h" +#include "../Misc/NameResolve.h" +#include "../Misc/DynImport.h" + +#include + +namespace blackbone +{ +#define SystemHandleInformation (SYSTEM_INFORMATION_CLASS)16 +#define ObjectNameInformation (OBJECT_INFORMATION_CLASS)1 + +Process::Process() + : _core() + , _modules( *this ) + , _memory( this ) + , _threads( _core ) + , _hooks( _memory ) + , _localHooks( *this ) + , _remote( *this ) + , _mmap( *this ) + , _nativeLdr( *this ) +{ + // Ensure InitOnce is called + InitializeOnce(); +} + +Process::~Process(void) +{ +} + +/// +/// Attach to existing process +/// +/// Process ID +/// Access mask +/// Status code +NTSTATUS Process::Attach( DWORD pid, DWORD access /*= DEFAULT_ACCESS_P*/ ) +{ + Detach(); + return _core.Open( pid, access ); +} + +/// +/// Attach to existing process +/// +/// Process handle +/// Status code +NTSTATUS Process::Attach( HANDLE hProc ) +{ + Detach(); + return _core.Open( hProc ); +} + +/// +/// Attach to existing process +/// +/// Process name +/// Access mask +/// Status code +NTSTATUS Process::Attach( const wchar_t* name, DWORD access /*= DEFAULT_ACCESS_P*/ ) +{ + auto pids = EnumByName( name ); + return pids.empty() ? STATUS_NOT_FOUND : Attach( pids.front(), access ); +} + +/// +/// Create new process and attach to it +/// +/// Executable path +/// Leave process in suspended state. To resume process one should resume its main thread +/// If 'suspended' is true, this flag will enforce process initialization via second thread +/// Process command line +/// Startup directory +/// Additional startup params +/// Status code +NTSTATUS Process::CreateAndAttach( + const std::wstring& path, + bool suspended /*= false*/, + bool forceInit /*= true*/, + const std::wstring& cmdLine /*= L""*/, + const wchar_t* currentDir /*= nullptr*/, + STARTUPINFOW* pStartup /*= nullptr*/ + ) +{ + Detach(); + + STARTUPINFOW si = { }; + PROCESS_INFORMATION pi = { }; + if (!pStartup) + pStartup = &si; + + if (!CreateProcessW( + path.c_str(), const_cast(cmdLine.c_str()), + nullptr, nullptr, FALSE, CREATE_SUSPENDED, nullptr, + currentDir, pStartup, &pi + )) + { + return LastNtStatus(); + } + + // Get handle ownership + auto status = _core.Open( pi.hProcess ); + if (NT_SUCCESS( status )) + { + // Check if process must be left in suspended mode + if (suspended) + { + // Create new thread to make sure LdrInitializeProcess gets called + if (forceInit) + EnsureInit(); + } + else + ResumeThread( pi.hThread ); + } + + // Close unneeded handles + CloseHandle( pi.hThread ); + + return status; +} + +/// +/// Detach form current process, if any +/// +/// Status code +NTSTATUS Process::Detach() +{ + // Reset data + _memory.reset(); + _modules.reset(); + _remote.reset(); + _mmap.reset(); + _hooks.reset(); + _core.Close(); + + return STATUS_SUCCESS; +} + +/// +/// Ensure LdrInitializeProcess gets called +/// +/// Status code +NTSTATUS Process::EnsureInit() +{ + auto pProc = _modules.GetNtdllExport( "NtYieldExecution", mt_default, Sections ); + if (pProc) + return _remote.ExecDirect( pProc->procAddress, 0 ); + + return STATUS_NOT_FOUND; +} + +/// +/// Suspend process +/// +/// Status code +NTSTATUS Process::Suspend() +{ + return SAFE_NATIVE_CALL( NtSuspendProcess, _core._hProcess ); +} + +/// +/// Resume process +/// +/// Status code +NTSTATUS Process::Resume() +{ + return SAFE_NATIVE_CALL( NtResumeProcess, _core._hProcess ); +} + +/// +/// Checks if process still exists +/// +/// +bool Process::valid() +{ + DWORD dwExitCode = 0; + + if (!_core.handle() || !GetExitCodeProcess( _core.handle(), &dwExitCode )) + return false; + + return (dwExitCode == STILL_ACTIVE); +} + +/// +/// Terminate process +/// +/// Exit code +/// Stratus code +NTSTATUS Process::Terminate( uint32_t code /*= 0*/ ) +{ + TerminateProcess( _core.handle(), code ); + return LastNtStatus(); +} + +/// +/// Enumerate all open handles +/// +/// Found handles or status code +call_result_t> Process::EnumHandles() +{ + ULONG bufSize = 0x10000; + uint8_t* buffer = (uint8_t*)VirtualAlloc( NULL, bufSize, MEM_COMMIT, PAGE_READWRITE ); + ULONG returnLength = 0; + std::vector handles; + + // Query handle list + NTSTATUS status = SAFE_NATIVE_CALL( NtQuerySystemInformation, SystemHandleInformation, buffer, bufSize, &returnLength ); + while (status == STATUS_INFO_LENGTH_MISMATCH) + { + bufSize *= 2; + VirtualFree( buffer, 0, MEM_RELEASE ); + buffer = (uint8_t*)VirtualAlloc( NULL, bufSize, MEM_COMMIT, PAGE_READWRITE ); + + status = SAFE_NATIVE_CALL( NtQuerySystemInformation, SystemHandleInformation, buffer, bufSize, &returnLength ); + } + + if (!NT_SUCCESS( status )) + { + VirtualFree( buffer, 0, MEM_RELEASE ); + return status; + } + + SYSTEM_HANDLE_INFORMATION_T* handleInfo = (SYSTEM_HANDLE_INFORMATION_T*)buffer; + for (ULONG i = 0; i < handleInfo->HandleCount; i++) + { + HandleInfo info; + Handle hLocal; + OBJECT_TYPE_INFORMATION_T* pTypeInfo = nullptr; + PVOID pNameInfo = nullptr; + UNICODE_STRING objectName = { 0 }; + + // Filter process + if (handleInfo->Handles[i].ProcessId != _core._pid) + continue; + + // Get local handle copy + status = SAFE_NATIVE_CALL( + NtDuplicateObject, + _core._hProcess, + reinterpret_cast(handleInfo->Handles[i].Handle), + GetCurrentProcess(), + &hLocal, 0, 0, DUPLICATE_SAME_ACCESS + ); + + if (!NT_SUCCESS( status )) + continue; + + // + // Get type information + // + pTypeInfo = (OBJECT_TYPE_INFORMATION_T*)malloc( 0x1000 ); + status = SAFE_NATIVE_CALL( NtQueryObject, hLocal, ObjectTypeInformation, pTypeInfo, 0x1000, nullptr ); + if (!NT_SUCCESS( status )) + { + continue; + } + + // + // Obtain object name + // + pNameInfo = malloc( 0x1000 ); + status = SAFE_NATIVE_CALL( NtQueryObject, hLocal, ObjectNameInformation, pNameInfo, 0x1000, &returnLength); + if (!NT_SUCCESS( status )) + { + pNameInfo = realloc( pNameInfo, returnLength ); + status = SAFE_NATIVE_CALL( NtQueryObject, hLocal, ObjectNameInformation, pNameInfo, returnLength, nullptr ); + if (!NT_SUCCESS( status )) + { + free( pTypeInfo ); + free( pNameInfo ); + continue; + } + } + + objectName = *(PUNICODE_STRING)pNameInfo; + + // + // Fill handle info structure + // + info.handle = reinterpret_cast(handleInfo->Handles[i].Handle); + info.access = handleInfo->Handles[i].GrantedAccess; + info.flags = handleInfo->Handles[i].Flags; + info.pObject = handleInfo->Handles[i].Object; + + if (pTypeInfo->Name.Length) + info.typeName = (wchar_t*)pTypeInfo->Name.Buffer; + + if (objectName.Length) + info.name = objectName.Buffer; + + // + // Type-specific info + // + if (_wcsicmp( info.typeName.c_str(), L"Section" ) == 0) + { + SECTION_BASIC_INFORMATION_T secInfo = { 0 }; + + status = SAFE_NATIVE_CALL( NtQuerySection, hLocal, SectionBasicInformation, &secInfo, (ULONG)sizeof( secInfo ), nullptr ); + if (NT_SUCCESS( status )) + { + info.section.reset( new SectionInfo() ); + + info.section->size = secInfo.Size.QuadPart; + info.section->attrib = secInfo.Attributes; + } + } + + handles.emplace_back( info ); + + free( pTypeInfo ); + free( pNameInfo ); + } + + VirtualFree( buffer, 0, MEM_RELEASE ); + return call_result_t>( handles, status ); +} + +/// +/// Search for process by executable name +/// +/// Process name. If empty - function will retrieve all existing processes +/// Found processses +std::vector Process::EnumByName( const std::wstring& name ) +{ + std::vector found; + auto hProcSnap = SnapHandle( CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ) ); + if (!hProcSnap) + return found; + + PROCESSENTRY32W tEntry = { 0 }; + tEntry.dwSize = sizeof( PROCESSENTRY32W ); + + // Iterate threads + for (BOOL success = Process32FirstW( hProcSnap, &tEntry ); + success != FALSE; + success = Process32NextW( hProcSnap, &tEntry )) + { + if (name.empty() || _wcsicmp( tEntry.szExeFile, name.c_str() ) == 0) + found.emplace_back( tEntry.th32ProcessID ); + } + + return found; +} + +/// +/// Search for process by executable name or by process ID +/// +/// Target process ID. rocess name. If empty - function will retrieve all existing processes +/// Process executable name. If empty - function will retrieve all existing processes +/// Found processses +/// If set to true, function will retrieve info ablout process threads +/// Status code +call_result_t> Process::EnumByNameOrPID( + uint32_t pid, + const std::wstring& name, + bool includeThreads /*= false*/ + ) +{ + ULONG bufSize = 0x100; + uint8_t tmpbuf[0x100]; + uint8_t* buffer = tmpbuf; + ULONG returnLength = 0; + std::vector found; + + // Query process info + NTSTATUS status = SAFE_NATIVE_CALL( NtQuerySystemInformation, (SYSTEM_INFORMATION_CLASS)57, buffer, bufSize, &returnLength ); + if (!NT_SUCCESS( status )) + { + bufSize = returnLength; + buffer = (uint8_t*)VirtualAlloc( NULL, bufSize, MEM_COMMIT, PAGE_READWRITE ); + status = SAFE_NATIVE_CALL( NtQuerySystemInformation, (SYSTEM_INFORMATION_CLASS)57, buffer, bufSize, &returnLength ); + if (!NT_SUCCESS( status )) + { + VirtualFree( buffer, 0, MEM_RELEASE ); + return status; + } + } + + // Parse info + for (auto pInfo = reinterpret_cast<_SYSTEM_PROCESS_INFORMATION_T*>(buffer);;) + { + // Skip idle process, compare name or compare pid + if (pInfo->UniqueProcessId != 0 && ((name.empty() && pid == 0) || _wcsicmp( name.c_str(), (wchar_t*)pInfo->ImageName.Buffer ) == 0 || pid == pInfo->UniqueProcessId)) + { + ProcessInfo info; + + info.pid = static_cast(pInfo->UniqueProcessId); + + if (pInfo->ImageName.Buffer) + info.imageName = reinterpret_cast(pInfo->ImageName.Buffer); + + // Get threads info + if (includeThreads) + { + int64_t minTime = 0xFFFFFFFFFFFFFFFF; + ULONG mainIdx = 0; + + for (ULONG i = 0; i < pInfo->NumberOfThreads; i++) + { + ThreadInfo tinfo; + auto& thd = pInfo->Threads[i]; + + tinfo.tid = static_cast(thd.ThreadInfo.ClientId.UniqueThread); + tinfo.startAddress = static_cast(thd.ThreadInfo.StartAddress); + + // Check for main thread + if (thd.ThreadInfo.CreateTime.QuadPart < minTime) + { + minTime = thd.ThreadInfo.CreateTime.QuadPart; + mainIdx = i; + } + + info.threads.emplace_back( tinfo ); + info.threads[mainIdx].mainThread = true; + } + } + + found.emplace_back( info ); + } + + if (pInfo->NextEntryOffset) + pInfo = reinterpret_cast<_SYSTEM_PROCESS_INFORMATION_T*>((uint8_t*)pInfo + pInfo->NextEntryOffset); + else + break; + } + + // Sort results + std::sort( found.begin(), found.end() ); + + VirtualFree( buffer, 0, MEM_RELEASE ); + return call_result_t>( found, status ); +} + + +} diff --git a/third/Blackbone/src/BlackBone/Process/Process.h b/third/Blackbone/src/BlackBone/Process/Process.h new file mode 100644 index 0000000000000000000000000000000000000000..8bdc75b6c260d5017ef9d65b877e2b0e19936cf4 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/Process.h @@ -0,0 +1,233 @@ +#pragma once + +#include "ProcessCore.h" +#include "ProcessMemory.h" +#include "ProcessModules.h" +#include "Threads/Threads.h" +#include "RPC/RemoteExec.h" +#include "RPC/RemoteHook.h" +#include "RPC/RemoteLocalHook.h" +#include "../ManualMap/Native/NtLoader.h" +#include "../ManualMap/MMap.h" + +#include "../Include/NativeStructures.h" +#include "../Include/CallResult.h" +#include "../Misc/InitOnce.h" + +#include +#include + +namespace blackbone +{ + +/// +/// Process thread information +/// +struct ThreadInfo +{ + uint32_t tid = 0; + uintptr_t startAddress = 0; + bool mainThread = false; +}; + +/// +/// Process information +/// +struct ProcessInfo +{ + uint32_t pid = 0; + std::wstring imageName; + std::vector threads; + + bool operator < (const ProcessInfo& other) + { + return this->pid < other.pid; + } +}; + +/// +/// Section object information +/// +struct SectionInfo +{ + ptr_t size = 0; + uint32_t attrib = 0; +}; + +/// +/// Process handle information +/// +struct HandleInfo +{ + HANDLE handle = nullptr; + uint32_t access = 0; + uint32_t flags = 0; + ptr_t pObject = 0; + + std::wstring typeName; + std::wstring name; + + // Object-specific info + std::shared_ptr section; +}; + +#define DEFAULT_ACCESS_P PROCESS_QUERY_INFORMATION | \ + PROCESS_VM_READ | \ + PROCESS_VM_WRITE | \ + PROCESS_VM_OPERATION | \ + PROCESS_CREATE_THREAD | \ + PROCESS_SET_QUOTA | \ + PROCESS_TERMINATE | \ + PROCESS_SUSPEND_RESUME | \ + PROCESS_DUP_HANDLE +class Process +{ +public: + BLACKBONE_API Process(); + BLACKBONE_API ~Process(void); + + /// + /// Attach to existing process + /// + /// Process ID + /// Access mask + /// Status code + BLACKBONE_API NTSTATUS Attach( DWORD pid, DWORD access = DEFAULT_ACCESS_P ); + + /// + /// Attach to existing process + /// + /// Process name + /// Access mask + /// Status code + BLACKBONE_API NTSTATUS Attach( const wchar_t* name, DWORD access = DEFAULT_ACCESS_P ); + + /// + /// Attach to existing process + /// + /// Process handle + /// Status code + BLACKBONE_API NTSTATUS Attach( HANDLE hProc ); + + /// + /// Create new process and attach to it + /// + /// Executable path + /// Leave process in suspended state. To resume process one should resume its main thread + /// If 'suspended' is true, this flag will enforce process initialization via second thread + /// Process command line + /// Startup directory + /// Additional startup params + /// Status code + BLACKBONE_API NTSTATUS CreateAndAttach( + const std::wstring& path, + bool suspended = false, + bool forceInit = true, + const std::wstring& cmdLine = L"", + const wchar_t* currentDir = nullptr, + STARTUPINFOW* pStartup = nullptr + ); + + /// + /// Detach form current process, if any + /// + /// Status code + BLACKBONE_API NTSTATUS Detach(); + + /// + /// Ensure LdrInitializeProcess gets called + /// + /// Status code + BLACKBONE_API NTSTATUS EnsureInit(); + + /// + /// Suspend process + /// + /// Status code + BLACKBONE_API NTSTATUS Suspend(); + + /// + /// Resume process + /// + /// Status code + BLACKBONE_API NTSTATUS Resume(); + + /// + /// Get process ID + /// + /// Process ID + BLACKBONE_API inline DWORD pid() const { return _core.pid(); } + + /// + /// Checks if process still exists + /// + /// true if process is valid and exists + BLACKBONE_API bool valid(); + + /// + /// Terminate process + /// + /// Exit code + /// Stratus code + BLACKBONE_API NTSTATUS Terminate( uint32_t code = 0 ); + + /// + /// Enumerate all open handles + /// + /// Found handles or status code + BLACKBONE_API call_result_t> EnumHandles(); + + /// + /// Search for process by executable name + /// + /// Process name. If empty - function will retrieve all existing processes + /// Found processses + BLACKBONE_API static std::vector EnumByName( const std::wstring& name ); + + /// + /// Search for process by executable name or by process ID + /// + /// Target process ID. rocess name. If empty - function will retrieve all existing processes + /// Process executable name. If empty - function will retrieve all existing processes + /// Found processses + /// If set to true, function will retrieve info ablout process threads + /// Status code + BLACKBONE_API static call_result_t> EnumByNameOrPID( + uint32_t pid, + const std::wstring& name, + bool includeThreads = false + ); + + // + // Subroutines + // + BLACKBONE_API ProcessCore& core() { return _core; } // Core routines and native + BLACKBONE_API ProcessMemory& memory() { return _memory; } // Memory manipulations + BLACKBONE_API ProcessModules& modules() { return _modules; } // Module management + BLACKBONE_API ProcessThreads& threads() { return _threads; } // Threads + BLACKBONE_API RemoteHook& hooks() { return _hooks; } // Hooking code remotely + BLACKBONE_API RemoteLocalHook& localHooks() { return _localHooks; } // Hooking code locally + BLACKBONE_API RemoteExec& remote() { return _remote; } // Remote code execution + BLACKBONE_API MMap& mmap() { return _mmap; } // Manual module mapping + BLACKBONE_API NtLdr& nativeLdr() { return _nativeLdr; } // Native loader routines + + // Sugar + BLACKBONE_API const Wow64Barrier& barrier() const { return _core._native->GetWow64Barrier(); } + +private: + Process(const Process&) = delete; + Process& operator =(const Process&) = delete; + +private: + ProcessCore _core; // Core routines and native subsystem + ProcessModules _modules; // Module management + ProcessMemory _memory; // Memory manipulations + ProcessThreads _threads; // Threads + RemoteHook _hooks; // Hooking code remotely + RemoteLocalHook _localHooks; // In-process remote hooks + RemoteExec _remote; // Remote code execution + MMap _mmap; // Manual module mapping + NtLdr _nativeLdr; // Native loader routines +}; + +} diff --git a/third/Blackbone/src/BlackBone/Process/ProcessCore.cpp b/third/Blackbone/src/BlackBone/Process/ProcessCore.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c6eaaf799349b0b9b2054438e80600adc9e06d92 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/ProcessCore.cpp @@ -0,0 +1,131 @@ +#include "../Config.h" +#include "ProcessCore.h" +#include "../Misc/DynImport.h" +#include "../Include/Macro.h" +#include <3rd_party/VersionApi.h> + +namespace blackbone +{ + +#ifdef COMPILER_GCC +#define PROCESS_DEP_ENABLE 0x00000001 +#endif + +ProcessCore::ProcessCore() + : _native( nullptr ) +{ +} + +ProcessCore::~ProcessCore() +{ + Close(); +} + +/// +/// Attach to existing process +/// +/// Process ID +/// Access mask +/// Status +NTSTATUS ProcessCore::Open( DWORD pid, DWORD access ) +{ + // Handle current process differently + _hProcess = (pid == GetCurrentProcessId()) ? GetCurrentProcess() : OpenProcess( access, false, pid ); + + // Some routines in win10 do not support pseudo handle + if (IsWindows10OrGreater() && pid == GetCurrentProcessId()) + _hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pid ); + + if (_hProcess) + { + _pid = pid; + return Init(); + } + + return LastNtStatus(); +} + +/// +/// Attach to existing process +/// +/// Process ID +/// Access mask +/// Status +NTSTATUS ProcessCore::Open( HANDLE handle ) +{ + _hProcess = handle; + _pid = GetProcessId( _hProcess ); + + return Init(); +} + + +/// +/// Initialize some internal data +/// +/// Status code +NTSTATUS ProcessCore::Init() +{ + // Detect x86 OS + SYSTEM_INFO info = { { 0 } }; + GetNativeSystemInfo( &info ); + + if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) + { + _native = std::make_unique( _hProcess ); + } + else + { + // Detect wow64 barrier + BOOL wowSrc = FALSE; + IsWow64Process( GetCurrentProcess(), &wowSrc ); + + if (wowSrc == TRUE) + _native = std::make_unique( _hProcess ); + else + _native = std::make_unique( _hProcess ); + } + + // Get DEP info + // For native x64 processes DEP is always enabled + if (_native->GetWow64Barrier().targetWow64 == false) + { + _dep = true; + } + else + { + DWORD flags = 0; + BOOL perm = 0; + + if (SAFE_CALL( GetProcessDEPPolicy, _hProcess, &flags, &perm )) + _dep = (flags & PROCESS_DEP_ENABLE) != 0; + } + + return STATUS_SUCCESS; +} + +/// +/// Close current process handle +/// +void ProcessCore::Close() +{ + _hProcess.reset(); + _native.reset(); + _pid = 0; +} + +bool ProcessCore::isProtected() +{ + if (_hProcess) + { + _PROCESS_EXTENDED_BASIC_INFORMATION_T info = { 0 }; + info.Size = sizeof( info ); + + _native->QueryProcessInfoT( ProcessBasicInformation, &info, sizeof( info ) ); + return info.Flags.IsProtectedProcess; + } + + return false; +} + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/ProcessCore.h b/third/Blackbone/src/BlackBone/Process/ProcessCore.h new file mode 100644 index 0000000000000000000000000000000000000000..502874ed2d7551fdb863e64b7c6475c8404020ea --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/ProcessCore.h @@ -0,0 +1,118 @@ +#pragma once + +#include "../Include/NativeStructures.h" +#include "../Include/HandleGuard.h" +#include "../Subsystem/Wow64Subsystem.h" +#include "../Subsystem/x86Subsystem.h" + +#include +#include + +namespace blackbone +{ + +class ProcessCore +{ +public: + + /// + /// Check if target process is running in WOW64 mode + /// + /// true if process is WOW64 + BLACKBONE_API inline bool isWow64() const { return _native->GetWow64Barrier().targetWow64; } + + /// + /// Get process handle + /// + /// Process handle + BLACKBONE_API inline HANDLE handle() const { return _hProcess; } + + /// + /// Get process ID + /// + /// Process ID + BLACKBONE_API inline DWORD pid() const { return _pid; } + + /// + /// Get process data execution prevention state + /// + /// true if DEP is enabled for process + BLACKBONE_API inline bool DEP() const { return _dep; }; + + /// + /// Get system routines + /// + /// + BLACKBONE_API inline Native* native() { return _native.get(); } + + /// + /// Get WOW64 PEB + /// + /// Retrieved PEB32 + /// PEB pointer + BLACKBONE_API inline ptr_t peb32( _PEB32* ppeb = nullptr ) { return _native->getPEB( ppeb ); } + + /// + /// Get native PEB + /// + /// Retrieved PEB64 + /// PEB pointer + BLACKBONE_API inline ptr_t peb64( _PEB64* ppeb = nullptr ) { return _native->getPEB( ppeb ); } + + /// + /// Get PEB + /// + /// Retrieved PEB + /// PEB pointer + template + BLACKBONE_API inline ptr_t peb( _PEB_T* ppeb = nullptr ) { return _native->getPEB( ppeb ); } + + /// + /// Check if process is a protected process + /// + /// true if protected + BLACKBONE_API bool isProtected(); + +private: + friend class Process; + using ptrNative = std::unique_ptr; + +private: + ProcessCore(); + ProcessCore( const ProcessCore& ) = delete; + ~ProcessCore(); + + /// + /// Attach to existing process + /// + /// Process ID + /// Access mask + /// Status + NTSTATUS Open( DWORD pid, DWORD access ); + + /// + /// Attach to existing process by handle + /// + /// Process handle + /// Status + NTSTATUS Open( HANDLE handle ); + + /// + /// Initialize some internal data + /// + /// Status code + NTSTATUS Init(); + + /// + /// Close current process handle + /// + void Close(); + +private: + Handle _hProcess; // Process handle + DWORD _pid = 0; // Process ID + ptrNative _native; // Api wrapper + bool _dep = true; // DEP state for process +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/ProcessMemory.cpp b/third/Blackbone/src/BlackBone/Process/ProcessMemory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..04bba612eece654978ac53060358a2bb3f763e87 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/ProcessMemory.cpp @@ -0,0 +1,205 @@ +#include "ProcessMemory.h" +#include "Process.h" +#include "../Misc/Trace.hpp" + +namespace blackbone +{ + +ProcessMemory::ProcessMemory( Process* process ) + : RemoteMemory( process ) + , _process( process ) + , _core( process->core() ) +{ +} + +ProcessMemory::~ProcessMemory() +{ +} + +/// +/// Allocate new memory block +/// +/// Block size +/// Memory protection +/// Desired base address of new block +/// false if caller will be responsible for block deallocation +/// Memory block. If failed - returned block will be invalid +call_result_t ProcessMemory::Allocate( size_t size, DWORD protection /*= PAGE_EXECUTE_READWRITE*/, ptr_t desired /*= 0*/, bool own /*= true*/ ) +{ + return MemBlock::Allocate( *this, size, desired, protection, own ); +} + +/// +/// Free memory +/// +/// Memory address to release. +/// Region size +/// Release/decommit +/// Status +NTSTATUS ProcessMemory::Free( ptr_t pAddr, size_t size /*= 0*/, DWORD freeType /*= MEM_RELEASE*/ ) +{ +#ifdef _DEBUG + assert( freeType != MEM_RELEASE || size == 0 ); + if (freeType == MEM_DECOMMIT) { + BLACKBONE_TRACE( L"Free: Decommit at address 0x%p (0x%x bytes)", static_cast(pAddr), size ); + } else { + BLACKBONE_TRACE( L"Free: Free at address 0x%p", static_cast(pAddr) ); + } +#endif + return _core.native()->VirtualFreeExT( pAddr, size, freeType ); +} + +/// +/// Get memory region info +/// +/// Memory address +/// Retrieved info +/// Status +NTSTATUS ProcessMemory::Query( ptr_t pAddr, PMEMORY_BASIC_INFORMATION64 pInfo ) +{ + return _core.native()->VirtualQueryExT( pAddr, pInfo ); +} + +/// +/// Change memory protection +/// +/// Memory address +/// Region size +/// New memory protection flags +/// Old protection flags +/// Status +NTSTATUS ProcessMemory::Protect( ptr_t pAddr, size_t size, DWORD flProtect, DWORD *pOld /*= NULL*/ ) +{ + DWORD junk = 0; + if (pOld == nullptr) + pOld = &junk; + + return _core.native()->VirtualProtectExT( pAddr, size, CastProtection( flProtect, _core.DEP() ), pOld ); +} + +/// +/// Read data +/// +/// Memoey address to read from +/// Size of data to read +/// Output buffer +/// +/// If true, function will try to read all committed pages in range ignoring uncommitted ones. +/// Otherwise function will fail if there is at least one non-committed page in region. +/// +/// Status +NTSTATUS ProcessMemory::Read( ptr_t dwAddress, size_t dwSize, PVOID pResult, bool handleHoles /*= false*/ ) +{ + DWORD64 dwRead = 0; + if (dwAddress == 0) + return STATUS_INVALID_ADDRESS; + + // Simple read + if (!handleHoles) + { + return _core.native()->ReadProcessMemoryT( dwAddress, pResult, dwSize, &dwRead ); + } + // Read all committed memory regions + else + { + MEMORY_BASIC_INFORMATION64 mbi = { 0 }; + + for (ptr_t memptr = dwAddress; memptr < dwAddress + dwSize; memptr = mbi.BaseAddress + mbi.RegionSize) + { + if (_core.native()->VirtualQueryExT( memptr, &mbi ) != STATUS_SUCCESS) + continue; + + // Filter empty regions + if (mbi.State != MEM_COMMIT || mbi.Protect == PAGE_NOACCESS) + continue; + + uint64_t region_ptr = memptr - dwAddress; + + auto status = _core.native()->ReadProcessMemoryT( + mbi.BaseAddress, + reinterpret_cast(pResult) + region_ptr, + static_cast(mbi.RegionSize), + &dwRead + ); + + if (!NT_SUCCESS( status )) + return status; + } + } + + return STATUS_SUCCESS; +} + +/// +/// Read data +/// +/// Base address + list of offsets +/// Size of data to read +/// Output buffer +/// +/// If true, function will try to read all committed pages in range ignoring uncommitted ones. +/// Otherwise function will fail if there is at least one non-committed page in region. +/// +/// Status +NTSTATUS ProcessMemory::Read( const std::vector& adrList, size_t dwSize, PVOID pResult, bool handleHoles /*= false */ ) +{ + if (adrList.empty()) + return STATUS_INVALID_PARAMETER; + if(adrList.size() == 1) + return Read( adrList.front(), dwSize, pResult, handleHoles ); + + bool wow64 = _process->barrier().targetWow64; + ptr_t ptr = wow64 ? Read( adrList[0] ).result( 0 ) : Read( adrList[0] ).result( 0 ); + + for (size_t i = 1; i < adrList.size() - 1; i++) + ptr = wow64 ? Read( ptr + adrList[i] ).result( 0 ) : Read( ptr + adrList[i] ).result( 0 ); + + return Read( ptr + adrList.back(), dwSize, pResult, handleHoles ); +} + +/// +/// Write data +/// +/// Memory address to write to +/// Size of data to write +/// Buffer to write +/// Status +NTSTATUS ProcessMemory::Write( ptr_t pAddress, size_t dwSize, const void* pData ) +{ + return _core.native()->WriteProcessMemoryT( pAddress, pData, dwSize ); +} + +/// +/// Write data +/// +/// Base address + list of offsets +/// Size of data to write +/// Buffer to write +/// Status +NTSTATUS ProcessMemory::Write( const std::vector& adrList, size_t dwSize, const void* pData ) +{ + if (adrList.empty()) + return STATUS_INVALID_PARAMETER; + if (adrList.size() == 1) + return Write( adrList.front(), dwSize, pData ); + + bool wow64 = _process->barrier().targetWow64; + ptr_t ptr = wow64 ? Read( adrList[0] ).result( 0 ) : Read( adrList[0] ).result( 0 ); + + for (size_t i = 1; i < adrList.size() - 1; i++) + ptr = wow64 ? Read( ptr + adrList[i] ).result( 0 ) : Read( ptr + adrList[i] ).result( 0 ); + + return Write( ptr + adrList.back(), dwSize, pData ); +} + +/// +/// Enumerate valid memory regions +/// +/// If true - non-allocated regions will be included in list +/// Found regions +std::vector ProcessMemory::EnumRegions( bool includeFree /*= false*/ ) +{ + return _core.native()->EnumRegions( includeFree ); +} + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/ProcessMemory.h b/third/Blackbone/src/BlackBone/Process/ProcessMemory.h new file mode 100644 index 0000000000000000000000000000000000000000..4e5c28c9b0aa9dc85f692149106f44f7d37d2654 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/ProcessMemory.h @@ -0,0 +1,193 @@ +#pragma once + +#include "../Include/Winheaders.h" +#include "RPC/RemoteMemory.h" +#include "MemBlock.h" + +#include +#include + +namespace blackbone +{ + +class ProcessMemory : public RemoteMemory +{ +public: + BLACKBONE_API ProcessMemory( class Process* process ); + BLACKBONE_API ~ProcessMemory(); + + /// + /// Allocate new memory block + /// + /// Block size + /// Memory protection + /// Desired base address of new block + /// false if caller will be responsible for block deallocation + /// Memory block. If failed - returned block will be invalid + BLACKBONE_API call_result_t Allocate( size_t size, DWORD protection = PAGE_EXECUTE_READWRITE, ptr_t desired = 0, bool own = true ); + + /// + /// Free memory + /// + /// Memory address to release. + /// Region size + /// Release/decommit + /// Status + BLACKBONE_API NTSTATUS Free( ptr_t pAddr, size_t size = 0, DWORD freeType = MEM_RELEASE ); + + /// + /// Get memory region info + /// + /// Memory address + /// Retrieved info + /// Status + BLACKBONE_API NTSTATUS Query( ptr_t pAddr, PMEMORY_BASIC_INFORMATION64 pInfo ); + + /// + /// Change memory protection + /// + /// Memory address + /// Region size + /// New memory protection flags + /// Old protection flags + /// Status + BLACKBONE_API NTSTATUS Protect( ptr_t pAddr, size_t size, DWORD flProtect, DWORD *pOld = NULL ); + + /// + /// Read data + /// + /// Memory address to read from + /// Size of data to read + /// Output buffer + /// + /// If true, function will try to read all committed pages in range ignoring uncommitted ones. + /// Otherwise function will fail if there is at least one non-committed page in region. + /// + /// Status + BLACKBONE_API NTSTATUS Read( ptr_t dwAddress, size_t dwSize, PVOID pResult, bool handleHoles = false ); + + /// + /// Read data + /// + /// Base address + list of offsets + /// Size of data to read + /// Output buffer + /// + /// If true, function will try to read all committed pages in range ignoring uncommitted ones. + /// Otherwise function will fail if there is at least one non-committed page in region. + /// + /// Status + BLACKBONE_API NTSTATUS Read( const std::vector& adrList, size_t dwSize, PVOID pResult, bool handleHoles = false ); + + /// + /// Write data + /// + /// Memory address to write to + /// Size of data to write + /// Buffer to write + /// Status + BLACKBONE_API NTSTATUS Write( ptr_t pAddress, size_t dwSize, const void* pData ); + + /// + /// Write data + /// + /// Base address + list of offsets + /// Size of data to write + /// Buffer to write + /// Status + BLACKBONE_API NTSTATUS Write( const std::vector& adrList, size_t dwSize, const void* pData ); + + /// + /// Read data + /// + /// Address to read from + /// Read data + template + inline call_result_t Read( ptr_t dwAddress ) + { + auto res = reinterpret_cast(_malloca( sizeof( T ) )); + auto status = Read( dwAddress, sizeof( T ), res ); + return call_result_t( *res, status ); + }; + + /// + /// Read data + /// + /// Base address + list of offsets + /// Read data + template + inline call_result_t Read( std::vector&& adrList ) + { + auto res = reinterpret_cast(_malloca( sizeof( T ) )); + auto status = Read( std::forward>( adrList ), sizeof( T ), res ); + return call_result_t( *res, status ); + } + + /// + /// Read data + /// + /// Address to read from + /// Read data + /// Status code + template + inline NTSTATUS Read( ptr_t dwAddress, T& result ) + { + return Read( dwAddress, sizeof( result ), &result ); + }; + + /// + /// Read data + /// + /// Base address + list of offsets + /// Read data + /// Status code + template + inline NTSTATUS Read( std::vector&& adrList, T& result ) + { + return Read( std::forward>( adrList ), sizeof( result ), &result ); + }; + + /// + /// Write data + /// + /// Size of data to write + /// Data to write + /// Status + template + inline NTSTATUS Write( ptr_t dwAddress, const T& data ) + { + return Write( dwAddress, sizeof( T ), &data ); + } + + /// + /// Write data + /// + /// Base address + list of offset + /// Data to write + /// Status + template + inline NTSTATUS Write( std::vector&& adrList, const T& data ) + { + return Write( std::forward>( adrList ), sizeof( T ), &data ); + } + + /// + /// Enumerate valid memory regions + /// + /// If true - non-allocated regions will be included in list + /// Found regions + BLACKBONE_API std::vector EnumRegions( bool includeFree = false ); + + BLACKBONE_API inline class ProcessCore& core() { return _core; } + BLACKBONE_API inline class Process* process() { return _process; } + +private: + ProcessMemory( const ProcessMemory& ) = delete; + ProcessMemory& operator =( const ProcessMemory& ) = delete; + +private: + class Process* _process; // Owning process object + class ProcessCore& _core; // Core routines +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/ProcessModules.cpp b/third/Blackbone/src/BlackBone/Process/ProcessModules.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a4af2cd35e47741f053666e840a3dd0e2404bb30 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/ProcessModules.cpp @@ -0,0 +1,961 @@ +#include "../Config.h" +#include "ProcessModules.h" +#include "Process.h" +#include "RPC/RemoteExec.h" +#include "../Misc/NameResolve.h" +#include "../Misc/Utils.h" +#include "../Symbols/SymbolData.h" +#include "../Asm/AsmFactory.h" + +#include +#include + +#ifdef COMPILER_MSVC +#include +#include +#endif + +#include <3rd_party/VersionApi.h> + +namespace blackbone +{ +ProcessModules::ProcessModules( class Process& proc ) + : _proc( proc ) + , _memory( _proc.memory() ) + , _core( _proc.core() ) + , _ldrPatched( false ) +{ +} + +ProcessModules::~ProcessModules() +{ +} + +/// +/// Get module by name +/// +/// Module name +/// Module type. 32 bit or 64 bit +/// Saerch type. +/// Module data. nullptr if not found +ModuleDataPtr ProcessModules::GetModule( + const std::wstring& name, + eModSeachType search /*= LdrList*/, + eModType type /*= mt_default*/ + ) +{ + std::wstring namecopy( Utils::StripPath( name ) ); + return GetModule( namecopy, search, type ); +} + +/// +/// Get module by name +/// +/// Module name. +/// Search type. +/// Module type. 32 bit or 64 bit +/// Import module name. Used only to resolve ApiSchema during manual map +/// Module data. nullptr if not found +ModuleDataPtr ProcessModules::GetModule( + std::wstring& name, + eModSeachType search /*= LdrList*/, + eModType type /*= mt_default*/, + const wchar_t* baseModule /*= L""*/ + ) +{ + NameResolve::Instance().ResolvePath( name, Utils::StripPath( baseModule ), L"", NameResolve::ApiSchemaOnly, _proc ); + + // Detect module type + if (type == mt_default) + type = _proc.barrier().targetWow64 ? mt_mod32 : mt_mod64; + + CSLock lck( _modGuard ); + + auto key = std::make_pair( name, type ); + + // Fast lookup + if (_modules.count( key ) && (_modules[key]->manual || ValidateModule( _modules[key]->baseAddress ))) + return _modules[key]; + + UpdateModuleCache( search, type ); + + if (_modules.count( key )) + return _modules[key]; + + return nullptr; +} + +/// +/// Get module by base address +/// +/// Module base address +/// If true modBase must exactly match module base address +/// Search type. +/// Module type. 32 bit or 64 bit +/// Module data. nullptr if not found +ModuleDataPtr ProcessModules::GetModule( + module_t modBase, + bool strict /*= true*/, + eModSeachType search /*= LdrList*/, + eModType type /*= mt_default */ + ) +{ + // Detect module type + if (type == mt_default) + type = _proc.barrier().targetWow64 ? mt_mod32 : mt_mod64; + + CSLock lck( _modGuard ); + + auto compFn = [modBase, strict]( const mapModules::value_type& val ) + { + if (strict) + return (val.second->baseAddress == modBase); + else + return (modBase >= val.second->baseAddress && modBase < val.second->baseAddress + val.second->size); + }; + + auto iter = std::find_if( _modules.begin(), _modules.end(), compFn ); + + if (iter != _modules.end()) + return iter->second; + + UpdateModuleCache( search , type ); + + iter = std::find_if( _modules.begin(), _modules.end(), compFn ); + + if (iter != _modules.end()) + return iter->second; + else + return nullptr; +} + +/// +/// Get process main module +/// +/// Module data. nullptr if not found +ModuleDataPtr ProcessModules::GetMainModule() +{ + if (_proc.barrier().x86OS) + { + _PEB32 peb = { 0 }; + if (_proc.core().peb32( &peb ) == 0) + return nullptr; + + return GetModule( peb.ImageBaseAddress ); + } + else + { + _PEB64 peb = { 0 }; + if (_proc.core().peb64( &peb ) == 0) + return nullptr; + + return GetModule( peb.ImageBaseAddress ); + } +} + +/// +/// Enumerate all process modules +/// +/// Search method +/// Module list +const ProcessModules::mapModules& ProcessModules::GetAllModules( eModSeachType search /*= LdrList*/ ) +{ + eModType mt = _core.isWow64() ? mt_mod32 : mt_mod64; + CSLock lck( _modGuard ); + + // Remove non-manual modules + for (auto iter = _modules.begin(); iter != _modules.end();) + { + if (!iter->second->manual) + _modules.erase( iter++ ); + else + ++iter; + } + + UpdateModuleCache( search, mt ); + + // Do additional search in case of loader lists + // This, however won't search for 32 bit modules in native x64 process + if (search == LdrList && mt == mt_mod32) + UpdateModuleCache( search, mt_mod64 ); + + return _modules; +} + +/// +/// Get list of manually mapped modules +/// +/// List of modules +ProcessModules::mapModules ProcessModules::GetManualModules() +{ + ProcessModules::mapModules mods; + std::copy_if( + _modules.begin(), _modules.end(), + std::inserter( mods, mods.end() ), + []( const auto& mod ) { return mod.second->manual; } + ); + + return mods; +} + +/// +/// Get export address. Forwarded exports will be automatically resolved if forward module is present +/// +/// Module to search in +/// Function name or ordinal +/// Import module name. Only used to resolve ApiSchema during manual map. +/// Export info. If failed procAddress field is 0 +call_result_t ProcessModules::GetExport( const ModuleDataPtr& hMod, const char* name_ord, const wchar_t* baseModule /*= L""*/ ) +{ + return GetExport( *hMod, name_ord, baseModule ); +} + +/// +/// Get export address. Forwarded exports will be automatically resolved if forward module is present +/// +/// Module to search in +/// Function name or ordinal +/// Import module name. Only used to resolve ApiSchema during manual map. +/// Export info. If failed procAddress field is 0 +call_result_t ProcessModules::GetExport( const ModuleData& hMod, const char* name_ord, const wchar_t* baseModule /*= L"0"*/ ) +{ + exportData data; + + // Invalid module + if (hMod.baseAddress == 0) + return STATUS_INVALID_PARAMETER_1; + + std::unique_ptr expData( nullptr, &free ); + + IMAGE_DOS_HEADER hdrDos = { 0 }; + uint8_t hdrNt32[sizeof( IMAGE_NT_HEADERS64 )] = { 0 }; + auto phdrNt32 = reinterpret_cast(hdrNt32); + auto phdrNt64 = reinterpret_cast(hdrNt32); + DWORD expSize = 0; + uintptr_t expBase = 0; + + _memory.Read( hMod.baseAddress, sizeof( hdrDos ), &hdrDos ); + + if (hdrDos.e_magic != IMAGE_DOS_SIGNATURE) + return STATUS_INVALID_IMAGE_NOT_MZ; + + _memory.Read( hMod.baseAddress + hdrDos.e_lfanew, sizeof( IMAGE_NT_HEADERS64 ), &hdrNt32 ); + + if (phdrNt32->Signature != IMAGE_NT_SIGNATURE) + return STATUS_INVALID_IMAGE_FORMAT; + + if (phdrNt32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + expBase = phdrNt32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + else + expBase = phdrNt64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + + // Exports are present + if (expBase) + { + if (phdrNt32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + expSize = phdrNt32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; + else + expSize = phdrNt64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; + + expData.reset( reinterpret_cast(malloc( expSize )) ); + IMAGE_EXPORT_DIRECTORY* pExpData = expData.get(); + + if( auto status = _memory.Read( hMod.baseAddress + expBase, expSize, pExpData ); !NT_SUCCESS( status ) ) + return status; + + // Fix invalid directory size + if (expSize <= sizeof( IMAGE_EXPORT_DIRECTORY )) + { + // New size should take care of max number of present names (max name length is assumed to be 255 chars) + expSize = static_cast( + pExpData->AddressOfNameOrdinals - expBase + + max( pExpData->NumberOfFunctions, pExpData->NumberOfNames ) * 255 + ); + + expData.reset( reinterpret_cast(malloc( expSize )) ); + pExpData = expData.get(); + if (auto status = _memory.Read( hMod.baseAddress + expBase, expSize, pExpData ); !NT_SUCCESS( status )) + return status; + } + + WORD* pAddressOfOrds = reinterpret_cast( + pExpData->AddressOfNameOrdinals + reinterpret_cast(pExpData) - expBase); + + DWORD* pAddressOfNames = reinterpret_cast( + pExpData->AddressOfNames + reinterpret_cast(pExpData) - expBase); + + DWORD* pAddressOfFuncs = reinterpret_cast( + pExpData->AddressOfFunctions + reinterpret_cast(pExpData) - expBase); + + for (DWORD i = 0; i < pExpData->NumberOfFunctions; ++i) + { + WORD OrdIndex = 0xFFFF; + char *pName = nullptr; + + // Find by index + if (reinterpret_cast(name_ord) <= 0xFFFF) + { + OrdIndex = static_cast(i); + } + // Find by name + else if (reinterpret_cast(name_ord) > 0xFFFF && i < pExpData->NumberOfNames) + { + pName = (char*)(pAddressOfNames[i] + reinterpret_cast(pExpData) - expBase); + OrdIndex = static_cast(pAddressOfOrds[i]); + } + else + return STATUS_NOT_FOUND; + + if ((reinterpret_cast(name_ord) <= 0xFFFF && (WORD)((uintptr_t)name_ord) == (OrdIndex + pExpData->Base)) || + (reinterpret_cast(name_ord) > 0xFFFF && strcmp( pName, name_ord ) == 0)) + { + data.procAddress = pAddressOfFuncs[OrdIndex] + hMod.baseAddress; + + // Check forwarded export + if (data.procAddress >= hMod.baseAddress + expBase && + data.procAddress <= hMod.baseAddress + expBase + expSize) + { + char forwardStr[255] = { 0 }; + + _memory.Read( data.procAddress, sizeof( forwardStr ), forwardStr ); + + std::string chainExp( forwardStr ); + + std::string strDll = chainExp.substr( 0, chainExp.find( "." ) ) + ".dll"; + std::string strName = chainExp.substr( chainExp.find( "." ) + 1, strName.npos ); + std::wstring wDll( Utils::AnsiToWstring( strDll ) ); + + // Fill export data info + data.isForwarded = true; + data.forwardModule = wDll; + data.forwardByOrd = (strName.find( "#" ) == 0); + + if (data.forwardByOrd) + data.forwardOrdinal = static_cast(atoi( strName.c_str() + 1 )); + else + data.forwardName = strName; + + // Check if forward mod is loaded + auto mt = (phdrNt32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) ? mt_mod32 : mt_mod64; + auto hChainMod = GetModule( wDll, LdrList, mt, baseModule ); + if (hChainMod == nullptr) + return call_result_t( data, STATUS_SOME_NOT_MAPPED ); + + // Import by ordinal + if (data.forwardByOrd) + return GetExport( hChainMod, reinterpret_cast(data.forwardOrdinal), wDll.c_str() ); + // Import by name + else + return GetExport( hChainMod, strName.c_str(), wDll.c_str() ); + } + + return data; + } + } + } + + return STATUS_NOT_FOUND; +} + +/// +/// Get export address. Forwarded exports will be automatically resolved if forward module is present +/// +/// Module name to search in +/// Function name or ordinal +/// Export info. If failed procAddress field is 0 +call_result_t ProcessModules::GetExport( const std::wstring& modName, const char* name_ord ) +{ + return GetExport( GetModule( modName ), name_ord ); +} + +/// +/// Get export from ntdll +/// +/// Function name or ordinal +/// Module type. 32 bit or 64 bit +/// Search type. +/// Export info. If failed procAddress field is 0 +call_result_t ProcessModules::GetNtdllExport( + const char* name_ord, + eModType type /*= mt_default*/, + eModSeachType search /*= LdrList */ + ) +{ + auto mod = GetModule( L"ntdll.dll", search, type ); + if (!mod) + return STATUS_NOT_FOUND; + + return GetExport( mod, name_ord ); +} + +/// +/// Inject image into target process +/// +/// Full-qualified image path +/// Injection status code +/// Module info. nullptr if failed +call_result_t ProcessModules::Inject( const std::wstring& path, ThreadPtr pThread /*= nullptr*/ ) +{ + NTSTATUS status = STATUS_SUCCESS; + ModuleDataPtr mod; + pe::PEImage img; + uint32_t ustrSize = 0; + ptr_t res = 0; + + img.Load( path, true ); + img.Release(); + + // Already loaded + if (mod = GetModule( path, LdrList, img.mType() )) + return call_result_t( mod, STATUS_IMAGE_ALREADY_LOADED ); + + // Image path + auto modName = _memory.Allocate( 0x1000, PAGE_READWRITE ); + if (!modName) + return modName.status; + + // Write dll name into target process + auto fillDllName = [&modName, &path]( auto& ustr ) + { + ustr.Buffer = modName->ptr::type>() + sizeof( ustr ); + ustr.MaximumLength = ustr.Length = static_cast(path.size() * sizeof( wchar_t )); + + modName->Write( 0, ustr ); + modName->Write( sizeof( ustr ), path.size() * sizeof( wchar_t ), path.c_str() ); + + return static_cast(sizeof( ustr )); + }; + + if (img.mType() == mt_mod32) + { + _UNICODE_STRING32 ustr = { 0 }; + ustrSize = fillDllName( ustr ); + } + else if (img.mType() == mt_mod64) + { + _UNICODE_STRING64 ustr = { 0 }; + ustrSize = fillDllName( ustr ); + } + else + return STATUS_INVALID_IMAGE_FORMAT; + + // Image and process have same processor architecture + bool sameArch = (img.mType() == mt_mod64 && _core.isWow64() == false) || (img.mType() == mt_mod32 && _core.isWow64() == true); + auto pLoadLibrary = GetExport( GetModule( L"kernel32.dll", LdrList, img.mType() ), "LoadLibraryW" ); + + // Can't inject 32bit dll into native process + if (!_proc.core().isWow64() && img.mType() == mt_mod32) + return STATUS_INVALID_IMAGE_WIN_32; + + auto switchMode = NoSwitch; + if (_proc.core().isWow64() && img.mType() == mt_mod64) + switchMode = ForceSwitch; + + auto pLdrLoadDll = GetNtdllExport( "LdrLoadDll", img.mType(), Sections ); + if (!pLdrLoadDll) + return pLdrLoadDll.status; + + // Patch LdrFindOrMapDll to enable kernel32.dll loading + if (switchMode == ForceSwitch && !_ldrPatched && IsWindows7OrGreater() && !IsWindows8OrGreater()) + { + uint8_t patch[] = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }; + auto patchBase = g_symbols.LdrKernel32PatchAddress; + + if (patchBase != 0) + { + DWORD flOld = 0; + _memory.Protect( patchBase, sizeof( patch ), PAGE_EXECUTE_READWRITE, &flOld ); + _memory.Write( patchBase, sizeof( patch ), patch ); + _memory.Protect( patchBase, sizeof( patch ), flOld, nullptr ); + } + + _ldrPatched = true; + } + + auto a = AsmFactory::GetAssembler( img.mType() ); + + a->GenCall( pLdrLoadDll->procAddress, { 0, 0, modName->ptr(), modName->ptr() + 0x800 } ); + (*a)->ret(); + + _proc.remote().CreateRPCEnvironment( Worker_None, true ); + + // Execute call + if (pThread != nullptr) + { + if (pThread == _proc.remote().getWorker()) + status = _proc.remote().ExecInWorkerThread( (*a)->make(), (*a)->getCodeSize(), res ); + else + status = _proc.remote().ExecInAnyThread( (*a)->make(), (*a)->getCodeSize(), res, pThread ); + + if (NT_SUCCESS( status )) + status = static_cast(res); + } + else + { + status = _proc.remote().ExecInNewThread( (*a)->make(), (*a)->getCodeSize(), res, switchMode ); + if (NT_SUCCESS( status )) + status = static_cast(res); + } + + // Retry with LoadLibrary if possible + if (!NT_SUCCESS(status) && pLoadLibrary && sameArch) + { + auto result = _proc.remote().ExecDirect( pLoadLibrary->procAddress, modName->ptr() + ustrSize ); + if (result == 0) + { + return status; + } + } + + return GetModule( path, LdrList, img.mType() ); +} + +/// +/// Unload specific module from target process. Can't be used to unload manually mapped modules +/// +/// Module to unload +/// true on success +NTSTATUS ProcessModules::Unload( const ModuleDataPtr& hMod ) +{ + // Module not present or is manually mapped + if (hMod->manual || !ValidateModule( hMod->baseAddress )) + return STATUS_NOT_FOUND; + + // Unload routine + auto pUnload = GetNtdllExport( "LdrUnloadDll", hMod->type ); + if (!pUnload) + return pUnload.status; + + // Special case for unloading 64 bit modules from WOW64 process + auto threadSwitch = NoSwitch; + if (_proc.core().isWow64() && hMod->type == mt_mod64) + threadSwitch = ForceSwitch; + + uint64_t res = 0; + auto a = AsmFactory::GetAssembler( hMod->type ); + + a->GenCall( pUnload->procAddress, { hMod->baseAddress } ); + (*a)->ret(); + + _proc.remote().ExecInNewThread( (*a)->make(), (*a)->getCodeSize(), res, threadSwitch ); + + // Remove module from cache + _modules.erase( std::make_pair( hMod->name, hMod->type ) ); + return true; +} + +/// +/// Unlink module from most loader structures +/// +/// Module to unlink +/// true on success +bool ProcessModules::Unlink( const ModuleDataPtr& mod ) +{ + return _proc.nativeLdr().Unlink( *mod ); +} + +bool ProcessModules::Unlink( const ModuleData& mod ) +{ + return _proc.nativeLdr().Unlink( mod ); +} + +/// +/// Ensure module is a valid PE image +/// +/// Module base address +/// true on success +bool ProcessModules::ValidateModule( module_t base ) +{ + IMAGE_DOS_HEADER idh = { 0 }; + IMAGE_NT_HEADERS inth = { 0 }; + + // Validate memory and headers + if (_memory.Read( base, sizeof(idh), &idh ) == STATUS_SUCCESS) + if (idh.e_magic == IMAGE_DOS_SIGNATURE) + if(_memory.Read( base + idh.e_lfanew, sizeof(inth), &inth ) == STATUS_SUCCESS) + if (inth.Signature == IMAGE_NT_SIGNATURE) + return true; + + return false; +} + +/// +/// Store manually mapped module in module list +/// +/// Module data +/// Module info +ModuleDataPtr ProcessModules::AddManualModule( const ModuleData& mod ) +{ + auto canonicalized = Canonicalize( mod, true ); + auto key = std::make_pair( canonicalized.name, canonicalized.type ); + return _modules.emplace( key, std::make_shared( canonicalized ) ).first->second; +} + +/// +/// Canonicalize paths and set module type to manual if requested +/// +/// Module data +/// Value to set ModuleData::manual to +/// Module data +ModuleData ProcessModules::Canonicalize( const ModuleData& mod, bool manual ) +{ + ModuleData result = {}; + + result.baseAddress = mod.baseAddress; + result.ldrPtr = mod.ldrPtr; + result.size = mod.size; + result.type = mod.type; + result.fullPath = Utils::ToLower( mod.fullPath ); + result.name = Utils::ToLower( mod.name ); + result.manual = manual; + + return result; +} + +/// +/// Remove module from module list +/// +/// Module file name +/// Module type. 32 bit or 64 bit +void ProcessModules::RemoveManualModule( const std::wstring& filename, eModType mt ) +{ + auto key = std::make_pair( Utils::ToLower( Utils::StripPath( filename ) ), mt ); + if (_modules.count( key )) + _modules.erase( key ); +} + +void ProcessModules::UpdateModuleCache( eModSeachType search, eModType type ) +{ + for (const auto& mod : _core.native()->EnumModules( search, type )) + _modules.emplace( std::make_pair( mod->name, mod->type ), mod ); +} + + +using namespace asmjit; +using namespace asmjit::host; + +#ifdef COMPILER_MSVC + +/// +/// Inject pure IL image. +/// +/// NET runtime version to use +/// Path to image +/// Method to call +/// Arguments passed into method +/// Return code +/// true on success +bool ProcessModules::InjectPureIL( + const std::wstring& netVersion, + const std::wstring& netAssemblyPath, + const std::wstring& netAssemblyMethod, + const std::wstring& netAssemblyArgs, + DWORD& returnCode + ) +{ + // split netAssemblyMethod string into class and method names + size_t idx = netAssemblyMethod.find_last_of( '.' ); + if (idx == std::wstring::npos) + return false; + + std::wstring MethodName = netAssemblyMethod.substr( idx + 1 ); + std::wstring tmp = netAssemblyMethod; + tmp.erase( idx ); + std::wstring ClassName = tmp; + + auto mem = _memory.Allocate( 0x10000 ); + if (!mem) + { + returnCode = 7; + return false; + } + + auto address = std::move( mem.result() ); + uintptr_t offset = 4; + uintptr_t address_VersionString, address_netAssemblyDll, address_netAssemblyClass, + address_netAssemblyMethod, address_netAssemblyArgs; + + const std::wstring* strArr[] = { &netVersion, &netAssemblyPath, &ClassName, &MethodName, &netAssemblyArgs }; + + uintptr_t* ofstArr[] = { + &address_VersionString, &address_netAssemblyDll, &address_netAssemblyClass, + &address_netAssemblyMethod, &address_netAssemblyArgs + }; + + // Write strings + for (int i = 0; i < ARRAYSIZE( strArr ); i++) + { + size_t len = strArr[i]->length(); + + *(ofstArr[i]) = address.ptr() + offset; + + // runtime version to use + if (address.Write( offset, len * sizeof(wchar_t) + 2, strArr[i]->c_str( ) ) != STATUS_SUCCESS) + { + returnCode = 5; + return false; + } + + offset = Align( offset + len * sizeof( wchar_t ) + 2, sizeof( uint64_t ) ); + } + + offset += 4; + + GUID GArray[] = { CLSID_CLRMetaHost, IID_ICLRMetaHost, IID_ICLRRuntimeInfo, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost }; + + // COM object GUIDs + if (address.Write( offset, sizeof(GArray), GArray ) != STATUS_SUCCESS) + { + returnCode = 10; + return false; + } + + uintptr_t address_CLSID_CLRMetaHost = address.ptr() + offset + 0; + uintptr_t address_IID_ICLRMetaHost = address.ptr() + offset + 0x10; + uintptr_t address_IID_ICLRRuntimeInfo = address.ptr() + offset + 0x20; + uintptr_t address_CLSID_CLRRuntimeHost = address.ptr() + offset + 0x30; + uintptr_t address_IID_ICLRRuntimeHost = address.ptr() + offset + 0x40; + + offset += sizeof(GArray); + + std::wstring libName = L"mscoree.dll"; + + NameResolve::Instance().ResolvePath( libName, L"", L"", NameResolve::EnsureFullPath, _proc ); + + auto pMscoree = Inject( libName ); + if(!pMscoree) + { + returnCode = pMscoree.status; + return false; + } + + // CLRCreateInstance address + auto pfnCreateInstance = GetExport( pMscoree.result(), "CLRCreateInstance" ); + if (!pfnCreateInstance) + return false; + + // Scary assembler code incoming! + auto pAsm = AsmFactory::GetAssembler( _proc.core().isWow64() ); + auto& a = *pAsm; + AsmStackAllocator sa( a.assembler(), 0x30 ); // 0x30 - 6 arguments of ExecuteInDefaultAppDomain + + // Stack will be reserved manually + a.EnableX64CallStack( false ); + + Label L_Exit = a->newLabel(); + Label L_Error1 = a->newLabel(); + Label L_Error2 = a->newLabel(); + Label L_Error3 = a->newLabel(); + Label L_Error4 = a->newLabel(); + Label L_Error5 = a->newLabel(); + Label L_Error6 = a->newLabel(); + Label L_SkipStart = a->newLabel(); + Label L_ReleaseInterface = a->newLabel(); + + // stack variables for the injected code + ALLOC_STACK_VAR( sa, stack_MetaHost, ICLRMetaHost* ); + ALLOC_STACK_VAR( sa, stack_RuntimeInfo, ICLRRuntimeInfo* ); + ALLOC_STACK_VAR( sa, stack_RuntimeHost, ICLRRuntimeHost* ); + ALLOC_STACK_VAR( sa, stack_IsStarted, BOOL ); + ALLOC_STACK_VAR( sa, stack_StartupFlags, DWORD ); + ALLOC_STACK_VAR( sa, stack_returnCode, HRESULT ); + +#ifdef USE64 + GpReg callReg = r13; + +#else + GpReg callReg = edx; + + a->push( a->zbp ); + a->mov( a->zbp, a->zsp ); +#endif + + // function prologue + a->sub( a->zsp, Align( sa.getTotalSize(), 0x10 ) + 8 ); + a->xor_( a->zsi, a->zsi ); + + // CLRCreateInstance() + a.GenCall( (uintptr_t)pfnCreateInstance->procAddress, { address_CLSID_CLRMetaHost, address_IID_ICLRMetaHost, &stack_MetaHost } ); + // success? + a->test( a->zax, a->zax ); + a->jnz( L_Error1 ); + + // pMetaHost->GetRuntime() + a->mov( a->zax, stack_MetaHost ); + a->mov( a->zcx, a->intptr_ptr( a->zax ) ); + a->mov( callReg, a->intptr_ptr( a->zcx, 3 * sizeof( void* ) ) ); + a.GenCall( callReg, { a->zcx, address_VersionString, address_IID_ICLRRuntimeInfo, &stack_RuntimeInfo } ); + // success? + a->test( a->zax, a->zax ); + a->jnz( L_Error2 ); + + // pRuntimeInterface->IsStarted() + a->mov( a->zcx, stack_RuntimeInfo ); + a->mov( a->zax, a->intptr_ptr( a->zcx ) ); + a->mov( callReg, a->intptr_ptr( a->zax, 14 * sizeof( void* ) ) ); + a.GenCall( callReg, { a->zcx, &stack_IsStarted, &stack_StartupFlags } ); + // success? + a->test( a->zax, a->zax ); + a->jnz( L_Error3 ); + + // pRuntimeTime->GetInterface() + a->mov( a->zcx, stack_RuntimeInfo ); + a->mov( a->zax, a->intptr_ptr( a->zcx ) ); + a->mov( callReg, a->intptr_ptr( a->zax, 9 * sizeof( void* ) ) ); + a.GenCall( callReg, { a->zcx, address_CLSID_CLRRuntimeHost, address_IID_ICLRRuntimeHost, &stack_RuntimeHost } ); + // success? + a->test( a->zax, a->zax ); + a->jnz( L_Error3 ); + + // jump if already started + a->cmp( stack_IsStarted, a->zsi ); + a->jne( L_SkipStart ); + + // pRuntimeHost->Start() + a->mov( a->zcx, stack_RuntimeHost ); + a->mov( a->zax, a->intptr_ptr( a->zcx ) ); + a->mov( callReg, a->intptr_ptr( a->zax, 3 * sizeof( void* ) ) ); + a.GenCall( callReg, { a->zcx } ); + // success? + a->test( a->zax, a->zax ); + a->jnz( L_Error5 ); + + // pRuntimeHost->ExecuteInDefaultAppDomain() + a->bind( L_SkipStart ); + + a->mov( a->zcx, stack_RuntimeHost ); + a->mov( a->zax, a->intptr_ptr( a->zcx ) ); + a->mov( callReg, a->intptr_ptr( a->zax, 11 * sizeof( void* ) ) ); + a.GenCall( callReg, { a->zcx, address_netAssemblyDll, address_netAssemblyClass, address_netAssemblyMethod, + address_netAssemblyArgs, &stack_returnCode } ); + // success? + a->test( a->zax, a->zax ); + a->jnz( L_Error6 ); + + // Release unneeded interfaces + a->mov( a->zcx, stack_RuntimeHost ); + a->call( L_ReleaseInterface ); + a->mov( a->zcx, stack_RuntimeInfo ); + a->call( L_ReleaseInterface ); + a->mov( a->zcx, stack_MetaHost ); + a->call( L_ReleaseInterface ); + + // Write the managed code's return value to the first DWORD + // in the allocated buffer + a->mov( eax, stack_returnCode ); + a->mov( a->zdx, address.ptr() ); + a->mov( dword_ptr( a->zdx ), eax ); + a->mov( a->zax, 0 ); + + // stack restoration + a->bind( L_Exit ); + +#ifdef USE64 + a->add( a->zsp, Align( sa.getTotalSize(), 0x10 ) + 8 ); +#else + a->mov( a->zsp, a->zbp ); + a->pop( a->zbp ); +#endif + + a->ret(); + + // CLRCreateInstance() failed + a->bind( L_Error1 ); + a->mov( a->zax, 1 ); + a->jmp( L_Exit ); + + // pMetaHost->GetRuntime() failed + a->bind( L_Error2 ); + a->mov( a->zcx, stack_MetaHost ); + a->call( L_ReleaseInterface ); + a->mov( a->zax, 2 ); + a->jmp( L_Exit ); + + // pRuntimeInterface->IsStarted() failed + a->bind( L_Error3 ); + a->mov( a->zcx, stack_RuntimeInfo ); + a->call( L_ReleaseInterface ); + a->mov( a->zcx, stack_MetaHost ); + a->call( L_ReleaseInterface ); + a->mov( a->zax, 3 ); + a->jmp( L_Exit ); + + // pRuntimeTime->GetInterface() failed + a->bind( L_Error4 ); + a->mov( a->zcx, stack_RuntimeInfo ); + a->call( L_ReleaseInterface ); + a->mov( a->zcx, stack_MetaHost ); + a->call( L_ReleaseInterface ); + a->mov( a->zax, 4 ); + a->jmp( L_Exit ); + + // pRuntimeHost->Start() failed + a->bind( L_Error5 ); + a->mov( a->zcx, stack_RuntimeHost ); + a->call( L_ReleaseInterface ); + a->mov( a->zcx, stack_RuntimeInfo ); + a->call( L_ReleaseInterface ); + a->mov( a->zcx, stack_MetaHost ); + a->call( L_ReleaseInterface ); + a->mov( a->zax, 5 ); + a->jmp( L_Exit ); + + // pRuntimeHost->ExecuteInDefaultAppDomain() failed + a->bind( L_Error6 ); + a->push( a->zax ); + a->mov( a->zcx, stack_RuntimeHost ); + a->call( L_ReleaseInterface ); + a->mov( a->zcx, stack_RuntimeInfo ); + a->call( L_ReleaseInterface ); + a->mov( a->zcx, stack_MetaHost ); + a->call( L_ReleaseInterface ); + a->mov( a->zax, 6 ); + a->pop( a->zax ); + a->jmp( L_Exit ); + + // void __fastcall ReleaseInterface(IUnknown* pInterface) + a->bind( L_ReleaseInterface ); + a->mov( a->zax, a->zcx ); + a->mov( a->zcx, a->intptr_ptr( a->zax ) ); + a->mov( callReg, a->intptr_ptr( a->zcx, 2 * sizeof( void* ) ) ); + a.GenCall( callReg, { a->zax } ); + + a->ret(); + + // write JIT code to target + size_t codeSize = a->getCodeSize(); + ptr_t codeAddress = address.ptr() + offset; + + std::vector codeBuffer( codeSize ); + + a->setBaseAddress( codeAddress ); + a->relocCode( codeBuffer.data() ); + if (address.Write( offset, codeSize, codeBuffer.data() ) != STATUS_SUCCESS) + { + returnCode = 17; + return false; + } + + // run ze codez + _proc.remote().ExecDirect( (ptr_t)codeAddress, 0 ); + + // Get the managed return value + address.Read( 0, 4, &returnCode ); + + return true; +} + +#endif // COMPILER_MSVC + +/// +/// Reset local data +/// +void ProcessModules::reset() +{ + CSLock lck( _modGuard ); + + _modules.clear(); + _ldrPatched = false; +} + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/ProcessModules.h b/third/Blackbone/src/BlackBone/Process/ProcessModules.h new file mode 100644 index 0000000000000000000000000000000000000000..2d8e43ecc80fcee286b018db30b6961689ca35e6 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/ProcessModules.h @@ -0,0 +1,254 @@ +#pragma once + +#include "../Config.h" +#include "../Include/Winheaders.h" +#include "../Include/CallResult.h" +#include "../Include/Types.h" +#include "../PE/PEImage.h" +#include "../Misc/Utils.h" +#include "Threads/Thread.h" + +#include +#include +#include +#include + +namespace std +{ + template <> + struct hash < struct pair > + { + size_t operator()( const pair& value ) const + { + hash sh; + return sh( value.first ) ^ value.second; + } + }; +} + + +namespace blackbone +{ + +struct exportData +{ + ptr_t procAddress = 0; // Function address + + std::wstring forwardModule; // Name of forward module + std::string forwardName; // Forwarded function name + WORD forwardOrdinal = 0; // Forwarded function ordinal + + bool isForwarded = false; // Function is forwarded to another module + bool forwardByOrd = false; // Forward is done by ordinal +}; + +class ProcessModules +{ +public: + using mapModules = std::unordered_map, ModuleDataPtr> ; + +public: + BLACKBONE_API ProcessModules( class Process& proc ); + BLACKBONE_API ~ProcessModules(); + + /// + /// Get module by name + /// + /// Module name + /// Module type. 32 bit or 64 bit + /// Search type. + /// Module data. nullptr if not found + BLACKBONE_API ModuleDataPtr GetModule( + const std::wstring& name, + eModSeachType search = LdrList, + eModType type = mt_default + ); + + /// + /// Get module by name + /// + /// Module name. + /// Search type. + /// Module type. 32 bit or 64 bit + /// Import module name. Used only to resolve ApiSchema during manual map + /// Module data. nullptr if not found + BLACKBONE_API ModuleDataPtr GetModule( + std::wstring& name, + eModSeachType search = LdrList, + eModType type = mt_default, + const wchar_t* baseModule = L"" + ); + + /// + /// Get module by base address + /// + /// Module base address + /// If true modBase must exactly match module base address + /// Search type. + /// Module type. 32 bit or 64 bit + /// Module data. nullptr if not found + BLACKBONE_API ModuleDataPtr GetModule( + module_t modBase, + bool strict = true, + eModSeachType search = LdrList, + eModType type = mt_default + ); + + /// + /// Get process main module + /// + /// Module data. nullptr if not found + BLACKBONE_API ModuleDataPtr GetMainModule(); + + /// + /// Enumerate all process modules + /// + /// Search method + /// Module list + BLACKBONE_API const mapModules& GetAllModules( eModSeachType search = LdrList ); + + /// + /// Get list of manually mapped modules + /// + /// List of modules + BLACKBONE_API mapModules GetManualModules(); + + /// + /// Get export address. Forwarded exports will be automatically resolved if forward module is present + /// + /// Module to search in + /// Function name or ordinal + /// Import module name. Only used to resolve ApiSchema during manual map. + /// Export info. If failed procAddress field is 0 + BLACKBONE_API call_result_t GetExport( + const ModuleDataPtr& hMod, + const char* name_ord, + const wchar_t* baseModule = L"" + ); + + /// + /// Get export address. Forwarded exports will be automatically resolved if forward module is present + /// + /// Module to search in + /// Function name or ordinal + /// Import module name. Only used to resolve ApiSchema during manual map. + /// Export info. If failed procAddress field is 0 + BLACKBONE_API call_result_t GetExport( + const ModuleData& hMod, + const char* name_ord, + const wchar_t* baseModule = L"" + ); + + /// + /// Get export address. Forwarded exports will be automatically resolved if forward module is present + /// + /// Module name to search in + /// Function name or ordinal + /// Export info. If failed procAddress field is 0 + BLACKBONE_API call_result_t GetExport( const std::wstring& modName, const char* name_ord ); + + /// + /// Get export from ntdll + /// + /// Function name or ordinal + /// Module type. 32 bit or 64 bit + /// Search type. + /// Export info. If failed procAddress field is 0 + BLACKBONE_API call_result_t GetNtdllExport( + const char* name_ord, + eModType type = mt_default, + eModSeachType search = LdrList + ); + + /// + /// Inject image into target process + /// + /// Full-qualified image path + /// Module info. nullptr if failed + BLACKBONE_API call_result_t Inject( const std::wstring& path, ThreadPtr pThread = nullptr ); + +#ifdef COMPILER_MSVC + /// + /// Inject pure IL image. + /// + /// NET runtime version to use + /// Path to image + /// Method to call + /// Arguments passed into method + /// Return code + /// true on success + BLACKBONE_API bool InjectPureIL( + const std::wstring& netVersion, + const std::wstring& netAssemblyPath, + const std::wstring& netAssemblyMethod, + const std::wstring& netAssemblyArgs, + DWORD& returnCode + ); +#endif + + /// + /// Unload specific module from target process. Can't be used to unload manually mapped modules + /// + /// Module to unload + /// true on success + BLACKBONE_API NTSTATUS Unload( const ModuleDataPtr& hMod ); + + /// + /// Unlink module from most loader structures + /// + /// Module to unlink + /// true on success + BLACKBONE_API bool Unlink( const ModuleDataPtr& mod ); + BLACKBONE_API bool Unlink( const ModuleData& mod ); + + /// + /// Store manually mapped module in module list + /// + /// Module data + /// Module info + BLACKBONE_API ModuleDataPtr AddManualModule( const ModuleData& mod ); + + /// + /// Canonicalize paths and set module type to manual if requested + /// + /// Module data + /// Value to set ModuleData::manual to + /// Module data + BLACKBONE_API ModuleData Canonicalize( const ModuleData& mod, bool manual ); + + /// + /// Remove module from module list + /// + /// Module file name + /// Module type. 32 bit or 64 bit + BLACKBONE_API void RemoveManualModule( const std::wstring& filename, eModType mt ); + + /// + /// Ensure module is a valid PE image + /// + /// Module base address + /// true on success + BLACKBONE_API bool ValidateModule( module_t base ); + + /// + /// Reset local data + /// + BLACKBONE_API void reset(); + +private: + ProcessModules( const ProcessModules& ) = delete; + ProcessModules operator =(const ProcessModules&) = delete; + + void UpdateModuleCache( eModSeachType search, eModType type ); + +private: + class Process& _proc; + class ProcessMemory& _memory; + class ProcessCore& _core; + + mapModules _modules; // Fast lookup cache + CriticalSection _modGuard; // Module guard + bool _ldrPatched; // Win7 loader patch flag +}; + +}; diff --git a/third/Blackbone/src/BlackBone/Process/RPC/RemoteContext.hpp b/third/Blackbone/src/BlackBone/Process/RPC/RemoteContext.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e30f6c1a6c6d31c74b25f118de5fdcf9095584a6 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/RPC/RemoteContext.hpp @@ -0,0 +1,285 @@ +#pragma once + +#include "../ProcessCore.h" +#include "../ProcessMemory.h" +#include "../Threads/Thread.h" +#include "../../Include/Macro.h" + +namespace blackbone +{ + +/// +/// Remote function context during hook breakpoint. +/// +class RemoteContext +{ +public: + BLACKBONE_API RemoteContext( + ProcessMemory& memory, + Thread& thd, + _CONTEXT64& ctx, + ptr_t frame_ptr, + BOOL x64, + int wordSize + ) + : _memory( memory ) + , _thd( thd ) + , _ctx( ctx ) + , _x64Target( x64 ) + , _wordSize( wordSize ) + , _frame_ptr( frame_ptr != 0 ? frame_ptr : ctx.Rsp ) + { + } + + BLACKBONE_API ~RemoteContext() + { + } + + // Native context + BLACKBONE_API inline _CONTEXT64& native() + { + return _ctx; + } + + /// + /// Get current process thread where exception occurred + /// + /// Thread + BLACKBONE_API inline Thread& getThread() + { + return _thd; + } + + /// + /// + /// + /// Return address + BLACKBONE_API inline const ptr_t returnAddress() const + { + ptr_t val = 0; + _memory.Read( _frame_ptr, _wordSize, &val ); + + return val; + } + + /// + /// Set return address of current frame + /// + /// New return address + /// true on success + BLACKBONE_API inline bool returnAddress( ptr_t val ) const + { + return (_memory.Write( _frame_ptr, _wordSize, &val ) == STATUS_SUCCESS); + } + + /// + /// Set new integer return value. Has no effect on FPU. + /// Has effect only if called in return callback + /// + /// New return value + BLACKBONE_API inline void setReturnValue( ptr_t val ) const + { + memcpy( &_ctx.Rax, &val, _wordSize ); + } + + /// + /// Raise exception on function return + /// + /// Masked return address + BLACKBONE_API ptr_t hookReturn() + { + ptr_t val = returnAddress(); + SET_BIT( val, (_wordSize * 8 - 1) ); + if (returnAddress( val ) == false) + return 0; + + return val; + } + + /// + /// Remove exception on return + /// + /// Return address + BLACKBONE_API ptr_t unhookReturn() + { + auto val = returnAddress(); + RESET_BIT( val, (_wordSize * 8 - 1) ); + if (!returnAddress( val )) + return 0; + + return val; + } + + /// + /// Get argument value. + /// Argument index is 0 based. + /// For x86 function works only with stack arguments + /// For x64 only integer arguments can be retrieved + /// + /// 0-based argument index + /// Argument value + BLACKBONE_API DWORD64 getArg( int index ) + { + if(_x64Target) + { + switch (index) + { + case 0: + return _ctx.Rcx; + case 1: + return _ctx.Rdx; + case 2: + return _ctx.R8; + case 3: + return _ctx.R9; + + default: + return _memory.Read( _ctx.Rsp + 0x28 + (index - 4) * _wordSize ).result( 0 ); + } + } + else + { + DWORD64 val = 0; + _memory.Read( _ctx.Rsp + 4 + index * _wordSize, _wordSize, &val ); + return val; + } + } + + /// + /// Set argument value. + /// For x86 function works only with stack arguments. + /// For x64 only integer arguments can be set + /// + /// 0-based argument index + /// New argument value + /// true on success + BLACKBONE_API bool setArg( int index, DWORD64 val ) + { + if (_x64Target) + { + switch (index) + { + case 0: + _ctx.Rcx = val; + break; + case 1: + _ctx.Rdx = val; + break; + case 2: + _ctx.R8 = val; + break; + case 3: + _ctx.R9 = val; + break; + + default: + return (_memory.Write( _ctx.Rsp + 0x28 + (index - 4) * _wordSize, val ) == STATUS_SUCCESS); + } + + return true; + } + else + { + return (_memory.Write( _ctx.Rsp + 4 + index * _wordSize, _wordSize, &val ) == STATUS_SUCCESS); + } + } + + + /// + /// Get last thread error code + /// + /// Last error code, -1 if function failed + BLACKBONE_API DWORD lastError() + { + ptr_t pteb = 0; + LONG offset = 0; + + if( _x64Target ) + { + pteb = _thd.teb( (_TEB64*)nullptr ); + offset = FIELD_OFFSET( _TEB64, LastErrorValue ); + } + else + { + pteb = _thd.teb( (_TEB32*)nullptr ); + offset = FIELD_OFFSET( _TEB32, LastErrorValue ); + } + + if (pteb) + return _memory.Read( pteb + offset ).result( 0xFFFFFFFF ); + + return 0xFFFFFFFF; + } + + /// + /// Set last thread error code + /// + /// Last error code, -1 if function failed + BLACKBONE_API DWORD lastError( DWORD newError ) + { + ptr_t pteb = 0; + LONG offset = 0; + + if (_x64Target) + { + pteb = _thd.teb( (_TEB64*)nullptr ); + offset = FIELD_OFFSET( _TEB64, LastErrorValue ); + } + else + { + pteb = _thd.teb( (_TEB32*)nullptr ); + offset = FIELD_OFFSET( _TEB32, LastErrorValue ); + } + + if (!pteb) + return 0xFFFFFFFF; + + return _memory.Write( pteb + offset, newError ); + } + + + /// + /// Get arbitrary thread data + /// + /// Data value + BLACKBONE_API ptr_t getUserContext() + { + auto pteb = _thd.teb( (_TEB64*)nullptr ); + if (!pteb) + return 0; + + return _memory.Read( pteb + FIELD_OFFSET( _NT_TIB_T, ArbitraryUserPointer ) ).result( 0 ); + } + + /// + /// Set arbitrary thread data + /// + /// true on success + BLACKBONE_API bool setUserContext( ptr_t context ) + { + auto pteb = _thd.teb( (_TEB64*)nullptr ); + if(pteb) + { + if (_memory.Write( pteb + FIELD_OFFSET( _NT_TIB_T, ArbitraryUserPointer ), context ) == STATUS_SUCCESS) + return true; + } + + return false; + } + + +private: + RemoteContext( const RemoteContext& ) = delete; + RemoteContext& operator = ( const RemoteContext& ) = delete; + +private: + ProcessMemory& _memory; // Process memory routines + Thread& _thd; // Current thread + _CONTEXT64& _ctx; // Current thread context + + BOOL _x64Target = FALSE; // Target process is 64 bit + int _wordSize = 4; // 4 for x86, 8 for x64 + ptr_t _frame_ptr = 0; // Top stack frame pointer +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/RPC/RemoteExec.cpp b/third/Blackbone/src/BlackBone/Process/RPC/RemoteExec.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a36b44e69dfa8165f328954e5401e01477d7e49 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/RPC/RemoteExec.cpp @@ -0,0 +1,685 @@ +#include "RemoteExec.h" +#include "../Process.h" +#include "../../Misc/DynImport.h" +#include "../../Symbols/SymbolData.h" + +#include <3rd_party/VersionApi.h> +#include +#include +#include + +namespace blackbone +{ + +RemoteExec::RemoteExec( Process& proc ) + : _process( proc ) + , _mods( _process.modules() ) + , _memory( _process.memory() ) + , _threads( _process.threads() ) + , _hWaitEvent( NULL ) + , _apcPatched( false ) +{ +} + +RemoteExec::~RemoteExec() +{ + TerminateWorker(); +} + +/// +/// Create new thread and execute code in it. Wait until execution ends +/// +/// Code to execute +/// Code size +/// Code return value +/// Switch wow64 thread to long mode upon creation +/// Status +NTSTATUS RemoteExec::ExecInNewThread( + PVOID pCode, size_t size, + uint64_t& callResult, + eThreadModeSwitch modeSwitch /*= AutoSwitch*/ + ) +{ + NTSTATUS status = STATUS_SUCCESS; + + // Write code + if (!NT_SUCCESS( status = CopyCode( pCode, size ) )) + return status; + + bool switchMode = false; + switch (modeSwitch) + { + case blackbone::ForceSwitch: + switchMode = true; + break; + + case blackbone::AutoSwitch: + switchMode = _process.barrier().type == wow_64_32; + break; + } + + auto a = switchMode ? AsmFactory::GetAssembler( AsmFactory::asm64 ) + : AsmFactory::GetAssembler( _process.core().isWow64() ); + + a->GenPrologue( switchMode ); + + // Prepare thread to run in x64 mode + if(switchMode) + { + // Allocate new x64 activation stack + auto createActStack = _mods.GetNtdllExport( "RtlAllocateActivationContextStack", mt_mod64 ); + if (createActStack) + { + a->GenCall( createActStack->procAddress, { _userData.ptr() + 0x3100 } ); + + (*a)->mov( (*a)->zax, _userData.ptr() + 0x3100 ); + (*a)->mov( (*a)->zax, (*a)->intptr_ptr( (*a)->zax ) ); + + (*a)->mov( (*a)->zdx, asmjit::host::dword_ptr_abs( 0x30 ).setSegment( asmjit::host::gs ) ); + (*a)->mov( (*a)->intptr_ptr( (*a)->zdx, 0x2C8 ), (*a)->zax ); + } + } + + a->GenCall( _userCode.ptr(), { } ); + (*a)->mov( (*a)->zdx, _userData.ptr() + INTRET_OFFSET ); + (*a)->mov( asmjit::host::dword_ptr( (*a)->zdx ), (*a)->zax ); + a->GenEpilogue( switchMode, 4 ); + + // Execute code in newly created thread + if (!NT_SUCCESS( status = _userCode.Write( size, (*a)->getCodeSize(), (*a)->make() ) )) + return status; + + auto thread = _threads.CreateNew( _userCode.ptr() + size, _userData.ptr()/*, HideFromDebug*/ ); + if (!thread) + return thread.status; + if (!(*thread)->Join()) + return LastNtStatus(); + + callResult = _userData.Read( INTRET_OFFSET, 0 ); + return STATUS_SUCCESS; +} + +/// +/// Execute code in context of our worker thread +/// +/// Cde to execute +/// Code size. +/// Execution result +/// Status +NTSTATUS RemoteExec::ExecInWorkerThread( PVOID pCode, size_t size, uint64_t& callResult ) +{ + NTSTATUS status = STATUS_SUCCESS; + + // Delegate to another thread + if (_hijackThread) + return ExecInAnyThread( pCode, size, callResult, _hijackThread ); + + assert( _workerThread ); + assert( _hWaitEvent != NULL ); + if (!_workerThread || !_hWaitEvent) + return STATUS_INVALID_PARAMETER; + + // Write code + if (!NT_SUCCESS( status = CopyCode( pCode, size ) )) + return status; + + if (_hWaitEvent) + ResetEvent( _hWaitEvent ); + + // Patch KiUserApcDispatcher + /*if (!_apcPatched && IsWindows7OrGreater() && !IsWindows8OrGreater()) + { + if (_proc.barrier().type == wow_64_32) + { + auto patchBase = g_PatternLoader->data().APC64PatchAddress; + + if (patchBase != 0) + { + DWORD flOld = 0; + _memory.Protect(patchBase, 6, PAGE_EXECUTE_READWRITE, &flOld); + _memory.Write(patchBase + 0x2, (uint8_t)0x0C); + _memory.Write( patchBase + 0x4, (uint8_t)0x90 ); + _memory.Protect( patchBase, 6, flOld, nullptr ); + } + + _apcPatched = true; + } + else + _apcPatched = true; + }*/ + + auto pRemoteCode = _userCode.ptr(); + + // Execute code in thread context + // TODO: Find out why am I passing pRemoteCode as an argument??? + if (NT_SUCCESS( _process.core().native()->QueueApcT( _workerThread->handle(), pRemoteCode, pRemoteCode ) )) + { + status = WaitForSingleObject( _hWaitEvent, 30 * 1000 /*wait 30s*/ ); + callResult = _userData.Read( RET_OFFSET, 0 ); + } + else + return LastNtStatus(); + + // Ensure APC function fully returns + Sleep( 1 ); + + return status; +} + +/// +/// Execute code in context of any existing thread +/// +/// Cde to execute +/// Code size. +/// Execution result +/// Target thread +/// Status +NTSTATUS RemoteExec::ExecInAnyThread( PVOID pCode, size_t size, uint64_t& callResult, ThreadPtr& thd ) +{ + NTSTATUS status = STATUS_SUCCESS; + _CONTEXT32 ctx32 = { 0 }; + _CONTEXT64 ctx64 = { 0 }; + + assert( _hWaitEvent != NULL ); + if (_hWaitEvent == NULL) + return STATUS_NOT_FOUND; + + // Write code + if (!NT_SUCCESS( status = CopyCode( pCode, size ) )) + return status; + + if (_hWaitEvent) + ResetEvent( _hWaitEvent ); + + if (!thd->Suspend()) + return LastNtStatus(); + + auto a = AsmFactory::GetAssembler( _process.core().isWow64() ); + if (!_process.core().isWow64()) + { + const int count = 15; + static const asmjit::GpReg regs[] = + { + asmjit::host::rax, asmjit::host::rbx, asmjit::host::rcx, asmjit::host::rdx, asmjit::host::rsi, + asmjit::host::rdi, asmjit::host::r8, asmjit::host::r9, asmjit::host::r10, asmjit::host::r11, + asmjit::host::r12, asmjit::host::r13, asmjit::host::r14, asmjit::host::r15, asmjit::host::rbp + }; + + if (!NT_SUCCESS( status = thd->GetContext( ctx64, CONTEXT64_CONTROL, true ) )) + { + thd->Resume(); + return status; + } + + // + // Preserve thread context + // I don't care about FPU, XMM and anything else + // Stack must be aligned on 16 bytes + // + (*a)->sub( asmjit::host::rsp, count * sizeof( uint64_t ) ); + (*a)->pushf(); + + // Save registers + for (int i = 0; i < count; i++) + (*a)->mov( asmjit::Mem( asmjit::host::rsp, i * sizeof( uint64_t ) ), regs[i] ); + + a->GenCall( _userCode.ptr(), { _userData.ptr() } ); + AddReturnWithEvent( *a ); + + // Restore registers + for (int i = 0; i < count; i++) + (*a)->mov( regs[i], asmjit::Mem( asmjit::host::rsp, i * sizeof( uint64_t ) ) ); + + (*a)->popf(); + (*a)->add( asmjit::host::rsp, count * sizeof( uint64_t ) ); + + // jmp [rip] + (*a)->dw( '\xFF\x25' ); + (*a)->dd( 0 ); + (*a)->dq( ctx64.Rip ); + } + else + { + if (!NT_SUCCESS( status = thd->GetContext( ctx32, CONTEXT_CONTROL, true ) )) + { + thd->Resume(); + return status; + } + + (*a)->pusha(); + (*a)->pushf(); + + a->GenCall( _userCode.ptr(), { _userData.ptr() } ); + (*a)->add( asmjit::host::esp, sizeof( uint32_t ) ); + AddReturnWithEvent( *a, mt_mod32, rt_int32, INTRET_OFFSET ); + + (*a)->popf(); + (*a)->popa(); + + (*a)->push( static_cast(ctx32.Eip) ); + (*a)->ret(); + } + + if (NT_SUCCESS( status = _userCode.Write( size, (*a)->getCodeSize(), (*a)->make() ) )) + { + if (_process.core().isWow64()) + { + ctx32.Eip = static_cast(_userCode.ptr() + size); + status = thd->SetContext( ctx32, true ); + } + else + { + ctx64.Rip = _userCode.ptr() + size; + status = thd->SetContext( ctx64, true ); + } + } + + thd->Resume(); + if (NT_SUCCESS( status )) + { + WaitForSingleObject( _hWaitEvent, 20 * 1000/*INFINITE*/ ); + status = _userData.Read( RET_OFFSET, callResult ); + } + + return status; +} + + +/// +/// Create new thread with specified entry point and argument +/// +/// Entry point +/// Thread function argument +/// Thread exit code +DWORD RemoteExec::ExecDirect( ptr_t pCode, ptr_t arg ) +{ + auto thread = _threads.CreateNew( pCode, arg/*, HideFromDebug*/ ); + if (!thread) + return thread.status; + + (*thread)->Join(); + return (*thread)->ExitCode(); +} + +/// +/// Create environment for future remote procedure calls +/// +/// _userData layout (x86/x64): +/// -------------------------------------------------------------------------------------------------------------------------- +/// | Internal return value | Return value | Last Status code | Event handle | Space for copied arguments and strings | +/// ------------------------------------------------------------------------------------------------------------------------- +/// | 8/8 bytes | 8/8 bytes | 8/8 bytes | 8/8 bytes | | +/// -------------------------------------------------------------------------------------------------------------------------- +/// +/// Worket thread mode +/// Create sync event for worker thread +/// Status +NTSTATUS RemoteExec::CreateRPCEnvironment( WorkerThreadMode mode /*= Worker_None*/, bool bEvent /*= false*/ ) +{ + DWORD thdID = GetTickCount(); // randomize thread id + NTSTATUS status = STATUS_SUCCESS; + + auto allocMem = [this]( auto& result, uint32_t size = 0x1000, DWORD prot = PAGE_EXECUTE_READWRITE ) -> NTSTATUS + { + if (!result.valid()) + { + auto mem = _memory.Allocate( size, prot ); + if (!mem) + return mem.status; + + result = std::move( *mem ); + } + + return STATUS_SUCCESS; + }; + + // + // Allocate environment codecave + // + if (!NT_SUCCESS( status = allocMem( _workerCode ) )) + return status; + if (!NT_SUCCESS( status = allocMem( _userCode ) )) + return status; + if (!NT_SUCCESS( status = allocMem( _userData, 0x4000, PAGE_READWRITE ) )) + return status; + + // Create RPC thread + if (mode == Worker_CreateNew) + { + auto thd = CreateWorkerThread(); + if (!thd) + return thd.status; + + thdID = thd.result(); + } + // Get thread to hijack + else if (mode == Worker_UseExisting) + { + _hijackThread = _process.threads().getMostExecuted(); + if (!_hijackThread) + return STATUS_INVALID_THREAD; + + thdID = _hijackThread->id(); + } + + // Create RPC sync event + if (bEvent) + status = CreateAPCEvent( thdID ); + + return status; +} + +/// +/// Create worker RPC thread +/// +/// Thread ID +call_result_t RemoteExec::CreateWorkerThread() +{ + auto a = AsmFactory::GetAssembler( _process.core().isWow64() ); + asmjit::Label l_loop = (*a)->newLabel(); + + // + // Create execution thread + // + if(!_workerThread || !_workerThread->valid()) + { + /*if (_proc.barrier().type == wow_64_32) + { + a->SwitchTo64(); + + // Align stack on 16 byte boundary + (*a)->and_( (*a)->zsp, -16 ); + + // Allocate new x64 activation stack + auto createActStack = _mods.GetNtdllExport( "RtlAllocateActivationContextStack", mt_mod64 ); + if(createActStack) + { + a->GenCall( createActStack->procAddress, { _userData.ptr() + 0x3000 } ); + (*a)->mov( (*a)->zax, _userData.ptr() + 0x3000 ); + (*a)->mov( (*a)->zax, (*a)->intptr_ptr( (*a)->zax ) ); + + (*a)->mov( (*a)->zdx, asmjit::host::dword_ptr_abs( 0x18 ).setSegment( asmjit::host::fs ) ); + (*a)->mov( (*a)->intptr_ptr( (*a)->zdx, 0x2c8 ), (*a)->zax ); + } + }*/ + + auto ntdll = _mods.GetModule( L"ntdll.dll", Sections ); + auto proc = _mods.GetExport( ntdll, "NtDelayExecution" ); + auto pExitThread = _mods.GetExport( ntdll, "NtTerminateThread" ); + if (!proc || !pExitThread) + return proc.status ? proc.status : pExitThread.status; + + /* + for(;;) + SleepEx(5, TRUE); + + ExitThread(SetEvent(m_hWaitEvent)); + */ + (*a)->bind( l_loop ); + a->GenCall( proc->procAddress, { TRUE, _workerCode.ptr() } ); + (*a)->jmp( l_loop ); + + a->ExitThreadWithStatus( pExitThread->procAddress, _userData.ptr() ); + + // Write code into process + LARGE_INTEGER liDelay = { { 0 } }; + liDelay.QuadPart = -10 * 1000 * 5; + + _workerCode.Write( 0, liDelay ); + _workerCode.Write( sizeof(LARGE_INTEGER), (*a)->getCodeSize(), (*a)->make() ); + + auto thd = _threads.CreateNew( _workerCode.ptr() + sizeof( LARGE_INTEGER ), _userData.ptr()/*, HideFromDebug*/ ); + if (!thd) + return thd.status; + + _workerThread = std::move( thd.result() ); + } + + return _workerThread->id(); +} + + +/// +/// Create event to synchronize APC procedures +/// +/// The thread identifier. +/// Status code +NTSTATUS RemoteExec::CreateAPCEvent( DWORD threadID ) +{ + if (_hWaitEvent) + return STATUS_SUCCESS; + + auto a = AsmFactory::GetAssembler( _process.core().isWow64() ); + + wchar_t pEventName[128] = { }; + size_t len = sizeof( pEventName ); + OBJECT_ATTRIBUTES obAttr = { }; + UNICODE_STRING ustr = { }; + + // Event name + swprintf_s( pEventName, ARRAYSIZE( pEventName ), L"\\BaseNamedObjects\\_MMapEvent_0x%x_0x%x", threadID, GetTickCount() ); + + wchar_t* szStringSecurityDis = L"S:(ML;;NW;;;LW)D:(A;;GA;;;S-1-15-2-1)(A;;GA;;;WD)"; + PSECURITY_DESCRIPTOR pDescriptor = nullptr; + ConvertStringSecurityDescriptorToSecurityDescriptorW( szStringSecurityDis, SDDL_REVISION_1, &pDescriptor, NULL ); + auto guard = std::unique_ptr( pDescriptor, &LocalFree ); + + // Prepare Arguments + ustr.Length = static_cast(wcslen( pEventName ) * sizeof(wchar_t)); + ustr.MaximumLength = static_cast(len); + ustr.Buffer = pEventName; + + obAttr.ObjectName = &ustr; + obAttr.Length = sizeof(obAttr); + obAttr.SecurityDescriptor = pDescriptor; + + auto pOpenEvent = _mods.GetNtdllExport( "NtOpenEvent", mt_default, Sections ); + if (!pOpenEvent) + return pOpenEvent.status; + + auto status = SAFE_NATIVE_CALL( NtCreateEvent, &_hWaitEvent, EVENT_ALL_ACCESS, &obAttr, 0, static_cast(FALSE) ); + if (!NT_SUCCESS( status )) + return status; + + HANDLE hRemoteHandle = nullptr; + if (!DuplicateHandle( GetCurrentProcess(), _hWaitEvent, _process.core().handle(), &hRemoteHandle, 0, FALSE, DUPLICATE_SAME_ACCESS )) + return LastNtStatus(); + + return _userData.Write( EVENT_OFFSET, sizeof( int32_t ), &hRemoteHandle ); +} + +/// +/// Generate assembly code for remote call. +/// +/// Underlying assembler object +/// Remote function pointer +/// Function arguments +/// Calling convention +/// Return type +/// Status code +NTSTATUS RemoteExec::PrepareCallAssembly( + IAsmHelper& a, + ptr_t pfn, + std::vector& args, + eCalligConvention cc, + eReturnType retType + ) +{ + uintptr_t data_offset = ARGS_OFFSET; + + // Invalid calling convention + if (cc < cc_cdecl || cc > cc_fastcall) + return STATUS_INVALID_PARAMETER_3; + + // Copy structures and strings + for (auto& arg : args) + { + // Transform 64 bit imm values + if (arg.type == AsmVariant::imm && arg.size > sizeof( uint32_t ) && a.assembler()->getArch() == asmjit::kArchX86) + { + arg.type = AsmVariant::dataStruct; + arg.buf.resize( arg.size ); + memcpy( arg.buf.data(), &arg.imm_val64, arg.size ); + arg.imm_val64 = reinterpret_cast(arg.buf.data()); + } + + if (arg.type == AsmVariant::dataStruct || arg.type == AsmVariant::dataPtr) + { + _userData.Write( data_offset, arg.size, reinterpret_cast(arg.imm_val) ); + arg.new_imm_val = _userData.ptr() + data_offset; + + // Add some padding after data + data_offset += arg.size + 0x10; + } + } + + // Insert hidden variable if return type is struct. + // This variable contains address of buffer in which return value is copied + if (retType == rt_struct) + { + args.emplace( args.begin(), AsmVariant( _userData.ptr() + ARGS_OFFSET ) ); + args.front().new_imm_val = args.front().imm_val; + args.front().type = AsmVariant::structRet; + } + + a.GenPrologue(); + a.GenCall( pfn, args, cc ); + + // Retrieve result from XMM0 or ST0 + if (retType == rt_float || retType == rt_double) + { + a->mov( a->zax, _userData.ptr() + RET_OFFSET ); + +#ifdef USE64 + if (retType == rt_double) + a->movsd( asmjit::Mem( a->zax, 0 ), asmjit::host::xmm0 ); + else + a->movss( asmjit::Mem( a->zax, 0 ), asmjit::host::xmm0 ); +#else + a->fstp( asmjit::Mem( a->zax, 0, retType * sizeof( float ) ) ); +#endif + } + + AddReturnWithEvent( a, mt_default, retType ); + a.GenEpilogue(); + + return STATUS_SUCCESS; +} + +/// +/// Copy executable code into remote codecave for future execution +/// +/// Code to copy +/// Code size +/// Status +NTSTATUS RemoteExec::CopyCode( PVOID pCode, size_t size ) +{ + if (!_userCode.valid()) + { + auto mem = _memory.Allocate( size ); + if (!mem) + return mem.status; + + _userCode = std::move( mem.result() ); + } + + // Reallocate for larger code + if (size > _userCode.size()) + { + auto res = _userCode.Realloc( size ); + if (!res) + return res.status; + } + + return _userCode.Write( 0, size, pCode ); +} + +/// +/// Generate return from function with event synchronization +/// +/// Target assembly helper +/// 32/64bit loader +/// Function return type +/// Return value offset +void RemoteExec::AddReturnWithEvent( + IAsmHelper& a, + eModType mt /*= mt_default*/, + eReturnType retType /*= rt_int32 */, + uint32_t retOffset /*= RET_OFFSET*/ + ) +{ + // Allocate block if missing + if (!_userData.valid()) + { + auto mem = _memory.Allocate( 0x4000, PAGE_READWRITE ); + if (!mem) + return; + + _userData = std::move( mem.result() ); + } + + ptr_t ptr = _userData.ptr(); + auto pSetEvent = _process.modules().GetNtdllExport( "NtSetEvent", mt ); + if(pSetEvent) + a.SaveRetValAndSignalEvent( pSetEvent->procAddress, ptr + retOffset, ptr + EVENT_OFFSET, ptr + ERR_OFFSET, retType ); +} + +/// +/// Terminate existing worker thread +/// +void RemoteExec::TerminateWorker() +{ + // Close remote event handle + ptr_t hRemoteEvent = 0; + _userData.Read( EVENT_OFFSET, hRemoteEvent ); + if (hRemoteEvent) + { + HANDLE hLocal = nullptr; + DuplicateHandle( + _process.core().handle(), + reinterpret_cast(hRemoteEvent), + GetCurrentProcess(), + &hLocal, + 0, false, + DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS + ); + + if (hLocal) + CloseHandle( hLocal ); + + _userData.Write( EVENT_OFFSET, 0ll ); + } + + // Close event + if(_hWaitEvent) + { + CloseHandle( _hWaitEvent ); + _hWaitEvent = NULL; + } + + // Stop thread + if(_workerThread && _workerThread->valid()) + { + _workerThread->Terminate(); + _workerThread->Join(); + _workerThread->Close(); + _workerThread.reset(); + _workerCode.Free(); + } +} + +/// +/// Reset instance +/// +void RemoteExec::reset() +{ + TerminateWorker(); + + _userCode.Reset(); + _userData.Reset(); + _workerCode.Reset(); + + _apcPatched = false; +} + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/RPC/RemoteExec.h b/third/Blackbone/src/BlackBone/Process/RPC/RemoteExec.h new file mode 100644 index 0000000000000000000000000000000000000000..082e03f3b31321c9a5cdedeb93579ed9ce6afab2 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/RPC/RemoteExec.h @@ -0,0 +1,230 @@ +#pragma once + +#include "../../Include/Winheaders.h" +#include "../../Asm/AsmFactory.h" +#include "../Threads/Threads.h" +#include "../MemBlock.h" + +// User data offsets +#define INTRET_OFFSET 0x00 +#define RET_OFFSET 0x08 +#define ERR_OFFSET 0x10 +#define EVENT_OFFSET 0x18 +#define ARGS_OFFSET 0x20 + + +namespace blackbone +{ + +enum WorkerThreadMode +{ + Worker_None, // No worker thread + Worker_CreateNew, // Create dedicated worker thread + Worker_UseExisting, // Hijack existing thread +}; + +class RemoteExec +{ + using vecArgs = std::vector; + +public: + BLACKBONE_API RemoteExec( class Process& proc ); + BLACKBONE_API ~RemoteExec(); + + /// + /// Create environment for future remote procedure calls + /// + /// _userData layout (x86/x64): + /// -------------------------------------------------------------------------------------------------------------------------- + /// | Internal return value | Return value | Last Status code | Event handle | Space for copied arguments and strings | + /// ------------------------------------------------------------------------------------------------------------------------- + /// | 8/8 bytes | 8/8 bytes | 8/8 bytes | 8/8 bytes | | + /// -------------------------------------------------------------------------------------------------------------------------- + /// + /// Worket thread mode + /// Create sync event for worker thread + /// Status + BLACKBONE_API NTSTATUS CreateRPCEnvironment( WorkerThreadMode mode = Worker_None, bool bEvent = false ); + + /// + /// Create new thread and execute code in it. Wait until execution ends + /// + /// Code to execute + /// Code size + /// Code return value + /// Switch wow64 thread to long mode upon creation + /// Status + BLACKBONE_API NTSTATUS ExecInNewThread( + PVOID pCode, size_t size, + uint64_t& callResult, + eThreadModeSwitch modeSwitch = AutoSwitch + ); + + /// + /// Execute code in context of our worker thread + /// + /// Cde to execute + /// Code size. + /// Execution result + /// Status + BLACKBONE_API NTSTATUS ExecInWorkerThread( PVOID pCode, size_t size, uint64_t& callResult ); + + /// + /// Execute code in context of any existing thread + /// + /// Cde to execute + /// Code size. + /// Execution result + /// Target thread + /// Status + BLACKBONE_API NTSTATUS ExecInAnyThread( PVOID pCode, size_t size, uint64_t& callResult, ThreadPtr& thread ); + + /// + /// Create new thread with specified entry point and argument + /// + /// Entry point + /// Thread function argument + /// Thread exit code + BLACKBONE_API DWORD ExecDirect( ptr_t pCode, ptr_t arg ); + + /// + /// Generate assembly code for remote call. + /// + /// Underlying assembler object + /// Remote function pointer + /// Function arguments + /// Calling convention + /// Return type + /// Status code + BLACKBONE_API NTSTATUS PrepareCallAssembly( + IAsmHelper& a, + ptr_t pfn, + std::vector& args, + eCalligConvention cc, + eReturnType retType + ); + + /// + /// Generate return from function with event synchronization + /// + /// Target assembly helper + /// 32/64bit loader + /// Function return type + /// Return value offset + BLACKBONE_API void AddReturnWithEvent( + IAsmHelper& a, + eModType mt = mt_default, + eReturnType retType = rt_int32, + uint32_t retOffset = RET_OFFSET + ); + + /// + /// Save value in rax to user buffer + /// + /// Target assembly helper + BLACKBONE_API void SaveCallResult( IAsmHelper& a, uint32_t retOffset = RET_OFFSET ) + { + a->mov( a->zdx, _userData.ptr() + retOffset ); + a->mov( asmjit::host::dword_ptr( a->zdx ), a->zax ); + } + + /// + /// Retrieve call result + /// + /// Retrieved result + /// true on success + template + NTSTATUS GetCallResult( T& result ) + { + if constexpr (sizeof( T ) > sizeof( uint64_t )) + { + if constexpr (std::is_reference_v) + return _userData.Read( _userData.Read( RET_OFFSET, 0 ), sizeof( T ), reinterpret_cast(&result) ); + else + return _userData.Read( ARGS_OFFSET, sizeof( T ), reinterpret_cast(&result) ); + } + else + return _userData.Read( RET_OFFSET, sizeof( T ), reinterpret_cast(&result) ); + } + + /// + /// Retrieve last NTSTATUS code + /// + /// + BLACKBONE_API NTSTATUS GetLastStatus() + { + return _userData.Read( ERR_OFFSET, STATUS_NOT_FOUND ); + } + + /// + /// Terminate existing worker thread + /// + BLACKBONE_API void TerminateWorker(); + + /// + /// Get worker thread + /// + /// + BLACKBONE_API ThreadPtr getWorker() { return _workerThread; } + + /// + /// Get execution thread + /// + /// + BLACKBONE_API ThreadPtr getExecThread() { return _hijackThread ? _hijackThread : _workerThread; } + + /// + /// Ge memory routines + /// + /// + BLACKBONE_API class ProcessMemory& memory() { return _memory; } + + /// + /// Reset instance + /// + BLACKBONE_API void reset(); + +private: + + /// + /// Create worker RPC thread + /// + /// Thread ID + call_result_t CreateWorkerThread(); + + /// + /// Create event to synchronize APC procedures + /// + /// The thread identifier. + /// Status code + NTSTATUS CreateAPCEvent( DWORD threadID ); + + /// + /// Copy executable code into remote codecave for future execution + /// + /// Code to copy + /// Code size + /// Status + NTSTATUS CopyCode( PVOID pCode, size_t size ); + + RemoteExec( const RemoteExec& ) = delete; + RemoteExec& operator =(const RemoteExec&) = delete; + +private: + // Process routines + class Process& _process; + class ProcessModules& _mods; + class ProcessMemory& _memory; + class ProcessThreads& _threads; + + ThreadPtr _workerThread; // Worker thread handle + ThreadPtr _hijackThread; // Thread to use for hijacking + HANDLE _hWaitEvent; // APC sync event handle + MemBlock _workerCode; // Worker thread address space + MemBlock _userCode; // Codecave for code execution + MemBlock _userData; // Region to store copied structures and strings + bool _apcPatched; // KiUserApcDispatcher was patched +}; + + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/RPC/RemoteFunction.hpp b/third/Blackbone/src/BlackBone/Process/RPC/RemoteFunction.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6ed8ca7f24122c56c6e837b4fbb6da31c9f7162c --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/RPC/RemoteFunction.hpp @@ -0,0 +1,261 @@ +#pragma once + +#include "../../Include/CallResult.h" +#include "../../Asm/IAsmHelper.h" +#include "../Process.h" + +#include + +// TODO: Find more elegant way to deduce calling convention +// than defining each one manually + +namespace blackbone +{ +template +class RemoteFunctionBase +{ +public: + using ReturnType = std::conditional_t, int, R>; + + struct CallArguments + { + CallArguments( const Args&... args ) + : arguments{ AsmVariant( args )... } + { + } + + template + CallArguments( const std::tuple& args, std::index_sequence ) + : arguments{ std::get( args )... } + { + } + + CallArguments( const std::initializer_list& args ) + : arguments{ args } + { + // Since initializer_list can't be moved from, dataStruct types must be fixed + for (auto& arg : arguments) + { + if (!arg.buf.empty()) + arg.imm_val = reinterpret_cast(arg.buf.data()); + } + } + + // Manually set argument to custom value + void set( int pos, const AsmVariant& newVal ) + { + if (arguments.size() > static_cast(pos)) + arguments[pos] = newVal; + } + + std::vector arguments; + }; + +public: + RemoteFunctionBase( Process& proc, ptr_t ptr ) + : _process( proc ) + , _ptr( ptr ) + { + static_assert( + (... && !std::is_reference_v), + "Please replace reference type with pointer type in function type specification" + ); + } + + call_result_t Call( CallArguments& args, ThreadPtr contextThread = nullptr ) + { + ReturnType result = {}; + uint64_t tmpResult = 0; + NTSTATUS status = STATUS_SUCCESS; + auto a = AsmFactory::GetAssembler( _process.core().isWow64() ); + + // Ensure RPC environment exists + status = _process.remote().CreateRPCEnvironment( Worker_None, contextThread != nullptr ); + if (!NT_SUCCESS( status )) + return call_result_t( result, status ); + + // FPU check + constexpr bool isFloat = std::is_same_v; + constexpr bool isDouble = std::is_same_v || std::is_same_v; + + // Deduce return type + eReturnType retType = rt_int32; + + if constexpr (isFloat) + retType = rt_float; + else if constexpr (isDouble) + retType = rt_double; + else if constexpr (sizeof( ReturnType ) == sizeof( uint64_t )) + retType = rt_int64; + else if constexpr (!std::is_reference_v && sizeof( ReturnType ) > sizeof( uint64_t )) + retType = rt_struct; + + _process.remote().PrepareCallAssembly( *a, _ptr, args.arguments, Conv, retType ); + + // Choose execution thread + if (!contextThread) + { + status = _process.remote().ExecInNewThread( (*a)->make(), (*a)->getCodeSize(), tmpResult ); + } + else if (contextThread == _process.remote().getWorker()) + { + status = _process.remote().ExecInWorkerThread( (*a)->make(), (*a)->getCodeSize(), tmpResult ); + } + else + { + status = _process.remote().ExecInAnyThread( (*a)->make(), (*a)->getCodeSize(), tmpResult, contextThread ); + } + + // Get function return value + if (!NT_SUCCESS( status ) || !NT_SUCCESS( status = _process.remote().GetCallResult( result ) )) + return call_result_t( result, status ); + + // Update arguments + for (auto& arg : args.arguments) + if (arg.type == AsmVariant::dataPtr) + _process.memory().Read( arg.new_imm_val, arg.size, reinterpret_cast(arg.imm_val) ); + + return call_result_t( result, STATUS_SUCCESS ); + } + + call_result_t Call( const Args&... args ) + { + CallArguments a( args... ); + return Call( a, nullptr ); + } + + call_result_t Call( const std::tuple& args, ThreadPtr contextThread = nullptr ) + { + CallArguments a( args, std::index_sequence_for() ); + return Call( a, contextThread ); + } + + call_result_t Call( const std::initializer_list& args, ThreadPtr contextThread = nullptr ) + { + CallArguments a( args ); + return Call( a, contextThread ); + } + + call_result_t operator()( const Args&... args ) + { + CallArguments a( args... ); + return Call( a ); + } + + auto MakeArguments( const Args&... args ) + { + return CallArguments( args... ); + } + + auto MakeArguments( const std::initializer_list& args ) + { + return CallArguments( args ); + } + + auto MakeArguments( const std::tuple& args ) + { + return CallArguments( args, std::index_sequence_for() ); + } + + bool valid() const { return _ptr != 0; } + explicit operator bool() const { return valid(); } + +private: + Process& _process; + ptr_t _ptr = 0; +}; + +// Remote function pointer +template +class RemoteFunction; + +// +// Calling convention specialization +// +template \ +class RemoteFunction : public RemoteFunctionBase +{ +public: + using RemoteFunctionBase::RemoteFunctionBase; + + RemoteFunction( Process& proc, R( __cdecl* ptr )(Args...) ) + : RemoteFunctionBase( proc, reinterpret_cast(ptr) ) + { + } +}; + +// Under AMD64 these will be same declarations as __cdecl, so compilation will fail. +#ifdef USE32 +template +class RemoteFunction : public RemoteFunctionBase +{ +public: + using RemoteFunctionBase::RemoteFunctionBase; + + RemoteFunction( Process& proc, R( __stdcall* ptr )(Args...) ) + : RemoteFunctionBase( proc, reinterpret_cast(ptr) ) + { + } +}; + +template +class RemoteFunction : public RemoteFunctionBase +{ +public: + using RemoteFunctionBase::RemoteFunctionBase; + + RemoteFunction( Process& proc, R( __thiscall* ptr )(Args...) ) + : RemoteFunctionBase( proc, reinterpret_cast(ptr) ) + { + } +}; + +template +class RemoteFunction : public RemoteFunctionBase +{ +public: + using RemoteFunctionBase::RemoteFunctionBase; + + RemoteFunction( Process& proc, R( __fastcall* ptr )(Args...) ) + : RemoteFunctionBase( proc, reinterpret_cast(ptr) ) + { + } +}; +#endif + +/// +/// Get remote function object +/// +/// Function address in the remote process +/// Function object +template +RemoteFunction MakeRemoteFunction( Process& process, ptr_t ptr ) +{ + return RemoteFunction( process, ptr ); +} + +/// +/// Get remote function object +/// +/// Function address in the remote process +/// Function object +template +RemoteFunction MakeRemoteFunction( Process& process, T ptr ) +{ + return RemoteFunction( process, ptr ); +} + +/// +/// Get remote function object +/// +/// Remote module name +/// Function name or ordinal +/// Function object +template +RemoteFunction MakeRemoteFunction( Process& process, const std::wstring& modName, const char* name_ord ) +{ + auto ptr = process.modules().GetExport( modName, name_ord ); + return RemoteFunction( process, ptr ? ptr->procAddress : 0 ); +} + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/RPC/RemoteHook.cpp b/third/Blackbone/src/BlackBone/Process/RPC/RemoteHook.cpp new file mode 100644 index 0000000000000000000000000000000000000000..46dbf1ff0c8049961223b485a8e57d33200490fc --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/RPC/RemoteHook.cpp @@ -0,0 +1,705 @@ +#include "RemoteHook.h" +#include "../Process.h" + +#include + +namespace blackbone +{ + +// Maximum possible instruction length for x86-64 +// CPU will raise #GP if length exceeds this value +#define MAX_INSTRUCTION_LENGTH 15 + +RemoteHook::RemoteHook( class ProcessMemory& memory ) + : _memory( memory ) + , _core( _memory.core() ) +{ +} + +RemoteHook::~RemoteHook() +{ + reset(); +} + +/// +/// Debug selected process +/// +/// true on success +NTSTATUS RemoteHook::EnsureDebug() +{ + // Close previous debug object + if (_debugPID != 0 && _debugPID != _core.pid()) + { + EndDebug(); + } + // Already debugging + else if (_debugPID == _core.pid()) + { + return STATUS_SUCCESS; + } + + // + // Check if debug is possible. + // + BOOL isDebugged = FALSE; + + // Can't debug x64 process from x32 one. + if (_core.native()->GetWow64Barrier().type == wow_32_64) + return STATUS_OBJECT_TYPE_MISMATCH; + + // Already under debugger + CheckRemoteDebuggerPresent( _core.handle(), &isDebugged ); + if (isDebugged == TRUE) + return STATUS_ALREADY_REGISTERED; + + // Event thread already exists + if (_hEventThd != NULL) + return STATUS_TOO_MANY_THREADS; + + // Create debug event thread + _hEventThd = CreateThread( NULL, 0, &RemoteHook::EventThreadWrap, this, 0, NULL ); + return (_hEventThd != NULL) ? STATUS_SUCCESS : LastNtStatus(); +} + +/// +/// Stop process debug +/// +void RemoteHook::EndDebug() +{ + // Stop event thread + if (_hEventThd != NULL) + { + _active = false; + WaitForSingleObject( _hEventThd, INFINITE ); + CloseHandle( _hEventThd ); + _hEventThd = NULL; + } +} + +/// +/// Hook specified address +/// +/// Hook type +/// Address +/// Callback +/// Class reference. +/// Thread to hook. Valid only for HWBP +/// Status code +NTSTATUS RemoteHook::ApplyP( eHookType type, uint64_t ptr, fnCallback newFn, const void* pClass /*= nullptr*/, ThreadPtr pThread /*= nullptr*/ ) +{ + NTSTATUS status = EnsureDebug(); + if (!NT_SUCCESS( status )) + return status; + + // Wait for debug event thread + DWORD exitCode = 0; + GetExitCodeThread( _hEventThd, &exitCode ); + while (!_active && exitCode == STILL_ACTIVE) + { + Sleep( 10 ); + GetExitCodeThread( _hEventThd, &exitCode ); + } + + HookData data = { { 0 } }; + + // Store old byte + data.oldByte = _memory.Read( ptr ).result(); + data.type = type; + data.onExecute.freeFn = newFn; + data.onExecute.classFn.classPtr = pClass; + data.threadID = (pThread != nullptr) ? pThread->id() : 0; + + // Set HWBP + CSLock lck( _lock ); + if(type == hwbp) + { + // Set for single thread + if (pThread != nullptr) + { + data.hwbp_idx = pThread->AddHWBP( ptr, hwbp_execute, hwbp_1 ).result( -1 ); + if (data.hwbp_idx == -1) + return STATUS_NO_MORE_ENTRIES; + } + // Set for all threads + else + { + for (auto& thread : _memory.process()->threads().getAll()) + thread->AddHWBP( ptr, hwbp_execute, hwbp_1 ); + } + } + // Write int3 + else + { + DWORD flOld = 0; + _memory.Protect( ptr, sizeof( uint8_t ), PAGE_EXECUTE_READWRITE, &flOld ); + status = _memory.Write( ptr, 0xCC ); + _memory.Protect( ptr, sizeof( uint8_t ), flOld, nullptr ); + + if (!NT_SUCCESS( status )) + return status; + } + + // Store hooked address + _hooks.emplace( ptr, data ); + + return STATUS_SUCCESS; +} + +/// +/// Hook function return +/// This hook will only work if function is hooked normally +/// +/// Hooked function address +/// Callback +/// Class reference. +/// Status code +NTSTATUS RemoteHook::AddReturnHookP( uint64_t ptr, fnCallback newFn, const void* pClass /*= nullptr */ ) +{ + CSLock lck( _lock ); + if(_hooks.count(ptr)) + { + auto& hook = _hooks[ptr]; + + // Add return callback + hook.onReturn.freeFn = newFn; + hook.onReturn.classFn.classPtr = pClass; + hook.flags |= returnHook; + + return STATUS_SUCCESS; + } + + return STATUS_NOT_FOUND; +} + +/// +/// Remove existing hook +/// +/// Hooked address +void RemoteHook::Remove( uint64_t ptr ) +{ + // Restore hooked function + CSLock lck( _lock ); + if (_hooks.count( ptr )) + { + auto& hook = _hooks[ptr]; + + Restore( hook, ptr ); + _hooks.erase( ptr ); + } +} + +/// +/// Restore hooked function +/// +/// Hook data +/// Hooked address +void RemoteHook::Restore( const HookData &hook, uint64_t ptr ) +{ + // Remove HWBP + if (hook.type == hwbp) + { + if (hook.threadID != 0) + { + Thread( hook.threadID, &_core ).RemoveHWBP( hook.hwbp_idx ); + } + else + { + auto threads = _memory.process()->threads().getAll(); + for (auto& thread : threads) + thread->RemoveHWBP( ptr ); + } + } + // Restore original byte + else + { + DWORD flOld = 0; + _memory.Protect( ptr, sizeof( uint8_t ), PAGE_EXECUTE_READWRITE, &flOld ); + _memory.Write( ptr, hook.oldByte ); + _memory.Protect( ptr, sizeof( uint8_t ), flOld, nullptr ); + } +} + +/// +/// Wrapper for debug event thread +/// +/// RemoteHook pointer +/// Status code +DWORD RemoteHook::EventThreadWrap( LPVOID lpParam ) +{ + if (lpParam) + return reinterpret_cast(lpParam)->EventThread(); + + return ERROR_INVALID_PARAMETER; +} + +/// +/// Debug thread +/// +/// Error code +DWORD RemoteHook::EventThread() +{ + // Try to debug process + if (DebugActiveProcess( _core.pid() ) != TRUE) + return LastNtStatus(); + + DebugSetProcessKillOnExit( FALSE ); + + _debugPID = _core.pid(); + + // Determine if target is Wow64 + _x64Target = !_core.native()->GetWow64Barrier().targetWow64; + _wordSize = _x64Target ? sizeof( int64_t ) : sizeof( int32_t ); + + // + // Reset debug flag in PEB + // + _memory.Write( fieldPtr( _core.peb64(), &_PEB64::BeingDebugged ), uint8_t( 0 ) ); + if (!_x64Target) + _memory.Write( fieldPtr( _core.peb32(), &_PEB32::BeingDebugged ), uint8_t( 0 ) ); + + _active = true; + + // Process debug events + while (_active) + { + DEBUG_EVENT DebugEv = { 0 }; + DWORD status = DBG_CONTINUE; + + if (!WaitForDebugEvent( &DebugEv, 100 )) + continue; + + _lock.lock(); + switch (DebugEv.dwDebugEventCode) + { + case EXCEPTION_DEBUG_EVENT: + status = OnDebugEvent( DebugEv ); + break; + + // Add HWBP to created thread + case CREATE_THREAD_DEBUG_EVENT: + for(auto& hook : _hooks) + if (hook.second.type == hwbp && hook.second.threadID == 0) + { + Thread th( DebugEv.u.CreateThread.hThread, &_core ); + th.AddHWBP( hook.first, hwbp_execute, hwbp_1 ); + } + break; + + default: + break; + } + + ContinueDebugEvent( DebugEv.dwProcessId, DebugEv.dwThreadId, status ); + _lock.unlock(); + } + + // Safely detach debugger + if (_debugPID != 0) + { + DebugActiveProcessStop( _debugPID ); + + _debugPID = 0; + } + + return STATUS_SUCCESS; +} + +/// +/// Debug event handler +/// +/// Debug event data +/// Status +DWORD RemoteHook::OnDebugEvent( const DEBUG_EVENT& DebugEv ) +{ + switch (DebugEv.u.Exception.ExceptionRecord.ExceptionCode) + { + case static_cast(EXCEPTION_BREAKPOINT): + case static_cast(STATUS_WX86_BREAKPOINT): + return OnBreakpoint( DebugEv ); + + case static_cast(EXCEPTION_SINGLE_STEP): + case static_cast(STATUS_WX86_SINGLE_STEP): + return OnSinglestep( DebugEv ); + + case static_cast(EXCEPTION_ACCESS_VIOLATION): + return OnAccessViolation( DebugEv ); + + default: + return static_cast(DBG_EXCEPTION_NOT_HANDLED); + } +} + +/// +/// Int 3 handler +/// +/// Debug event data +/// Status +DWORD RemoteHook::OnBreakpoint( const DEBUG_EVENT& DebugEv ) +{ + // Prevent highest bit extension. + ptr_t addr = (uintptr_t)DebugEv.u.Exception.ExceptionRecord.ExceptionAddress; + ptr_t ip = 0, sp = 0; + Thread thd( DebugEv.dwThreadId, &_core ); + + if (_hooks.count( addr )) + { + _CONTEXT64 ctx64; + _CONTEXT32 ctx32; + thd.GetContext( ctx64, CONTEXT64_FULL, true ); + + if (_memory.core().isWow64()) + { + thd.GetContext( ctx32, WOW64_CONTEXT_FULL, true ); + ip = ctx32.Eip; + sp = ctx32.Esp; + } + else + { + ip = ctx64.Rip; + sp = ctx64.Rsp; + } + + // Get stack frame pointer + std::vector> results; + StackBacktrace( ip, sp, thd, results, 1 ); + + RemoteContext context( _memory, thd, ctx64, !results.empty() ? results.back().first : 0, _x64Target, _wordSize ); + + // Execute user callback + auto& hook = _hooks[addr]; + + if (hook.onExecute.classFn.classPtr && hook.onExecute.classFn.ptr != nullptr) + hook.onExecute.classFn.ptr( hook.onExecute.classFn.classPtr, context ); + else if (hook.onExecute.freeFn != nullptr) + hook.onExecute.freeFn( context ); + + // Raise exceptions upon return + if (hook.flags & returnHook) + { + hook.entryCtx = ctx64; + auto newReturn = context.hookReturn(); + _retHooks.emplace( newReturn, addr ); + } + + // Resume execution + DWORD flOld = 0; + _memory.Protect( addr, sizeof( hook.oldByte ), PAGE_EXECUTE_READWRITE, &flOld ); + _memory.Write( addr, hook.oldByte ); + _memory.Protect( addr, sizeof( hook.oldByte ), flOld, nullptr ); + + _repatch[addr] = true; + + // Single-step failed instruction + ctx64.Rip -= sizeof( uint8_t ); + ctx64.EFlags |= 0x100; + thd.SetContext( ctx64, true ); + + return DBG_CONTINUE; + } + + return (DWORD)DBG_EXCEPTION_NOT_HANDLED; +} + +/// +/// Trace and hardware breakpoints handler +/// +/// Debug event data +/// Status +DWORD RemoteHook::OnSinglestep( const DEBUG_EVENT& DebugEv ) +{ + // Prevent highest bit extension. + ptr_t addr = (uintptr_t)DebugEv.u.Exception.ExceptionRecord.ExceptionAddress; + ptr_t ip = 0, sp = 0; + bool use64 = !_core.native()->GetWow64Barrier().x86OS; + _CONTEXT32 ctx32 = { 0 }; + _CONTEXT64 ctx64 = { 0 }; + + Thread thd( DebugEv.dwThreadId, &_core ); + + thd.GetContext( ctx64, CONTEXT64_ALL, true ); + ip = ctx64.Rip; + sp = ctx64.Rsp; + + // Use 32 bit context if available + if (_memory.core().isWow64()) + { + thd.GetContext( ctx32, use64 ? WOW64_CONTEXT_ALL : CONTEXT_ALL, true ); + ip = ctx32.Eip; + sp = ctx32.Esp; + } + + // X86 workaround + if (!use64) + ctx64.FromCtx32( ctx32 ); + + // Detect hardware breakpoint + DWORD index = 0; + for (; index < 4; index++) + { + if (ctx64.Dr6 & (1ll << index)) + if ((use64 && (ctx64.Dr7 & 1ll << (2 * index))) || (!use64 && (ctx32.Dr7 & 1ll << (2 * index)))) + if ((use64 && *(&ctx64.Dr0 + index) == addr) || (!use64 && *(&ctx32.Dr0 + index) == addr)) + break; + } + + if (index < 4) + { + // Get stack frame pointer + std::vector> results; + StackBacktrace( ip, sp, thd, results, 1 ); + + RemoteContext context( _memory, thd, ctx64, !results.empty() ? results.back().first : 0, _x64Target, _wordSize ); + + // Execute user callback + if(_hooks.count( addr )) + { + auto& hook = _hooks[addr]; + if (hook.onExecute.classFn.classPtr && hook.onExecute.classFn.ptr != nullptr) + hook.onExecute.classFn.ptr( hook.onExecute.classFn.classPtr, context ); + else if (hook.onExecute.freeFn != nullptr) + hook.onExecute.freeFn( context ); + + // Raise exception upon return + if (hook.flags & returnHook) + { + hook.entryCtx = ctx64; + auto newReturn = context.hookReturn(); + _retHooks.emplace( newReturn, addr ); + } + + ctx64.ContextFlags = use64 ? CONTEXT64_ALL : WOW64_CONTEXT_ALL; + use64 ? ctx64.EFlags |= 0x100 : ctx32.EFlags |= 0x100; // Single step + _repatch[addr] = true; + } + + auto andVal = ~(1ll << (2 * index)); + if (use64) + { + ctx64.ContextFlags |= CONTEXT64_DEBUG_REGISTERS; + *(&ctx64.Dr0 + index) = 0; + ctx64.Dr7 &= andVal; + ctx64.Dr6 = 0; + thd.SetContext( ctx64, true ); + } + else + { + ctx32.ContextFlags |= WOW64_CONTEXT_DEBUG_REGISTERS; + *(&ctx32.Dr0 + index) = 0; + ctx32.Dr7 &= andVal; + ctx32.Dr6 = 0; + thd.SetContext( ctx32, true ); + } + + return DBG_CONTINUE; + } + + // Restore pending hooks + for(auto place : _repatch) + { + if (place.second == true && _hooks.count( place.first )) + { + auto& hook = _hooks[place.first]; + + if (hook.type == hwbp) + { + thd.AddHWBP( place.first, hwbp_execute, hwbp_1 ); + } + else if (hook.type == int3) + { + DWORD flOld = 0; + _memory.Protect( addr, sizeof( hook.oldByte ), PAGE_EXECUTE_READWRITE, &flOld ); + _memory.Write( place.first, uint8_t( 0xCC ) ); + _memory.Protect( addr, sizeof( hook.oldByte ), flOld, nullptr ); + } + + place.second = false; + } + } + + return DBG_CONTINUE; +} + +/// +/// Access violation handler +/// Used when hooking function return +/// +/// Debug event data +/// Status +DWORD RemoteHook::OnAccessViolation( const DEBUG_EVENT& DebugEv ) +{ + // Prevent highest bit extension. + ptr_t addr = (size_t)DebugEv.u.Exception.ExceptionRecord.ExceptionAddress; + ptr_t ip = 0, sp = 0; + _CONTEXT32 ctx32; + _CONTEXT64 ctx64; + + Thread thd( DebugEv.dwThreadId, &_core ); + + thd.GetContext( ctx64, CONTEXT64_ALL, true ); + ip = ctx64.Rip; + sp = ctx64.Rsp; + + // Use 32 bit context if available + if(_memory.core().isWow64()) + { + thd.GetContext( ctx32, WOW64_CONTEXT_ALL, true ); + ip = ctx32.Eip; + sp = ctx32.Esp; + } + + // Get stack frame pointer + std::vector> results; + StackBacktrace( ip, sp, thd, results, 1 ); + + RemoteContext context( _memory, thd, ctx64, !results.empty() ? results.back().first : 0, _x64Target, _wordSize ); + + // Under AMD64 exception is thrown before 'ret' gets executed + // Return must be detected manually + if (_x64Target && results.size() > 0) + addr = results.back().second; + + // Test if this is a return hook + if (_retHooks.count( addr )) + { + // Execute user callback + auto& hook = _hooks[_retHooks[addr]]; + + if (hook.flags & returnHook) + { + RemoteContext fixedContext( _memory, thd, hook.entryCtx, !results.empty() ? results.back().first : 0, _x64Target, _wordSize ); + + if (hook.onReturn.classFn.classPtr && hook.onReturn.classFn.ptr != nullptr) + hook.onReturn.classFn.ptr( hook.onExecute.classFn.classPtr, fixedContext ); + else if (hook.onReturn.freeFn != nullptr) + hook.onReturn.freeFn( fixedContext ); + + hook.entryCtx = { 0 }; + } + + _retHooks.erase( addr ); + } + + // Under AMD64there is no need to update IP, because exception is thrown before actual return. + // Return address still must be fixed though. + if(_x64Target) + { + auto retAddr = context.returnAddress(); + if (retAddr & 0x8000000000000000) + { + context.unhookReturn(); + return (DWORD)DBG_CONTINUE; + } + } + else + { + auto retAddr = addr; + if(retAddr & 0x80000000) + { + RESET_BIT( retAddr, (_wordSize * 8 - 1) ); + ctx64.Rip = retAddr; + thd.SetContext( ctx64, true ); + return (DWORD)DBG_CONTINUE; + } + } + + return (DWORD)DBG_EXCEPTION_NOT_HANDLED; +} + +/// +/// Walk stack frames +/// +/// Thread instruction pointer +/// >Thread stack pointer +/// Stack owner +/// Stack frames +/// Max frame count +/// Frame count +DWORD RemoteHook::StackBacktrace( ptr_t ip, ptr_t sp, Thread& thd, std::vector>& results, int depth /*= 100 */ ) +{ + int i = 0; + uint64_t stack_base = 0; + + // Get stack base + if(_core.isWow64()) + { + _TEB32 teb32 = { { 0 } }; + if (thd.teb( &teb32 ) == 0) + return 0; + + stack_base = teb32.NtTib.StackBase; + } + else + { + _TEB64 teb64 = { { 0 } }; + if (thd.teb( &teb64 ) == 0) + return 0; + + stack_base = teb64.NtTib.StackBase; + } + + // Store exception address + results.emplace_back( 0, ip ); + + // Walk stack + for (ptr_t stackPtr = sp; stackPtr < stack_base && i < depth; stackPtr += _wordSize) + { + ptr_t stack_val = 0; + _memory.Read( stackPtr, _wordSize, &stack_val ); + MEMORY_BASIC_INFORMATION64 meminfo = { 0 }; + + ptr_t original = stack_val & 0x7FFFFFFFFFFFFFFF; + + // Invalid value + if (stack_val < _core.native()->minAddr() || original > _core.native()->maxAddr()) + continue; + + // Check if memory is executable + if (_core.native()->VirtualQueryExT( original, &meminfo ) != STATUS_SUCCESS) + continue; + + if ( meminfo.AllocationProtect != PAGE_EXECUTE_READ && + meminfo.AllocationProtect != PAGE_EXECUTE_WRITECOPY && + meminfo.AllocationProtect != PAGE_EXECUTE_READWRITE) + { + continue; + } + + uint8_t codeChunk[6] = {0}; + _memory.Read( original - 6, sizeof(codeChunk), codeChunk ); + + // Detect 'call' instruction + // TODO: Implement more reliable way to detect 'call' + if (codeChunk[0] == 0xFF || codeChunk[1] == 0xE8 || codeChunk[4] == 0xFF) + { + results.emplace_back( stackPtr, stack_val ); + i++; + } + } + + return i; +} + +/// +/// Stop debug and remove all hooks +/// +void RemoteHook::reset() +{ + if (!_hooks.empty()) + { + _lock.lock(); + for (auto& hook : _hooks) + Restore( hook.second, hook.first ); + + _hooks.clear(); + _repatch.clear(); + + _lock.unlock(); + + // Wait for last events to finish + Sleep( 100 ); + } + + EndDebug(); +} + +} diff --git a/third/Blackbone/src/BlackBone/Process/RPC/RemoteHook.h b/third/Blackbone/src/BlackBone/Process/RPC/RemoteHook.h new file mode 100644 index 0000000000000000000000000000000000000000..fbfd573bd2b9acc28c02cc877673c51f3beed132 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/RPC/RemoteHook.h @@ -0,0 +1,258 @@ +#pragma once + +#include "../../Config.h" +#include "RemoteContext.hpp" + +#include "../../Include/Winheaders.h" +#include "../../Include/Macro.h" +#include "../../Misc/Utils.h" +#include "../Threads/Threads.h" + +#include +#include +#include + +namespace blackbone +{ + +class RemoteHook +{ +public: + + // Hook type + enum eHookType + { + int3 = 0, // Default int 3 breakpoint + hwbp // Hardware breakpoint + }; + + enum eHookFlags + { + none = 0, // No flags + returnHook = 1, // Hook function return + }; + + // Hook callback prototype + using fnCallback = void( *)(RemoteContext& context); + using fnClassCallback = void( __thiscall* )(const void* __this, RemoteContext& context); + + /// + /// Hook descriptor + /// + struct HookData + { + // Callback pointer + union callback + { + struct _classFn + { + fnClassCallback ptr; // Class member function pointer + const void* classPtr; // Class instance + }; + + fnCallback freeFn; // Free function pointer + _classFn classFn; // Class member pointer + }; + + callback onExecute; // Callback called upon address breakpoint + callback onReturn; // Callback called upon function return + eHookType type; // int 3 or HWBP + eHookFlags flags; // Some hooking flags + uint8_t oldByte; // Original byte in case of int 3 hook + DWORD threadID; // Thread id for HWBP (0 means global hook for all threads) + int hwbp_idx; // Index of HWBP if applied to one thread only + _CONTEXT64 entryCtx; // Thread context on function entry (used in function return hook) + }; + + using mapHook = std::map; + using mapAddress = std::map; + using setAddresses = std::map; + +public: + BLACKBONE_API RemoteHook( class ProcessMemory& memory ); + BLACKBONE_API ~RemoteHook(); + + /// + /// Hook specified address + /// + /// Hook type + /// Address + /// Callback + /// Thread to hook. Valid only for HWBP + /// true on success + BLACKBONE_API inline NTSTATUS Apply( eHookType type, uint64_t ptr, fnCallback newFn, ThreadPtr pThread = nullptr ) + { + return ApplyP( type, ptr, newFn, nullptr, pThread ); + } + + /// + /// Hook function return + /// This hook will only work if function is hooked normally + /// + /// Hooked function address + /// Callback + /// true on success + BLACKBONE_API inline NTSTATUS AddReturnHook( uint64_t ptr, fnCallback newFn ) + { + return AddReturnHookP( ptr, newFn, nullptr ); + } + + // FIXME: Alternative for MinGW +#ifdef COMPILER_MSVC + /// + /// Hook specified address + /// + /// + /// Hook type + /// Address + /// Callback + /// Class reference. + /// Thread to hook. Valid only for HWBP + /// true on success + template + inline NTSTATUS Apply( eHookType type, uint64_t ptr, void(C::* newFn)(RemoteContext& ctx), const C& classRef, ThreadPtr pThread = nullptr ) + { + return ApplyP( type, ptr, brutal_cast(newFn), &classRef, pThread ); + } + + /// + /// Hook function return + /// This hook will only work if function is hooked normally + /// + /// Hooked function address + /// Callback + /// Class reference. + /// true on success + template + inline NTSTATUS AddReturnHook( uint64_t ptr, void(C::* newFn)(RemoteContext& ctx), const C& classRef ) + { + return AddReturnHookP( ptr, brutal_cast(newFn), &classRef ); + } +#endif // COMPILER_MSVC + + /// + /// Remove existing hook + /// + /// Hooked address + BLACKBONE_API void Remove( uint64_t ptr ); + + /// + /// Stop debug and remove all hooks + /// + BLACKBONE_API void reset(); + +private: + + /// + /// Hook specified address + /// + /// Hook type + /// Address + /// Callback + /// Class reference. + /// Thread to hook. Valid only for HWBP + /// true on success + BLACKBONE_API NTSTATUS ApplyP( eHookType type, uint64_t ptr, fnCallback newFn, const void* pClass = nullptr, ThreadPtr pThread = nullptr ); + + /// + /// Hook function return + /// This hook will only work if function is hooked normally + /// + /// Hooked function address + /// Callback + /// Class reference. + /// true on success + BLACKBONE_API NTSTATUS AddReturnHookP( uint64_t ptr, fnCallback newFn, const void* pClass = nullptr ); + + /// + /// Restore hooked function + /// + /// Hook data + /// Hooked address + BLACKBONE_API void Restore( const HookData &hook, uint64_t ptr ); + + /// + /// Debug selected process + /// + /// true on success + NTSTATUS EnsureDebug(); + + /// + /// Stop process debug + /// + void EndDebug(); + + /// + /// Wrapper for debug event thread + /// + /// RemoteHook pointer + /// Error code + static DWORD __stdcall EventThreadWrap( LPVOID lpParam ); + + /// + /// Debug thread + /// + /// Error code + DWORD EventThread(); + + /// + /// Debug event handler + /// + /// Debug event data + /// Status + DWORD OnDebugEvent( const DEBUG_EVENT& DebugEv ); + + /// + /// Int 3 handler + /// + /// Debug event data + /// Status + DWORD OnBreakpoint( const DEBUG_EVENT& DebugEv ); + + /// + /// Trace and hardware breakpoints handler + /// + /// Debug event data + /// Status + DWORD OnSinglestep( const DEBUG_EVENT& DebugEv ); + + /// + /// Access violation handler + /// Used when hooking function return + /// + /// Debug event data + /// Status + DWORD OnAccessViolation( const DEBUG_EVENT& DebugEv ); + + /// + /// Walk stack frames + /// + /// Thread instruction pointer + /// >Thread stack pointer + /// Stack owner + /// Stack frames + /// Max frame count + /// Frame count + DWORD StackBacktrace( ptr_t ip, ptr_t sp, Thread& thd, std::vector>& results, int depth = 100 ); + + RemoteHook( const RemoteHook& ) = delete; + RemoteHook& operator =( const RemoteHook& ) = delete; + +private: + class ProcessMemory& _memory; + class ProcessCore& _core; + CriticalSection _lock; // Hook lock + + DWORD _debugPID = 0; // PID of process being debugged + HANDLE _hEventThd = NULL; // Debug Event thread + BOOL _x64Target = FALSE; // Target is x64 process + int _wordSize = 4; // 4 or 8 bytes + bool _active = false; // Event thread activity flag + mapHook _hooks; // Hooked callbacks + setAddresses _repatch; // Pending repatch addresses + mapAddress _retHooks; // Hooked return addresses +}; + +ENUM_OPS( RemoteHook::eHookFlags ) + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/RPC/RemoteLocalHook.cpp b/third/Blackbone/src/BlackBone/Process/RPC/RemoteLocalHook.cpp new file mode 100644 index 0000000000000000000000000000000000000000..35fa00c917112483a6eb3f6feea5510509c99fd3 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/RPC/RemoteLocalHook.cpp @@ -0,0 +1,173 @@ +#include "RemoteLocalHook.h" + +#include "../Process.h" +#include "../../Asm/LDasm.h" + +namespace blackbone +{ + +RemoteLocalHook::RemoteLocalHook( class Process& process ) + : _process( process ) +{ +} + +RemoteLocalHook::~RemoteLocalHook() +{ + Restore(); +} + +NTSTATUS RemoteLocalHook::AllocateMem( ptr_t /*address*/, size_t codeSize ) +{ + auto pagesize = _process.core().native()->pageSize(); + auto size = Align( codeSize, pagesize ) + Align( sizeof( _ctx ), pagesize ); + + auto allocation = _process.memory().Allocate( size, PAGE_EXECUTE_READWRITE ); + if (!allocation) + return allocation.status; + + _hookData = std::move( allocation.result() ); + _pHookCode = _hookData.ptr(); + _pThunkCode = _pHookCode + _hookData.size() - pagesize; + + return allocation.status; +} + +NTSTATUS RemoteLocalHook::SetHook( ptr_t address, asmjit::Assembler& hook ) +{ + _address = address; + NTSTATUS status = AllocateMem( address, hook.getCodeSize() ); + if (!NT_SUCCESS( status )) + return status; + + return _process.core().isWow64() ? SetHook32( address, hook ) : SetHook64( address, hook ); +} + +NTSTATUS RemoteLocalHook::SetHook32( ptr_t address, asmjit::Assembler& hook ) +{ + NTSTATUS status = STATUS_SUCCESS; + auto& mem = _process.memory(); + + if (!CopyOldCode( address, false )) + return STATUS_PARTIAL_COPY; + + _ctx.hook32.codeSize = 5; + _ctx.hook32.jmp.opcode = 0xE9; + _ctx.hook32.jmp.ptr = static_cast(_pThunkCode - address - 5); + + uint8_t buf[0x1000] = { 0 }; + hook.setBaseAddress( _hookData.ptr() ); + hook.relocCode( buf ); + + mem.Write( _pHookCode, buf ); + mem.Write( _pThunkCode, _ctx.hook32.codeSize + _ctx.hook32.jmp_size, _ctx.hook32.original_code ); + + DWORD flOld = 0; + mem.Protect( address, sizeof( _ctx.hook32.jmp_code ), PAGE_EXECUTE_READWRITE, &flOld ); + status = mem.Write( address, _ctx.hook32.jmp_code ); + mem.Protect( address, sizeof( _ctx.hook32.jmp_code ), flOld ); + + if (NT_SUCCESS( status )) + _hooked = true; + + return status; +} + +NTSTATUS RemoteLocalHook::SetHook64( ptr_t /*address*/, asmjit::Assembler& /*hook*/ ) +{ + _hook64 = true; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS RemoteLocalHook::Restore() +{ + if (!_hooked) + return STATUS_SUCCESS; + + DWORD flOld = 0; + _process.memory().Protect( _address, sizeof( _ctx.hook32.jmp_code ), PAGE_EXECUTE_READWRITE, &flOld ); + NTSTATUS status = _process.memory().Write( _address, _ctx.hook32.codeSize, _ctx.hook32.original_code ); + _process.memory().Protect( _address, sizeof( _ctx.hook32.jmp_code ), flOld ); + + if (NT_SUCCESS( status )) + { + _hookData.Free(); + _pHookCode = _pThunkCode = 0; + _address = 0; + _hooked = false; + } + + return status; +} + +bool RemoteLocalHook::CopyOldCode( ptr_t address, bool x64 ) +{ + _process.memory().Read( address, sizeof( _ctx.hook32.original_code ), _ctx.hook32.original_code ); + + // Store original bytes + uint8_t* src = _ctx.hook32.original_code; + uint8_t* old = (uint8_t*)(_hookData.ptr() + _hookData.size() - _process.core().native()->pageSize()); + uint32_t all_len = 0; + ldasm_data ld = { 0 }; + + do + { + uint32_t len = ldasm( src, &ld, x64 ); + + // Determine code end + if (ld.flags & F_INVALID + || (len == 1 && (src[ld.opcd_offset] == 0xCC || src[ld.opcd_offset] == 0xC3)) + || (len == 3 && src[ld.opcd_offset] == 0xC2) + || len + all_len > 128) + { + break; + } + + // if instruction has relative offset, calculate new offset + if (ld.flags & F_RELATIVE) + { + int32_t diff = 0; + const uintptr_t ofst = (ld.disp_offset != 0 ? ld.disp_offset : ld.imm_offset); + const uintptr_t sz = ld.disp_size != 0 ? ld.disp_size : ld.imm_size; + + memcpy( &diff, src + ofst, sz ); + + if(x64) + { + // exit if jump is greater then 2GB + /*if (_abs64( src + len + diff - old ) > INT_MAX) + { + break; + } + else + { + diff += static_cast(src - old); + memcpy( old + ofst, &diff, sz ); + }*/ + } + else + { + //diff += src - old; + memcpy( src + ofst, &diff, sz ); + } + } + + src += len; + old += len; + all_len += len; + + } while (all_len < sizeof( _ctx.hook32.jmp_code )); + + // Failed to copy old code, use backup plan + if (all_len >= sizeof( _ctx.hook32.jmp_code )) + { + _ctx.hook32.jmp_size = 5; + _ctx.hook32.codeSize = all_len; + *src = 0xE9; + //*(int32_t*)(src + 1) = (int32_t)address + all_len - (int32_t)old - 5; + return true; + } + + return false; +} + +} diff --git a/third/Blackbone/src/BlackBone/Process/RPC/RemoteLocalHook.h b/third/Blackbone/src/BlackBone/Process/RPC/RemoteLocalHook.h new file mode 100644 index 0000000000000000000000000000000000000000..653772042e9e44f7e01acdc53be5cd7be4850d15 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/RPC/RemoteLocalHook.h @@ -0,0 +1,85 @@ +#pragma once + +#include "../../Config.h" +#include "../../Asm/AsmFactory.h" +#include "../../Include/Types.h" +#include "../MemBlock.h" + + +namespace blackbone +{ + +/// +/// Hook data, sizeof = 0x50 bytes +/// +#pragma pack(push, 1) +struct HookCtx32 +{ + uint32_t codeSize; // Size of saved code + uint32_t jmp_size; // Size of jump from thunk to original + uint8_t original_code[29]; // Original function code + + union + { + uint8_t jmp_code[5]; // Jump instruction + struct + { + uint8_t opcode; + int32_t ptr; + } jmp; + }; +}; + +struct HookCtx64 +{ + uint64_t dst_ptr; // Target address + uint32_t codeSize; // Size of saved code + uint8_t original_code[32]; // Original function code + uint8_t far_jmp[6]; // Far jump code +}; +#pragma pack(pop) + +union HookCtx +{ + HookCtx32 hook32; + HookCtx64 hook64; +}; + + +/// +/// In-process remote hook +/// +class RemoteLocalHook +{ +public: + RemoteLocalHook( class Process& process ); + ~RemoteLocalHook(); + + NTSTATUS SetHook( ptr_t address, asmjit::Assembler& hook ); + NTSTATUS Restore(); + +private: + RemoteLocalHook( const RemoteLocalHook& ) = delete; + RemoteLocalHook& operator = (const RemoteLocalHook&) = delete; + + NTSTATUS AllocateMem( ptr_t address, size_t codeSize ); + + NTSTATUS SetHook32( ptr_t address, asmjit::Assembler& hook ); + + NTSTATUS SetHook64( ptr_t address, asmjit::Assembler& hook ); + + bool CopyOldCode( ptr_t address, bool x64 ); + +private: + class Process& _process; + HookCtx _ctx; + MemBlock _hookData; + ptr_t _pHookCode = 0; + ptr_t _pThunkCode = 0; + ptr_t _address = 0; + + bool _hooked = false; + bool _hook64 = false; +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/RPC/RemoteMemory.cpp b/third/Blackbone/src/BlackBone/Process/RPC/RemoteMemory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..929945694ed4977596c0dd0ebdf96a2b27c7bc83 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/RPC/RemoteMemory.cpp @@ -0,0 +1,565 @@ +#include "RemoteMemory.h" +#include "../Process.h" +#include "../../Misc/Trace.hpp" + +namespace blackbone +{ + +RemoteMemory::RemoteMemory( Process* process ) + : _process( process ) +{ + _pipeName = Utils::RandomANString() + L"_" + std::to_wstring( _process->pid() ) + L"_" + std::to_wstring( GetCurrentProcessId() ); +} + +RemoteMemory::~RemoteMemory() +{ + reset(); +} + +/// +/// Map entire process address space +/// +/// Set to true to map section objects. They are converted to private pages before locking +/// Status code +NTSTATUS RemoteMemory::Map( bool mapSections ) +{ + MapMemoryResult result = { 0 }; + + // IPC + if (!_hPipe) + _hPipe = CreateNamedPipeW( (L"\\\\.\\pipe\\" + _pipeName).c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE, 1, 0, 0, 0, NULL ); + + Driver().EnsureLoaded(); + NTSTATUS status = Driver().MapMemory( _process->pid(), _pipeName, mapSections, result ); + + if (NT_SUCCESS( status )) + { + std::swap( _mapDatabase, result.regions ); + + _pSharedData = (PageContext*)result.hostSharedPage; + _targetShare = result.targetSharedPage; + _targetPipe = result.targetPipe; + } + + return status; +} + +/// +/// Map specific memory region +/// +/// Region base +/// Region size +/// Status code +NTSTATUS RemoteMemory::Map( ptr_t base, uint32_t size ) +{ + MapMemoryRegionResult memRes = { 0 }; + + // IPC + if (!_hPipe) + _hPipe = CreateNamedPipeW( (L"\\\\.\\pipe\\" + _pipeName).c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE, 1, 0, 0, 0, NULL ); + + Driver().EnsureLoaded(); + NTSTATUS status = Driver().MapMemoryRegion( _process->pid(), base, size, memRes ); + + // Update regions + if (NT_SUCCESS( status )) + { + MapMemoryResult rgnRes = { }; + + if (NT_SUCCESS( Driver().MapMemory( _process->pid(), _pipeName, false, rgnRes ) )) + std::swap( _mapDatabase, rgnRes.regions ); + } + + return status; +} + +/// +/// Unmap process address space from current process +/// +/// Status code +NTSTATUS RemoteMemory::Unmap( ) +{ + NTSTATUS status = Driver().UnmapMemory( _process->pid() ); + + if (NT_SUCCESS( status )) + { + _mapDatabase.clear(); + + _pSharedData = nullptr; + _targetShare = 0; + _targetPipe = NULL; + } + + return status; +} + +/// +/// Unmap specific memory region from current process +/// +/// Region base +/// Region size +/// Status code +NTSTATUS RemoteMemory::Unmap( ptr_t base, uint32_t size ) +{ + auto searchFn = [&base]( const decltype(_mapDatabase)::value_type& val ) + { + return base >= val.first.first && base < val.first.first + val.first.second; + }; + + NTSTATUS status = Driver().UnmapMemoryRegion( _process->pid(), base, size ); + + if (NT_SUCCESS( status )) + { + // Remove region + auto iter = std::find_if( _mapDatabase.begin(), _mapDatabase.end(), searchFn ); + if (iter != _mapDatabase.end()) + _mapDatabase.erase( iter ); + } + + return status; +} + + +/// +/// Translate target address accordingly to current address space +/// +/// Address to translate +/// If set to true, routine will try to map non-existing region upon translation failure +/// Translated address +blackbone::ptr_t RemoteMemory::TranslateAddress( ptr_t address, bool resolveFault /*= true */ ) +{ + auto searchFn = [&address]( const decltype(_mapDatabase)::value_type& val ) + { + return address >= val.first.first && address < val.first.first + val.first.second; + }; + + auto iter = std::find_if( _mapDatabase.begin(), _mapDatabase.end(), searchFn ); + + // Primitive Page fault. Try to resolve missing page + if (iter == _mapDatabase.end() && resolveFault && NT_SUCCESS( Map( address, 1 ) )) + // Second chance + iter = std::find_if( _mapDatabase.begin(), _mapDatabase.end(), searchFn ); + + if (iter != _mapDatabase.end()) + return iter->second + (address - iter->first.first); + + return 0; +} + +/// +/// Setup one of the 4 possible memory hooks: +/// +/// +/// Type of hook to install +/// MemVirtualAlloc - hook NtAllocateVirtualMemory +/// MemVirtualFree - hook NtFreeVirtualMemory +/// MemMapSection - hook NtMapViewOfSection +/// MemUnmapSection - hook NtUnmapViewOfSection +/// +/// true on success +NTSTATUS RemoteMemory::SetupHook( OperationType hkType ) +{ + static const char* procNames[] = { "NtAllocateVirtualMemory", "NtFreeVirtualMemory", "NtMapViewOfSection", "NtUnmapViewOfSection" }; + + uint8_t* pTranslated = nullptr; + ptr_t pProc = 0; + + // Can't setup hook without target pipe and shared data + if (_targetPipe == NULL || !_pSharedData || !_targetShare) + return STATUS_NONE_MAPPED; + + // Cross-architecture code generation isn't supported yet + auto barrier = _process->barrier().type; + if (barrier != wow_32_32 && barrier != wow_64_64) + return STATUS_CONTEXT_MISMATCH; + + // Already hooked + if (_hooked[hkType]) + return STATUS_ALREADY_REGISTERED; + + auto& modules = _process->modules(); + + // Local and remote process address + pProc = modules.GetExport( modules.GetModule( L"ntdll.dll" ), procNames[hkType] ).result( exportData() ).procAddress; + pTranslated = (uint8_t*)TranslateAddress( pProc ); + if (!pTranslated) + return STATUS_INVALID_ADDRESS; + + // IPC + if (!_hPipe) + _hPipe = CreateNamedPipeW( (L"\\\\.\\pipe\\" + _pipeName).c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE, 1, 0, 0, 0, NULL ); + + // Listening thread + if (_hThread == NULL) + { + _hThread = CreateThread( NULL, 0, &RemoteMemory::HookThreadWrap, this, 0, NULL ); + InitializeCriticalSection( &_pSharedData->csLock ); + } + + // Setup hook data + BuildTrampoline( hkType, (uintptr_t)pProc, pTranslated ); + BuildGenericHookFn( hkType ); + + // Copy hook + memcpy( pTranslated, (uint8_t*)_pSharedData + sizeof( HookData ) * hkType + FIELD_OFFSET( HookData, jump_buf ), sizeof( _pSharedData->hkVirtualAlloc.jump_buf ) ); + + _hooked[hkType] = true; + return STATUS_SUCCESS; +} + +/// +/// Restore previously hooked function +/// +/// Hook type. For more info see SetupHook +/// true on success +bool RemoteMemory::RestoreHook( OperationType hkType ) +{ + uint8_t* pTranslated = nullptr; + ptr_t pProc = 0; + static const char* procNames[] = { "NtAllocateVirtualMemory", "NtFreeVirtualMemory", "NtMapViewOfSection", "NtUnmapViewOfSection" }; + + // Not hooked + if (!_hooked[hkType]) + return false; + + auto& modules = _process->modules(); + + // Local and remote proc address + pProc = modules.GetExport( modules.GetModule( L"ntdll.dll" ), procNames[hkType] ).result( exportData() ).procAddress; + pTranslated = (uint8_t*)TranslateAddress( pProc ); + if (!pTranslated) + return false; + + // Restore bytes + memcpy( pTranslated, (uint8_t*)_pSharedData + sizeof( HookData ) * hkType + FIELD_OFFSET( HookData, original_code ), + sizeof( _pSharedData->hkVirtualAlloc.original_code ) / 2 ); + + // Reset hook data + memset( (uint8_t*)_pSharedData + sizeof( HookData ) * hkType, 0x00, sizeof( HookData ) ); + + _hooked[hkType] = false; + return true; +} + + +/// +/// Unmap any mapped memory, restore hooks and free resources +/// +void RemoteMemory::reset() +{ + _active = false; + + if (_hThread != NULL) + { + TerminateThread( _hThread, 0 ); + _hThread = NULL; + } + + _hPipe.reset(); + + for (int i = 0; i < 4; i++) + RestoreHook( (OperationType)i ); + + if (!_mapDatabase.empty() && !NT_SUCCESS( Unmap() )) + { + _mapDatabase.clear(); + + _pSharedData = nullptr; + _targetShare = 0; + _targetPipe = NULL; + } +} + +/// +/// Hook thread wrapper +/// +/// RemoteMemory instance +/// 0 +DWORD CALLBACK RemoteMemory::HookThreadWrap( LPVOID lpParam ) +{ + ((RemoteMemory*)lpParam)->HookThread(); + return 0; +} + +/// +/// Thread responsible for mapping and unmapping regions intercepted by remote hooks +/// +void RemoteMemory::HookThread() +{ + DWORD bytes = 0; + + // Wait for target process to connect + ConnectNamedPipe( _hPipe, NULL ); + _active = true; + + while (_active) + { + OperationData opData = { 0 }; + + // Target endpoint closed + if (!ReadFile( _hPipe, &opData, sizeof( opData ), &bytes, NULL )) + { + _active = false; + _hThread = NULL; + return; + } + + // Update mapping + if (opData.allocType == MemVirtualAlloc || opData.allocType == MemMapSection) + { + BLACKBONE_TRACE( L"Allocated 0x%x bytes at %p", opData.allocSize, opData.allocAddress ); + Map( opData.allocAddress, opData.allocSize ); + } + else + { + BLACKBONE_TRACE( L"Freed 0x%x bytes at %p", opData.allocSize, opData.allocAddress ); + Unmap( opData.allocAddress, opData.allocSize ); + } + } +} + +#ifdef USE64 + +/// +/// Build remote hook function +/// +/// Hooked function +void RemoteMemory::BuildGenericHookFn( OperationType opType ) +{ + static int argc[] = { 6, 4, 10, 2 }; + static int allocIdx[] = { 1, 1, 2, 1 }; + static int sizeIdx[] = { 3, 2, 6, -1 }; + static int testIdx[] = { 4, -1, -1, -1 }; + + int hookDataOfs = sizeof( HookData ) * opType; + + auto pAsm = AsmFactory::GetAssembler( _process->core().isWow64() ); + auto& a = *pAsm; + AsmStackAllocator sa( a.assembler(), 0x60 ); + asmjit::Label skip1 = a->newLabel(); + ALLOC_STACK_VAR( sa, data, OperationData ); + ALLOC_STACK_VAR( sa, junk, SIZE_T ); + size_t stack_size = Align( sa.getTotalSize(), 0x10 ); + + auto& modules = _process->modules(); + + auto pEnterCS = modules.GetExport( modules.GetModule( L"ntdll.dll" ), "RtlEnterCriticalSection" ).result( exportData() ); + auto pLeaveCS = modules.GetExport( modules.GetModule( L"ntdll.dll" ), "RtlLeaveCriticalSection" ).result( exportData() ); + auto pWrite = modules.GetExport( modules.GetModule( L"kernel32.dll" ), "WriteFile" ).result( exportData() ); + + a.GenPrologue(); + a.EnableX64CallStack( false ); + a->sub( asmjit::host::rsp, stack_size ); + + // Call original function + for (int i = 0; i < argc[opType] - 4; i++) + { + a->mov( asmjit::host::rax, asmjit::host::qword_ptr( asmjit::host::rsp, (int32_t)stack_size + 0x8 + 0x20 + i * 8 ) ); + a->mov( asmjit::host::qword_ptr( asmjit::host::rsp, 0x20 + i * 8 ), asmjit::host::rax ); + } + + a->mov( asmjit::host::rax, _targetShare + hookDataOfs + FIELD_OFFSET( HookData, original_code ) ); + a->call( asmjit::host::rax ); + + // Test if call was successful + a->test( asmjit::host::rax, asmjit::host::rax ); + a->jnz( skip1 ); + + // Test if memory was committed + if (opType == MemVirtualAlloc) + { + a->mov( asmjit::host::eax, asmjit::host::dword_ptr( asmjit::host::rsp, (int32_t)stack_size + 0x8 + 0x20 ) ); + a->cmp( asmjit::host::eax, MEM_COMMIT ); + a->jne( skip1 ); + } + + // RtlEnterCriticalSection + a.GenCall( (uintptr_t)pEnterCS.procAddress, { _targetShare + FIELD_OFFSET( PageContext, csLock ) } ); + + // Storage pointer + a->lea( asmjit::host::rdx, data ); + + // Allocation address + if (allocIdx[opType] > 3) + a->mov( asmjit::host::rax, asmjit::host::qword_ptr( asmjit::host::rsp, (int32_t)stack_size + 0x8 + 0x20 + (allocIdx[opType] - 4) * 8 ) ); + else + a->mov( asmjit::host::rax, asmjit::host::qword_ptr( asmjit::host::rsp, (int32_t)stack_size + 0x8 + allocIdx[opType] * 8 ) ); + + if (opType != MemUnmapSection) + a->mov( asmjit::host::rax, asmjit::host::qword_ptr( asmjit::host::rax ) ); + + a->mov( asmjit::host::qword_ptr( asmjit::host::rdx, FIELD_OFFSET( OperationData, allocAddress ) ), asmjit::host::rax ); + + if (sizeIdx[opType] != -1) + { + // Region size + if (sizeIdx[opType] > 3) + a->mov( asmjit::host::rax, asmjit::host::qword_ptr( asmjit::host::rsp, (int32_t)stack_size + 0x8 + 0x20 + (sizeIdx[opType] - 4) * 8 ) ); + else + a->mov( asmjit::host::rax, asmjit::host::qword_ptr( asmjit::host::rsp, (int32_t)stack_size + 0x8 + sizeIdx[opType] * 8 ) ); + + a->mov( asmjit::host::eax, asmjit::host::dword_ptr( asmjit::host::rax ) ); + a->mov( asmjit::host::dword_ptr( asmjit::host::rdx, FIELD_OFFSET( OperationData, allocSize ) ), asmjit::host::eax ); + } + else + a->mov( asmjit::host::dword_ptr( asmjit::host::rdx, FIELD_OFFSET( OperationData, allocSize ) ), 0 ); + + // Operation type + a->mov( asmjit::host::dword_ptr( asmjit::host::rdx, FIELD_OFFSET( OperationData, allocType ) ), opType ); + + a.GenCall( (uintptr_t)pWrite.procAddress, { (uint64_t)_targetPipe, &data, sizeof( OperationData ), &junk, 0 } ); + + // RtlEnterCriticalSection + a.GenCall( (uintptr_t)pLeaveCS.procAddress, { _targetShare + FIELD_OFFSET( PageContext, csLock ) } ); + + // Ignore return value + a->xor_( asmjit::host::rax, asmjit::host::rax ); + + a->bind( skip1 ); + a->add( asmjit::host::rsp, stack_size ); + a->ret(); + + a->setBaseAddress( _targetShare + hookDataOfs + FIELD_OFFSET( HookData, hook_code ) ); + a->relocCode( (uint8_t*)_pSharedData + hookDataOfs + FIELD_OFFSET( HookData, hook_code ) ); +} + +/// +/// Build hook trampoline +/// +/// Hooked function type +/// Original function ptr +/// Original function address in local address space +void RemoteMemory::BuildTrampoline( OperationType opType, uintptr_t /*pOriginal*/, uint8_t* pOriginalLocal ) +{ + int hookDataOfs = sizeof( HookData ) * opType; + uint8_t * pJumpBuf = (uint8_t*)_pSharedData + hookDataOfs + FIELD_OFFSET( HookData, jump_buf ); + + memcpy( (uint8_t*)_pSharedData + hookDataOfs + FIELD_OFFSET( HookData, original_code ), pOriginalLocal, 12 ); + + // mov rax, pOriginal + // call rax + *(uint16_t*)pJumpBuf = 0xB848; + *(uint64_t*)(pJumpBuf + 2) = _targetShare + hookDataOfs + FIELD_OFFSET( HookData, hook_code ); + *(uint16_t*)(pJumpBuf + 10) = 0xE0FF; +} + + +#else + +/// +/// Build remote hook function +/// +/// Hooked function +void RemoteMemory::BuildGenericHookFn( OperationType opType ) +{ + static int argc[] = { 6, 4, 10, 2 }; + static int allocIdx[] = { 1, 1, 2, 1 }; + static int sizeIdx[] = { 3, 2, 6, -1 }; + static int testIdx[] = { 4, -1, -1, -1 }; + + int hookDataOfs = sizeof( HookData ) * opType; + + auto pAsm = AsmFactory::GetAssembler( _process->core().isWow64() ); + auto& a = *pAsm; + AsmStackAllocator sa( a.assembler() ); + asmjit::Label skip1 = a->newLabel(); + ALLOC_STACK_VAR( sa, data, OperationData ); + ALLOC_STACK_VAR( sa, junk, DWORD ); + + auto& modules = _process->modules(); + + auto pEnterCS = modules.GetExport( modules.GetModule( L"ntdll.dll" ), "RtlEnterCriticalSection" ).result( exportData() ).procAddress; + auto pLeaveCS = modules.GetExport( modules.GetModule( L"ntdll.dll" ), "RtlLeaveCriticalSection" ).result( exportData() ).procAddress; + auto pWrite = modules.GetExport( modules.GetModule( L"kernel32.dll" ), "WriteFile" ).result( exportData() ).procAddress; + + a.GenPrologue(); + a->sub( asmjit::host::esp, sa.getTotalSize() ); + + // Call original + for (int i = 0; i < argc[opType]; i++) + a->push( asmjit::host::dword_ptr( asmjit::host::ebp, (argc[opType] - i) * 4 + 4 ) ); + + a->call( _targetShare + hookDataOfs + FIELD_OFFSET( HookData, original_code ) ); + + // Test if call was successful + a->test( asmjit::host::eax, asmjit::host::eax ); + a->jnz( skip1 ); + + if (testIdx[opType] != -1) + { + // Test if memory was committed + a->mov( asmjit::host::eax, asmjit::host::dword_ptr( asmjit::host::ebp, 8 + testIdx[opType] * 4 ) ); + a->cmp( asmjit::host::eax, MEM_COMMIT ); + a->jne( skip1 ); + } + + // RtlEnterCriticalSection + a.GenCall( (uintptr_t)pEnterCS, { (uintptr_t)_targetShare + FIELD_OFFSET( PageContext, csLock ) } ); + + // Storage pointer + a->lea( asmjit::host::edx, data ); + + // + // Allocation address + // + a->mov( asmjit::host::eax, asmjit::host::dword_ptr( asmjit::host::ebp, 8 + 4 * allocIdx[opType] ) ); + if (opType != MemUnmapSection) + a->mov( asmjit::host::eax, asmjit::host::dword_ptr( asmjit::host::eax ) ); + a->mov( asmjit::host::dword_ptr( asmjit::host::edx, FIELD_OFFSET( OperationData, allocAddress ) ), asmjit::host::eax ); + a->mov( asmjit::host::dword_ptr( asmjit::host::edx, FIELD_OFFSET( OperationData, allocAddress ) + 4 ), 0 ); + + // + // Region size + // + if (sizeIdx[opType] != -1) + { + a->mov( asmjit::host::eax, asmjit::host::dword_ptr( asmjit::host::ebp, 8 + 4 * sizeIdx[opType] ) ); + a->mov( asmjit::host::eax, asmjit::host::dword_ptr( asmjit::host::eax ) ); + } + else + a->xor_( asmjit::host::eax, asmjit::host::eax ); + + a->mov( asmjit::host::dword_ptr( asmjit::host::edx, FIELD_OFFSET( OperationData, allocSize ) ), asmjit::host::eax ); + + // Operation type + a->mov( asmjit::host::dword_ptr( asmjit::host::edx, FIELD_OFFSET( OperationData, allocType ) ), opType ); + + a.GenCall( (uintptr_t)pWrite, { (uintptr_t)_targetPipe, asmjit::host::edx, sizeof( OperationData ), &junk, 0 } ); + a.GenCall( (uintptr_t)pLeaveCS, { (uintptr_t)_targetShare + FIELD_OFFSET( PageContext, csLock ) } ); + + // Ignore return value + a->xor_( asmjit::host::eax, asmjit::host::eax ); + + a->bind( skip1 ); + a.GenEpilogue( false, argc[opType] * 4 ); + + a->setBaseAddress( _targetShare + hookDataOfs + FIELD_OFFSET( HookData, hook_code ) ); + a->relocCode( (uint8_t*)_pSharedData + hookDataOfs + FIELD_OFFSET( HookData, hook_code ) ); +} + +/// +/// Build hook trampoline +/// +/// Hooked function type +/// Original function ptr +/// Original function address in local address space +void RemoteMemory::BuildTrampoline( OperationType opType, uintptr_t pOriginal, uint8_t* pOriginalLocal ) +{ + int hookDataOfs = sizeof( HookData ) * opType; + uintptr_t pNew = (uintptr_t)_targetShare + hookDataOfs + FIELD_OFFSET( HookData, hook_code ); + uintptr_t pTrampoline = (uintptr_t)_targetShare + hookDataOfs + FIELD_OFFSET( HookData, original_code ); + + uint8_t* pJumpBuf = (uint8_t*)_pSharedData + hookDataOfs + FIELD_OFFSET( HookData, jump_buf ); + uint8_t* pOriginalBuf = (uint8_t*)_pSharedData + hookDataOfs + FIELD_OFFSET( HookData, original_code ); + + memcpy( (uint8_t*)_pSharedData + hookDataOfs + FIELD_OFFSET( HookData, original_code ), pOriginalLocal, 5 ); + + pJumpBuf[0] = 0xE9; + *(int32_t*)(pJumpBuf + 1) = pNew - pOriginal - 5; + + pOriginalBuf[5] = 0xE9; + *(int32_t*)(pOriginalBuf + 6) = (pOriginal + 5) - (int32_t)(pTrampoline + 5) - 5; +} + +#endif +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/RPC/RemoteMemory.h b/third/Blackbone/src/BlackBone/Process/RPC/RemoteMemory.h new file mode 100644 index 0000000000000000000000000000000000000000..894bd840dbe753d5a8d6ae025e15c90d16829959 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/RPC/RemoteMemory.h @@ -0,0 +1,162 @@ +#pragma once + +#include "../../Config.h" +#include "../../DriverControl/DriverControl.h" + +#include +#include + +namespace blackbone +{ + + +class RemoteMemory +{ +public: +#ifdef USE64 + struct HookData + { + uint8_t original_code[24]; // Original 5 bytes + jmp + uint8_t jump_buf[12]; // Trampoline + uint8_t hook_code[384]; // Hook function + }; +#else + struct HookData + { + uint8_t original_code[10]; // Original 5 bytes + jmp + uint8_t jump_buf[5]; // Trampoline + uint8_t hook_code[384]; // Hook function + }; +#endif + + enum OperationType + { + MemVirtualAlloc = 0, // MemVirtualAlloc + MemVirtualFree, // MemVirtualFree + MemMapSection, // MemMapSection + MemUnmapSection, // MemUnmapSection + }; + + struct OperationData + { + ptr_t allocAddress; // Allocated region base + uint32_t allocSize; // Allocated region size + OperationType allocType; // Operation type + }; + + struct PageContext + { + HookData hkVirtualAlloc; // NtAllocateVirtualMemory context + HookData hkVirtualFree; // NtFreeVirtualMemory context + HookData hkMapSection; // NtMapViewOfSection context + HookData hkUnmapSection; // NtUnmapViewOfSection context + CRITICAL_SECTION csLock; // Lock to sync multi-threaded mappings + }; + +public: + BLACKBONE_API RemoteMemory( class Process* process ); + BLACKBONE_API ~RemoteMemory(); + + /// + /// Map entire process address space + /// + /// Set to true to map section objects. They are converted to private pages before locking + /// Status code + BLACKBONE_API NTSTATUS Map( bool mapSections ); + + /// + /// Map specific memory region + /// + /// Region base + /// Region size + /// Status code + BLACKBONE_API NTSTATUS Map( ptr_t base, uint32_t size ); + + /// + /// Unmap process address space from current process + /// + /// Status code + BLACKBONE_API NTSTATUS Unmap(); + + /// + /// Unmap specific memory region from current process + /// + /// Region base + /// Region size + /// Status code + BLACKBONE_API NTSTATUS Unmap( ptr_t base, uint32_t size ); + + /// + /// Translate target address accordingly to current address space + /// + /// Address to translate + /// If set to true, routine will try to map non-existing region upon translation failure + /// Translated address + BLACKBONE_API ptr_t TranslateAddress( ptr_t address, bool resolveFault = true ); + + /// + /// Setup one of the 4 possible memory hooks: + /// + /// + /// Type of hook to install + /// MemVirtualAlloc - hook NtAllocateVirtualMemory + /// MemVirtualFree - hook NtFreeVirtualMemory + /// MemMapSection - hook NtMapViewOfSection + /// MemUnmapSection - hook NtUnmapViewOfSection + /// + /// true on success + BLACKBONE_API NTSTATUS SetupHook( OperationType hkType ); + + /// + /// Restore previously hooked function + /// + /// Hook type. For more info see SetupHook + /// true on success + BLACKBONE_API bool RestoreHook( OperationType hkType ); + + /// + /// Unmap any mapped memory, restore hooks and free resources + /// + BLACKBONE_API void reset(); + +private: + /// + /// Hook thread wrapper + /// + /// RemoteMemory instance + /// 0 + static DWORD CALLBACK HookThreadWrap( LPVOID lpParam ); + + /// + /// Thread responsible for mapping and unmapping regions intercepted by remote hooks + /// + void HookThread(); + + /// + /// Build remote hook function + /// + /// Hooked function + void BuildGenericHookFn( OperationType opType ); + + /// + /// Build hook trampoline + /// + /// Hooked function type + /// Original function ptr + /// Original function address in local address space + void BuildTrampoline( OperationType opType, uintptr_t pOriginal, uint8_t* pOriginalLocal ); + +private: + class Process* _process = nullptr; // Target process + mapMemoryMap _mapDatabase; // Region map + std::wstring _pipeName; // Pipe name used to gather hook data + Handle _hPipe; // Hook pipe handle + HANDLE _targetPipe = NULL; // Hook pipe handle in target process + HANDLE _hThread = NULL; // Hook thread listener + PageContext* _pSharedData = nullptr; // Hook related data, shared between processes + ptr_t _targetShare = 0; // Address of shared in data in target process + bool _active = false; // Hook thread activity flag + bool _hooked[4] = { 0 }; // Hook state +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/Threads/Thread.cpp b/third/Blackbone/src/BlackBone/Process/Threads/Thread.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f531336652a55cbb6d5004447b991d4ed723caf3 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/Threads/Thread.cpp @@ -0,0 +1,389 @@ +#include "Thread.h" +#include "../ProcessCore.h" +#include "../../Misc/DynImport.h" +#include "../../Include/Macro.h" + +namespace blackbone +{ + +Thread::Thread( DWORD id, ProcessCore* core, DWORD access /*= DEFAULT_ACCESS*/ ) + : _core( core ) + , _id( id ) + , _handle( OpenThread( access, FALSE, id ) ) +{ +} + +Thread::Thread( HANDLE handle, ProcessCore* core ) + : _core( core ) + , _handle( handle ) +{ + _id = (handle ? GetThreadIdT( handle ) : 0); +} + +Thread::~Thread() +{ + Close(); +} + +/// +/// Get WOW64 TEB +/// +/// Process TEB +/// TEB pointer +blackbone::ptr_t Thread::teb( _TEB32* pteb ) const +{ + return _core->native()->getTEB( _handle, pteb ); +} + +/// +/// Get Native TEB +/// +/// Process TEB +/// TEB pointer +blackbone::ptr_t Thread::teb( _TEB64* pteb ) const +{ + return _core->native()->getTEB( _handle, pteb ); +} + +/// +/// Suspend thread +/// +/// true on success +bool Thread::Suspend() +{ + // Prevent deadlock + if (_id == GetCurrentThreadId()) + return true; + + // Target process is x86 and not running on x86 OS + const auto& barrier = _core->native()->GetWow64Barrier(); + if (barrier.type == wow_64_32 && !barrier.x86OS) + return (SAFE_CALL(Wow64SuspendThread, _handle ) != -1); + else + return (SuspendThread( _handle ) != -1); +} + +/// +/// Resumes thread. +/// +/// true on success +bool Thread::Resume() +{ + if (_id == GetCurrentThreadId()) + return true; + + return (ResumeThread( _handle ) != -1); +} + +/// +/// Check if thread is suspended +/// +/// true if suspended +bool Thread::Suspended() +{ + if (_id == GetCurrentThreadId()) + return false; + + auto count = (_core->isWow64() && !_core->native()->GetWow64Barrier().x86OS) + ? SAFE_CALL( Wow64SuspendThread, _handle ) + : SuspendThread( _handle ); + + ResumeThread( _handle ); + return count > 0; +} + +/// +/// Get WOW64 thread context +/// +/// Returned context +/// Context flags. +/// true if thread shouldn't be suspended before retrieving context +/// Status code +NTSTATUS Thread::GetContext( _CONTEXT32& ctx, DWORD flags /*= CONTEXT_ALL*/, bool dontSuspend /*= false*/ ) +{ + NTSTATUS status = STATUS_INVALID_THREAD; + + memset( &ctx, 0x00, sizeof( ctx ) ); + ctx.ContextFlags = flags; + + if (dontSuspend || Suspend()) + { + status = _core->native()->GetThreadContextT( _handle, ctx ); + if (!dontSuspend) + Resume(); + } + + return status; +} + +/// +/// Get native thread context +/// +/// Returned context +/// Context flags. +/// true if thread shouldn't be suspended before retrieving context +/// Status code +NTSTATUS Thread::GetContext( _CONTEXT64& ctx, DWORD flags /*= CONTEXT64_ALL*/, bool dontSuspend /*= false*/ ) +{ + NTSTATUS status = STATUS_INVALID_THREAD; + + memset( &ctx, 0x00, sizeof(ctx) ); + ctx.ContextFlags = flags; + + if (dontSuspend || Suspend()) + { + status = _core->native()->GetThreadContextT( _handle, ctx ); + if (!dontSuspend) + Resume(); + } + + return status; +} + +/// +/// Set WOW64 thread context +/// +/// Context to set +/// true if thread shouldn't be suspended before retrieving context +/// Status code +NTSTATUS Thread::SetContext( _CONTEXT32& ctx, bool dontSuspend /*= false */ ) +{ + NTSTATUS status = STATUS_INVALID_THREAD; + if (dontSuspend || Suspend()) + { + status = _core->native()->SetThreadContextT( _handle, ctx ); + if (!dontSuspend) + Resume(); + } + + return status; +} + +/// +/// Set native thread context +/// +/// Context to set +/// true if thread shouldn't be suspended before retrieving context +/// Status code +NTSTATUS Thread::SetContext( _CONTEXT64& ctx, bool dontSuspend /*= false*/ ) +{ + NTSTATUS status = STATUS_INVALID_THREAD; + if(dontSuspend || Suspend()) + { + status = _core->native()->SetThreadContextT( _handle, ctx ); + if(!dontSuspend) + Resume(); + } + + return status; +} + +/// +/// Terminate thread +/// +/// Exit code +/// Status code +NTSTATUS Thread::Terminate( DWORD code /*= 0*/ ) +{ + SetLastNtStatus( STATUS_SUCCESS ); + TerminateThread( _handle, code ); + return LastNtStatus(); +} + +/// +/// Join thread +/// +/// Join timeout +/// true on success +bool Thread::Join( int timeout /*= INFINITE*/ ) +{ + return (WaitForSingleObject( _handle, timeout ) == WAIT_OBJECT_0); +} + +/// +/// Add hardware breakpoint to thread +/// +/// Breakpoint address +/// Breakpoint type(read/write/execute) +/// Number of bytes to include into breakpoint +/// Index of used breakpoint; -1 if failed +call_result_t Thread::AddHWBP( ptr_t addr, HWBPType type, HWBPLength length ) +{ + _CONTEXT64 context64 = { 0 }; + _CONTEXT32 context32 = { 0 }; + bool use64 = !_core->native()->GetWow64Barrier().x86OS; + + // CONTEXT_DEBUG_REGISTERS can be operated without thread suspension + auto status = use64 ? GetContext( context64, CONTEXT64_DEBUG_REGISTERS, true ) : GetContext( context32, CONTEXT_DEBUG_REGISTERS, true ); + auto pDR7 = use64 ? reinterpret_cast(&context64.Dr7) : reinterpret_cast(&context32.Dr7); + if (!NT_SUCCESS( status )) + return status; + + // Check if HWBP is already present + for (int i = 0; i < 4; i++) + { + if ( (use64 && *(&context64.Dr0 + i) == addr && context64.Dr7 & (1ll << 2 * i)) || + (!use64 && *(&context32.Dr0 + i) == addr && context32.Dr7 & (1ll << 2 * i))) + return i; + } + + // Get free DR + int freeIdx = pDR7->getFreeIndex(); + + // If all 4 registers are occupied - error + if (freeIdx < 0) + return STATUS_NO_MORE_ENTRIES; + + // Enable corresponding HWBP and local BP flag + + pDR7->l_enable = 1; + pDR7->setLocal( freeIdx, 1 ); + pDR7->setRW( freeIdx, static_cast(type) ); + pDR7->setLen( freeIdx, static_cast(length) ); + + use64 ? *(&context64.Dr0 + freeIdx) = addr : *(&context32.Dr0 + freeIdx) = static_cast(addr); + + // Write values to registers + status = use64 ? SetContext( context64, true ) : SetContext( context32, true ); + return call_result_t( freeIdx, status ); +} + +/// +/// Remove existing hardware breakpoint +/// +/// Breakpoint index +/// true on success +NTSTATUS Thread::RemoveHWBP( int idx ) +{ + if (idx < 0 || idx > 4) + return false; + + _CONTEXT64 context64 = { 0 }; + _CONTEXT32 context32 = { 0 }; + bool use64 = !_core->native()->GetWow64Barrier().x86OS; + auto status = use64 ? GetContext( context64, CONTEXT64_DEBUG_REGISTERS, true ) : GetContext( context32, CONTEXT_DEBUG_REGISTERS, true ); + auto pDR7 = use64 ? reinterpret_cast(&context64.Dr7) : reinterpret_cast(&context32.Dr7); + if (!NT_SUCCESS( status )) + return status; + + pDR7->setLocal( idx, 0 ); + pDR7->setLen( idx, 0 ); + pDR7->setRW( idx, 0 ); + if (pDR7->empty()) + pDR7->l_enable = 0; + + return use64 ? SetContext( context64 ) : SetContext( context32 ); +} + +/// +/// Remove existing hardware breakpoint +/// +/// Breakpoint address +/// true on success +NTSTATUS Thread::RemoveHWBP( ptr_t ptr ) +{ + _CONTEXT64 context64 = { 0 }; + _CONTEXT32 context32 = { 0 }; + bool use64 = !_core->native()->GetWow64Barrier().x86OS; + auto status = use64 ? GetContext( context64, CONTEXT64_DEBUG_REGISTERS, true ) : GetContext( context32, CONTEXT_DEBUG_REGISTERS, true ); + auto pDR7 = use64 ? reinterpret_cast(&context64.Dr7) : reinterpret_cast(&context32.Dr7); + if (!NT_SUCCESS( status )) + return false; + + // Search for breakpoint + for (int i = 0; i < 4; i++) + { + if ((&context64.Dr0)[i] == ptr || (&context32.Dr0)[i] == static_cast(ptr)) + { + use64 ? *(&context64.Dr0 + i) = 0 : *(&context32.Dr0 + i) = 0; + + pDR7->setLocal( i, 0 ); + pDR7->setLen( i, 0 ); + pDR7->setRW( i, 0 ); + if (pDR7->empty()) + pDR7->l_enable = 0; + + return use64 ? SetContext( context64 ) : SetContext( context32 ); + } + } + + return STATUS_NOT_FOUND; +} + +/// +/// Get thread exit code +/// +/// Thread exit code +DWORD Thread::ExitCode() const +{ + DWORD code = MAXULONG32_2; + GetExitCodeThread( _handle, &code ); + + return code; +} + +/// +/// Get thread creation time +/// +/// Thread creation time +uint64_t Thread::startTime() const +{ + FILETIME times[4] = { }; + + if (GetThreadTimes( _handle, ×[0], ×[1], ×[2], ×[3] )) + return (static_cast(times[0].dwHighDateTime) << 32) | times[0].dwLowDateTime; + + return MAXULONG64_2; +} + +/// +/// Get total execution time(user mode and kernel mode) +/// +/// Total execution time +uint64_t Thread::execTime() const +{ + FILETIME times[4] = { }; + + if (GetThreadTimes( _handle, ×[0], ×[1], ×[2], ×[3] )) + return ((static_cast(times[2].dwHighDateTime) << 32) | times[2].dwLowDateTime) + + ((static_cast(times[3].dwHighDateTime) << 32) | times[3].dwLowDateTime); + + return MAXULONG64_2; +} + +/// +/// Close handle +/// +void Thread::Close() +{ + _handle.reset(); + _id = 0; +} + +/// +/// GetThreadId support for XP +/// +/// Thread handle +/// Thread ID +DWORD Thread::GetThreadIdT( HANDLE hThread ) +{ + static auto pGetThreadId = (decltype(&GetThreadId))GetProcAddress( GetModuleHandleW( L"kernel32.dll" ), "GetThreadId" ); + if (pGetThreadId != nullptr) + { + return pGetThreadId( hThread ); + } + // XP version + else + { + _THREAD_BASIC_INFORMATION_T tbi = { 0 }; + ULONG bytes = 0; + + if (NT_SUCCESS( SAFE_NATIVE_CALL( NtQueryInformationThread, hThread, (THREADINFOCLASS)0, &tbi, (ULONG)sizeof( tbi ), &bytes ) )) + return tbi.ClientID.UniqueThread; + + return 0; + } +} + + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/Threads/Thread.h b/third/Blackbone/src/BlackBone/Process/Threads/Thread.h new file mode 100644 index 0000000000000000000000000000000000000000..2c8669298d5233c7643925df078d22c1f30a5a12 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/Threads/Thread.h @@ -0,0 +1,276 @@ +#pragma once + +#include "../../Config.h" +#include "../../Include/Winheaders.h" +#include "../../Include/NativeStructures.h" +#include "../../Include/CallResult.h" +#include "../../Include/HandleGuard.h" +#include "../../Include/Types.h" +#include "../../Misc/Utils.h" + +#include + +namespace blackbone +{ + +#define DEFAULT_ACCESS_T THREAD_SUSPEND_RESUME | \ + THREAD_GET_CONTEXT | \ + THREAD_SET_CONTEXT | \ + THREAD_QUERY_INFORMATION | \ + THREAD_TERMINATE | \ + SYNCHRONIZE + +#define MAXULONG64_2 ((uint64_t)~((uint64_t)0)) +#define MAXULONG32_2 ((uint32_t)~((uint32_t)0)) + + +// Breakpoint type +enum HWBPType +{ + hwbp_access = 3, // Read or write + hwbp_write = 1, // Write only + hwbp_execute = 0, // Execute only +}; + +enum HWBPLength +{ + hwbp_1 = 0, // 1 byte + hwbp_2 = 1, // 2 bytes + hwbp_4 = 3, // 4 bytes + hwbp_8 = 2, // 8 bytes +}; + + +/// +/// DR7 register bitfield +/// +struct regDR7 +{ + // + // Local/global enabled index + // + uint32_t l0 : 1; + uint32_t g0 : 1; + uint32_t l1 : 1; + uint32_t g1 : 1; + uint32_t l2 : 1; + uint32_t g2 : 1; + uint32_t l3 : 1; + uint32_t g3 : 1; + + uint32_t l_enable : 1; // Local breakpoints, obsolete for P6+ + uint32_t g_enable : 1; // Global breakpoints, obsolete for P6+ + uint32_t one : 1; // Reserved + uint32_t rtm : 1; // Restricted transactional memory + uint32_t ice : 1; // ICE debugger + uint32_t gd : 1; // General detect table + uint32_t tr1 : 1; // Trace 1 + uint32_t tr2 : 1; // Trace2 + + // + // Breakpoint type/length + // + uint32_t rw0 : 2; + uint32_t len0 : 2; + uint32_t rw1 : 2; + uint32_t len1 : 2; + uint32_t rw2 : 2; + uint32_t len2 : 2; + uint32_t rw3 : 2; + uint32_t len3 : 2; + + inline void setLocal( int idx, int val ) { idx == 0 ? l0 = val : (idx == 1 ? l1 = val : (idx == 2 ? l2 = val : l3 = val)); } + inline void setRW ( int idx, int val ) { idx == 0 ? rw0 = val : (idx == 1 ? rw1 = val : (idx == 2 ? rw2 = val : rw3 = val)); } + inline void setLen ( int idx, int val ) { idx == 0 ? len0 = val : (idx == 1 ? len1 = val : (idx == 2 ? len2 = val : len3 = val)); } + + inline bool empty() const { return (l0 | l1 | l2 | l3) ? false : true; } + inline int getFreeIndex() const { return !l0 ? 0 : (!l1 ? 1 : (!l2 ? 2 : (!l3 ? 3 : -1))); } +}; + + +/// +/// Thread management +/// +class Thread +{ +public: + BLACKBONE_API Thread( DWORD id, class ProcessCore* hProcess, DWORD access = DEFAULT_ACCESS_T ); + BLACKBONE_API Thread( HANDLE handle, class ProcessCore* hProcess ); + BLACKBONE_API ~Thread(); + + BLACKBONE_API Thread( const Thread& ) = delete; + BLACKBONE_API Thread& operator =( const Thread& ) = delete; + + BLACKBONE_API Thread( Thread&& ) = default; + BLACKBONE_API Thread& operator =( Thread&& ) = default; + + /// + /// Get thread ID + /// + /// Thread ID + BLACKBONE_API DWORD id() const { return _id; } + + /// + /// Get thread handle + /// + /// Thread hande + BLACKBONE_API HANDLE handle() const { return _handle; } + + /// + /// Check if thread exists + /// + /// true if thread exists + BLACKBONE_API bool valid() const { return (_handle && ExitCode() == STILL_ACTIVE); } + + /// + /// Get WOW64 TEB + /// + /// Process TEB + /// TEB pointer + BLACKBONE_API ptr_t teb( _TEB32* pteb ) const; + + /// + /// Get Native TEB + /// + /// Process TEB + /// TEB pointer + BLACKBONE_API ptr_t teb( _TEB64* pteb ) const; + + /// + /// Get TEB + /// + /// TEB pointer + BLACKBONE_API ptr_t teb() const { return teb( (TEB_T*)nullptr ); } + + /// + /// Get thread creation time + /// + /// Thread creation time + BLACKBONE_API uint64_t startTime() const; + + /// + /// Get total execution time(user mode and kernel mode) + /// + /// Total execution time + BLACKBONE_API uint64_t execTime() const; + + /// + /// Suspend thread + /// + /// true on success + BLACKBONE_API bool Suspend(); + + /// + /// Resumes thread. + /// + /// true on success + BLACKBONE_API bool Resume(); + + /// + /// Check if thread is suspended + /// + /// true if suspended + BLACKBONE_API bool Suspended(); + + /// + /// Get WOW64 thread context + /// + /// Returned context + /// Context flags. + /// true if thread shouldn't be suspended before retrieving context + /// Status code + BLACKBONE_API NTSTATUS GetContext( _CONTEXT32& ctx, DWORD flags = CONTEXT_ALL, bool dontSuspend = false ); + + /// + /// Get native thread context + /// + /// Returned context + /// Context flags. + /// true if thread shouldn't be suspended before retrieving context + /// Status code + BLACKBONE_API NTSTATUS GetContext( _CONTEXT64& ctx, DWORD flags = CONTEXT64_ALL, bool dontSuspend = false ); + + /// + /// Set WOW64 thread context + /// + /// Context to set + /// true if thread shouldn't be suspended before retrieving context + /// Status code + BLACKBONE_API NTSTATUS SetContext( _CONTEXT32& ctx, bool dontSuspend = false ); + + /// + /// Set native thread context + /// + /// Context to set + /// true if thread shouldn't be suspended before retrieving context + /// Status code + BLACKBONE_API NTSTATUS SetContext( _CONTEXT64& ctx, bool dontSuspend = false ); + + /// + /// Terminate thread + /// + /// Exit code + /// Status code + BLACKBONE_API NTSTATUS Terminate( DWORD code = 0 ); + + /// + /// Join thread + /// + /// Join timeout + /// true on success + BLACKBONE_API bool Join( int timeout = INFINITE ); + + /// + /// Get thread exit code + /// + /// Thread exit code + BLACKBONE_API DWORD ExitCode() const; + + /// + /// Add hardware breakpoint to thread + /// + /// Breakpoint address + /// Breakpoint type(read/write/execute) + /// Number of bytes to include into breakpoint + /// Index of used breakpoint; -1 if failed + BLACKBONE_API call_result_t AddHWBP( ptr_t addr, HWBPType type, HWBPLength length ); + + /// + /// Remove existing hardware breakpoint + /// + /// Breakpoint index + /// Status code + BLACKBONE_API NTSTATUS RemoveHWBP( int idx ); + + /// + /// Remove existing hardware breakpoint + /// + /// Breakpoint address + /// Status code + BLACKBONE_API NTSTATUS RemoveHWBP( ptr_t ptr ); + + /// + /// Close handle + /// + BLACKBONE_API void Close(); + + BLACKBONE_API inline bool operator ==( const Thread& other ) { return (_id == other._id); } + +private: + /// + /// GetThreadId support for XP + /// + /// Thread handle + /// Thread ID + DWORD GetThreadIdT( HANDLE hThread ); + +private: + class ProcessCore* _core; // Core routines + + DWORD _id = 0; // Thread ID + Handle _handle; // Thread handle +}; + +using ThreadPtr = std::shared_ptr; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/Threads/Threads.cpp b/third/Blackbone/src/BlackBone/Process/Threads/Threads.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ba5b143dbbdaa21ba1b78be75d38fcffbcfcef42 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/Threads/Threads.cpp @@ -0,0 +1,178 @@ +#include "Threads.h" +#include "../ProcessCore.h" +#include "../../DriverControl/DriverControl.h" + +#include +#include +#include + +namespace blackbone +{ + +ProcessThreads::ProcessThreads( ProcessCore& core ) + : _core( core ) +{ +} + +ProcessThreads::~ProcessThreads() +{ +} + +/// +/// Create the thread. +/// +/// Thread enty point +/// Thread argument. +/// Thread creation flags +/// New thread object +call_result_t ProcessThreads::CreateNew( ptr_t threadProc, ptr_t arg, enum CreateThreadFlags flags /*= NoThreadFlags*/ ) +{ + HANDLE hThd = NULL; + auto status = _core.native()->CreateRemoteThreadT( hThd, threadProc, arg, flags, THREAD_ALL_ACCESS ); + if (!NT_SUCCESS( status )) + { + // Ensure full thread access + status = _core.native()->CreateRemoteThreadT( hThd, threadProc, arg, flags, THREAD_QUERY_LIMITED_INFORMATION ); + if (NT_SUCCESS( status )) + { + if (Driver().loaded()) + status = Driver().PromoteHandle( GetCurrentProcessId(), hThd, THREAD_ALL_ACCESS ); + } + } + + if (!NT_SUCCESS( status )) + return status; + + return std::make_shared( hThd, &_core ); +} + +/// +/// Gets all process threads +/// +/// Threads collection +std::vector ProcessThreads::getAll() const +{ + std::vector result; + auto hThreadSnapshot = SnapHandle( CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ) ); + if (!hThreadSnapshot) + return result; + + THREADENTRY32 tEntry = { 0 }; + tEntry.dwSize = sizeof( THREADENTRY32 ); + + // Iterate threads + for (BOOL success = Thread32First( hThreadSnapshot, &tEntry ); + success != FALSE; + success = Thread32Next( hThreadSnapshot, &tEntry )) + { + if (tEntry.th32OwnerProcessID != _core.pid()) + continue; + + result.emplace_back( std::make_shared( tEntry.th32ThreadID, &_core ) ); + } + + return result; +} + +/// +/// Get main process thread +/// +/// Pointer to thread object, nullptr if failed +ThreadPtr ProcessThreads::getMain() const +{ + uint64_t mintime = MAXULONG64_2; + auto threads = getAll(); + ThreadPtr result = !threads.empty() ? threads.front() : threads.front(); + + for (const auto& thread : threads) + { + uint64_t time = thread->startTime(); + if (time < mintime) + { + mintime = time; + result = thread; + } + } + + return result; +} + +/// +/// Get least executed thread +/// +/// Pointer to thread object, nullptr if failed +ThreadPtr ProcessThreads::getLeastExecuted() const +{ + uint64_t mintime = MAXULONG64_2; + auto threads = getAll(); + ThreadPtr result = !threads.empty() ? threads.front() : threads.front(); + + for (const auto& thread : threads) + { + uint64_t time = thread->execTime(); + if (time < mintime) + { + mintime = time; + result = thread; + } + } + + return result; +} + +/// +/// Get most executed thread +/// +/// Pointer to thread object, nullptr if failed +ThreadPtr ProcessThreads::getMostExecuted() const +{ + uint64_t maxtime = 0; + auto threads = getAll(); + ThreadPtr result = !threads.empty() ? threads.front() : threads.front(); + + for (const auto& thread : threads) + { + if (thread->id() == GetCurrentThreadId()) + continue; + + uint64_t time = thread->execTime(); + if (thread->id() != GetCurrentThreadId() && time >= maxtime) + { + maxtime = time; + result = thread; + } + } + + return result; +} + +/// +/// Get random thread +/// +/// Pointer to thread object, nullptr if failed +ThreadPtr ProcessThreads::getRandom() const +{ + auto threads = getAll(); + if (threads.empty()) + return nullptr; + + static std::random_device rd; + std::uniform_int_distribution dist( 0, threads.size() - 1 ); + + return threads[dist(rd)]; +} + +/// +/// Get thread by ID +/// +/// Thread ID +/// Pointer to thread object, nullptr if failed +ThreadPtr ProcessThreads::get( DWORD id ) const +{ + auto threads = getAll(); + auto iter = std::find_if( threads.begin(), threads.end(), [id]( const auto& thread ) { return thread->id() == id; } ); + + return iter != threads.end() ? *iter : nullptr; +} + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Process/Threads/Threads.h b/third/Blackbone/src/BlackBone/Process/Threads/Threads.h new file mode 100644 index 0000000000000000000000000000000000000000..f34152c6aa556ca9ee2a0fab2c755d5efd5b98b5 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Process/Threads/Threads.h @@ -0,0 +1,75 @@ +#pragma once + +#include "../../Include/Winheaders.h" +#include "Thread.h" + +#include +#include + +namespace blackbone +{ + +class ProcessThreads +{ +public: + BLACKBONE_API ProcessThreads( class ProcessCore& core ); + BLACKBONE_API ~ProcessThreads(); + + ProcessThreads( const ProcessThreads& ) = delete; + ProcessThreads& operator =( const ProcessThreads& ) = delete; + + /// + /// Create the thread. + /// + /// Thread enty point + /// Thread argument. + /// Thread creation flags + /// New thread object + BLACKBONE_API call_result_t CreateNew( + ptr_t threadProc, + ptr_t arg, + enum CreateThreadFlags flags = static_cast(0) + ); + + /// + /// Gets all process threads + /// + /// Threads collection + BLACKBONE_API std::vector getAll() const; + + /// + /// Get main process thread + /// + /// Pointer to thread object, nullptr if failed + BLACKBONE_API ThreadPtr getMain() const; + + /// + /// Get least executed thread + /// + /// Pointer to thread object, nullptr if failed + BLACKBONE_API ThreadPtr getLeastExecuted() const; + + /// + /// Get most executed thread + /// + /// Pointer to thread object, nullptr if failed + BLACKBONE_API ThreadPtr getMostExecuted() const; + + /// + /// Get random thread + /// + /// Pointer to thread object, nullptr if failed + BLACKBONE_API ThreadPtr getRandom() const; + + /// + /// Get thread by ID + /// + /// Thread ID + /// Pointer to thread object, nullptr if failed + BLACKBONE_API ThreadPtr get( DWORD id ) const; + +private: + class ProcessCore& _core; // Core process functions +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Subsystem/NativeSubsystem.cpp b/third/Blackbone/src/BlackBone/Subsystem/NativeSubsystem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..651dbadd1e816b32006af8ca91dfbdfd905cec51 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Subsystem/NativeSubsystem.cpp @@ -0,0 +1,700 @@ +#include "NativeSubsystem.h" +#include "../Misc/Utils.h" +#include "../Misc/DynImport.h" +#include "../Misc/Trace.hpp" +#include "../Include/Macro.h" + +#include +#include + +namespace blackbone +{ + +Native::Native( HANDLE hProcess, bool x86OS /*= false*/ ) + : _hProcess( hProcess ) +{ + SYSTEM_INFO info = { { 0 } }; + GetNativeSystemInfo( &info ); + _pageSize = info.dwPageSize; + + // x86 OS, emulate WOW64 processes + if (x86OS) + { + _wowBarrier.sourceWow64 = true; + _wowBarrier.targetWow64 = true; + _wowBarrier.type = wow_32_32; + _wowBarrier.x86OS = true; + } + else + { + BOOL wowSrc = FALSE, wowTgt = FALSE; + IsWow64Process( GetCurrentProcess(), &wowSrc ); + IsWow64Process( _hProcess, &wowTgt ); + + _wowBarrier.sourceWow64 = (wowSrc == TRUE); + _wowBarrier.targetWow64 = (wowTgt == TRUE); + + if (wowSrc == TRUE && wowTgt == TRUE) + _wowBarrier.type = wow_32_32; + else if (wowSrc == FALSE && wowTgt == FALSE) + _wowBarrier.type = wow_64_64; + else if (wowSrc == TRUE) + { + _wowBarrier.type = wow_32_64; + _wowBarrier.mismatch = true; + } + else + { + _wowBarrier.type = wow_64_32; + _wowBarrier.mismatch = true; + } + } +} + +/* +*/ +Native::~Native() +{ +} + +/// +/// Allocate virtual memory +/// +/// Allocation address +/// Region size +/// Allocation type +/// Memory protection +/// Status code +NTSTATUS Native::VirtualAllocExT( ptr_t& lpAddress, size_t dwSize, DWORD flAllocationType, DWORD flProtect ) +{ + SetLastNtStatus( STATUS_SUCCESS ); + lpAddress = reinterpret_cast(VirtualAllocEx( _hProcess, reinterpret_cast(lpAddress), dwSize, flAllocationType, flProtect )); + return LastNtStatus(); +} + + +/// +/// Free virtual memory +/// +/// Memory address +/// Region size +/// Memory release type. +/// Status code +NTSTATUS Native::VirtualFreeExT( ptr_t lpAddress, size_t dwSize, DWORD dwFreeType ) +{ + SetLastNtStatus( STATUS_SUCCESS ); + VirtualFreeEx( _hProcess, reinterpret_cast(lpAddress), dwSize, dwFreeType ); + return LastNtStatus(); +} + +/// +/// Query virtual memory +/// +/// Address to query +/// Retrieved memory info +/// Status code +NTSTATUS Native::VirtualQueryExT( ptr_t lpAddress, PMEMORY_BASIC_INFORMATION64 lpBuffer ) +{ + SetLastNtStatus( STATUS_SUCCESS ); + VirtualQueryEx( + _hProcess, reinterpret_cast(lpAddress), + reinterpret_cast(lpBuffer), + sizeof( MEMORY_BASIC_INFORMATION ) + ); + + return LastNtStatus(); +} + +/// +/// Query virtual memory +/// +/// Address to query +/// Retrieved memory info +/// Status code +NTSTATUS Native::VirtualQueryExT( ptr_t lpAddress, MEMORY_INFORMATION_CLASS infoClass, LPVOID lpBuffer, size_t bufSize ) +{ + SIZE_T retLen = 0; + + SetLastNtStatus( STATUS_SUCCESS ); + return SAFE_NATIVE_CALL( + NtQueryVirtualMemory, _hProcess, reinterpret_cast(lpAddress), + infoClass, lpBuffer, bufSize, &retLen + ); +} + +/// +/// Change memory protection +/// +/// Memory address. +/// Region size +/// New protection. +/// Old protection +/// Status code +NTSTATUS Native::VirtualProtectExT( ptr_t lpAddress, DWORD64 dwSize, DWORD flProtect, DWORD* flOld ) +{ + DWORD junk = 0; + if (!flOld) + flOld = &junk; + + SetLastNtStatus( STATUS_SUCCESS ); + VirtualProtectEx( _hProcess, reinterpret_cast(lpAddress), static_cast(dwSize), flProtect, flOld ); + + return LastNtStatus(); +} + +/// +/// Read virtual memory +/// +/// Memory address +/// Output buffer +/// Number of bytes to read +/// Mumber of bytes read +/// Status code +NTSTATUS Native::ReadProcessMemoryT( ptr_t lpBaseAddress, LPVOID lpBuffer, size_t nSize, DWORD64 *lpBytes /*= nullptr */ ) +{ + SetLastNtStatus( STATUS_SUCCESS ); + ReadProcessMemory( _hProcess, reinterpret_cast(lpBaseAddress), lpBuffer, nSize, reinterpret_cast(lpBytes) ); + return LastNtStatus(); +} + +/// +/// Write virtual memory +/// +/// Memory address +/// Buffer to write +/// Number of bytes to read +/// Mumber of bytes read +/// Status code +NTSTATUS Native::WriteProcessMemoryT( ptr_t lpBaseAddress, LPCVOID lpBuffer, size_t nSize, DWORD64 *lpBytes /*= nullptr */ ) +{ + SetLastNtStatus( STATUS_SUCCESS ); + WriteProcessMemory( _hProcess, reinterpret_cast(lpBaseAddress), lpBuffer, nSize, reinterpret_cast(lpBytes) ); + return LastNtStatus(); +} + +/// +/// Call NtQueryInformationProcess for underlying process +/// +/// Information class +/// Output buffer +/// Buffer size +/// Status code +NTSTATUS Native::QueryProcessInfoT( PROCESSINFOCLASS infoClass, LPVOID lpBuffer, uint32_t bufSize ) +{ + ULONG length = 0; + return SAFE_NATIVE_CALL( NtQueryInformationProcess, _hProcess, infoClass, lpBuffer, bufSize, &length ); +} + +/// +/// Call NtSetInformationProcess for underlying process +/// +/// Information class +/// Input buffer +/// Buffer size +/// Status code +NTSTATUS Native::SetProcessInfoT( PROCESSINFOCLASS infoClass, LPVOID lpBuffer, uint32_t bufSize ) +{ + return SAFE_NATIVE_CALL( NtSetInformationProcess, _hProcess, infoClass, lpBuffer, bufSize ); +} + +/// +/// Creates new thread in the remote process +/// +/// Created thread handle +/// Thread entry point +/// Thread argument +/// Creation flags +/// Access override +/// Status code +NTSTATUS Native::CreateRemoteThreadT( HANDLE& hThread, ptr_t entry, ptr_t arg, CreateThreadFlags flags, DWORD access /*= THREAD_ALL_ACCESS*/ ) +{ + SetLastNtStatus( STATUS_SUCCESS ); + NTSTATUS status = 0; + auto pCreateThread = GET_IMPORT( NtCreateThreadEx ); + + if (pCreateThread) + { + status = pCreateThread( + &hThread, access, NULL, + _hProcess, reinterpret_cast(entry), + reinterpret_cast(arg), static_cast(flags), + 0, 0x1000, 0x100000, NULL + ); + + if (!NT_SUCCESS( status )) + hThread = NULL; + } + else + { + DWORD win32Flags = 0; + + if (flags & CreateSuspended) + win32Flags = CREATE_SUSPENDED; + + hThread = CreateRemoteThread( + _hProcess, NULL, 0, reinterpret_cast(entry), + reinterpret_cast(arg), win32Flags, NULL + ); + + status = LastNtStatus(); + } + + return status; +} + +/// +/// Get native thread context +/// +/// Thread handle. +/// Thread context +/// Status code +NTSTATUS Native::GetThreadContextT( HANDLE hThread, _CONTEXT64& ctx ) +{ + SetLastNtStatus( STATUS_SUCCESS ); + GetThreadContext( hThread, reinterpret_cast(&ctx) ); + return LastNtStatus(); +} + +/// +/// Get WOW64 thread context +/// +/// Thread handle. +/// Thread context +/// Status code +NTSTATUS Native::GetThreadContextT( HANDLE hThread, _CONTEXT32& ctx ) +{ + // Target process is x64. WOW64 CONTEXT is not available. + if (_wowBarrier.targetWow64 == false) + { + return 0; + } + else + { + SetLastNtStatus( STATUS_SUCCESS ); + SAFE_CALL( Wow64GetThreadContext, hThread, reinterpret_cast(&ctx) ); + return LastNtStatus(); + } +} + +/// +/// Set native thread context +/// +/// Thread handle. +/// Thread context +/// Status code +NTSTATUS Native::SetThreadContextT( HANDLE hThread, _CONTEXT64& ctx ) +{ + SetLastNtStatus( STATUS_SUCCESS ); + SetThreadContext( hThread, reinterpret_cast(&ctx) ); + return LastNtStatus(); +} + +/// +/// Set WOW64 thread context +/// +/// Thread handle. +/// Thread context +/// Status code +NTSTATUS Native::SetThreadContextT( HANDLE hThread, _CONTEXT32& ctx ) +{ + // Target process is x64. 32bit CONTEXT is not available. + if (_wowBarrier.targetWow64 == false) + { + return 0; + } + else + { + SetLastNtStatus( STATUS_SUCCESS ); + SAFE_CALL( Wow64SetThreadContext, hThread, reinterpret_cast(&ctx)); + return LastNtStatus(); + } +} + +/// +/// NtQueueApcThread +/// +/// Thread handle. +/// APC function +/// APC argument +/// Status code +NTSTATUS Native::QueueApcT( HANDLE hThread, ptr_t func, ptr_t arg ) +{ + if (_wowBarrier.type == wow_64_32) + { + return SAFE_NATIVE_CALL( RtlQueueApcWow64Thread, hThread, reinterpret_cast(func), reinterpret_cast(arg), nullptr, nullptr ); + //func = (~func) << 2; + } + + return SAFE_NATIVE_CALL( NtQueueApcThread, hThread, reinterpret_cast(func), reinterpret_cast(arg), nullptr, nullptr ); +} + +/// +/// Get WOW64 PEB +/// +/// Retrieved PEB +/// PEB pointer +ptr_t Native::getPEB( _PEB32* ppeb ) +{ + // Target process is x64. PEB32 is not available. + if (_wowBarrier.targetWow64 == false) + { + return 0; + } + else + { + ptr_t ptr = 0; + if (NT_SUCCESS( SAFE_NATIVE_CALL( NtQueryInformationProcess, _hProcess, ProcessWow64Information, &ptr, (ULONG)sizeof( ptr ), nullptr ) ) && ppeb) + ReadProcessMemory( _hProcess, reinterpret_cast(ptr), ppeb, sizeof(_PEB32), NULL ); + + return ptr; + } +} + +/// +/// Get native PEB +/// +/// Retrieved PEB +/// PEB pointer +ptr_t Native::getPEB( _PEB64* ppeb ) +{ + PROCESS_BASIC_INFORMATION pbi = { 0 }; + ULONG bytes = 0; + + if (NT_SUCCESS( SAFE_NATIVE_CALL( NtQueryInformationProcess, _hProcess, ProcessBasicInformation, &pbi, (ULONG)sizeof( pbi ), &bytes ) ) && ppeb) + ReadProcessMemory( _hProcess, pbi.PebBaseAddress, ppeb, sizeof(_PEB32), NULL ); + + return reinterpret_cast(pbi.PebBaseAddress); +} + +/// +/// Get WOW64 TEB +/// +/// Retrieved TEB +/// TEB pointer +ptr_t Native::getTEB( HANDLE hThread, _TEB32* pteb ) +{ + // Target process is x64. TEB32 is not available. + if (_wowBarrier.targetWow64 == false) + { + return 0; + } + // Retrieving TEB32 from x64 process. + else + { + _THREAD_BASIC_INFORMATION_T tbi = { 0 }; + ULONG bytes = 0; + + if (NT_SUCCESS( SAFE_NATIVE_CALL( NtQueryInformationThread, hThread, (THREADINFOCLASS)0, &tbi, (ULONG)sizeof( tbi ), &bytes ) ) && pteb) + ReadProcessMemory( _hProcess, (const uint8_t*)tbi.TebBaseAddress + 0x2000, pteb, sizeof(_TEB32), NULL ); + + return tbi.TebBaseAddress + 0x2000; + } + +} + +/// +/// Get native TEB +/// +/// Retrieved TEB +/// TEB pointer +ptr_t Native::getTEB( HANDLE hThread, _TEB64* pteb ) +{ + _THREAD_BASIC_INFORMATION_T tbi = { 0 }; + ULONG bytes = 0; + + if (NT_SUCCESS( SAFE_NATIVE_CALL( NtQueryInformationThread, hThread, (THREADINFOCLASS)0, &tbi, (ULONG)sizeof( tbi ), &bytes ) ) && pteb) + ReadProcessMemory( _hProcess, reinterpret_cast(tbi.TebBaseAddress), pteb, sizeof(_TEB64), NULL ); + + return tbi.TebBaseAddress; +} + +/// +/// Enumerate valid memory regions +/// +/// If true - non-allocated regions will be included in list +/// Found regions +std::vector Native::EnumRegions( bool includeFree /*= false*/ ) +{ + MEMORY_BASIC_INFORMATION64 mbi = { 0 }; + std::vector results; + + for (ptr_t memptr = minAddr(); memptr < maxAddr(); memptr = mbi.BaseAddress + mbi.RegionSize) + { + auto status = VirtualQueryExT( memptr, &mbi ); + + if (status == STATUS_INVALID_PARAMETER || status == STATUS_ACCESS_DENIED) + break; + else if (status != STATUS_SUCCESS) + continue; + + // Filter, if required + if (includeFree || mbi.State & (MEM_COMMIT | MEM_RESERVE)) + results.emplace_back( mbi ); + } + + return results; +} + +/// +/// Enumerate process modules +/// +/// Found modules +/// Module count +template +std::vector Native::EnumModulesT() +{ + NTSTATUS status = STATUS_SUCCESS; + _PEB_T peb = { }; + _PEB_LDR_DATA2_T ldr = { }; + std::vector result; + + if (getPEB( &peb ) != 0 && ReadProcessMemoryT( peb.Ldr, &ldr, sizeof( ldr ), 0 ) == STATUS_SUCCESS) + { + for (T head = ldr.InLoadOrderModuleList.Flink; + NT_SUCCESS( status ) && head != (peb.Ldr + FIELD_OFFSET( _PEB_LDR_DATA2_T, InLoadOrderModuleList )); + status = ReadProcessMemoryT( static_cast(head), &head, sizeof( head ) )) + { + ModuleData data; + wchar_t localPath[512] = { 0 }; + _LDR_DATA_TABLE_ENTRY_BASE_T localdata = { { 0 } }; + + ReadProcessMemoryT( head, &localdata, sizeof( localdata ), 0 ); + ReadProcessMemoryT( localdata.FullDllName.Buffer, localPath, localdata.FullDllName.Length ); + + data.baseAddress = localdata.DllBase; + data.size = localdata.SizeOfImage; + data.fullPath = Utils::ToLower( localPath ); + data.name = Utils::StripPath( data.fullPath ); + data.type = (sizeof( T ) < sizeof( uint64_t )) ? mt_mod32 : mt_mod64; + data.ldrPtr = static_cast(head); + data.manual = false; + + result.emplace_back( std::make_shared( data ) ); + } + } + else + { + BLACKBONE_TRACE( L"NativeModules: Failed to get PEB/LDR address. Not yet initialized" ); + } + + return result; +} + +/// +/// Enum process section objects +/// +/// Found modules +/// Sections count +std::vector Native::EnumSections() +{ + MEMORY_BASIC_INFORMATION64 mbi = { 0 }; + ptr_t lastBase = 0; + std::vector result; + + for (ptr_t memptr = minAddr(); memptr < maxAddr(); memptr = mbi.BaseAddress + mbi.RegionSize) + { + auto status = VirtualQueryExT( memptr, &mbi ); + + if (status == STATUS_INVALID_PARAMETER || status == STATUS_ACCESS_DENIED || status == STATUS_PROCESS_IS_TERMINATING) + break; + else if (status != STATUS_SUCCESS) + continue; + + // Filter non-section regions + if (mbi.State != MEM_COMMIT || mbi.Type != SEC_IMAGE || lastBase == mbi.AllocationBase) + continue; + + uint8_t buf[0x1000] = { 0 }; + _UNICODE_STRING_T* ustr = (decltype(ustr))(buf + 0x800); + + status = VirtualQueryExT( mbi.AllocationBase, MemorySectionName, ustr, sizeof(buf) / 2 ); + + // Get additional + if (NT_SUCCESS( status )) + { + ModuleData data; + + IMAGE_DOS_HEADER* phdrDos = reinterpret_cast(buf); + IMAGE_NT_HEADERS32 *phdrNt32 = nullptr; + IMAGE_NT_HEADERS64 *phdrNt64 = nullptr; + + if (ReadProcessMemoryT( mbi.AllocationBase, buf, 0x800 ) != STATUS_SUCCESS) + continue; + + phdrNt32 = reinterpret_cast(buf + phdrDos->e_lfanew); + phdrNt64 = reinterpret_cast(phdrNt32); + + // If no PE header present + if (phdrDos->e_magic != IMAGE_DOS_SIGNATURE || phdrNt32->Signature != IMAGE_NT_SIGNATURE) + { + // Iterate until region end + MEMORY_BASIC_INFORMATION64 mbi2 = { 0 }; + for (ptr_t memptr2 = mbi.AllocationBase; memptr2 < maxAddr(); memptr2 = mbi2.BaseAddress + mbi2.RegionSize) + if (!NT_SUCCESS( VirtualQueryExT( memptr2, &mbi2 ) ) || mbi2.Type != SEC_IMAGE) + { + data.size = static_cast(mbi2.BaseAddress - mbi.AllocationBase); + break; + } + + data.type = mt_unknown; + } + else if( phdrNt32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC ) + { + data.size = phdrNt32->OptionalHeader.SizeOfImage; + data.type = mt_mod32; + } + else if (phdrNt32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) + { + data.size = phdrNt64->OptionalHeader.SizeOfImage; + data.type = mt_mod64; + } + else + continue; + + // Hack for x86 OS + if (_wowBarrier.x86OS == true) + { + _UNICODE_STRING_T* ustr32 = reinterpret_cast<_UNICODE_STRING_T*>(ustr); + data.fullPath = Utils::ToLower( reinterpret_cast((uintptr_t)ustr32->Buffer) ); + } + else + data.fullPath = Utils::ToLower( reinterpret_cast((uintptr_t)ustr->Buffer) ); + + data.name = Utils::StripPath( data.fullPath ); + data.baseAddress = mbi.AllocationBase; + data.ldrPtr = 0; + data.manual = false; + + result.emplace_back( std::make_shared( data ) ); + } + + lastBase = mbi.AllocationBase; + } + + return result; +} + +/// +/// Enum pages containing valid PE headers +/// +/// Found modules +/// Sections count +std::vector Native::EnumPEHeaders() +{ + MEMORY_BASIC_INFORMATION64 mbi = { 0 }; + uint8_t buf[0x1000]; + ptr_t lastBase = 0; + std::vector result; + + for (ptr_t memptr = minAddr(); memptr < maxAddr(); memptr = mbi.BaseAddress + mbi.RegionSize) + { + auto status = VirtualQueryExT( memptr, &mbi ); + + if (status == STATUS_INVALID_PARAMETER || status == STATUS_ACCESS_DENIED || status == STATUS_PROCESS_IS_TERMINATING) + break; + else if (status != STATUS_SUCCESS) + continue; + + // Filter regions + if (mbi.State != MEM_COMMIT || + mbi.AllocationProtect == PAGE_NOACCESS || + mbi.AllocationProtect & PAGE_GUARD || + lastBase == mbi.AllocationBase) + { + continue; + } + + ModuleData data; + + IMAGE_DOS_HEADER* phdrDos = reinterpret_cast(buf); + IMAGE_NT_HEADERS32 *phdrNt32 = nullptr; + IMAGE_NT_HEADERS64 *phdrNt64 = nullptr; + + if (ReadProcessMemoryT( mbi.AllocationBase, buf, 0x1000 ) != STATUS_SUCCESS) + continue; + + phdrNt32 = reinterpret_cast(buf + phdrDos->e_lfanew); + phdrNt64 = reinterpret_cast(phdrNt32); + + if (phdrDos->e_magic != IMAGE_DOS_SIGNATURE || phdrNt32->Signature != IMAGE_NT_SIGNATURE) + continue; + + if (phdrNt32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + data.size = phdrNt32->OptionalHeader.SizeOfImage; + data.type = mt_mod32; + } + else if (phdrNt32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) + { + data.size = phdrNt64->OptionalHeader.SizeOfImage; + data.type = mt_mod64; + } + + data.baseAddress = mbi.AllocationBase; + data.ldrPtr = 0; + data.manual = false; + + // Try to get section name + _UNICODE_STRING_T* ustr = (decltype(ustr))buf; + status = VirtualQueryExT( mbi.AllocationBase, MemorySectionName, ustr, sizeof(buf) ); + + if (status == STATUS_SUCCESS) + { + // Hack for x86 OS + if (_wowBarrier.x86OS == true) + { + _UNICODE_STRING_T* ustr32 = reinterpret_cast<_UNICODE_STRING_T*>(ustr); + data.fullPath = Utils::ToLower( reinterpret_cast((uintptr_t)ustr32->Buffer) ); + } + else + data.fullPath = Utils::ToLower( reinterpret_cast((uintptr_t)ustr->Buffer) ); + + data.name = Utils::StripPath( data.fullPath ); + } + else + { + wchar_t name[64] = { 0 }; + wsprintfW( name, L"Unknown_0x%I64x", data.baseAddress ); + + data.fullPath = name; + data.name = data.fullPath; + } + + result.emplace_back( std::make_shared( data ) ); + + lastBase = mbi.AllocationBase; + } + + return result; +} + +/// +/// Enumerate process modules +/// +/// Found modules +/// Module type: x86 or x64 +/// Module count +std::vector Native::EnumModules( eModSeachType search/*= LdrList*/, eModType mtype /*= mt_default */ ) +{ + if (search == LdrList) + { + // Detect module type + if (mtype == mt_default) + mtype = _wowBarrier.targetWow64 ? mt_mod32 : mt_mod64; + + return CALL_64_86( mtype == mt_mod64, EnumModulesT ); + } + else if(search == Sections) + { + return EnumSections(); + } + else if(search == PEHeaders) + { + return EnumPEHeaders(); + } + + return std::vector(); +} + + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Subsystem/NativeSubsystem.h b/third/Blackbone/src/BlackBone/Subsystem/NativeSubsystem.h new file mode 100644 index 0000000000000000000000000000000000000000..bf5c39351288a590b55357df7027d9ece9cd72e5 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Subsystem/NativeSubsystem.h @@ -0,0 +1,260 @@ +#pragma once + +#include "../Include/Winheaders.h" +#include "../Include/Types.h" +#include "../Include/Macro.h" + +#include +#include +#include +#include +#include + + +namespace blackbone +{ + +enum CreateThreadFlags +{ + NoThreadFlags = 0x0000, + CreateSuspended = 0x0001, + NoDllCallbacks = 0x0002, + HideFromDebug = 0x0004, +}; + +ENUM_OPS(CreateThreadFlags) + +class Native +{ +public: + BLACKBONE_API Native( HANDLE hProcess, bool x86OS = false ); + BLACKBONE_API ~Native(); + + BLACKBONE_API inline const Wow64Barrier& GetWow64Barrier() const { return _wowBarrier; } + + /// + /// Allocate virtual memory + /// + /// Allocation address + /// Region size + /// Allocation type + /// Memory protection + /// Status code + virtual NTSTATUS VirtualAllocExT( ptr_t& lpAddress, size_t dwSize, DWORD flAllocationType, DWORD flProtect ); + + /// + /// Free virtual memory + /// + /// Memory address + /// Region size + /// Memory release type. + /// Status code + virtual NTSTATUS VirtualFreeExT( ptr_t lpAddress, size_t dwSize, DWORD dwFreeType ); + + /// + /// Change memory protection + /// + /// Memory address. + /// Region size + /// New protection. + /// Old protection + /// Status code + virtual NTSTATUS VirtualProtectExT( ptr_t lpAddress, DWORD64 dwSize, DWORD flProtect, DWORD* flOld ); + + /// + /// Read virtual memory + /// + /// Memory address + /// Output buffer + /// Number of bytes to read + /// Mumber of bytes read + /// Status code + virtual NTSTATUS ReadProcessMemoryT( ptr_t lpBaseAddress, LPVOID lpBuffer, size_t nSize, DWORD64 *lpBytes = nullptr ); + + /// + /// Write virtual memory + /// + /// Memory address + /// Buffer to write + /// Number of bytes to read + /// Mumber of bytes read + /// Status code + virtual NTSTATUS WriteProcessMemoryT( ptr_t lpBaseAddress, LPCVOID lpBuffer, size_t nSize, DWORD64 *lpBytes = nullptr ); + + /// + /// Query virtual memory + /// + /// Address to query + /// Retrieved memory info + /// Status code + virtual NTSTATUS VirtualQueryExT( ptr_t lpAddress, PMEMORY_BASIC_INFORMATION64 lpBuffer ); + + /// + /// Query virtual memory + /// + /// Address to query + /// Retrieved memory info + /// Status code + virtual NTSTATUS VirtualQueryExT( ptr_t lpAddress, MEMORY_INFORMATION_CLASS infoClass, LPVOID lpBuffer, size_t bufSize ); + + /// + /// Call NtQueryInformationProcess for underlying process + /// + /// Information class + /// Output buffer + /// Buffer size + /// Status code + virtual NTSTATUS QueryProcessInfoT( PROCESSINFOCLASS infoClass, LPVOID lpBuffer, uint32_t bufSize ); + + /// + /// Call NtSetInformationProcess for underlying process + /// + /// Information class + /// Input buffer + /// Buffer size + /// Status code + virtual NTSTATUS SetProcessInfoT( PROCESSINFOCLASS infoClass, LPVOID lpBuffer, uint32_t bufSize ); + + /// + /// Creates new thread in the remote process + /// + /// Created thread handle + /// Thread entry point + /// Thread argument + /// Creation flags + /// Access override + /// Status code + virtual NTSTATUS CreateRemoteThreadT( HANDLE& hThread, ptr_t entry, ptr_t arg, CreateThreadFlags flags, DWORD access = THREAD_ALL_ACCESS ); + + /// + /// Get native thread context + /// + /// Thread handle. + /// Thread context + /// Status code + virtual NTSTATUS GetThreadContextT( HANDLE hThread, _CONTEXT64& ctx ); + + /// + /// Get WOW64 thread context + /// + /// Thread handle. + /// Thread context + /// Status code + virtual NTSTATUS GetThreadContextT( HANDLE hThread, _CONTEXT32& ctx ); + + /// + /// Set native thread context + /// + /// Thread handle. + /// Thread context + /// Status code + virtual NTSTATUS SetThreadContextT( HANDLE hThread, _CONTEXT64& ctx ); + + /// + /// Set WOW64 thread context + /// + /// Thread handle. + /// Thread context + /// Status code + virtual NTSTATUS SetThreadContextT( HANDLE hThread, _CONTEXT32& ctx ); + + /// + /// NtQueueApcThread + /// + /// Thread handle. + /// APC function + /// APC argument + /// Status code + virtual NTSTATUS QueueApcT( HANDLE hThread, ptr_t func, ptr_t arg ); + + /// + /// Get WOW64 PEB + /// + /// Retrieved PEB + /// PEB pointer + virtual ptr_t getPEB( _PEB32* ppeb ); + + /// + /// Get native PEB + /// + /// Retrieved PEB + /// PEB pointer + virtual ptr_t getPEB( _PEB64* ppeb ); + + /// + /// Get WOW64 TEB + /// + /// Retrieved TEB + /// TEB pointer + virtual ptr_t getTEB( HANDLE hThread, _TEB32* pteb ); + + /// + /// Get native TEB + /// + /// Retrieved TEB + /// TEB pointer + virtual ptr_t getTEB( HANDLE hThread, _TEB64* pteb ); + + /// + /// Enumerate valid memory regions + /// + /// If true - non-allocated regions will be included in list + /// Found regions> + BLACKBONE_API std::vector EnumRegions( bool includeFree = false ); + + /// + /// Enumerate process modules + /// + /// Found modules + /// Module type: x86 or x64 + /// Module count + BLACKBONE_API std::vector EnumModules( eModSeachType search = LdrList, eModType mtype = mt_default ); + + /// + /// Get lowest possible valid address value + /// + /// Address value + BLACKBONE_API inline ptr_t minAddr() const { return 0x10000; } + + /// + /// Get highest possible valid address value + /// + /// Address value + BLACKBONE_API inline ptr_t maxAddr() const { return 0x7FFFFFFEFFFF; } + + /// + /// Get page size + /// + /// Address value + BLACKBONE_API inline uint32_t pageSize() const { return _pageSize; } +private: + + /// + /// Enumerate process modules + /// + /// Found modules + /// Module count + template + std::vector EnumModulesT(); + + /// + /// Enum process section objects + /// + /// Found modules + /// Sections count + std::vector EnumSections(); + + /// + /// Enum pages containing valid PE headers + /// + /// Found modules + /// Sections count + std::vector EnumPEHeaders(); + +protected: + HANDLE _hProcess; // Process handle + Wow64Barrier _wowBarrier; // WOW64 barrier info + uint32_t _pageSize; +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Subsystem/Wow64Subsystem.cpp b/third/Blackbone/src/BlackBone/Subsystem/Wow64Subsystem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b9543b8f0f4fb0ea20fba51fa9d051b8c70783ee --- /dev/null +++ b/third/Blackbone/src/BlackBone/Subsystem/Wow64Subsystem.cpp @@ -0,0 +1,385 @@ +#include "Wow64Subsystem.h" +#include "../Misc/DynImport.h" +#include "../Include/Macro.h" +#include <3rd_party/rewolf-wow64ext/src/wow64ext.h> + +namespace blackbone +{ + +NativeWow64::NativeWow64( HANDLE hProcess ) + : Native( hProcess ) +{ +} + +NativeWow64::~NativeWow64() +{ +} + +/// +/// Allocate virtual memory +/// +/// Allocation address +/// Region size +/// Allocation type +/// Memory protection +/// Status code +NTSTATUS NativeWow64::VirtualAllocExT( ptr_t& lpAddress, size_t dwSize, DWORD flAllocationType, DWORD flProtect ) +{ + DWORD64 size64 = dwSize; + static ptr_t ntavm = GetProcAddress64( getNTDLL64(), "NtAllocateVirtualMemory" ); + if (ntavm == 0) + return STATUS_ORDINAL_NOT_FOUND; + + return static_cast(X64Call( ntavm, 6, (DWORD64)_hProcess, (DWORD64)&lpAddress, 0ull, (DWORD64)&size64, (DWORD64)flAllocationType, (DWORD64)flProtect )); +} + +/// +/// Free virtual memory +/// +/// Memory address +/// Region size +/// Memory release type. +/// Status code +NTSTATUS NativeWow64::VirtualFreeExT( ptr_t lpAddress, size_t dwSize, DWORD dwFreeType ) +{ + static ptr_t ntfvm = GetProcAddress64( getNTDLL64(), "NtFreeVirtualMemory" ); + if (ntfvm == 0) + return STATUS_ORDINAL_NOT_FOUND; + + DWORD64 tmpAddr = lpAddress; + DWORD64 tmpSize = dwSize; + + return static_cast(X64Call( ntfvm, 4, (DWORD64)_hProcess, (DWORD64)&tmpAddr, (DWORD64)&tmpSize, (DWORD64)dwFreeType )); +} + +/// +/// Query virtual memory +/// +/// Address to query +/// Retrieved memory info +/// Status code +NTSTATUS NativeWow64::VirtualQueryExT( ptr_t lpAddress, PMEMORY_BASIC_INFORMATION64 lpBuffer ) +{ + static ptr_t ntqvm = GetProcAddress64( getNTDLL64(), "NtQueryVirtualMemory" ); + if (ntqvm == 0) + return STATUS_ORDINAL_NOT_FOUND; + + return static_cast(X64Call( ntqvm, 6, (DWORD64)_hProcess, lpAddress, 0ull, (DWORD64)lpBuffer, (DWORD64)sizeof( MEMORY_BASIC_INFORMATION64 ), 0ull )); +} + +/// +/// Query virtual memory +/// +/// Address to query +/// Retrieved memory info +/// Status code +NTSTATUS NativeWow64::VirtualQueryExT( ptr_t lpAddress, MEMORY_INFORMATION_CLASS infoClass, LPVOID lpBuffer, size_t bufSize ) +{ + static ptr_t ntqvm = GetProcAddress64( getNTDLL64(), "NtQueryVirtualMemory" ); + if (ntqvm == 0) + return STATUS_ORDINAL_NOT_FOUND; + + return static_cast(X64Call( ntqvm, 6, (DWORD64)_hProcess, lpAddress, (DWORD64)infoClass, (DWORD64)lpBuffer, (DWORD64)bufSize, 0ull )); +} + +/// +/// Change memory protection +/// +/// Memory address. +/// Region size +/// New protection. +/// Old protection +/// Status code +NTSTATUS NativeWow64::VirtualProtectExT( ptr_t lpAddress, DWORD64 dwSize, DWORD flProtect, DWORD* flOld ) +{ + static ptr_t ntpvm = GetProcAddress64( getNTDLL64(), "NtProtectVirtualMemory" ); + if (ntpvm == 0) + return STATUS_ORDINAL_NOT_FOUND; + + return static_cast(X64Call( ntpvm, 5, (DWORD64)_hProcess, (DWORD64)&lpAddress, (DWORD64)&dwSize, (DWORD64)flProtect, (DWORD64)flOld )); +} + +/// +/// Read virtual memory +/// +/// Memory address +/// Output buffer +/// Number of bytes to read +/// Mumber of bytes read +/// Status code +NTSTATUS NativeWow64::ReadProcessMemoryT( ptr_t lpBaseAddress, LPVOID lpBuffer, size_t nSize, DWORD64 *lpBytes /*= nullptr */ ) +{ + DWORD64 junk = 0; + if (lpBytes == nullptr) + lpBytes = &junk; + + return SAFE_NATIVE_CALL( NtWow64ReadVirtualMemory64, _hProcess, lpBaseAddress, lpBuffer, nSize, lpBytes ); +} + +/// +/// Write virtual memory +/// +/// Memory address +/// Buffer to write +/// Number of bytes to read +/// Mumber of bytes read +/// Status code +NTSTATUS NativeWow64::WriteProcessMemoryT( ptr_t lpBaseAddress, LPCVOID lpBuffer, size_t nSize, DWORD64 *lpBytes /*= nullptr */ ) +{ + DWORD64 junk = 0; + if (lpBytes == nullptr) + lpBytes = &junk; + + return SAFE_NATIVE_CALL( NtWow64WriteVirtualMemory64, _hProcess, lpBaseAddress, (LPVOID)lpBuffer, nSize, lpBytes ); +} + +/// +/// Call NtQueryInformationProcess for underlying process +/// +/// Information class +/// Output buffer +/// Buffer size +/// Status code +NTSTATUS NativeWow64::QueryProcessInfoT( PROCESSINFOCLASS infoClass, LPVOID lpBuffer, uint32_t bufSize ) +{ + ULONG length = 0; + return SAFE_NATIVE_CALL( NtWow64QueryInformationProcess64, _hProcess, infoClass, lpBuffer, bufSize, &length ); +} + + +/// +/// Call NtSetInformationProcess for underlying process +/// +/// Information class +/// Input buffer +/// Buffer size +/// Status code +NTSTATUS NativeWow64::SetProcessInfoT( PROCESSINFOCLASS infoClass, LPVOID lpBuffer, uint32_t bufSize ) +{ + static ptr_t ntspi = GetProcAddress64( getNTDLL64(), "NtSetInformationProcess" ); + if (ntspi == 0) + return STATUS_ORDINAL_NOT_FOUND; + + return static_cast(X64Call( ntspi, 4, (DWORD64)_hProcess, (DWORD64)infoClass, (DWORD64)lpBuffer, (DWORD64)bufSize )); +} + +/// +/// Creates new thread in the remote process +/// +/// Created thread handle +/// Thread entry point +/// Thread argument +/// Creation flags +/// Status code*/ +NTSTATUS NativeWow64::CreateRemoteThreadT( HANDLE& hThread, ptr_t entry, ptr_t arg, CreateThreadFlags flags, DWORD access ) +{ + // Try to use default routine if possible + /*if(_wowBarrier.targetWow64 == true) + { + return Native::CreateRemoteThreadT( hThread, entry, arg, flags, access ); + } + else*/ + { + static DWORD64 NtCreateThreadEx = GetProcAddress64( getNTDLL64(), "NtCreateThreadEx" ); + if (NtCreateThreadEx == 0) + return STATUS_ORDINAL_NOT_FOUND; + + // hThread can't be used directly because x64Call will zero stack space near variable + DWORD64 hThd2 = NULL; + + NTSTATUS status = static_cast(X64Call( + NtCreateThreadEx, 11, (DWORD64)&hThd2, (DWORD64)access, 0ull, + (DWORD64)_hProcess, (DWORD64)entry, (DWORD64)arg, (DWORD64)flags, + 0ull, 0x1000ull, 0x100000ull, 0ull + )); + + hThread = reinterpret_cast(hThd2); + return status; + } +} + + +/// +/// Get WOW64 thread context +/// +/// Thread handle. +/// Thread context +/// Status code +NTSTATUS NativeWow64::GetThreadContextT( HANDLE hThread, _CONTEXT32& ctx ) +{ + // Target process is x64. 32bit CONTEXT is not available. + if (_wowBarrier.targetWow64 == false) + { + return STATUS_NOT_SUPPORTED; + } + else + { + SetLastNtStatus( STATUS_SUCCESS ); + GetThreadContext( hThread, reinterpret_cast(&ctx) ); + return LastNtStatus(); + } +} + + +/// +/// Get native thread context +/// +/// Thread handle. +/// Thread context +/// Status code +NTSTATUS NativeWow64::GetThreadContextT( HANDLE hThread, _CONTEXT64& ctx ) +{ + static ptr_t gtc = GetProcAddress64( getNTDLL64(), "NtGetContextThread" ); + if (gtc == 0) + return STATUS_ORDINAL_NOT_FOUND; + + return static_cast(X64Call( gtc, 2, (DWORD64)hThread, (DWORD64)&ctx )); +} + +/// +/// Set WOW64 thread context +/// +/// Thread handle. +/// Thread context +/// Status code +NTSTATUS NativeWow64::SetThreadContextT( HANDLE hThread, _CONTEXT32& ctx ) +{ + // Target process is x64. 32bit CONTEXT is not available. + if (_wowBarrier.targetWow64 == false) + { + return STATUS_NOT_SUPPORTED; + } + else + { + SetLastNtStatus( STATUS_SUCCESS ); + SetThreadContext( hThread, reinterpret_cast(&ctx) ); + return LastNtStatus(); + } +} + +/// +/// Set native thread context +/// +/// Thread handle. +/// Thread context +/// Status code +NTSTATUS NativeWow64::SetThreadContextT( HANDLE hThread, _CONTEXT64& ctx ) +{ + static ptr_t stc = GetProcAddress64( getNTDLL64(), "NtSetContextThread" ); + if (stc == 0) + return STATUS_ORDINAL_NOT_FOUND; + + return static_cast(X64Call( stc, 2, (DWORD64)hThread, (DWORD64)&ctx )); +} + +/// +/// NtQueueApcThread +/// +/// Thread handle. +/// APC function +/// APC argument +/// Status code +NTSTATUS NativeWow64::QueueApcT( HANDLE hThread, ptr_t func, ptr_t arg ) +{ + if (_wowBarrier.targetWow64) + return Native::QueueApcT( hThread, func, arg ); + + static ptr_t qat = GetProcAddress64( getNTDLL64(), "NtQueueApcThread" ); + if (qat == 0) + return STATUS_ORDINAL_NOT_FOUND; + + return static_cast(X64Call( qat, 5, (DWORD64)hThread, func, arg, 0ull, 0ull )); +} + +/// +/// Gets WOW64 PEB +/// +/// Retrieved PEB +/// PEB pointer +ptr_t NativeWow64::getPEB( _PEB32* ppeb ) +{ + // Target process is x64. PEB32 is not available. + if (_wowBarrier.targetWow64 == false) + { + return 0; + } + else + { + PROCESS_BASIC_INFORMATION pbi = { 0 }; + ULONG bytes = 0; + + if (NT_SUCCESS( SAFE_NATIVE_CALL( NtQueryInformationProcess, _hProcess, ProcessBasicInformation, &pbi, (ULONG)sizeof( pbi ), &bytes ) ) && ppeb) + ReadProcessMemory( _hProcess, pbi.PebBaseAddress, ppeb, sizeof(_PEB32), NULL ); + + return reinterpret_cast(pbi.PebBaseAddress); + } +} + +/// +/// Get native PEB +/// +/// Retrieved PEB +/// PEB pointer +ptr_t NativeWow64::getPEB( _PEB64* ppeb ) +{ + _PROCESS_BASIC_INFORMATION_T info = { 0 }; + ULONG bytes = 0; + + SAFE_NATIVE_CALL( NtWow64QueryInformationProcess64, _hProcess, ProcessBasicInformation, &info, (ULONG)sizeof( info ), &bytes ); + if (bytes > 0 && NT_SUCCESS( SAFE_NATIVE_CALL( NtWow64ReadVirtualMemory64, _hProcess, info.PebBaseAddress, ppeb, (ULONG)sizeof( _PEB64 ), nullptr ) )) + return info.PebBaseAddress; + + return 0; +} + +/// +/// Get WOW64 TEB +/// +/// Retrieved TEB +/// TEB pointer +ptr_t NativeWow64::getTEB( HANDLE hThread, _TEB32* pteb ) +{ + // Target process is x64. TEB32 is not available. + if (_wowBarrier.targetWow64 == false) + { + return 0; + } + else + { + _THREAD_BASIC_INFORMATION_T tbi = { 0 }; + ULONG bytes = 0; + + if (NT_SUCCESS( SAFE_NATIVE_CALL( NtQueryInformationThread, hThread, (THREADINFOCLASS)0, &tbi, (ULONG)sizeof( tbi ), &bytes ) ) && pteb) + ReadProcessMemory( _hProcess, (LPCVOID)((uintptr_t)tbi.TebBaseAddress), pteb, sizeof( _TEB32 ), nullptr ); + + return static_cast(tbi.TebBaseAddress); + } +} + +/// +/// Get native TEB +/// +/// Retrieved TEB +/// TEB pointer +ptr_t NativeWow64::getTEB( HANDLE hThread, _TEB64* pteb ) +{ + _THREAD_BASIC_INFORMATION_T info = { 0 }; + ULONG bytes = 0; + + static ptr_t ntQit = GetProcAddress64( getNTDLL64(), "NtQueryInformationThread" ); + + if (ntQit == 0) + { + SetLastNtStatus( STATUS_ORDINAL_NOT_FOUND ); + return 0; + } + + X64Call( ntQit, 5, (DWORD64)hThread, 0ull, (DWORD64)&info, (DWORD64)sizeof(info), (DWORD64)&bytes ); + + if (bytes > 0 && NT_SUCCESS( SAFE_NATIVE_CALL( NtWow64ReadVirtualMemory64, _hProcess, info.TebBaseAddress, pteb, sizeof( _TEB64 ), nullptr ) )) + return static_cast(info.TebBaseAddress); + + return 0; +} + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Subsystem/Wow64Subsystem.h b/third/Blackbone/src/BlackBone/Subsystem/Wow64Subsystem.h new file mode 100644 index 0000000000000000000000000000000000000000..b1e23c69deb24ed4da045aad7327cc54202adfeb --- /dev/null +++ b/third/Blackbone/src/BlackBone/Subsystem/Wow64Subsystem.h @@ -0,0 +1,177 @@ +#pragma once + +#include "NativeSubsystem.h" + +namespace blackbone +{ + +class NativeWow64 : public Native +{ +public: + BLACKBONE_API NativeWow64( HANDLE hProcess ); + BLACKBONE_API ~NativeWow64(); + + /// + /// Allocate virtual memory + /// + /// Allocation address + /// Region size + /// Allocation type + /// Memory protection + /// Status code + virtual NTSTATUS VirtualAllocExT( ptr_t& lpAddress, size_t dwSize, DWORD flAllocationType, DWORD flProtect ); + + /// + /// Free virtual memory + /// + /// Memory address + /// Region size + /// Memory release type. + /// Status code + virtual NTSTATUS VirtualFreeExT( ptr_t lpAddress, size_t dwSize, DWORD dwFreeType ); + + /// + /// Change memory protection + /// + /// Memory address. + /// Region size + /// New protection. + /// Old protection + /// Status code + virtual NTSTATUS VirtualProtectExT( ptr_t lpAddress, DWORD64 dwSize, DWORD flProtect, DWORD* flOld ); + + /// + /// Read virtual memory + /// + /// Memory address + /// Output buffer + /// Number of bytes to read + /// Mumber of bytes read + /// Status code + virtual NTSTATUS ReadProcessMemoryT( ptr_t lpBaseAddress, LPVOID lpBuffer, size_t nSize, DWORD64 *lpBytes = nullptr ); + + /// + /// Write virtual memory + /// + /// Memory address + /// Buffer to write + /// Number of bytes to read + /// Mumber of bytes read + /// Status code + virtual NTSTATUS WriteProcessMemoryT( ptr_t lpBaseAddress, LPCVOID lpBuffer, size_t nSize, DWORD64 *lpBytes = nullptr ); + + /// + /// Query virtual memory + /// + /// Address to query + /// Retrieved memory info + /// Status code + virtual NTSTATUS VirtualQueryExT( ptr_t lpAddress, PMEMORY_BASIC_INFORMATION64 lpBuffer ); + + /// + /// Query virtual memory + /// + /// Address to query + /// Retrieved memory info + /// Status code + virtual NTSTATUS VirtualQueryExT( ptr_t lpAddress, MEMORY_INFORMATION_CLASS infoClass, LPVOID lpBuffer, size_t bufSize ); + + /// + /// Call NtQueryInformationProcess for underlying process + /// + /// Information class + /// Output buffer + /// Buffer size + /// Status code + virtual NTSTATUS QueryProcessInfoT( PROCESSINFOCLASS infoClass, LPVOID lpBuffer, uint32_t bufSize ); + + /// + /// Call NtSetInformationProcess for underlying process + /// + /// Information class + /// Input buffer + /// Buffer size + /// Status code + virtual NTSTATUS SetProcessInfoT( PROCESSINFOCLASS infoClass, LPVOID lpBuffer, uint32_t bufSize ); + + /// + /// Creates new thread in the remote process + /// + /// Created thread handle + /// Thread entry point + /// Thread argument + /// Creation flags + /// Status code + virtual NTSTATUS CreateRemoteThreadT( HANDLE& hThread, ptr_t entry, ptr_t arg, CreateThreadFlags flags, DWORD access = THREAD_ALL_ACCESS ); + + /// + /// Get native thread context + /// + /// Thread handle. + /// Thread context + /// Status code + virtual NTSTATUS GetThreadContextT( HANDLE hThread, _CONTEXT64& ctx ); + + /// + /// Get WOW64 thread context + /// + /// Thread handle. + /// Thread context + /// Status code + virtual NTSTATUS GetThreadContextT( HANDLE hThread, _CONTEXT32& ctx ); + + /// + /// Set native thread context + /// + /// Thread handle. + /// Thread context + /// Status code + virtual NTSTATUS SetThreadContextT( HANDLE hThread, _CONTEXT64& ctx ); + + /// + /// Set WOW64 thread context + /// + /// Thread handle. + /// Thread context + /// Status code + virtual NTSTATUS SetThreadContextT( HANDLE hThread, _CONTEXT32& ctx ); + + /// + /// NtQueueApcThread + /// + /// Thread handle. + /// APC function + /// APC argument + /// Status code + virtual NTSTATUS QueueApcT( HANDLE hThread, ptr_t func, ptr_t arg ); + + /// + /// Get WOW64 PEB + /// + /// Retrieved PEB + /// PEB pointer + virtual ptr_t getPEB( _PEB32* ppeb ); + + /// + /// Get native PEB + /// + /// Retrieved PEB + /// PEB pointer + virtual ptr_t getPEB( _PEB64* ppeb ); + + /// + /// Get WOW64 TEB + /// + /// Retrieved TEB + /// TEB pointer + virtual ptr_t getTEB( HANDLE hThread, _TEB32* pteb ); + + /// + /// Get native TEB + /// + /// Retrieved TEB + /// TEB pointer + virtual ptr_t getTEB( HANDLE hThread, _TEB64* pteb ); +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Subsystem/x86Subsystem.cpp b/third/Blackbone/src/BlackBone/Subsystem/x86Subsystem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1cb58fb6ab003dea3b940b0cf097ac2c1599e1e9 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Subsystem/x86Subsystem.cpp @@ -0,0 +1,153 @@ +#include "x86Subsystem.h" +#include "../Misc/DynImport.h" +#include "../Include/Macro.h" + +namespace blackbone +{ + +x86Native::x86Native( HANDLE hProcess ) + : Native( hProcess, true ) +{ +} + +x86Native::~x86Native() +{ +} + +/// +/// Query virtual memory +/// +/// Address to query +/// Retrieved memory info +/// Status code +NTSTATUS x86Native::VirtualQueryExT( ptr_t lpAddress, PMEMORY_BASIC_INFORMATION64 lpBuffer ) +{ + MEMORY_BASIC_INFORMATION tmp = { 0 }; + + NTSTATUS status = SAFE_NATIVE_CALL( + NtQueryVirtualMemory, + _hProcess, reinterpret_cast(lpAddress), + MemoryBasicInformation, &tmp, sizeof( tmp ), nullptr + ); + if (status != STATUS_SUCCESS) + return status; + + // Map values + lpBuffer->AllocationBase = reinterpret_cast(tmp.AllocationBase); + lpBuffer->AllocationProtect = tmp.AllocationProtect; + lpBuffer->BaseAddress = reinterpret_cast(tmp.BaseAddress); + lpBuffer->Protect = tmp.Protect; + lpBuffer->RegionSize = tmp.RegionSize; + lpBuffer->State = tmp.State; + lpBuffer->Type = tmp.Type; + + return status; +} + +/// +/// Get WOW64 thread context +/// +/// Thread handle. +/// Thread context +/// Status code +NTSTATUS x86Native::GetThreadContextT( HANDLE hThread, _CONTEXT32& ctx ) +{ + SetLastNtStatus( STATUS_SUCCESS ); + GetThreadContext( hThread, reinterpret_cast(&ctx) ); + return LastNtStatus(); +} + +/// +/// Get native thread context +/// +/// Thread handle. +/// Thread context +/// Status code +NTSTATUS x86Native::GetThreadContextT( HANDLE /*hThread*/, _CONTEXT64& /*ctx*/ ) +{ + // There is no x64 context under x86 OS + return STATUS_NOT_SUPPORTED; +} + +/// +/// Set WOW64 thread context +/// +/// Thread handle. +/// Thread context +/// Status code +NTSTATUS x86Native::SetThreadContextT( HANDLE hThread, _CONTEXT32& ctx ) +{ + SetLastNtStatus( STATUS_SUCCESS ); + SetThreadContext( hThread, reinterpret_cast(&ctx) ); + return LastNtStatus(); +} + +/// +/// Set native thread context +/// +/// Thread handle. +/// Thread context +/// Status code +NTSTATUS x86Native::SetThreadContextT( HANDLE /*hThread*/, _CONTEXT64& /*ctx*/ ) +{ + // There is no x64 context under x86 OS + return STATUS_NOT_SUPPORTED; +} + +/// +/// Gets WOW64 PEB +/// +/// Retrieved PEB +/// PEB pointer +ptr_t x86Native::getPEB( _PEB32* ppeb ) +{ + PROCESS_BASIC_INFORMATION pbi = { 0 }; + ULONG bytes = 0; + + if (NT_SUCCESS( SAFE_NATIVE_CALL( NtQueryInformationProcess, _hProcess, ProcessBasicInformation, &pbi, (ULONG)sizeof( pbi ), &bytes ) ) && ppeb) + ReadProcessMemory( _hProcess, pbi.PebBaseAddress, ppeb, sizeof(_PEB32), NULL ); + + return reinterpret_cast(pbi.PebBaseAddress); +} + +/// +/// Get native PEB +/// +/// Retrieved PEB +/// PEB pointer +ptr_t x86Native::getPEB( _PEB64* /*ppeb*/ ) +{ + // There is no x64 PEB under x86 OS + SetLastNtStatus( STATUS_NOT_SUPPORTED ); + return 0; +} + +/// +/// Get WOW64 TEB +/// +/// Retrieved TEB +/// TEB pointer +ptr_t x86Native::getTEB( HANDLE hThread, _TEB32* pteb ) +{ + _THREAD_BASIC_INFORMATION_T tbi = { 0 }; + ULONG bytes = 0; + + if (NT_SUCCESS( SAFE_NATIVE_CALL( NtQueryInformationThread, hThread, (THREADINFOCLASS)0, &tbi, (ULONG)sizeof( tbi ), &bytes ) ) && pteb) + ReadProcessMemory( _hProcess, (LPCVOID)((uintptr_t)tbi.TebBaseAddress), pteb, sizeof(_TEB32), NULL ); + + return tbi.TebBaseAddress; +} + +/// +/// Get native TEB +/// +/// Retrieved TEB +/// TEB pointer +ptr_t x86Native::getTEB( HANDLE /*hThread*/, _TEB64* /*pteb*/ ) +{ + // There is no x64 TEB under x86 OS + SetLastNtStatus( STATUS_NOT_SUPPORTED ); + return 0; +} + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Subsystem/x86Subsystem.h b/third/Blackbone/src/BlackBone/Subsystem/x86Subsystem.h new file mode 100644 index 0000000000000000000000000000000000000000..c5ae57be739ffdc80b18704f3bc6384ad1e7b34a --- /dev/null +++ b/third/Blackbone/src/BlackBone/Subsystem/x86Subsystem.h @@ -0,0 +1,88 @@ +#pragma once + +#include "NativeSubsystem.h" + +namespace blackbone +{ + +/// +/// X86 OS subsystem. Used +/// +class x86Native : public Native +{ +public: + BLACKBONE_API x86Native( HANDLE hProcess ); + BLACKBONE_API ~x86Native(); + + /// + /// Query virtual memory + /// + /// Address to query + /// Retrieved memory info + /// Status code + virtual NTSTATUS VirtualQueryExT( ptr_t lpAddress, PMEMORY_BASIC_INFORMATION64 lpBuffer ); + + /// + /// Get WOW64 thread context + /// + /// Thread handle. + /// Thread context + /// Status code + virtual NTSTATUS GetThreadContextT( HANDLE hThread, _CONTEXT32& ctx ); + + /// + /// Get native thread context + /// + /// Thread handle. + /// Thread context + /// Status code + virtual NTSTATUS GetThreadContextT( HANDLE hThread, _CONTEXT64& ctx ); + + /// + /// Set WOW64 thread context + /// + /// Thread handle. + /// Thread context + /// Status code + virtual NTSTATUS SetThreadContextT( HANDLE hThread, _CONTEXT32& ctx ); + + /// + /// Set native thread context + /// + /// Thread handle. + /// Thread context + /// Status code + virtual NTSTATUS SetThreadContextT( HANDLE hThread, _CONTEXT64& ctx ); + + /// + /// Gets WOW64 PEB + /// + /// Retrieved PEB + /// PEB pointer + virtual ptr_t getPEB( _PEB32* ppeb ); + + /// + /// Get native PEB + /// + /// Retrieved PEB + /// PEB pointer + virtual ptr_t getPEB( _PEB64* ppeb ); + + /// + /// Get WOW64 TEB + /// + /// Retrieved TEB + /// TEB pointer + virtual ptr_t getTEB( HANDLE hThread, _TEB32* pteb ); + + /// + /// Get native TEB + /// + /// Retrieved TEB + /// TEB pointer + virtual ptr_t getTEB( HANDLE hThread, _TEB64* pteb ); + +private: +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Symbols/PDBHelper.cpp b/third/Blackbone/src/BlackBone/Symbols/PDBHelper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb4a8ffe756b996ebe25ccf1fae74822f03c3d88 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Symbols/PDBHelper.cpp @@ -0,0 +1,169 @@ +#include "PDBHelper.h" +#include "../Misc/Trace.hpp" + +#include +#include + +#define CHECK_SUCCESS(e)\ +{ \ + HRESULT hresult = (e); \ + if(FAILED(hresult)) \ + { \ + BLACKBONE_TRACE( "PDB: %s: (%s) failed with HRESULT 0x%08x", __FUNCTION__, #e , hresult ); \ + return hresult; \ + } \ +} + +namespace blackbone +{ + +PDBHelper::PDBHelper() +{ + CoInitialize( nullptr ); + + // If _NT_SYMBOL_PATH exists, use it + wchar_t path[MAX_PATH] = { }; + if (GetEnvironmentVariableW( L"_NT_SYMBOL_PATH", path, _countof( path ) ) == 0) + { + if (GetTempPathW( _countof( path ), path ) != 0) + { + std::wstringstream wss; + wss << L"srv*" << path << L"Symbols*http://msdl.microsoft.com/download/symbols"; + _sympath = wss.str(); + } + } +} + +PDBHelper::~PDBHelper() +{ + // Must be released before CoUninitialize + _global.Release(); + _session.Release(); + _source.Release(); + + CoUninitialize(); +} + +/// +/// Initialize symbols for target file +/// +/// Fully qualified path to target PE file +/// Base ptr to add to RVAs +/// Status code +HRESULT PDBHelper::Init( const std::wstring& file, ptr_t base /*= 0*/ ) +{ + CHECK_SUCCESS( CoCreateDiaDataSource() ); + CHECK_SUCCESS( _source->loadDataForExe( file.c_str(), _sympath.empty() ? nullptr : _sympath.c_str(), nullptr ) ); + CHECK_SUCCESS( _source->openSession( &_session ) ); + CHECK_SUCCESS( _session->get_globalScope( &_global ) ); + + _base = base; + return PopulateSymbols(); +} + +/// +/// Get symbol RVA +/// +/// Symbol name +/// Resulting RVA +/// Status code +HRESULT PDBHelper::GetSymAddress( const std::wstring& symName, ptr_t& result ) +{ + auto found = _cache.find( symName ); + if (found != _cache.end()) + { + result = _base + found->second; + return S_OK; + } + + return E_PDB_DBG_NOT_FOUND; +} + +/// +/// Initialize DIA +/// +/// Status code +HRESULT PDBHelper::CoCreateDiaDataSource() +{ + const auto pSource = reinterpret_cast(&_source); + + // Try to get from COM + HRESULT hr = CoCreateInstance( CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER, __uuidof(IDiaDataSource), pSource ); + + // Retry with direct export call + if (hr == REGDB_E_CLASSNOTREG) + { + HMODULE hMod = LoadLibraryW( L"msdia140.dll" ); + if (!hMod) + { + const auto err = GetLastError(); + BLACKBONE_TRACE( "PDB: Failed to load msdia140.dll, error 0x%08x", err ); + return HRESULT_FROM_WIN32( err ); + } + + auto DllGetClassObject = reinterpret_cast(GetProcAddress( hMod, "DllGetClassObject" )); + if (!DllGetClassObject) + { + const auto err = GetLastError(); + BLACKBONE_TRACE( "PDB: Failed to get DllGetClassObject from msdia140.dll" ); + return HRESULT_FROM_WIN32( err ); + } + + CComPtr classFactory; + CHECK_SUCCESS( DllGetClassObject( CLSID_DiaSource, IID_IClassFactory, &classFactory ) ); + hr = classFactory->CreateInstance( nullptr, IID_IDiaDataSource, pSource ); + } + + if (FAILED( hr )) + { + BLACKBONE_TRACE( "PDB: %s failed with HRESULT 0x%08x", __FUNCTION__, hr ); + } + + return hr; +} + +/// +/// Build module symbol map +/// +/// Status code +HRESULT PDBHelper::PopulateSymbols() +{ + CComPtr symbols; + CHECK_SUCCESS( _global->findChildren( SymTagNull, nullptr, nsNone, &symbols ) ); + + ULONG count = 0; + CComPtr symbol; + while (SUCCEEDED( symbols->Next( 1, &symbol, &count ) ) && count != 0) + { + DWORD rva = 0; + BSTR name = nullptr; + + symbol->get_relativeVirtualAddress( &rva ); + symbol->get_undecoratedName( &name ); + + if (name && rva) + { + std::wstring wname( name ); + + // Remove x86 __stdcall decoration + if (wname[0] == L'@' || wname[0] == L'_') + { + wname.erase( 0, 1 ); + } + + auto pos = wname.rfind( L'@' ); + if (pos != wname.npos) + { + wname.erase( pos ); + } + + _cache.emplace( std::move( wname ), rva ); + } + + symbol.Release(); + } + + return S_OK; +} + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Symbols/PDBHelper.h b/third/Blackbone/src/BlackBone/Symbols/PDBHelper.h new file mode 100644 index 0000000000000000000000000000000000000000..e0ee0368fcea296136ae8ed41326d35ba7c38362 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Symbols/PDBHelper.h @@ -0,0 +1,58 @@ +#pragma once +#include "../include/Types.h" +#include <3rd_party/DIA/dia2.h> +#include +#include +#include +#include + +namespace blackbone +{ + +class PDBHelper +{ +public: + PDBHelper(); + ~PDBHelper(); + + /// + /// Initialize symbols for target file + /// + /// Fully qualified path to target PE file + /// Base ptr to add to RVAs + /// Status code + HRESULT Init( const std::wstring& file, ptr_t base = 0 ); + + /// + /// Get symbol RVA + /// + /// Symbol name + /// Resulting RVA + /// Status code + HRESULT GetSymAddress( const std::wstring& symName, ptr_t& result ); + +private: + /// + /// Initialize DIA + /// + /// Status code + HRESULT CoCreateDiaDataSource(); + + /// + /// Build module symbol map + /// + /// Status code + HRESULT PopulateSymbols(); + +private: + // DIA interfaces + CComPtr _source; + CComPtr _session; + CComPtr _global; + + uint64_t _base = 0; // Base ptr to add to RVAs + std::wstring _sympath; // Symbol cache directory + std::unordered_map _cache; // Symbol name <--> RVA map +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Symbols/PatternLoader.cpp b/third/Blackbone/src/BlackBone/Symbols/PatternLoader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d7ea4a7d915bacf1c92952462276fb3acd0c5bb --- /dev/null +++ b/third/Blackbone/src/BlackBone/Symbols/PatternLoader.cpp @@ -0,0 +1,286 @@ +#include "PatternLoader.h" +#include "../Include/Winheaders.h" +#include "../Patterns/PatternSearch.h" +#include "../Misc/Trace.hpp" +#include <3rd_party/VersionApi.h> + +#include +#include + +namespace blackbone +{ + +struct OffsetData +{ + PatternSearch pattern; + bool bit64; + int32_t functionOffset; + int32_t dataStartOffset; + int32_t dataOperandOffset; + int32_t dataInstructionSize; +}; + +struct ScanParams +{ + ptr_t start = 0; + ptr_t size = 0; + ptr_t diff = 0; +}; + +void FindPattern( const ScanParams& scan32, const ScanParams& scan64, const OffsetData& rule, ptr_t& result ) +{ + // Skip if already found + if (result != 0) + { + return; + } + + const ScanParams& scan = rule.bit64 ? scan64 : scan32; + + std::vector found; + rule.pattern.Search( reinterpret_cast(scan.start), static_cast(scan.size), found ); + if (!found.empty()) + { + // Plain pointer sum + if (rule.functionOffset != -1) + { + result = found.front() - rule.functionOffset + scan.diff; + } + // Pointer dereference inside instruction + else if (rule.dataStartOffset != 0) + { + if (rule.bit64) + { + result = *reinterpret_cast(found.front() + (rule.dataStartOffset + rule.dataOperandOffset)) + + (found.front() + rule.dataStartOffset + rule.dataInstructionSize) + scan.diff; + } + else + { + result = *reinterpret_cast(found.front() + rule.dataStartOffset); + } + } + } +}; + +/// +/// Fill OS-dependent patterns +/// +/// Pattern collection +/// Result +void OSFillPatterns( std::unordered_map& patterns, SymbolData& result ) +{ + if (IsWindows10RS3OrGreater()) + { + // LdrpHandleTlsData + // 74 33 44 8D 43 09 + auto offset = IsWindows10RS4OrGreater() ? 0x44 : 0x43; + patterns.emplace( &result.LdrpHandleTlsData64, OffsetData{ "\x74\x33\x44\x8d\x43\x09", true, offset } ); + + // RtlInsertInvertedFunctionTable + // 8B FA 49 8D 43 20 + patterns.emplace( &result.RtlInsertInvertedFunctionTable64, OffsetData{ "\x8b\xfa\x49\x8d\x43\x20", true, 0x10 } ); + + // RtlpInsertInvertedFunctionTableEntry + // 49 8B E8 48 8B FA 0F 84 + patterns.emplace( &result.LdrpInvertedFunctionTable64, OffsetData{ "\x49\x8b\xe8\x48\x8b\xfa\x0f\x84", true, -1, -0xF, 2, 6 } ); + + // RtlInsertInvertedFunctionTable + // 53 56 57 8D 45 F8 8B FA + patterns.emplace( &result.RtlInsertInvertedFunctionTable32, OffsetData{ "\x53\x56\x57\x8d\x45\xf8\x8b\xfa", false, 0x8 } ); + + // RtlpInsertInvertedFunctionTableEntry + // 33 F6 46 3B C6 + patterns.emplace( &result.LdrpInvertedFunctionTable32, OffsetData{ "\x33\xF6\x46\x3B\xC6", false, -1, -0x1B } ); + + // LdrpHandleTlsData + // 33 F6 85 C0 79 03 - RS5+ + // 8B C1 8D 4D AC/BC 51 - RS3-RS4 + const auto pattern = IsWindows10RS4OrGreater() ? "\x8b\xc1\x8d\x4d\xac\x51" : "\x8b\xc1\x8d\x4d\xbc\x51"; + const auto data = IsWindows10RS5OrGreater() ? OffsetData{ "\x33\xf6\x85\xc0\x79\x03", false, 0x2C } : OffsetData{ pattern, false, 0x18 }; + patterns.emplace( &result.LdrpHandleTlsData32, data ); + + // LdrProtectMrdata + // 75 24 85 F6 75 08 + patterns.emplace( &result.LdrProtectMrdata, OffsetData{ "\x75\x24\x85\xf6\x75\x08", false, 0x1C } ); + } + else if (IsWindows10RS2OrGreater()) + { + // LdrpHandleTlsData + // 74 33 44 8D 43 09 + patterns.emplace( &result.LdrpHandleTlsData64, OffsetData{ "\x74\x33\x44\x8d\x43\x09", true, 0x43 } ); + + // RtlInsertInvertedFunctionTable + // 8B FA 49 8D 43 20 + patterns.emplace( &result.RtlInsertInvertedFunctionTable64, OffsetData{ "\x8b\xfa\x49\x8d\x43\x20", true, 0x10 } ); + + // RtlpInsertInvertedFunctionTableEntry + // 49 8B E8 48 8B FA 0F 84 + patterns.emplace( &result.LdrpInvertedFunctionTable64, OffsetData{ "\x49\x8b\xe8\x48\x8b\xfa\x0f\x84", true, -1, -0xF, 2, 6 } ); + + // RtlInsertInvertedFunctionTable + // 8D 45 F0 89 55 F8 50 8D 55 F4 + patterns.emplace( &result.RtlInsertInvertedFunctionTable32, OffsetData{ "\x8d\x45\xf0\x89\x55\xf8\x50\x8d\x55\xf4", false, 0xB } ); + patterns.emplace( &result.LdrpInvertedFunctionTable32, OffsetData{ "\x8d\x45\xf0\x89\x55\xf8\x50\x8d\x55\xf4", false, -1, 0x4C } ); + + // LdrpHandleTlsData + // 8B C1 8D 4D BC 51 + patterns.emplace( &result.LdrpHandleTlsData32, OffsetData{ "\x8b\xc1\x8d\x4d\xbc\x51", false, 0x18 } ); + + // LdrProtectMrdata + // 75 24 85 F6 75 08 + patterns.emplace( &result.LdrProtectMrdata, OffsetData{ "\x75\x24\x85\xf6\x75\x08", false, 0x1C } ); + } + else if (IsWindows8Point1OrGreater()) + { + // LdrpHandleTlsData + // 44 8D 43 09 4C 8D 4C 24 38 + patterns.emplace( &result.LdrpHandleTlsData64, OffsetData{ "\x44\x8d\x43\x09\x4c\x8d\x4c\x24\x38", true, 0x43 } ); + + // RtlInsertInvertedFunctionTable + // 8B C3 2B D3 48 8D 48 01 + patterns.emplace( &result.RtlInsertInvertedFunctionTable64, OffsetData{ "\x8b\xc3\x2b\xd3\x48\x8d\x48\x01", true, 0x84 } ); + patterns.emplace( &result.LdrpInvertedFunctionTable64, OffsetData{ "\x8b\xc3\x2b\xd3\x48\x8d\x48\x01", true, -1, -0x27, 3, 7 } ); + + // RtlInsertInvertedFunctionTable + // 53 56 57 8B DA 8B F9 50 + patterns.emplace( &result.RtlInsertInvertedFunctionTable32, OffsetData{ "\x53\x56\x57\x8b\xda\x8b\xf9\x50", false, 0xB } ); + patterns.emplace( &result.LdrpInvertedFunctionTable32, OffsetData{ "\x53\x56\x57\x8b\xda\x8b\xf9\x50", false, -1, IsWindows10OrGreater() ? 0x22 : 0x23 } ); + + // LdrpHandleTlsData + // 50 6A 09 6A 01 8B C1 + patterns.emplace( &result.LdrpHandleTlsData32, OffsetData{ "\x50\x6a\x09\x6a\x01\x8b\xc1", false, 0x1B } ); + + // LdrProtectMrdata + // 83 7D 08 00 8B 35 + patterns.emplace( &result.LdrProtectMrdata, OffsetData{ PatternSearch( "\x83\x7d\x08\x00\x8b\x35", 6 ), false, 0x12 } ); + } + else if (IsWindows8OrGreater()) + { + // LdrpHandleTlsData + // 48 8B 79 30 45 8D 66 01 + patterns.emplace( &result.LdrpHandleTlsData64, OffsetData{ "\x48\x8b\x79\x30\x45\x8d\x66\x01", true, 0x49 } ); + + // RtlInsertInvertedFunctionTable + // 8B FF 55 8B EC 51 51 53 57 8B 7D 08 8D + patterns.emplace( &result.RtlInsertInvertedFunctionTable32, OffsetData{ "\x8b\xff\x55\x8b\xec\x51\x51\x53\x57\x8b\x7d\x08\x8d", false, 0 } ); + patterns.emplace( &result.LdrpInvertedFunctionTable32, OffsetData{ "\x8b\xff\x55\x8b\xec\x51\x51\x53\x57\x8b\x7d\x08\x8d", false, -1, 0x26 } ); + + // LdrpHandleTlsData + // 8B 45 08 89 45 A0 + patterns.emplace( &result.LdrpHandleTlsData32, OffsetData{ "\x8b\x45\x08\x89\x45\xa0", false, 0xC } ); + } + else if (IsWindows7OrGreater()) + { + const bool update1 = WinVer().revision > 24059; + + // LdrpHandleTlsData + // 41 B8 09 00 00 00 48 8D 44 24 38 + patterns.emplace( &result.LdrpHandleTlsData64, OffsetData{ PatternSearch( "\x41\xb8\x09\x00\x00\x00\x48\x8d\x44\x24\x38", 11 ), true, update1 ? 0x23 : 0x27 } ); + + // LdrpFindOrMapDll patch address + // 48 8D 8C 24 98/90 00 00 00 41 B0 01 + auto pattern = update1 ? "\x48\x8D\x8C\x24\x90\x00\x00\x00\x41\xb0\x01" : "\x48\x8D\x8C\x24\x98\x00\x00\x00\x41\xb0\x01"; + patterns.emplace( &result.LdrKernel32PatchAddress, OffsetData{ PatternSearch( pattern, 11 ), true, -0x12 } ); + + // KiUserApcDispatcher patch address + // 48 8B 4C 24 18 48 8B C1 4C + patterns.emplace( &result.APC64PatchAddress, OffsetData{ "\x48\x8b\x4c\x24\x18\x48\x8b\xc1\x4c", true, 0 } ); + + // RtlInsertInvertedFunctionTable + // 8B FF 55 8B EC 56 68 + patterns.emplace( &result.RtlInsertInvertedFunctionTable32, OffsetData{ "\x8b\xff\x55\x8b\xec\x56\x68", false, 0 } ); + + // RtlLookupFunctionTable + 0x11 + // 89 5D E0 38 + patterns.emplace( &result.LdrpInvertedFunctionTable32, OffsetData{ "\x89\x5D\xE0\x38", false, -1, 0x1B } ); + + // LdrpHandleTlsData + // 74 20 8D 45 D4 50 6A 09 + patterns.emplace( &result.LdrpHandleTlsData32, OffsetData{ "\x74\x20\x8d\x45\xd4\x50\x6a\x09", false, 0x14 } ); + } +} + +/// +/// Scan ntdll for internal loader data +/// +/// Mapped x86 ntdll +/// Mapped x64 ntdll +/// Result +/// Status code +NTSTATUS ScanSymbolPatterns( const pe::PEImage& ntdll32, const pe::PEImage& ntdll64, SymbolData& result ) +{ + ScanParams scan32, scan64; + + scan32.diff = static_cast(ntdll32.imageBase()) - reinterpret_cast(ntdll32.base()); + scan64.diff = static_cast(ntdll64.imageBase()) - reinterpret_cast(ntdll64.base()); + + auto fillRanges = []( const pe::PEImage& file, ScanParams& params ) + { + for (const auto& sec : file.sections()) + { + if (_stricmp( reinterpret_cast(sec.Name), ".text" ) == 0) + { + params.start = reinterpret_cast(file.base()) + sec.VirtualAddress; + params.size = sec.Misc.VirtualSize; + break; + } + } + }; + + // Get code section bounds + fillRanges( ntdll32, scan32 ); + if (ntdll64.base()) + { + fillRanges( ntdll64, scan64 ); + } + + std::unordered_map patterns; + OSFillPatterns( patterns, result ); + + // Final search + for (const auto& e : patterns) + { + FindPattern( scan32, scan64, e.second, *e.first ); + } + + // Retry with old patterns + if (result.RtlInsertInvertedFunctionTable32 == 0 && IsWindows8Point1OrGreater() && !IsWindows10RS2OrGreater()) + { + // RtlInsertInvertedFunctionTable + // 8D 45 F4 89 55 F8 50 8D 55 FC + OffsetData rule1{ "\x8d\x45\xf4\x89\x55\xf8\x50\x8d\x55\xfc", false, 0xB }; + OffsetData rule2{ "\x8d\x45\xf4\x89\x55\xf8\x50\x8d\x55\xfc", false, -1, 0x1D }; + + FindPattern( scan32, scan64, rule1, result.RtlInsertInvertedFunctionTable32 ); + FindPattern( scan32, scan64, rule2, result.LdrpInvertedFunctionTable32 ); + } + + // Report errors +#ifndef BLACKBONE_NO_TRACE + if (result.LdrpHandleTlsData64 == 0) + BLACKBONE_TRACE( "PatternData: LdrpHandleTlsData64 not found" ); + if (result.LdrpHandleTlsData32 == 0) + BLACKBONE_TRACE( "PatternData: LdrpHandleTlsData32 not found" ); + if (IsWindows8Point1OrGreater() && result.LdrpInvertedFunctionTable64 == 0) + BLACKBONE_TRACE( "PatternData: LdrpInvertedFunctionTable64 not found" ); + if (result.LdrpInvertedFunctionTable32 == 0) + BLACKBONE_TRACE( "PatternData: LdrpInvertedFunctionTable32 not found" ); + if (IsWindows8Point1OrGreater() && result.RtlInsertInvertedFunctionTable64 == 0) + BLACKBONE_TRACE( "PatternData: RtlInsertInvertedFunctionTable64 not found" ); + if (result.RtlInsertInvertedFunctionTable32 == 0) + BLACKBONE_TRACE( "PatternData: RtlInsertInvertedFunctionTable32 not found" ); + if (IsWindows8Point1OrGreater() && result.LdrProtectMrdata == 0) + BLACKBONE_TRACE( "PatternData: LdrProtectMrdata not found" ); + if (IsWindows7OrGreater() && !IsWindows8OrGreater()) + { + if (result.LdrKernel32PatchAddress == 0) + BLACKBONE_TRACE( "PatternData: LdrKernel32PatchAddress not found" ); + if (result.APC64PatchAddress == 0) + BLACKBONE_TRACE( "PatternData: APC64PatchAddress not found" ); + } +#endif + + return STATUS_SUCCESS; +} + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Symbols/PatternLoader.h b/third/Blackbone/src/BlackBone/Symbols/PatternLoader.h new file mode 100644 index 0000000000000000000000000000000000000000..f59727e1c6137f1fa2226f8217822b606a09fb26 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Symbols/PatternLoader.h @@ -0,0 +1,17 @@ +#pragma once +#include "../Symbols/SymbolData.h" +#include "../PE/PEImage.h" + +namespace blackbone +{ + +/// +/// Scan ntdll for internal loader data +/// +/// Mapped x86 ntdll +/// Mapped x64 ntdll +/// Result +/// Status code +NTSTATUS ScanSymbolPatterns( const pe::PEImage& ntdll32, const pe::PEImage& ntdll64, SymbolData& result ); + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Symbols/SymbolData.cpp b/third/Blackbone/src/BlackBone/Symbols/SymbolData.cpp new file mode 100644 index 0000000000000000000000000000000000000000..19cc6167970738c6f8f9fc735532d4fc86d4eec6 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Symbols/SymbolData.cpp @@ -0,0 +1,7 @@ +#pragma once +#include "SymbolData.h" + +namespace blackbone +{ + SymbolData g_symbols; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Symbols/SymbolData.h b/third/Blackbone/src/BlackBone/Symbols/SymbolData.h new file mode 100644 index 0000000000000000000000000000000000000000..0c504aa040f4e6337f36bf481904acc41de1b5bb --- /dev/null +++ b/third/Blackbone/src/BlackBone/Symbols/SymbolData.h @@ -0,0 +1,27 @@ +#pragma once +#include "../include/Types.h" + +namespace blackbone +{ + +/// +/// Ntdll internal pointers +/// +struct SymbolData +{ + ptr_t LdrKernel32PatchAddress = 0; // Address to patch to enable kernel32 loading under win7 + ptr_t APC64PatchAddress = 0; // Address to patch for x64->WOW64 APC dispatching under win7 + ptr_t LdrpHandleTlsData32 = 0; // LdrpHandleTlsData address + ptr_t LdrpHandleTlsData64 = 0; // LdrpHandleTlsData address + ptr_t LdrpInvertedFunctionTable32 = 0; // LdrpInvertedFunctionTable address + ptr_t LdrpInvertedFunctionTable64 = 0; // LdrpInvertedFunctionTable address + ptr_t RtlInsertInvertedFunctionTable32 = 0; // RtlInsertInvertedFunctionTable address + ptr_t RtlInsertInvertedFunctionTable64 = 0; // RtlInsertInvertedFunctionTable address + ptr_t LdrpReleaseTlsEntry32 = 0; // LdrpReleaseTlsEntry address + ptr_t LdrpReleaseTlsEntry64 = 0; // LdrpReleaseTlsEntry address + ptr_t LdrProtectMrdata = 0; // LdrProtectMrdata address +}; + +extern SymbolData g_symbols; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Symbols/SymbolLoader.cpp b/third/Blackbone/src/BlackBone/Symbols/SymbolLoader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5d06932bc57118803588d2c1dbde0b0afb58d043 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Symbols/SymbolLoader.cpp @@ -0,0 +1,84 @@ +#include "SymbolLoader.h" +#include "PDBHelper.h" +#include "../Symbols/PatternLoader.h" +#include "../PE/PEImage.h" + +namespace blackbone +{ + +SymbolLoader::SymbolLoader() + : _x86OS( false ) + , _wow64Process( false ) +{ + SYSTEM_INFO info = { }; + GetNativeSystemInfo( &info ); + + if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) + { + _x86OS = true; + } + else + { + BOOL wowSrc = FALSE; + IsWow64Process( GetCurrentProcess(), &wowSrc ); + _wow64Process = wowSrc != 0; + } +} + +/// +/// Load symbol addresses from PDB or and pattern scans +/// +/// Found symbols +/// Status code +NTSTATUS SymbolLoader::Load( SymbolData& result ) +{ + pe::PEImage ntdll32, ntdll64; + PDBHelper sym32, sym64; + + wchar_t buf[MAX_PATH] = { 0 }; + GetWindowsDirectoryW( buf, MAX_PATH ); + + std::wstring windir( buf ); + + if (_x86OS) + { + ntdll32.Load( std::wstring( windir + L"\\System32\\ntdll.dll" ), true ); + } + else + { + FsRedirector fsr( _wow64Process ); + + ntdll64.Load( std::wstring( windir + L"\\System32\\ntdll.dll" ), true ); + ntdll32.Load( std::wstring( windir + L"\\SysWOW64\\ntdll.dll" ), true ); + } + + HRESULT hr = sym32.Init( ntdll32.path(), ntdll32.imageBase() ); + if (!_x86OS && SUCCEEDED( hr )) + { + FsRedirector fsr( _wow64Process ); + hr = sym64.Init( ntdll64.path(), ntdll64.imageBase() ); + } + + // Get addresses from pdb + if (SUCCEEDED( hr )) + { + sym32.GetSymAddress( L"LdrpHandleTlsData", result.LdrpHandleTlsData32 ); + sym64.GetSymAddress( L"LdrpHandleTlsData", result.LdrpHandleTlsData64 ); + + sym32.GetSymAddress( L"LdrpInvertedFunctionTable", result.LdrpInvertedFunctionTable32 ); + sym64.GetSymAddress( L"LdrpInvertedFunctionTable", result.LdrpInvertedFunctionTable64 ); + + sym32.GetSymAddress( L"RtlInsertInvertedFunctionTable", result.RtlInsertInvertedFunctionTable32 ); + sym64.GetSymAddress( L"RtlInsertInvertedFunctionTable", result.RtlInsertInvertedFunctionTable64 ); + + sym32.GetSymAddress( L"LdrpReleaseTlsEntry", result.LdrpReleaseTlsEntry32 ); + sym64.GetSymAddress( L"LdrpReleaseTlsEntry", result.LdrpReleaseTlsEntry64 ); + + sym32.GetSymAddress( L"LdrProtectMrdata", result.LdrProtectMrdata ); + } + + // Fill missing symbols from patterns + return ScanSymbolPatterns( ntdll32, ntdll64, result ); +} + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Symbols/SymbolLoader.h b/third/Blackbone/src/BlackBone/Symbols/SymbolLoader.h new file mode 100644 index 0000000000000000000000000000000000000000..3dcd7c9a81d5c7cced7555db9d4bc121b21128ce --- /dev/null +++ b/third/Blackbone/src/BlackBone/Symbols/SymbolLoader.h @@ -0,0 +1,24 @@ +#pragma once +#include "SymbolData.h" + +namespace blackbone +{ + +class SymbolLoader +{ +public: + SymbolLoader(); + + /// + /// Load symbol addresses from PDB or and pattern scans + /// + /// Found symbols + /// Status code + NTSTATUS Load( SymbolData& result ); + +private: + bool _x86OS; // x86 OS + bool _wow64Process; // Current process is wow64 process +}; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Syscalls/Syscall.h b/third/Blackbone/src/BlackBone/Syscalls/Syscall.h new file mode 100644 index 0000000000000000000000000000000000000000..f070a4e85ce027f5b14c6b1987737b8be8fa963c --- /dev/null +++ b/third/Blackbone/src/BlackBone/Syscalls/Syscall.h @@ -0,0 +1,71 @@ +#pragma once +#include "../Config.h" +#include "../Include/Winheaders.h" +#include +#include + +extern "C" void* syscall_stub(); + +namespace blackbone +{ +namespace syscall +{ + template + using to_int64 = std::conditional_t; + +#pragma warning(push) +#pragma warning(disable : 4100) + + template + R syscall( int index, Args... args ) + { + auto error = []( NTSTATUS status ) + { + if constexpr (std::is_same_v) + return status; + else + return R(); + }; + +#ifdef USE32 + return error( STATUS_NOT_SUPPORTED ); +#else + static_assert(sizeof( R ) <= sizeof( void* ), "Return types larger than void* aren't supported"); + if (index == -1) + return error( STATUS_INVALID_PARAMETER_1 ); + + // Cast types that otherwise will be only half-initialized + auto pfn = reinterpret_cast... )>(syscall_stub); + return pfn( index, sizeof...( Args ), to_int64( args )... ); +#endif + } + + template + NTSTATUS nt_syscall( int index, Args&&... args ) + { + return syscall( index, std::forward( args )... ); + } + + inline int get_index( const wchar_t* modName, const char* func ) + { +#ifdef USE32 + // Doesn't work for x86 + return -1; +#else + const auto pfn = reinterpret_cast(GetProcAddress( + GetModuleHandleW( modName ), + func + )); + + return pfn ? *reinterpret_cast(pfn + 4) : -1; +#endif + } + + inline int get_index( const char* func ) + { + return get_index( L"ntdll.dll", func ); + } + +#pragma warning(pop) +} +} diff --git a/third/Blackbone/src/BlackBone/Syscalls/Syscall32.asm b/third/Blackbone/src/BlackBone/Syscalls/Syscall32.asm new file mode 100644 index 0000000000000000000000000000000000000000..beb17cb3393d7984ba8f087d5df63009fc02ab16 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Syscalls/Syscall32.asm @@ -0,0 +1,35 @@ +.MODEL flat +.code + +x64_enter proc + retf +x64_enter endp + +x64_exit proc + mov dword ptr [esp + 4], 23h + retf +x64_exit endp + + +_syscall_stub proc + push ebp + mov ebp, esp + sub esp, 20h + + push 33h + call x64_enter + + db 48h + mov eax, 0DEADBEEFh + + call x64_exit + + mov dx, ds + mov ss, dx + + mov esp, ebp + pop ebp + ret +_syscall_stub endp + +end \ No newline at end of file diff --git a/third/Blackbone/src/BlackBone/Syscalls/Syscall64.asm b/third/Blackbone/src/BlackBone/Syscalls/Syscall64.asm new file mode 100644 index 0000000000000000000000000000000000000000..a85538653afa4e3c2eff6ff36f4ffba8249e3a57 --- /dev/null +++ b/third/Blackbone/src/BlackBone/Syscalls/Syscall64.asm @@ -0,0 +1,31 @@ +.code + +syscall_stub proc + mov eax, ecx + + ; validate number of arguments + cmp edx, 1 + jl skip + + mov r10, r8 + cmp edx, 2 + jl skip + + xchg rdx, r9 + cmp r9d, 3 + jl skip + + mov r8, [rsp + 28h] + cmp r9d, 4 + jl skip + + mov r9, [rsp + 30h] + +skip: + add rsp, 10h ; skip first 2 args + syscall + sub rsp, 10h + ret +syscall_stub endp + +end \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/BlackBoneDef.h b/third/Blackbone/src/BlackBoneDrv/BlackBoneDef.h new file mode 100644 index 0000000000000000000000000000000000000000..5d4a631b2966eee5440a5f201012e4bcff6a5d97 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/BlackBoneDef.h @@ -0,0 +1,527 @@ +#pragma once + +#define BLACKBONE_DEVICE_NAME L"BlackBone" +#define BLACKBONE_DEVICE_FILE L"\\\\.\\" BLACKBONE_DEVICE_NAME + +#define FILE_DEVICE_BLACKBONE 0x8005 + +#define BLACKBONE_FILE_EXT L".sys" +#define BLACKBONE_FILE_SUFFIX L"Drv" +#define BLACKBONE_FILE_NAME BLACKBONE_DEVICE_NAME BLACKBONE_FILE_SUFFIX BLACKBONE_FILE_EXT +#define BLACKBONE_FILE_NAME_7 BLACKBONE_DEVICE_NAME BLACKBONE_FILE_SUFFIX L"7" BLACKBONE_FILE_EXT +#define BLACKBONE_FILE_NAME_8 BLACKBONE_DEVICE_NAME BLACKBONE_FILE_SUFFIX L"8" BLACKBONE_FILE_EXT +#define BLACKBONE_FILE_NAME_81 BLACKBONE_DEVICE_NAME BLACKBONE_FILE_SUFFIX L"81" BLACKBONE_FILE_EXT +#define BLACKBONE_FILE_NAME_10 BLACKBONE_DEVICE_NAME BLACKBONE_FILE_SUFFIX L"10" BLACKBONE_FILE_EXT + +/* + Disable process DEP + + Input: + DISABLE_DEP + + Input size: + sizeof(DISABLE_DEP) + + Output: + void + + Output size: + 0 +*/ +#define IOCTL_BLACKBONE_DISABLE_DEP (ULONG)CTL_CODE(FILE_DEVICE_BLACKBONE, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + Change process protection state + + Input: + SET_PROC_PROTECTION + + Input size: + sizeof(SET_PROC_PROTECTION) + + Output: + void + + Output size: + 0 +*/ +#define IOCTL_BLACKBONE_SET_PROTECTION (ULONG)CTL_CODE(FILE_DEVICE_BLACKBONE, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + Change handle access rights + + Input: + GRANT_ACCESS + + Input size: + sizeof(GRANT_ACCESS) + + Output: + void + + Output size: + 0 +*/ +#define IOCTL_BLACKBONE_GRANT_ACCESS (ULONG)CTL_CODE(FILE_DEVICE_BLACKBONE, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + Read or write virtual memory of target process + + Input: + COPY_MEMORY + + Input size: + sizeof(COPY_MEMORY) + + Output: + void + + Output size: + 0 +*/ +#define IOCTL_BLACKBONE_COPY_MEMORY (ULONG)CTL_CODE(FILE_DEVICE_BLACKBONE, 0x803, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + Allocate or free memory + + Input: + ALLOCATE_FREE_MEMORY + + Input size: + sizeof(ALLOCATE_FREE_MEMORY) + + Output: + ALLOCATE_FREE_MEMORY_RESULT + + Output size: + sizeof(ALLOCATE_FREE_MEMORY_RESULT) +*/ +#define IOCTL_BLACKBONE_ALLOCATE_FREE_MEMORY (ULONG)CTL_CODE(FILE_DEVICE_BLACKBONE, 0x804, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + Change protection of memory region + + Input: + PROTECT_MEMORY + + Input size: + sizeof(PROTECT_MEMORY) + + Output: + void + + Output size: + 0 +*/ +#define IOCTL_BLACKBONE_PROTECT_MEMORY (ULONG)CTL_CODE(FILE_DEVICE_BLACKBONE, 0x805, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + Map entire address space of target process into calling process + + Input: + MAP_MEMORY + + Input size: + sizeof(MAP_MEMORY) + + Output: + ULONG sizeRequired - if output buffer isn't large enough to hold output data + MAP_MEMORY_REGION_RESULT result - if buffer is large enough to hold output data + + Output size: + sizeof(ULONG) - if output buffer isn't large enough to hold output data + >= sizeof(MAP_MEMORY_REGION_RESULT) - if buffer is large enough to hold output data +*/ +#define IOCTL_BLACKBONE_MAP_MEMORY (ULONG)CTL_CODE(FILE_DEVICE_BLACKBONE, 0x806, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + Map single memory region into calling process + + Input: + MAP_MEMORY_REGION + + Input size: + sizeof(MAP_MEMORY_REGION) + + Output: + MAP_MEMORY_REGION_RESULT + + Output size: + sizeof(MAP_MEMORY_REGION_RESULT) +*/ +#define IOCTL_BLACKBONE_MAP_REGION (ULONG)CTL_CODE(FILE_DEVICE_BLACKBONE, 0x807, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + Unmap all mapped memory from calling process + + Input: + UNMAP_MEMORY + + Input size: + sizeof(UNMAP_MEMORY) + + Output: + void + + Output size: + 0 +*/ +#define IOCTL_BLACKBONE_UNMAP_MEMORY (ULONG)CTL_CODE(FILE_DEVICE_BLACKBONE, 0x808, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + Unmap single memory region from calling process + + Input: + UNMAP_MEMORY_REGION + + Input size: + sizeof(UNMAP_MEMORY_REGION) + + Output: + UNMAP_MEMORY_REGION_RESULT + + Output size: + sizeof(UNMAP_MEMORY_REGION_RESULT) +*/ +#define IOCTL_BLACKBONE_UNMAP_REGION (ULONG)CTL_CODE(FILE_DEVICE_BLACKBONE, 0x809, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + Unlink target VAD from process VAD tree + + Input: + HIDE_VAD + + Input size: + sizeof(HIDE_VAD) + + Output: + NULL + + Output size: + 0 +*/ +#define IOCTL_BLACKBONE_HIDE_VAD (ULONG)CTL_CODE(FILE_DEVICE_BLACKBONE, 0x80A, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + Inject dll into arbitrary process + + Input: + INJECT_DLL + + Input size: + sizeof(INJECT_DLL) + + Output: + NULL + + Output size: + 0 +*/ +#define IOCTL_BLACKBONE_INJECT_DLL (ULONG)CTL_CODE(FILE_DEVICE_BLACKBONE, 0x80B, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + Manually map system driver + + Input: + MMAP_DRIVER + + Input size: + sizeof(MMAP_DRIVER) + + Output: + NULL + + Output size: + 0 +*/ +#define IOCTL_BLACKBONE_MAP_DRIVER (ULONG)CTL_CODE(FILE_DEVICE_BLACKBONE, 0x80C, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + Unlink process handle table from handle table list + + Input: + UNLINK_HTABLE + + Input size: + sizeof(UNLINK_HTABLE) + + Output: + NULL + + Output size: + 0 +*/ +#define IOCTL_BLACKBONE_UNLINK_HTABLE (ULONG)CTL_CODE(FILE_DEVICE_BLACKBONE, 0x80D, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* +Map entire address space of target process into calling process + + Input: + ENUM_REGIONS + + Input size: + sizeof(ENUM_REGIONS) + + Output: + ENUM_REGIONS_RESULT - enumerated regions + + Output size: + >= sizeof(ENUM_REGIONS_RESULT) +*/ +#define IOCTL_BLACKBONE_ENUM_REGIONS (ULONG)CTL_CODE(FILE_DEVICE_BLACKBONE, 0x80E, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + + +/// +/// Input for IOCTL_BLACKBONE_DISABLE_DEP +/// +typedef struct _DISABLE_DEP +{ + ULONG pid; // Process ID +} DISABLE_DEP, *PDISABLE_DEP; + +/// +/// Policy activation option +/// +typedef enum _PolicyOpt +{ + Policy_Disable, + Policy_Enable, + Policy_Keep, // Don't change current value +} PolicyOpt; + +/// +/// Input for IOCTL_BLACKBONE_SET_PROTECTION +/// +typedef struct _SET_PROC_PROTECTION +{ + ULONG pid; // Process ID + PolicyOpt protection; // Process protection + PolicyOpt dynamicCode; // DynamiCode policy + PolicyOpt signature; // BinarySignature policy +} SET_PROC_PROTECTION, *PSET_PROC_PROTECTION; + +/// +/// Input for IOCTL_BLACKBONE_GRANT_ACCESS +/// +typedef struct _HANDLE_GRANT_ACCESS +{ + ULONGLONG handle; // Handle to modify + ULONG pid; // Process ID + ULONG access; // Access flags to grant +} HANDLE_GRANT_ACCESS, *PHANDLE_GRANT_ACCESS; + +/// +/// Input for IOCTL_BLACKBONE_COPY_MEMORY +/// +typedef struct _COPY_MEMORY +{ + ULONGLONG localbuf; // Buffer address + ULONGLONG targetPtr; // Target address + ULONGLONG size; // Buffer size + ULONG pid; // Target process id + BOOLEAN write; // TRUE if write operation, FALSE if read +} COPY_MEMORY, *PCOPY_MEMORY; + +/// +/// Input for IOCTL_BLACKBONE_ALLOCATE_FREE_MEMORY +/// +typedef struct _ALLOCATE_FREE_MEMORY +{ + ULONGLONG base; // Region base address + ULONGLONG size; // Region size + ULONG pid; // Target process id + ULONG protection; // Memory protection for allocation + ULONG type; // MEM_RESERVE/MEM_COMMIT/MEM_DECOMMIT/MEM_RELEASE + BOOLEAN allocate; // TRUE if allocation, FALSE is freeing + BOOLEAN physical; // If set to TRUE, physical pages will be directly mapped into UM space +} ALLOCATE_FREE_MEMORY, *PALLOCATE_FREE_MEMORY; + +/// +/// Output for IOCTL_BLACKBONE_ALLOCATE_FREE_MEMORY +/// +typedef struct _ALLOCATE_FREE_MEMORY_RESULT +{ + ULONGLONG address; // Address of allocation + ULONGLONG size; // Allocated size +} ALLOCATE_FREE_MEMORY_RESULT, *PALLOCATE_FREE_MEMORY_RESULT; + +/// +/// Input for IOCTL_BLACKBONE_PROTECT_MEMORY +/// +typedef struct _PROTECT_MEMORY +{ + ULONGLONG base; // Region base address + ULONGLONG size; // Region size + ULONG pid; // Target process id + ULONG newProtection; // New protection value +} PROTECT_MEMORY, *PPROTECT_MEMORY; + +/// +/// Input for IOCTL_BLACKBONE_REMAP_MEMORY +/// +typedef struct _MAP_MEMORY +{ + ULONG pid; // Target process id + wchar_t pipeName[32]; // Hook pipe name + BOOLEAN mapSections; // Set to TRUE to map sections +} MAP_MEMORY, *PMAP_MEMORY; + +/// +/// Remapped region info +/// +typedef struct _MAP_MEMORY_RESULT_ENTRY +{ + ULONGLONG originalPtr; // Address in target process + ULONGLONG newPtr; // Mapped address in host process + ULONG size; // Region size +} MAP_MEMORY_RESULT_ENTRY, *PMAP_MEMORY_RESULT_ENTRY; + +/// +/// Output for IOCTL_BLACKBONE_REMAP_REGION +/// +typedef struct _MAP_MEMORY_RESULT +{ + ULONGLONG pipeHandle; // Pipe handle in target process + ULONGLONG targetPage; // Address of shared page in target process + ULONGLONG hostPage; // Address of shared page in host process + + ULONG count; // Number of REMAP_MEMORY_RESULT_ENTRY entries + + // List of remapped regions (variable-sized array) + MAP_MEMORY_RESULT_ENTRY entries[1]; +} MAP_MEMORY_RESULT, *PMAP_MEMORY_RESULT; + +/// +/// Input for IOCTL_BLACKBONE_REMAP_REGION +/// +typedef struct _MAP_MEMORY_REGION +{ + ULONGLONG base; // Region base address + ULONG pid; // Target process id + ULONG size; // Region size +} MAP_MEMORY_REGION, *PMAP_MEMORY_REGION; + +/// +/// Output for IOCTL_BLACKBONE_REMAP_REGION +/// +typedef struct _MAP_MEMORY_REGION_RESULT +{ + ULONGLONG originalPtr; // Address in target process + ULONGLONG newPtr; // Mapped address in host process + ULONGLONG removedPtr; // Unmapped region base, in case of conflicting region + ULONG size; // Mapped region size + ULONG removedSize; // Unmapped region size +} MAP_MEMORY_REGION_RESULT, *PMAP_MEMORY_REGION_RESULT; + +/// +/// Input for IOCTL_BLACKBONE_UNMAP_MEMORY +/// +typedef struct _UNMAP_MEMORY +{ + ULONG pid; // Target process ID +} UNMAP_MEMORY, *PUNMAP_MEMORY; + +/// +/// Input for IOCTL_BLACKBONE_UNMAP_REGION +/// +typedef struct _UNMAP_MEMORY_REGION +{ + ULONGLONG base; // Region base address + ULONG pid; // Target process ID + ULONG size; // Region size +} UNMAP_MEMORY_REGION, *PUNMAP_MEMORY_REGION; + + +/// +/// Input for IOCTL_BLACKBONE_HIDE_VAD +/// +typedef struct _HIDE_VAD +{ + ULONGLONG base; // Region base address + ULONGLONG size; // Region size + ULONG pid; // Target process ID +} HIDE_VAD, *PHIDE_VAD; + +typedef enum _InjectType +{ + IT_Thread, // CreateThread into LdrLoadDll + IT_Apc, // Force user APC into LdrLoadDll + IT_MMap, // Manual map +} InjectType; + +typedef enum _MmapFlags +{ + KNoFlags = 0x00, // No flags + KManualImports = 0x01, // Manually map import libraries + KWipeHeader = 0x04, // Wipe image PE headers + KHideVAD = 0x10, // Make image appear as PAGE_NOACESS region + KRebaseProcess = 0x40, // If target image is an .exe file, process base address will be replaced with mapped module value + KNoThreads = 0x80, // Don't create new threads, use hijacking + + KNoExceptions = 0x01000, // Do not create custom exception handler + KNoSxS = 0x08000, // Do not apply SxS activation context + KNoTLS = 0x10000, // Skip TLS initialization and don't execute TLS callbacks +} KMmapFlags; + +/// +/// Input for IOCTL_BLACKBONE_INJECT_DLL +/// +typedef struct _INJECT_DLL +{ + InjectType type; // Type of injection + wchar_t FullDllPath[512]; // Fully-qualified path to the target dll + wchar_t initArg[512]; // Init routine argument + ULONG initRVA; // Init routine RVA, if 0 - no init routine + ULONG pid; // Target process ID + BOOLEAN wait; // Wait on injection thread + BOOLEAN unlink; // Unlink module after injection + BOOLEAN erasePE; // Erase PE headers after injection + KMmapFlags flags; // Manual map flags + ULONGLONG imageBase; // Image address in memory to manually map + ULONG imageSize; // Size of memory image + BOOLEAN asImage; // Memory chunk has image layout +} INJECT_DLL, *PINJECT_DLL; + +/// +/// Input for IOCTL_BLACKBONE_MAP_DRIVER +/// +typedef struct _MMAP_DRIVER +{ + wchar_t FullPath[512]; // Fully-qualified path to the driver +} MMAP_DRIVER, *PMMAP_DRIVER; + +/// +/// Input for IOCTL_BLACKBONE_UNLINK_HTABLE +/// +typedef struct _UNLINK_HTABLE +{ + ULONG pid; // Process ID +} UNLINK_HTABLE, *PUNLINK_HTABLE; + +/// +/// Input for IOCTL_BLACKBONE_ENUM_REGIONS +/// +typedef struct _ENUM_REGIONS +{ + ULONG pid; // Process ID +} ENUM_REGIONS, *PENUM_REGIONS; + +typedef struct _MEM_REGION +{ + ULONGLONG BaseAddress; + ULONGLONG AllocationBase; + ULONG AllocationProtect; + ULONGLONG RegionSize; + ULONG State; + ULONG Protect; + ULONG Type; +} MEM_REGION, *PMEM_REGION; + +/// +/// Output for IOCTL_BLACKBONE_ENUM_REGIONS +/// +typedef struct _ENUM_REGIONS_RESULT +{ + ULONGLONG count; // Number of records + MEM_REGION regions[1]; // Found regions, variable-sized +} ENUM_REGIONS_RESULT, *PENUM_REGIONS_RESULT; \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/BlackBoneDrv.c b/third/Blackbone/src/BlackBoneDrv/BlackBoneDrv.c new file mode 100644 index 0000000000000000000000000000000000000000..83cf4caf4b0344a521087432ad17eff948be13f1 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/BlackBoneDrv.c @@ -0,0 +1,485 @@ +#include "BlackBoneDrv.h" +#include "Remap.h" +#include "Loader.h" +#include "Utils.h" +#include + +// OS Dependant data +DYNAMIC_DATA dynData; + +NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING registryPath ); +NTSTATUS BBInitDynamicData( IN OUT PDYNAMIC_DATA pData ); +NTSTATUS BBGetBuildNO( OUT PULONG pBuildNo ); +NTSTATUS BBScanSection( IN PCCHAR section, IN PCUCHAR pattern, IN UCHAR wildcard, IN ULONG_PTR len, OUT PVOID* ppFound ); +VOID BBUnload( IN PDRIVER_OBJECT DriverObject ); + +#pragma alloc_text(INIT, DriverEntry) +#pragma alloc_text(INIT, BBInitDynamicData) +#pragma alloc_text(INIT, BBGetBuildNO) +#pragma alloc_text(INIT, BBScanSection) + +/* +*/ +NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) +{ + NTSTATUS status = STATUS_SUCCESS; + PDEVICE_OBJECT deviceObject = NULL; + UNICODE_STRING deviceName; + UNICODE_STRING deviceLink; + + UNREFERENCED_PARAMETER( RegistryPath ); + + // Get OS Dependant offsets + InitializeDebuggerBlock( &g_KdBlock ); + status = BBInitDynamicData( &dynData ); + if (!NT_SUCCESS( status )) + { + if (status == STATUS_NOT_SUPPORTED) + DPRINT( "BlackBone: %s: Unsupported OS version. Aborting\n", __FUNCTION__ ); + + return status; + } + + // Initialize some loader structures + status = BBInitLdrData( (PKLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection ); + if (!NT_SUCCESS( status )) + return status; + // + // Globals init + // + InitializeListHead( &g_PhysProcesses ); + RtlInitializeGenericTableAvl( &g_ProcessPageTables, &AvlCompare, &AvlAllocate, &AvlFree, NULL ); + KeInitializeGuardedMutex( &g_globalLock ); + + // Setup process termination notifier + status = PsSetCreateProcessNotifyRoutine( BBProcessNotify, FALSE ); + if (!NT_SUCCESS( status )) + { + DPRINT( "BlackBone: %s: Failed to setup notify routine with staus 0x%X\n", __FUNCTION__, status ); + return status; + } + + RtlUnicodeStringInit( &deviceName, DEVICE_NAME ); + + status = IoCreateDevice( DriverObject, 0, &deviceName, FILE_DEVICE_BLACKBONE, 0, FALSE, &deviceObject ); + if (!NT_SUCCESS( status )) + { + DPRINT( "BlackBone: %s: IoCreateDevice failed with status 0x%X\n", __FUNCTION__, status ); + return status; + } + + DriverObject->MajorFunction[IRP_MJ_CREATE] = + DriverObject->MajorFunction[IRP_MJ_CLOSE] = + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = BBDispatch; + DriverObject->DriverUnload = BBUnload; + + RtlUnicodeStringInit( &deviceLink, DOS_DEVICE_NAME ); + + status = IoCreateSymbolicLink( &deviceLink, &deviceName ); + + if (!NT_SUCCESS( status )) + { + DPRINT( "BlackBone: %s: IoCreateSymbolicLink failed with status 0x%X\n", __FUNCTION__, status ); + IoDeleteDevice (deviceObject); + } + + return status; +} + + +/* +*/ +VOID BBUnload( IN PDRIVER_OBJECT DriverObject ) +{ + UNICODE_STRING deviceLinkUnicodeString; + + // Unregister notification + PsSetCreateProcessNotifyRoutine( BBProcessNotify, TRUE ); + + // Cleanup physical regions + BBCleanupProcessPhysList(); + + // Cleanup process mapping info + BBCleanupProcessTable(); + + RtlUnicodeStringInit( &deviceLinkUnicodeString, DOS_DEVICE_NAME ); + IoDeleteSymbolicLink( &deviceLinkUnicodeString ); + IoDeleteDevice( DriverObject->DeviceObject ); + + return; +} + +/// +/// Find pattern in kernel PE section +/// +/// Section name +/// Pattern data +/// Pattern wildcard symbol +/// Pattern length +/// Found address +/// Status code +NTSTATUS BBScanSection( IN PCCHAR section, IN PCUCHAR pattern, IN UCHAR wildcard, IN ULONG_PTR len, OUT PVOID* ppFound ) +{ + ASSERT( ppFound != NULL ); + if (ppFound == NULL) + return STATUS_INVALID_PARAMETER; + + PVOID base = GetKernelBase( NULL); + if (!base) + return STATUS_NOT_FOUND; + + PIMAGE_NT_HEADERS64 pHdr = RtlImageNtHeader( base ); + if (!pHdr) + return STATUS_INVALID_IMAGE_FORMAT; + + PIMAGE_SECTION_HEADER pFirstSection = (PIMAGE_SECTION_HEADER)(pHdr + 1); + for (PIMAGE_SECTION_HEADER pSection = pFirstSection; pSection < pFirstSection + pHdr->FileHeader.NumberOfSections; pSection++) + { + ANSI_STRING s1, s2; + RtlInitAnsiString( &s1, section ); + RtlInitAnsiString( &s2, (PCCHAR)pSection->Name ); + if (RtlCompareString( &s1, &s2, TRUE ) == 0) + { + PVOID ptr = NULL; + NTSTATUS status = BBSearchPattern( pattern, wildcard, len, (PUCHAR)base + pSection->VirtualAddress, pSection->Misc.VirtualSize, &ptr ); + if (NT_SUCCESS( status )) + *(PULONG)ppFound = (ULONG)((PUCHAR)ptr - (PUCHAR)base); + + return status; + } + } + + return STATUS_NOT_FOUND; +} + +/// +/// Get kernel build number +/// +/// Build number. +/// Status code +NTSTATUS BBGetBuildNO( OUT PULONG pBuildNo ) +{ + ASSERT( pBuildNo != NULL ); + if (pBuildNo == NULL) + return STATUS_INVALID_PARAMETER; + + NTSTATUS status = STATUS_SUCCESS; + UNICODE_STRING strRegKey = RTL_CONSTANT_STRING( L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion" ); + UNICODE_STRING strRegValue = RTL_CONSTANT_STRING( L"BuildLabEx" ); + UNICODE_STRING strRegValue10 = RTL_CONSTANT_STRING( L"UBR" ); + UNICODE_STRING strVerVal = { 0 }; + HANDLE hKey = NULL; + OBJECT_ATTRIBUTES keyAttr = { 0 }; + + InitializeObjectAttributes( &keyAttr, &strRegKey, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL ); + + status = ZwOpenKey( &hKey, KEY_READ, &keyAttr ); + if (NT_SUCCESS( status )) + { + PKEY_VALUE_FULL_INFORMATION pValueInfo = ExAllocatePoolWithTag( PagedPool, PAGE_SIZE, BB_POOL_TAG ); + ULONG bytes = 0; + + if (pValueInfo) + { + // Try query UBR value + status = ZwQueryValueKey( hKey, &strRegValue10, KeyValueFullInformation, pValueInfo, PAGE_SIZE, &bytes ); + if (NT_SUCCESS( status )) + { + *pBuildNo = *(PULONG)((PUCHAR)pValueInfo + pValueInfo->DataOffset); + goto skip1; + } + + status = ZwQueryValueKey( hKey, &strRegValue, KeyValueFullInformation, pValueInfo, PAGE_SIZE, &bytes ); + if (NT_SUCCESS( status )) + { + PWCHAR pData = (PWCHAR)((PUCHAR)pValueInfo->Name + pValueInfo->NameLength); + for (ULONG i = 0; i < pValueInfo->DataLength; i++) + { + if (pData[i] == L'.') + { + for (ULONG j = i + 1; j < pValueInfo->DataLength; j++) + { + if (pData[j] == L'.') + { + strVerVal.Buffer = &pData[i] + 1; + strVerVal.Length = strVerVal.MaximumLength = (USHORT)((j - i) * sizeof( WCHAR )); + status = RtlUnicodeStringToInteger( &strVerVal, 10, pBuildNo ); + + goto skip1; + } + } + } + } + + skip1:; + } + + ExFreePoolWithTag( pValueInfo, BB_POOL_TAG ); + } + else + status = STATUS_NO_MEMORY; + + ZwClose( hKey ); + } + else + DPRINT( "BlackBone: %s: ZwOpenKey failed with status 0x%X\n", __FUNCTION__, status ); + + return status; + +} + +/// +/// Initialize dynamic data. +/// +/// Data to initialize +/// Status code +NTSTATUS BBInitDynamicData( IN OUT PDYNAMIC_DATA pData ) +{ + NTSTATUS status = STATUS_SUCCESS; + RTL_OSVERSIONINFOEXW verInfo = { 0 }; + + if (pData == NULL) + return STATUS_INVALID_ADDRESS; + + RtlZeroMemory( pData, sizeof( DYNAMIC_DATA ) ); + pData->DYN_PDE_BASE = PDE_BASE; + pData->DYN_PTE_BASE = PTE_BASE; + + verInfo.dwOSVersionInfoSize = sizeof( verInfo ); + status = RtlGetVersion( (PRTL_OSVERSIONINFOW)&verInfo ); + + if (status == STATUS_SUCCESS) + { + ULONG ver_short = (verInfo.dwMajorVersion << 8) | (verInfo.dwMinorVersion << 4) | verInfo.wServicePackMajor; + pData->ver = (WinVer)ver_short; + + // Get kernel build number + status = BBGetBuildNO( &pData->buildNo ); + + // Validate current driver version + pData->correctBuild = TRUE; +#if defined(_WIN7_) + if (ver_short != WINVER_7 && ver_short != WINVER_7_SP1) + return STATUS_NOT_SUPPORTED; +#elif defined(_WIN8_) + if (ver_short != WINVER_8) + return STATUS_NOT_SUPPORTED; +#elif defined (_WIN81_) + if (ver_short != WINVER_81) + return STATUS_NOT_SUPPORTED; +#elif defined (_WIN10_) + if (ver_short < WINVER_10 || WINVER_10_RS5 < ver_short) + return STATUS_NOT_SUPPORTED; +#endif + + DPRINT( + "BlackBone: OS version %d.%d.%d.%d.%d - 0x%x\n", + verInfo.dwMajorVersion, + verInfo.dwMinorVersion, + verInfo.dwBuildNumber, + verInfo.wServicePackMajor, + pData->buildNo, + ver_short + ); + + switch (ver_short) + { + // Windows 7 + // Windows 7 SP1 + case WINVER_7: + case WINVER_7_SP1: + pData->KExecOpt = 0x0D2; + pData->Protection = 0x43C; // Bitfield, bit index - 0xB + pData->ObjTable = 0x200; + pData->VadRoot = 0x448; + pData->NtProtectIndex = 0x04D; + pData->NtCreateThdIndex = 0x0A5; + pData->NtTermThdIndex = 0x50; + pData->PrevMode = 0x1F6; + pData->ExitStatus = 0x380; + pData->MiAllocPage = (ver_short == WINVER_7_SP1) ? 0 : 0; + if (ver_short == WINVER_7_SP1) + { + if (NT_SUCCESS( BBScanSection( "PAGE", (PCUCHAR)"\x48\x8D\x56\x20\x48\x8B\x42\x08", 0xCC, 8, (PVOID)&pData->ExRemoveTable ) )) + pData->ExRemoveTable -= 0x36; + } + else + pData->ExRemoveTable = 0x32D404; + break; + + // Windows 8 + case WINVER_8: + pData->KExecOpt = 0x1B7; + pData->Protection = 0x648; + pData->ObjTable = 0x408; + pData->VadRoot = 0x590; + pData->NtProtectIndex = 0x04E; + pData->NtCreateThdIndex = 0x0AF; + pData->NtTermThdIndex = 0x51; + pData->PrevMode = 0x232; + pData->ExitStatus = 0x450; + pData->MiAllocPage = 0x3AF374; + pData->ExRemoveTable = 0x487518; + break; + + // Windows 8.1 + case WINVER_81: + pData->KExecOpt = 0x1B7; + pData->Protection = 0x67A; + pData->EProcessFlags2 = 0x2F8; + pData->ObjTable = 0x408; + pData->VadRoot = 0x5D8; + pData->NtCreateThdIndex = 0xB0; + pData->NtTermThdIndex = 0x52; + pData->PrevMode = 0x232; + pData->ExitStatus = 0x6D8; + pData->MiAllocPage = 0; + pData->ExRemoveTable = 0x432A88; // 0x38E320; + if (NT_SUCCESS( BBScanSection( "PAGE", (PCUCHAR)"\x48\x8D\x7D\x18\x48\x8B", 0xCC, 6, (PVOID)&pData->ExRemoveTable ) )) + pData->ExRemoveTable -= 0x5E; + break; + + // Windows 10, build 16299/15063/14393/10586 + case WINVER_10: + if (verInfo.dwBuildNumber == 10586) + { + pData->KExecOpt = 0x1BF; + pData->Protection = 0x6B2; + pData->EProcessFlags2 = 0x300; + pData->ObjTable = 0x418; + pData->VadRoot = 0x610; + pData->NtCreateThdIndex = 0xB4; + pData->NtTermThdIndex = 0x53; + pData->PrevMode = 0x232; + pData->ExitStatus = 0x6E0; + pData->MiAllocPage = 0; + if (NT_SUCCESS( BBScanSection( "PAGE", (PCUCHAR)"\x48\x8D\x7D\x18\x48\x8B", 0xCC, 6, (PVOID)&pData->ExRemoveTable ) )) + pData->ExRemoveTable -= 0x5C; + break; + } + else if (verInfo.dwBuildNumber == 14393) + { + pData->ver = WINVER_10_RS1; + pData->KExecOpt = 0x1BF; + pData->Protection = pData->buildNo >= 447 ? 0x6CA : 0x6C2; + pData->EProcessFlags2 = 0x300; + pData->ObjTable = 0x418; + pData->VadRoot = 0x620; + pData->NtCreateThdIndex = 0xB6; + pData->NtTermThdIndex = 0x53; + pData->PrevMode = 0x232; + pData->ExitStatus = 0x6F0; + pData->MiAllocPage = 0; + if (NT_SUCCESS( BBScanSection( "PAGE", (PCUCHAR)"\x48\x8D\x7D\x18\x48\x8B", 0xCC, 6, (PVOID)&pData->ExRemoveTable ) )) + pData->ExRemoveTable -= 0x60; + break; + } + else if (verInfo.dwBuildNumber == 15063) + { + pData->ver = WINVER_10_RS2; + pData->KExecOpt = 0x1BF; + pData->Protection = 0x6CA; + pData->EProcessFlags2 = 0x300; + pData->ObjTable = 0x418; + pData->VadRoot = 0x628; + pData->NtCreateThdIndex = 0xB9; + pData->NtTermThdIndex = 0x53; + pData->PrevMode = 0x232; + pData->ExitStatus = 0x6F8; + pData->MiAllocPage = 0; + if (NT_SUCCESS( BBScanSection( "PAGE", (PCUCHAR)"\x48\x8B\x47\x20\x48\x83\xC7\x18", 0xCC, 8, (PVOID)&pData->ExRemoveTable ) )) + pData->ExRemoveTable -= 0x34; + break; + } + else if (verInfo.dwBuildNumber == 16299) + { + pData->ver = WINVER_10_RS3; + pData->KExecOpt = 0x1BF; + pData->Protection = 0x6CA; + pData->EProcessFlags2 = 0x828; // MitigationFlags offset + pData->ObjTable = 0x418; + pData->VadRoot = 0x628; + pData->NtCreateThdIndex = 0xBA; + pData->NtTermThdIndex = 0x53; + pData->PrevMode = 0x232; + pData->ExitStatus = 0x700; + pData->MiAllocPage = 0; + if (NT_SUCCESS( BBScanSection( "PAGE", (PCUCHAR)"\x48\x83\xC7\x18\x48\x8B\x17", 0xCC, 7, (PVOID)&pData->ExRemoveTable ) )) + pData->ExRemoveTable -= 0x34; + break; + } + else if (verInfo.dwBuildNumber == 17134) + { + pData->ver = WINVER_10_RS4; + pData->KExecOpt = 0x1BF; + pData->Protection = 0x6CA; + pData->EProcessFlags2 = 0x828; // MitigationFlags offset + pData->ObjTable = 0x418; + pData->VadRoot = 0x628; + pData->NtCreateThdIndex = 0xBB; + pData->NtTermThdIndex = 0x53; + pData->PrevMode = 0x232; + pData->ExitStatus = 0x700; + pData->MiAllocPage = 0; + if (NT_SUCCESS( BBScanSection( "PAGE", (PCUCHAR)"\x48\x83\xC7\x18\x48\x8B\x17", 0xCC, 7, (PVOID)&pData->ExRemoveTable ) )) + pData->ExRemoveTable -= 0x34; + break; + } + else if (verInfo.dwBuildNumber == 17763) + { + pData->ver = WINVER_10_RS5; + pData->KExecOpt = 0x1BF; + pData->Protection = 0x6CA; + pData->EProcessFlags2 = 0x820; // MitigationFlags offset + pData->ObjTable = 0x418; + pData->VadRoot = 0x628; + pData->NtCreateThdIndex = 0xBC; + pData->NtTermThdIndex = 0x53; + pData->PrevMode = 0x232; + pData->ExitStatus = 0x700; + pData->MiAllocPage = 0; + if (NT_SUCCESS( BBScanSection( "PAGE", (PCUCHAR)"\x48\x83\xC7\x18\x48\x8B\x17", 0xCC, 7, (PVOID)&pData->ExRemoveTable ) )) + pData->ExRemoveTable -= 0x34; + break; + } + else + { + return STATUS_NOT_SUPPORTED; + } + default: + break; + } + + if (pData->ExRemoveTable != 0) + pData->correctBuild = TRUE; + + DPRINT( + "BlackBone: Dynamic search status: SSDT - %s, ExRemoveTable - %s\n", + GetSSDTBase() != NULL ? "SUCCESS" : "FAIL", + pData->ExRemoveTable != 0 ? "SUCCESS" : "FAIL" + ); + + if (pData->ver >= WINVER_10_RS1) + { + DPRINT( + "BlackBone: %s: g_KdBlock->KernBase: %p, GetKernelBase() = 0x%p \n", + __FUNCTION__, g_KdBlock.KernBase, GetKernelBase( NULL ) + ); + + ULONGLONG mask = (1ll << (PHYSICAL_ADDRESS_BITS - 1)) - 1; + dynData.DYN_PTE_BASE = (ULONG_PTR)g_KdBlock.PteBase; + dynData.DYN_PDE_BASE = (ULONG_PTR)((g_KdBlock.PteBase & ~mask) | ((g_KdBlock.PteBase >> 9) & mask)); + } + + DPRINT( "BlackBone: PDE_BASE: %p, PTE_BASE: %p\n", pData->DYN_PDE_BASE, pData->DYN_PTE_BASE ); + if (pData->DYN_PDE_BASE < MI_SYSTEM_RANGE_START || pData->DYN_PTE_BASE < MI_SYSTEM_RANGE_START) + { + DPRINT( "BlackBone: Invalid PDE/PTE base, aborting\n" ); + return STATUS_UNSUCCESSFUL; + } + + return (pData->VadRoot != 0 ? status : STATUS_INVALID_KERNEL_INFO_VERSION); + } + + return status; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/BlackBoneDrv.h b/third/Blackbone/src/BlackBoneDrv/BlackBoneDrv.h new file mode 100644 index 0000000000000000000000000000000000000000..23ccddd1b6a17b4bad81e762bf3ecd741e5f5c57 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/BlackBoneDrv.h @@ -0,0 +1,22 @@ +#pragma once + +#ifdef _M_IX86 +#error "x86 systems are not supported" +#endif + +#include + +#include "BlackBoneDef.h" +#include "Routines.h" +#include "Remap.h" + +#define DEVICE_NAME L"\\Device\\" ## BLACKBONE_DEVICE_NAME +#define DOS_DEVICE_NAME L"\\DosDevices\\" ## BLACKBONE_DEVICE_NAME + +/// +/// CTL dispatcher +/// +/// Device object +/// IRP +/// Status code +NTSTATUS BBDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); diff --git a/third/Blackbone/src/BlackBoneDrv/BlackBoneDrv.sln b/third/Blackbone/src/BlackBoneDrv/BlackBoneDrv.sln new file mode 100644 index 0000000000000000000000000000000000000000..539acb43c0035c5d387e51bcde4fc19a9b51eab4 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/BlackBoneDrv.sln @@ -0,0 +1,47 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26403.3 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackBoneDrv", "BlackBoneDrv.vcxproj", "{50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Win10Debug|x64 = Win10Debug|x64 + Win10Release|x64 = Win10Release|x64 + Win7 Debug|x64 = Win7 Debug|x64 + Win7 Release|x64 = Win7 Release|x64 + Win8 Debug|x64 = Win8 Debug|x64 + Win8 Release|x64 = Win8 Release|x64 + Win8.1 Debug|x64 = Win8.1 Debug|x64 + Win8.1 Release|x64 = Win8.1 Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win10Debug|x64.ActiveCfg = Win10Debug|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win10Debug|x64.Build.0 = Win10Debug|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win10Debug|x64.Deploy.0 = Win10Debug|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win10Release|x64.ActiveCfg = Win10Release|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win10Release|x64.Build.0 = Win10Release|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win10Release|x64.Deploy.0 = Win10Release|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win7 Debug|x64.ActiveCfg = Win7 Debug|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win7 Debug|x64.Build.0 = Win7 Debug|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win7 Debug|x64.Deploy.0 = Win7 Debug|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win7 Release|x64.ActiveCfg = Win7 Release|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win7 Release|x64.Build.0 = Win7 Release|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win7 Release|x64.Deploy.0 = Win7 Release|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win8 Debug|x64.Build.0 = Win8 Debug|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win8 Debug|x64.Deploy.0 = Win8 Debug|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win8 Release|x64.ActiveCfg = Win8 Release|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win8 Release|x64.Build.0 = Win8 Release|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win8 Release|x64.Deploy.0 = Win8 Release|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win8.1 Debug|x64.ActiveCfg = Win8.1 Debug|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win8.1 Debug|x64.Build.0 = Win8.1 Debug|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win8.1 Debug|x64.Deploy.0 = Win8.1 Debug|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win8.1 Release|x64.ActiveCfg = Win8.1 Release|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win8.1 Release|x64.Build.0 = Win8.1 Release|x64 + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F}.Win8.1 Release|x64.Deploy.0 = Win8.1 Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/third/Blackbone/src/BlackBoneDrv/BlackBoneDrv.vcxproj b/third/Blackbone/src/BlackBoneDrv/BlackBoneDrv.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..cfc4b9d0d8196cb796b3a78a43ff5e41ab4f1215 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/BlackBoneDrv.vcxproj @@ -0,0 +1,321 @@ + + + + + Win10Debug + x64 + + + Win10Release + x64 + + + Win8.1 Debug + x64 + + + Win8 Debug + x64 + + + Win8.1 Release + x64 + + + Win8 Release + x64 + + + Win7 Debug + x64 + + + Win7 Release + x64 + + + + {50429DDC-D8EC-4926-B913-D7ADE6A3DC9F} + {dd38f7fc-d7bd-488b-9242-7d8754cde80d} + v4.5 + 11.0 + Win8 Debug + Win32 + + + BlackBoneDrv + + + Driver + WDM + + + + WindowsV6.3 + true + WindowsKernelModeDriver10.0 + Desktop + false + + + + + true + WindowsKernelModeDriver10.0 + Desktop + false + + + Windows8 + true + WindowsKernelModeDriver10.0 + Desktop + false + + + WindowsV6.3 + false + WindowsKernelModeDriver10.0 + Desktop + false + + + + + false + WindowsKernelModeDriver10.0 + Desktop + false + + + Windows8 + false + WindowsKernelModeDriver10.0 + Desktop + false + + + Windows7 + true + WindowsKernelModeDriver10.0 + Desktop + false + + + Windows7 + false + WindowsKernelModeDriver10.0 + Desktop + false + + + + + + + + + + DbgengKernelDebugger + + + $(SolutionDir)bin\$(Platform)\$(ConfigurationName)\ + http://timestamp.verisign.com/scripts/timstamp.dll + $(SolutionDir)obj\$(Platform)\$(ConfigurationName)\ + $(TargetName)81 + + + $(SolutionDir)bin\$(Platform)\$(ConfigurationName)\ + http://timestamp.verisign.com/scripts/timstamp.dll + $(SolutionDir)obj\$(Platform)\$(ConfigurationName)\ + $(TargetName)10 + + + $(SolutionDir)bin\$(Platform)\$(ConfigurationName)\ + $(SolutionDir)obj\$(Platform)\$(ConfigurationName)\ + $(TargetName)8 + + + $(SolutionDir)bin\$(Platform)\$(ConfigurationName)\ + $(SolutionDir)obj\$(Platform)\$(ConfigurationName)\ + $(TargetName)7 + + + $(SolutionDir)bin\$(Platform)\$(ConfigurationName)\ + $(SolutionDir)obj\$(Platform)\$(ConfigurationName)\ + $(TargetName)7 + + + $(SolutionDir)bin\$(Platform)\$(ConfigurationName)\ + $(SolutionDir)obj\$(Platform)\$(ConfigurationName)\ + $(TargetName)81 + + + $(SolutionDir)bin\$(Platform)\$(ConfigurationName)\ + $(SolutionDir)obj\$(Platform)\$(ConfigurationName)\ + $(TargetName)10 + + + $(SolutionDir)bin\$(Platform)\$(ConfigurationName)\ + $(SolutionDir)obj\$(Platform)\$(ConfigurationName)\ + $(TargetName)8 + + + + CompileAsC + + + _WIN81_;%(PreprocessorDefinitions) + true + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + + + + + Default + + + _WIN10_;%(PreprocessorDefinitions) + true + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + + + + + CompileAsC + + _WIN8_;%(PreprocessorDefinitions) + + + + + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + CompileAsC + + + + + + CompileAsC + true + + _WIN7_;%(PreprocessorDefinitions) + + + + + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + CompileAsC + + _WIN7_;%(PreprocessorDefinitions) + + + + + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + CompileAsC + + + _WIN81_;%(PreprocessorDefinitions) + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + CompileAsC + + + _WIN10_;%(PreprocessorDefinitions) + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + CompileAsC + + _WIN8_;%(PreprocessorDefinitions) + + + + + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/BlackBoneDrv.vcxproj.filters b/third/Blackbone/src/BlackBoneDrv/BlackBoneDrv.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..41132417246310759c1d48cbc1ea3ef2468463b5 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/BlackBoneDrv.vcxproj.filters @@ -0,0 +1,114 @@ + + + + + ImageLoader + + + ImageLoader + + + ImageLoader + + + ImageLoader + + + Core + + + Core + + + Core + + + Helpers + + + Helpers + + + Core + + + Core + + + Helpers + + + Core + + + + + Include + + + Include\Native + + + Include\Native + + + Include\Native + + + Include\Native + + + Include + + + Include + + + Include + + + Include + + + Include\Native + + + Include + + + Include + + + Include\Native + + + Include\Native + + + Include + + + Include\Native + + + Include + + + + + {b7e17437-db3c-4555-9fd0-40e3b20f6b54} + + + {1777770d-b977-4802-9b7d-a2c21fcfed88} + + + {8be939a3-549a-412d-a84a-7412ef2ad186} + + + {5f2d2fea-d59d-40a3-a70f-9d75f5fdedf4} + + + {2ad9b16d-24eb-4a97-bb5b-d815b83b78c7} + + + \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/Dispatch.c b/third/Blackbone/src/BlackBoneDrv/Dispatch.c new file mode 100644 index 0000000000000000000000000000000000000000..6d4d4536a3aebfd6679aa9d73338bbb0308596ec --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/Dispatch.c @@ -0,0 +1,284 @@ +#include "BlackBoneDrv.h" +#include "Remap.h" +#include "Loader.h" + +#include + +#pragma alloc_text(PAGE, BBDispatch) + +/// +/// CTL dispatcher +/// +/// Device object +/// IRP +/// Status code +NTSTATUS BBDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) +{ + NTSTATUS status = STATUS_SUCCESS; + PIO_STACK_LOCATION irpStack; + PVOID ioBuffer = NULL; + ULONG inputBufferLength = 0; + ULONG outputBufferLength = 0; + ULONG ioControlCode = 0; + + UNREFERENCED_PARAMETER( DeviceObject ); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + irpStack = IoGetCurrentIrpStackLocation( Irp ); + ioBuffer = Irp->AssociatedIrp.SystemBuffer; + inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; + outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; + + switch (irpStack->MajorFunction) + { + case IRP_MJ_DEVICE_CONTROL: + { + ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; + + switch (ioControlCode) + { + case IOCTL_BLACKBONE_DISABLE_DEP: + { + if (inputBufferLength >= sizeof( DISABLE_DEP ) && ioBuffer) + Irp->IoStatus.Status = BBDisableDEP( (PDISABLE_DEP)ioBuffer ); + else + Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH; + } + break; + + case IOCTL_BLACKBONE_SET_PROTECTION: + { + if (inputBufferLength >= sizeof( SET_PROC_PROTECTION ) && ioBuffer) + Irp->IoStatus.Status = BBSetProtection( (PSET_PROC_PROTECTION)ioBuffer ); + else + Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH; + } + break; + + case IOCTL_BLACKBONE_GRANT_ACCESS: + { + if (inputBufferLength >= sizeof( HANDLE_GRANT_ACCESS ) && ioBuffer) + Irp->IoStatus.Status = BBGrantAccess( (PHANDLE_GRANT_ACCESS)ioBuffer ); + else + Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH; + } + break; + + case IOCTL_BLACKBONE_COPY_MEMORY: + { + if (inputBufferLength >= sizeof( COPY_MEMORY ) && ioBuffer) + Irp->IoStatus.Status = BBCopyMemory( (PCOPY_MEMORY)ioBuffer ); + else + Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH; + } + break; + + case IOCTL_BLACKBONE_ALLOCATE_FREE_MEMORY: + { + if (inputBufferLength >= sizeof( ALLOCATE_FREE_MEMORY ) && + outputBufferLength >= sizeof( ALLOCATE_FREE_MEMORY_RESULT ) && + ioBuffer) + { + ALLOCATE_FREE_MEMORY_RESULT result = { 0 }; + Irp->IoStatus.Status = BBAllocateFreeMemory( (PALLOCATE_FREE_MEMORY)ioBuffer, &result ); + + if (NT_SUCCESS( Irp->IoStatus.Status )) + { + RtlCopyMemory( ioBuffer, &result, sizeof( result ) ); + Irp->IoStatus.Information = sizeof( result ); + } + } + else + Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH; + } + break; + + case IOCTL_BLACKBONE_PROTECT_MEMORY: + { + if (inputBufferLength >= sizeof( PROTECT_MEMORY ) && ioBuffer) + Irp->IoStatus.Status = BBProtectMemory( (PPROTECT_MEMORY)ioBuffer ); + else + Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH; + } + break; + + case IOCTL_BLACKBONE_MAP_MEMORY: + { + if (inputBufferLength >= sizeof( MAP_MEMORY ) && ioBuffer && outputBufferLength >= sizeof( ULONG )) + { + ULONG_PTR sizeRequired = 0; + PPROCESS_MAP_ENTRY pProcessEntry = NULL; + + Irp->IoStatus.Status = BBMapMemory( (PMAP_MEMORY)ioBuffer, &pProcessEntry ); + + if (NT_SUCCESS( Irp->IoStatus.Status ) && pProcessEntry != NULL) + { + BBGetRequiredRemapOutputSize( &pProcessEntry->pageList, &sizeRequired ); + + // Return mapping results + if (outputBufferLength >= sizeRequired) + { + PMAP_MEMORY_RESULT pResult = (PMAP_MEMORY_RESULT)ioBuffer; + + // + // Fill output + // + pResult->count = 0; + pResult->hostPage = (ULONGLONG)pProcessEntry->host.sharedPage; + pResult->targetPage = (ULONGLONG)pProcessEntry->target.sharedPage; + pResult->pipeHandle = (ULONGLONG)pProcessEntry->targetPipe; + + for (PLIST_ENTRY pListEntry = pProcessEntry->pageList.Flink; + pListEntry != &pProcessEntry->pageList; + pListEntry = pListEntry->Flink) + { + PMAP_ENTRY pEntry = CONTAINING_RECORD( pListEntry, MAP_ENTRY, link ); + + pResult->entries[pResult->count].originalPtr = (ULONGLONG)pEntry->mem.BaseAddress; + pResult->entries[pResult->count].newPtr = pEntry->newPtr; + pResult->entries[pResult->count].size = (ULONG)pEntry->mem.RegionSize; + pResult->count++; + } + + Irp->IoStatus.Information = sizeRequired; + } + // Return number of bytes required + else + { + *(ULONG*)ioBuffer = (ULONG)sizeRequired; + Irp->IoStatus.Information = sizeof( ULONG ); + } + } + } + else + Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH; + } + break; + + case IOCTL_BLACKBONE_MAP_REGION: + { + if (inputBufferLength >= sizeof( MAP_MEMORY_REGION ) && + outputBufferLength >= sizeof( MAP_MEMORY_REGION_RESULT ) && ioBuffer) + { + MAP_MEMORY_REGION_RESULT result = { 0 }; + Irp->IoStatus.Status = BBMapMemoryRegion( (PMAP_MEMORY_REGION)ioBuffer, &result ); + + if (NT_SUCCESS( Irp->IoStatus.Status )) + { + RtlCopyMemory( ioBuffer, &result, sizeof( result ) ); + Irp->IoStatus.Information = sizeof( result ); + } + } + else + Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH; + } + break; + + case IOCTL_BLACKBONE_UNMAP_MEMORY: + { + if (inputBufferLength >= sizeof( UNMAP_MEMORY ) && ioBuffer) + Irp->IoStatus.Status = BBUnmapMemory( (PUNMAP_MEMORY)ioBuffer ); + else + Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH; + } + break; + + case IOCTL_BLACKBONE_UNMAP_REGION: + { + if (inputBufferLength >= sizeof( UNMAP_MEMORY_REGION ) && ioBuffer) + Irp->IoStatus.Status = BBUnmapMemoryRegion( (PUNMAP_MEMORY_REGION)ioBuffer ); + else + Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH; + } + break; + + case IOCTL_BLACKBONE_HIDE_VAD: + { + if (inputBufferLength >= sizeof( HIDE_VAD ) && ioBuffer) + Irp->IoStatus.Status = BBHideVAD( (PHIDE_VAD)ioBuffer ); + else + Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH; + } + break; + + case IOCTL_BLACKBONE_INJECT_DLL: + { + if (inputBufferLength >= sizeof( INJECT_DLL ) && ioBuffer) + Irp->IoStatus.Status = BBInjectDll( (PINJECT_DLL)ioBuffer ); + else + Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH; + } + break; + + case IOCTL_BLACKBONE_MAP_DRIVER: + { + if (inputBufferLength >= sizeof( MMAP_DRIVER ) && ioBuffer) + { + wchar_t buf[sizeof( ((PMMAP_DRIVER)ioBuffer)->FullPath )]; + UNICODE_STRING ustrPath; + + RtlCopyMemory( buf, ((PMMAP_DRIVER)ioBuffer)->FullPath, sizeof( ((PMMAP_DRIVER)ioBuffer)->FullPath ) ); + RtlUnicodeStringInit( &ustrPath, buf ); + Irp->IoStatus.Status = BBMMapDriver( &ustrPath ); + } + else + Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH; + } + break; + + case IOCTL_BLACKBONE_UNLINK_HTABLE: + { + if (inputBufferLength >= sizeof( UNLINK_HTABLE ) && ioBuffer) + Irp->IoStatus.Status = BBUnlinkHandleTable( (PUNLINK_HTABLE)ioBuffer ); + else + Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH; + } + break; + + case IOCTL_BLACKBONE_ENUM_REGIONS: + { + if (inputBufferLength >= sizeof( ENUM_REGIONS ) && outputBufferLength >= sizeof( ENUM_REGIONS_RESULT ) && ioBuffer) + { + ULONG count = (outputBufferLength - sizeof( ULONGLONG )) / sizeof( MEMORY_BASIC_INFORMATION ); + PENUM_REGIONS_RESULT pResult = ExAllocatePoolWithTag( PagedPool, outputBufferLength, BB_POOL_TAG ); + pResult->count = count; + + Irp->IoStatus.Status = BBEnumMemRegions( (PENUM_REGIONS)ioBuffer, pResult ); + + // Full info + if (NT_SUCCESS( Irp->IoStatus.Status )) + { + Irp->IoStatus.Information = sizeof( pResult->count ) + pResult->count * sizeof( MEMORY_BASIC_INFORMATION ); + RtlCopyMemory( ioBuffer, pResult, Irp->IoStatus.Information ); + } + // Size only + else + { + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof( pResult->count ); + RtlCopyMemory( ioBuffer, pResult, sizeof( pResult->count ) ); + } + + ExFreePoolWithTag( pResult, BB_POOL_TAG ); + } + else + Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH; + } + break; + + default: + DPRINT( "BlackBone: %s: Unknown IRP_MJ_DEVICE_CONTROL 0x%X\n", __FUNCTION__, ioControlCode ); + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + break; + } + } + break; + } + + status = Irp->IoStatus.Status; + IoCompleteRequest( Irp, IO_NO_INCREMENT ); + + return status; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/Imports.h b/third/Blackbone/src/BlackBoneDrv/Imports.h new file mode 100644 index 0000000000000000000000000000000000000000..57fcd7a0b87b0e3804fd72d83e1d76c363694ff7 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/Imports.h @@ -0,0 +1,207 @@ +#pragma once + +#include "NativeEnums.h" +#include "NativeStructs.h" + +NTSYSAPI +NTSTATUS +NTAPI +ZwQuerySystemInformation( + IN SYSTEM_INFORMATION_CLASS SystemInformationClass, + OUT PVOID SystemInformation, + IN ULONG SystemInformationLength, + OUT PULONG ReturnLength OPTIONAL + ); + +NTSYSAPI +NTSTATUS +NTAPI +ZwSetSystemInformation( + IN SYSTEM_INFORMATION_CLASS SystemInformationClass, + IN PVOID SystemInformation, + IN ULONG SystemInformationLength + ); + +NTSYSAPI +NTSTATUS +NTAPI +ZwQueryInformationProcess( + IN HANDLE ProcessHandle, + IN PROCESSINFOCLASS ProcessInformationClass, + OUT PVOID ProcessInformation, + IN ULONG ProcessInformationLength, + IN PULONG ReturnLength + ); + +NTSYSAPI +NTSTATUS +NTAPI +ZwQueryInformationThread( + IN HANDLE ThreadHandle, + IN THREADINFOCLASS ThreadInformationClass, + OUT PVOID ThreadInformation, + IN ULONG ThreadInformationLength, + OUT PULONG ReturnLength OPTIONAL + ); + +NTSYSAPI +NTSTATUS +NTAPI +ZwQueryVirtualMemory( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN MEMORY_INFORMATION_CLASS_EX MemoryInformationClass, + OUT PVOID Buffer, + IN SIZE_T Length, + OUT PSIZE_T ResultLength + ); + +NTSTATUS +NTAPI +ZwCreateThreadEx( + OUT PHANDLE hThread, + IN ACCESS_MASK DesiredAccess, + IN PVOID ObjectAttributes, + IN HANDLE ProcessHandle, + IN PVOID lpStartAddress, + IN PVOID lpParameter, + IN ULONG Flags, + IN SIZE_T StackZeroBits, + IN SIZE_T SizeOfStackCommit, + IN SIZE_T SizeOfStackReserve, + IN PNT_PROC_THREAD_ATTRIBUTE_LIST AttributeList + ); + +NTSTATUS +NTAPI +ZwTerminateThread( + IN HANDLE ThreadHandle, + IN NTSTATUS ExitStatus + ); + + + +NTKERNELAPI +NTSTATUS +NTAPI +MmCopyVirtualMemory( + IN PEPROCESS FromProcess, + IN PVOID FromAddress, + IN PEPROCESS ToProcess, + OUT PVOID ToAddress, + IN SIZE_T BufferSize, + IN KPROCESSOR_MODE PreviousMode, + OUT PSIZE_T NumberOfBytesCopied + ); + +NTKERNELAPI +PPEB +NTAPI +PsGetProcessPeb( IN PEPROCESS Process ); + +NTKERNELAPI +PVOID +NTAPI +PsGetThreadTeb( IN PETHREAD Thread ); + +NTKERNELAPI +PVOID +NTAPI +PsGetProcessWow64Process( IN PEPROCESS Process ); + +NTKERNELAPI +PVOID +NTAPI +PsGetCurrentProcessWow64Process( ); + +NTKERNELAPI +BOOLEAN +NTAPI +KeTestAlertThread( IN KPROCESSOR_MODE AlertMode ); + +NTKERNELAPI +BOOLEAN +NTAPI +PsIsProtectedProcess( IN PEPROCESS Process ); + +typedef VOID( NTAPI *PKNORMAL_ROUTINE )( + PVOID NormalContext, + PVOID SystemArgument1, + PVOID SystemArgument2 + ); + +typedef VOID( NTAPI* PKKERNEL_ROUTINE)( + PRKAPC Apc, + PKNORMAL_ROUTINE *NormalRoutine, + PVOID *NormalContext, + PVOID *SystemArgument1, + PVOID *SystemArgument2 + ); + +typedef VOID( NTAPI *PKRUNDOWN_ROUTINE )( PRKAPC Apc ); + +NTKERNELAPI +VOID +NTAPI +KeInitializeApc( + IN PKAPC Apc, + IN PKTHREAD Thread, + IN KAPC_ENVIRONMENT ApcStateIndex, + IN PKKERNEL_ROUTINE KernelRoutine, + IN PKRUNDOWN_ROUTINE RundownRoutine, + IN PKNORMAL_ROUTINE NormalRoutine, + IN KPROCESSOR_MODE ApcMode, + IN PVOID NormalContext + ); + +NTKERNELAPI +BOOLEAN +NTAPI +KeInsertQueueApc( + PKAPC Apc, + PVOID SystemArgument1, + PVOID SystemArgument2, + KPRIORITY Increment + ); + +NTSYSAPI +PIMAGE_NT_HEADERS +NTAPI +RtlImageNtHeader( PVOID Base ); + +NTSYSAPI +PVOID +NTAPI +RtlImageDirectoryEntryToData( + PVOID ImageBase, + BOOLEAN MappedAsImage, + USHORT DirectoryEntry, + PULONG Size + ); + + +typedef BOOLEAN ( *EX_ENUMERATE_HANDLE_ROUTINE )( +#if !defined(_WIN7_) + IN PHANDLE_TABLE HandleTable, +#endif + IN PHANDLE_TABLE_ENTRY HandleTableEntry, + IN HANDLE Handle, + IN PVOID EnumParameter + ); + +NTKERNELAPI +BOOLEAN +ExEnumHandleTable( + IN PHANDLE_TABLE HandleTable, + IN EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure, + IN PVOID EnumParameter, + OUT PHANDLE Handle + ); + +NTKERNELAPI +VOID +FASTCALL +ExfUnblockPushLock ( + IN OUT PEX_PUSH_LOCK PushLock, + IN OUT PVOID WaitBlock + ); \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/Inject.c b/third/Blackbone/src/BlackBoneDrv/Inject.c new file mode 100644 index 0000000000000000000000000000000000000000..137304ec6731c3755aad24e182623ac9220ac01b --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/Inject.c @@ -0,0 +1,453 @@ +#include "Private.h" +#include "Routines.h" +#include "Loader.h" +#include "Utils.h" +#include + +#define CALL_COMPLETE 0xC0371E7E + +typedef struct _INJECT_BUFFER +{ + UCHAR code[0x200]; + union + { + UNICODE_STRING path; + UNICODE_STRING32 path32; + }; + + wchar_t buffer[488]; + PVOID module; + ULONG complete; + NTSTATUS status; +} INJECT_BUFFER, *PINJECT_BUFFER; + +extern DYNAMIC_DATA dynData; + +PINJECT_BUFFER BBGetWow64Code( IN PVOID LdrLoadDll, IN PUNICODE_STRING pPath ); +PINJECT_BUFFER BBGetNativeCode( IN PVOID LdrLoadDll, IN PUNICODE_STRING pPath ); + +NTSTATUS BBApcInject( IN PINJECT_BUFFER pUserBuf, IN PEPROCESS pProcess, IN ULONG initRVA, IN PCWCHAR InitArg ); + +#pragma alloc_text(PAGE, BBInjectDll) +#pragma alloc_text(PAGE, BBGetWow64Code) +#pragma alloc_text(PAGE, BBGetNativeCode) +#pragma alloc_text(PAGE, BBExecuteInNewThread) +#pragma alloc_text(PAGE, BBApcInject) +#pragma alloc_text(PAGE, BBQueueUserApc) +#pragma alloc_text(PAGE, BBLookupProcessThread) + +/// +/// Inject dll into process +/// +/// Target PID +/// TFull-qualified dll path +/// Status code +NTSTATUS BBInjectDll( IN PINJECT_DLL pData ) +{ + NTSTATUS status = STATUS_SUCCESS; + NTSTATUS threadStatus = STATUS_SUCCESS; + PEPROCESS pProcess = NULL; + + status = PsLookupProcessByProcessId( (HANDLE)pData->pid, &pProcess ); + if (NT_SUCCESS( status )) + { + KAPC_STATE apc; + UNICODE_STRING ustrPath, ustrNtdll; + SET_PROC_PROTECTION prot = { 0 }; + PVOID pNtdll = NULL; + PVOID LdrLoadDll = NULL; + PVOID systemBuffer = NULL; + BOOLEAN isWow64 = (PsGetProcessWow64Process( pProcess ) != NULL) ? TRUE : FALSE; + + // Process in signaled state, abort any operations + if (BBCheckProcessTermination( PsGetCurrentProcess() )) + { + DPRINT( "BlackBone: %s: Process %u is terminating. Abort\n", __FUNCTION__, pData->pid ); + if (pProcess) + ObDereferenceObject( pProcess ); + + return STATUS_PROCESS_IS_TERMINATING; + } + + // Copy mmap image buffer to system space. + // Buffer will be released in mapping routine automatically + if (pData->type == IT_MMap && pData->imageBase) + { + __try + { + ProbeForRead( (PVOID)pData->imageBase, pData->imageSize, 1 ); + systemBuffer = ExAllocatePoolWithTag( PagedPool, pData->imageSize, BB_POOL_TAG ); + RtlCopyMemory( systemBuffer, (PVOID)pData->imageBase, pData->imageSize ); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + DPRINT( "BlackBone: %s: AV in user buffer: 0x%p - 0x%p\n", __FUNCTION__, + pData->imageBase, pData->imageBase + pData->imageSize ); + + if (pProcess) + ObDereferenceObject( pProcess ); + + return STATUS_INVALID_USER_BUFFER; + } + } + + KeStackAttachProcess( pProcess, &apc ); + + RtlInitUnicodeString( &ustrPath, pData->FullDllPath ); + RtlInitUnicodeString( &ustrNtdll, L"Ntdll.dll" ); + + // Handle manual map separately + if (pData->type == IT_MMap) + { + MODULE_DATA mod = { 0 }; + + __try { + status = BBMapUserImage( + pProcess, &ustrPath, systemBuffer, + pData->imageSize, pData->asImage, pData->flags, + pData->initRVA, pData->initArg, &mod + ); + } + __except (EXCEPTION_EXECUTE_HANDLER){ + DPRINT( "BlackBone: %s: Fatal exception in BBMapUserImage. Exception code 0x%x\n", __FUNCTION__, GetExceptionCode() ); + } + + KeUnstackDetachProcess( &apc ); + + if (pProcess) + ObDereferenceObject( pProcess ); + + return status; + } + + // Get ntdll base + pNtdll = BBGetUserModule( pProcess, &ustrNtdll, isWow64 ); + + if (!pNtdll) + { + DPRINT( "BlackBone: %s: Failed to get Ntdll base\n", __FUNCTION__ ); + status = STATUS_NOT_FOUND; + } + + // Get LdrLoadDll address + if (NT_SUCCESS( status )) + { + LdrLoadDll = BBGetModuleExport( pNtdll, "LdrLoadDll", pProcess, NULL ); + if (!LdrLoadDll) + { + DPRINT( "BlackBone: %s: Failed to get LdrLoadDll address\n", __FUNCTION__ ); + status = STATUS_NOT_FOUND; + } + } + + // If process is protected - temporarily disable protection + if (PsIsProtectedProcess( pProcess )) + { + prot.pid = pData->pid; + prot.protection = Policy_Disable; + prot.dynamicCode = Policy_Disable; + prot.signature = Policy_Disable; + BBSetProtection( &prot ); + } + + // Call LdrLoadDll + if (NT_SUCCESS( status )) + { + SIZE_T size = 0; + PINJECT_BUFFER pUserBuf = isWow64 ? BBGetWow64Code( LdrLoadDll, &ustrPath ) : BBGetNativeCode( LdrLoadDll, &ustrPath ); + + if (pData->type == IT_Thread) + { + status = BBExecuteInNewThread( pUserBuf, NULL, THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER, pData->wait, &threadStatus ); + + // Injection failed + if (!NT_SUCCESS( threadStatus )) + { + status = threadStatus; + DPRINT( "BlackBone: %s: User thread failed with status - 0x%X\n", __FUNCTION__, status ); + } + // Call Init routine + else + { + if (pUserBuf->module != 0 && pData->initRVA != 0) + { + RtlCopyMemory( pUserBuf->buffer, pData->initArg, sizeof( pUserBuf->buffer ) ); + BBExecuteInNewThread( + (PUCHAR)pUserBuf->module + pData->initRVA, + pUserBuf->buffer, + THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER, + TRUE, + &threadStatus + ); + } + else if (pUserBuf->module == 0) + DPRINT( "BlackBone: %s: Module base = 0. Aborting\n", __FUNCTION__ ); + } + } + else if (pData->type == IT_Apc) + { + status = BBApcInject( pUserBuf, pProcess, pData->initRVA, pData->initArg ); + } + else + { + DPRINT( "BlackBone: %s: Invalid injection type specified - %d\n", __FUNCTION__, pData->type ); + status = STATUS_INVALID_PARAMETER; + } + + // Post-inject stuff + if (NT_SUCCESS( status )) + { + // Unlink module + if (pData->unlink) + BBUnlinkFromLoader( pProcess, pUserBuf->module, isWow64 ); + + // Erase header + if (pData->erasePE) + { + __try + { + PIMAGE_NT_HEADERS64 pHdr = RtlImageNtHeader( pUserBuf->module ); + if (pHdr) + { + ULONG oldProt = 0; + size = (pHdr->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) ? + ((PIMAGE_NT_HEADERS32)pHdr)->OptionalHeader.SizeOfHeaders : + pHdr->OptionalHeader.SizeOfHeaders; + + if (NT_SUCCESS( ZwProtectVirtualMemory( ZwCurrentProcess(), &pUserBuf->module, &size, PAGE_EXECUTE_READWRITE, &oldProt ) )) + { + RtlZeroMemory( pUserBuf->module, size ); + ZwProtectVirtualMemory( ZwCurrentProcess(), &pUserBuf->module, &size, oldProt, &oldProt ); + + DPRINT( "BlackBone: %s: PE headers erased. \n", __FUNCTION__ ); + } + } + else + DPRINT( "BlackBone: %s: Failed to retrieve PE headers for image\n", __FUNCTION__ ); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + DPRINT( "BlackBone: %s: Exception during PE header erease: 0x%X\n", __FUNCTION__, GetExceptionCode() ); + } + } + } + + ZwFreeVirtualMemory( ZwCurrentProcess(), &pUserBuf, &size, MEM_RELEASE ); + } + + // Restore protection + if (prot.pid != 0) + { + prot.protection = Policy_Enable; + prot.dynamicCode = Policy_Enable; + prot.signature = Policy_Enable; + BBSetProtection( &prot ); + } + + KeUnstackDetachProcess( &apc ); + } + else + DPRINT( "BlackBone: %s: PsLookupProcessByProcessId failed with status 0x%X\n", __FUNCTION__, status ); + + if (pProcess) + ObDereferenceObject( pProcess ); + + return status; +} + +/// +/// Build injection code for wow64 process +/// Must be running in target process context +/// +/// LdrLoadDll address +/// Path to the dll +/// Code pointer. When not needed, it should be freed with ZwFreeVirtualMemory +PINJECT_BUFFER BBGetWow64Code( IN PVOID LdrLoadDll, IN PUNICODE_STRING pPath ) +{ + NTSTATUS status = STATUS_SUCCESS; + PINJECT_BUFFER pBuffer = NULL; + SIZE_T size = PAGE_SIZE; + + // Code + UCHAR code[] = + { + 0x68, 0, 0, 0, 0, // push ModuleHandle offset +1 + 0x68, 0, 0, 0, 0, // push ModuleFileName offset +6 + 0x6A, 0, // push Flags + 0x6A, 0, // push PathToFile + 0xE8, 0, 0, 0, 0, // call LdrLoadDll offset +15 + 0xBA, 0, 0, 0, 0, // mov edx, COMPLETE_OFFSET offset +20 + 0xC7, 0x02, 0x7E, 0x1E, 0x37, 0xC0, // mov [edx], CALL_COMPLETE + 0xBA, 0, 0, 0, 0, // mov edx, STATUS_OFFSET offset +31 + 0x89, 0x02, // mov [edx], eax + 0xC2, 0x04, 0x00 // ret 4 + }; + + status = ZwAllocateVirtualMemory( ZwCurrentProcess(), &pBuffer, 0, &size, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + if (NT_SUCCESS( status )) + { + // Copy path + PUNICODE_STRING32 pUserPath = &pBuffer->path32; + pUserPath->Length = pPath->Length; + pUserPath->MaximumLength = pPath->MaximumLength; + pUserPath->Buffer = (ULONG)(ULONG_PTR)pBuffer->buffer; + + // Copy path + memcpy( (PVOID)pUserPath->Buffer, pPath->Buffer, pPath->Length ); + + // Copy code + memcpy( pBuffer, code, sizeof( code ) ); + + // Fill stubs + *(ULONG*)((PUCHAR)pBuffer + 1) = (ULONG)(ULONG_PTR)&pBuffer->module; + *(ULONG*)((PUCHAR)pBuffer + 6) = (ULONG)(ULONG_PTR)pUserPath; + *(ULONG*)((PUCHAR)pBuffer + 15) = (ULONG)((ULONG_PTR)LdrLoadDll - ((ULONG_PTR)pBuffer + 15) - 5 + 1); + *(ULONG*)((PUCHAR)pBuffer + 20) = (ULONG)(ULONG_PTR)&pBuffer->complete; + *(ULONG*)((PUCHAR)pBuffer + 31) = (ULONG)(ULONG_PTR)&pBuffer->status; + + return pBuffer; + } + + UNREFERENCED_PARAMETER( pPath ); + return NULL; +} + +/// +/// Build injection code for native x64 process +/// Must be running in target process context +/// +/// LdrLoadDll address +/// Path to the dll +/// Code pointer. When not needed it should be freed with ZwFreeVirtualMemory +PINJECT_BUFFER BBGetNativeCode( IN PVOID LdrLoadDll, IN PUNICODE_STRING pPath ) +{ + NTSTATUS status = STATUS_SUCCESS; + PINJECT_BUFFER pBuffer = NULL; + SIZE_T size = PAGE_SIZE; + + // Code + UCHAR code[] = + { + 0x48, 0x83, 0xEC, 0x28, // sub rsp, 0x28 + 0x48, 0x31, 0xC9, // xor rcx, rcx + 0x48, 0x31, 0xD2, // xor rdx, rdx + 0x49, 0xB8, 0, 0, 0, 0, 0, 0, 0, 0, // mov r8, ModuleFileName offset +12 + 0x49, 0xB9, 0, 0, 0, 0, 0, 0, 0, 0, // mov r9, ModuleHandle offset +28 + 0x48, 0xB8, 0, 0, 0, 0, 0, 0, 0, 0, // mov rax, LdrLoadDll offset +32 + 0xFF, 0xD0, // call rax + 0x48, 0xBA, 0, 0, 0, 0, 0, 0, 0, 0, // mov rdx, COMPLETE_OFFSET offset +44 + 0xC7, 0x02, 0x7E, 0x1E, 0x37, 0xC0, // mov [rdx], CALL_COMPLETE + 0x48, 0xBA, 0, 0, 0, 0, 0, 0, 0, 0, // mov rdx, STATUS_OFFSET offset +60 + 0x89, 0x02, // mov [rdx], eax + 0x48, 0x83, 0xC4, 0x28, // add rsp, 0x28 + 0xC3 // ret + }; + + status = ZwAllocateVirtualMemory( ZwCurrentProcess(), &pBuffer, 0, &size, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + if (NT_SUCCESS( status )) + { + // Copy path + PUNICODE_STRING pUserPath = &pBuffer->path; + pUserPath->Length = 0; + pUserPath->MaximumLength = sizeof(pBuffer->buffer); + pUserPath->Buffer = pBuffer->buffer; + + RtlUnicodeStringCopy( pUserPath, pPath ); + + // Copy code + memcpy( pBuffer, code, sizeof( code ) ); + + // Fill stubs + *(ULONGLONG*)((PUCHAR)pBuffer + 12) = (ULONGLONG)pUserPath; + *(ULONGLONG*)((PUCHAR)pBuffer + 22) = (ULONGLONG)&pBuffer->module; + *(ULONGLONG*)((PUCHAR)pBuffer + 32) = (ULONGLONG)LdrLoadDll; + *(ULONGLONG*)((PUCHAR)pBuffer + 44) = (ULONGLONG)&pBuffer->complete; + *(ULONGLONG*)((PUCHAR)pBuffer + 60) = (ULONGLONG)&pBuffer->status; + + return pBuffer; + } + + UNREFERENCED_PARAMETER( pPath ); + return NULL; +} + +/// +/// Inject dll using APC +/// Must be running in target process context +/// +/// Injcetion code +/// Target process +/// Init routine RVA +/// Init routine argument +/// Status code +NTSTATUS BBApcInject( IN PINJECT_BUFFER pUserBuf, IN PEPROCESS pProcess, IN ULONG initRVA, IN PCWCHAR InitArg ) +{ + NTSTATUS status = STATUS_SUCCESS; + PETHREAD pThread = NULL; + + // Get suitable thread + status = BBLookupProcessThread( pProcess, &pThread ); + + if (NT_SUCCESS( status )) + { + status = BBQueueUserApc( pThread, pUserBuf->code, NULL, NULL, NULL, TRUE ); + + // Wait for completion + if (NT_SUCCESS( status )) + { + LARGE_INTEGER interval = { 0 }; + interval.QuadPart = -(5LL * 10 * 1000); + + for (ULONG i = 0; i < 10000; i++) + { + if (BBCheckProcessTermination( PsGetCurrentProcess() ) || PsIsThreadTerminating( pThread )) + { + status = STATUS_PROCESS_IS_TERMINATING; + break; + } + + if(pUserBuf->complete == CALL_COMPLETE) + break; + + if (!NT_SUCCESS( status = KeDelayExecutionThread( KernelMode, FALSE, &interval ) )) + break; + } + + // Check LdrLoadDll status + if (NT_SUCCESS( status )) + { + status = pUserBuf->status; + } + else + DPRINT( "BlackBone: %s: APC injection abnormal termination, status 0x%X\n", __FUNCTION__, status ); + + // Call init routine + if (NT_SUCCESS( status )) + { + if (pUserBuf->module != 0) + { + if(initRVA != 0) + { + RtlCopyMemory( (PUCHAR)pUserBuf->buffer, InitArg, sizeof( pUserBuf->buffer ) ); + BBQueueUserApc( pThread, (PUCHAR)pUserBuf->module + initRVA, pUserBuf->buffer, NULL, NULL, TRUE ); + + // Wait some time for routine to finish + interval.QuadPart = -(100LL * 10 * 1000); + KeDelayExecutionThread( KernelMode, FALSE, &interval ); + } + } + else + DPRINT( "BlackBone: %s: APC injection failed with unknown status\n", __FUNCTION__ ); + } + else + DPRINT( "BlackBone: %s: APC injection failed with status 0x%X\n", __FUNCTION__, status ); + } + } + else + DPRINT( "BlackBone: %s: Failed to locate thread\n", __FUNCTION__ ); + + if (pThread) + ObDereferenceObject( pThread ); + + return status; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/Loader.c b/third/Blackbone/src/BlackBoneDrv/Loader.c new file mode 100644 index 0000000000000000000000000000000000000000..2b3e04c982700a19a5c17aa4d83ba49d90721e08 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/Loader.c @@ -0,0 +1,934 @@ +#include "Private.h" +#include "Loader.h" +#include "BlackBoneDef.h" +#include "Utils.h" +#include + +NTSTATUS BBMapWorker ( IN PVOID pArg ); +VOID KernelApcPrepareCallback( PKAPC, PKNORMAL_ROUTINE*, PVOID*, PVOID*, PVOID* ); +VOID KernelApcInjectCallback ( PKAPC, PKNORMAL_ROUTINE*, PVOID*, PVOID*, PVOID* ); +BOOLEAN BBSkipThread ( IN PETHREAD pThread, IN BOOLEAN isWow64 ); + + +extern DYNAMIC_DATA dynData; + +#pragma alloc_text(PAGE, BBInitLdrData) +#pragma alloc_text(PAGE, BBGetSystemModule) +#pragma alloc_text(PAGE, BBGetUserModule) +#pragma alloc_text(PAGE, BBUnlinkFromLoader) +#pragma alloc_text(PAGE, BBGetModuleExport) +#pragma alloc_text(PAGE, BBLookupProcessThread) +#pragma alloc_text(PAGE, BBQueueUserApc) +#pragma alloc_text(PAGE, KernelApcPrepareCallback) +#pragma alloc_text(PAGE, KernelApcInjectCallback) +#pragma alloc_text(PAGE, BBMapWorker) +#pragma alloc_text(PAGE, BBMMapDriver) +#pragma alloc_text(PAGE, BBSkipThread) + +/// +/// Remove list entry +/// +/// Entry link +FORCEINLINE VOID RemoveEntryList32( IN PLIST_ENTRY32 Entry ) +{ + ((PLIST_ENTRY32)Entry->Blink)->Flink = Entry->Flink; + ((PLIST_ENTRY32)Entry->Flink)->Blink = Entry->Blink; +} + +/// +/// Initialize loader stuff +/// +/// Any valid system module +/// Status code +NTSTATUS BBInitLdrData( IN PKLDR_DATA_TABLE_ENTRY pThisModule ) +{ + PVOID kernelBase = GetKernelBase( NULL ); + if (kernelBase == NULL) + { + DPRINT( "BlackBone: %s: Failed to retrieve Kernel base address. Aborting\n", __FUNCTION__ ); + return STATUS_NOT_FOUND; + } + + // Get PsLoadedModuleList address + for (PLIST_ENTRY pListEntry = pThisModule->InLoadOrderLinks.Flink; pListEntry != &pThisModule->InLoadOrderLinks; pListEntry = pListEntry->Flink) + { + // Search for Ntoskrnl entry + PKLDR_DATA_TABLE_ENTRY pEntry = CONTAINING_RECORD( pListEntry, KLDR_DATA_TABLE_ENTRY, InLoadOrderLinks ); + if (kernelBase == pEntry->DllBase) + { + // Ntoskrnl is always first entry in the list + // Check if found pointer belongs to Ntoskrnl module + if ((PVOID)pListEntry->Blink >= pEntry->DllBase && (PUCHAR)pListEntry->Blink < (PUCHAR)pEntry->DllBase + pEntry->SizeOfImage) + { + PsLoadedModuleList = pListEntry->Blink; + break; + } + } + } + + if (!PsLoadedModuleList) + { + DPRINT( "BlackBone: %s: Failed to retrieve PsLoadedModuleList address. Aborting\n", __FUNCTION__ ); + return STATUS_NOT_FOUND; + } + + return STATUS_SUCCESS; +} + +/// +/// Get address of a system module +/// Either 'pName' or 'pAddress' is required to perform search +/// +/// Base name of the image (e.g. hal.dll) +/// Address inside module +/// Found loader entry. NULL if nothing found +PKLDR_DATA_TABLE_ENTRY BBGetSystemModule( IN PUNICODE_STRING pName, IN PVOID pAddress ) +{ + ASSERT( (pName != NULL || pAddress != NULL) && PsLoadedModuleList != NULL ); + if ((pName == NULL && pAddress == NULL) || PsLoadedModuleList == NULL) + return NULL; + + // No images + if (IsListEmpty( PsLoadedModuleList )) + return NULL; + + // Search in PsLoadedModuleList + for (PLIST_ENTRY pListEntry = PsLoadedModuleList->Flink; pListEntry != PsLoadedModuleList; pListEntry = pListEntry->Flink) + { + PKLDR_DATA_TABLE_ENTRY pEntry = CONTAINING_RECORD( pListEntry, KLDR_DATA_TABLE_ENTRY, InLoadOrderLinks ); + + // Check by name or by address + if ((pName && RtlCompareUnicodeString( &pEntry->BaseDllName, pName, TRUE ) == 0) || + (pAddress && pAddress >= pEntry->DllBase && (PUCHAR)pAddress < (PUCHAR)pEntry->DllBase + pEntry->SizeOfImage)) + { + return pEntry; + } + } + + return NULL; +} + +/// +/// Get module base address by name +/// +/// Target process +/// Nodule name to search for +/// If TRUE - search in 32-bit PEB +/// Found address, NULL if not found +PVOID BBGetUserModule( IN PEPROCESS pProcess, IN PUNICODE_STRING ModuleName, IN BOOLEAN isWow64 ) +{ + ASSERT( pProcess != NULL ); + if (pProcess == NULL) + return NULL; + + // Protect from UserMode AV + __try + { + LARGE_INTEGER time = { 0 }; + time.QuadPart = -250ll * 10 * 1000; // 250 msec. + + // Wow64 process + if (isWow64) + { + PPEB32 pPeb32 = (PPEB32)PsGetProcessWow64Process( pProcess ); + if (pPeb32 == NULL) + { + DPRINT( "BlackBone: %s: No PEB present. Aborting\n", __FUNCTION__ ); + return NULL; + } + + // Wait for loader a bit + for (INT i = 0; !pPeb32->Ldr && i < 10; i++) + { + DPRINT( "BlackBone: %s: Loader not intialiezd, waiting\n", __FUNCTION__ ); + KeDelayExecutionThread( KernelMode, TRUE, &time ); + } + + // Still no loader + if (!pPeb32->Ldr) + { + DPRINT( "BlackBone: %s: Loader was not intialiezd in time. Aborting\n", __FUNCTION__ ); + return NULL; + } + + // Search in InLoadOrderModuleList + for (PLIST_ENTRY32 pListEntry = (PLIST_ENTRY32)((PPEB_LDR_DATA32)pPeb32->Ldr)->InLoadOrderModuleList.Flink; + pListEntry != &((PPEB_LDR_DATA32)pPeb32->Ldr)->InLoadOrderModuleList; + pListEntry = (PLIST_ENTRY32)pListEntry->Flink) + { + UNICODE_STRING ustr; + PLDR_DATA_TABLE_ENTRY32 pEntry = CONTAINING_RECORD( pListEntry, LDR_DATA_TABLE_ENTRY32, InLoadOrderLinks ); + + RtlUnicodeStringInit( &ustr, (PWCH)pEntry->BaseDllName.Buffer ); + + if (RtlCompareUnicodeString( &ustr, ModuleName, TRUE ) == 0) + return (PVOID)pEntry->DllBase; + } + } + // Native process + else + { + PPEB pPeb = PsGetProcessPeb( pProcess ); + if (!pPeb) + { + DPRINT( "BlackBone: %s: No PEB present. Aborting\n", __FUNCTION__ ); + return NULL; + } + + // Wait for loader a bit + for (INT i = 0; !pPeb->Ldr && i < 10; i++) + { + DPRINT( "BlackBone: %s: Loader not intialiezd, waiting\n", __FUNCTION__ ); + KeDelayExecutionThread( KernelMode, TRUE, &time ); + } + + // Still no loader + if (!pPeb->Ldr) + { + DPRINT( "BlackBone: %s: Loader was not intialiezd in time. Aborting\n", __FUNCTION__ ); + return NULL; + } + + // Search in InLoadOrderModuleList + for (PLIST_ENTRY pListEntry = pPeb->Ldr->InLoadOrderModuleList.Flink; + pListEntry != &pPeb->Ldr->InLoadOrderModuleList; + pListEntry = pListEntry->Flink) + { + PLDR_DATA_TABLE_ENTRY pEntry = CONTAINING_RECORD( pListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks ); + if (RtlCompareUnicodeString( &pEntry->BaseDllName, ModuleName, TRUE ) == 0) + return pEntry->DllBase; + } + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + DPRINT( "BlackBone: %s: Exception, Code: 0x%X\n", __FUNCTION__, GetExceptionCode() ); + } + + return NULL; +} + +/// +/// Unlink user-mode module from Loader lists +/// +/// Target process +/// Module base +/// If TRUE - unlink from PEB32 Loader, otherwise use PEB64 +/// Status code +NTSTATUS BBUnlinkFromLoader( IN PEPROCESS pProcess, IN PVOID pBase, IN BOOLEAN isWow64 ) +{ + NTSTATUS status = STATUS_SUCCESS; + ASSERT( pProcess != NULL ); + if (pProcess == NULL) + return STATUS_INVALID_PARAMETER; + + // Protect from UserMode AV + __try + { + // Wow64 process + if (isWow64) + { + PPEB32 pPeb32 = (PPEB32)PsGetProcessWow64Process( pProcess ); + if (pPeb32 == NULL) + { + DPRINT( "BlackBone: %s: No PEB present. Aborting\n", __FUNCTION__ ); + return STATUS_NOT_FOUND; + } + + // Search in InLoadOrderModuleList + for (PLIST_ENTRY32 pListEntry = (PLIST_ENTRY32)((PPEB_LDR_DATA32)pPeb32->Ldr)->InLoadOrderModuleList.Flink; + pListEntry != &((PPEB_LDR_DATA32)pPeb32->Ldr)->InLoadOrderModuleList; + pListEntry = (PLIST_ENTRY32)pListEntry->Flink) + { + PLDR_DATA_TABLE_ENTRY32 pEntry = CONTAINING_RECORD( pListEntry, LDR_DATA_TABLE_ENTRY32, InLoadOrderLinks ); + + // Unlink + if ((PVOID)pEntry->DllBase == pBase) + { + RemoveEntryList32( &pEntry->InLoadOrderLinks ); + RemoveEntryList32( &pEntry->InInitializationOrderLinks ); + RemoveEntryList32( &pEntry->InMemoryOrderLinks ); + RemoveEntryList32( &pEntry->HashLinks ); + + break; + } + } + } + // Native process + else + { + PPEB pPeb = PsGetProcessPeb( pProcess ); + if (!pPeb) + { + DPRINT( "BlackBone: %s: No PEB present. Aborting\n", __FUNCTION__ ); + return STATUS_NOT_FOUND; + } + + // Search in InLoadOrderModuleList + for (PLIST_ENTRY pListEntry = pPeb->Ldr->InLoadOrderModuleList.Flink; + pListEntry != &pPeb->Ldr->InLoadOrderModuleList; + pListEntry = pListEntry->Flink) + { + PLDR_DATA_TABLE_ENTRY pEntry = CONTAINING_RECORD( pListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks ); + + // Unlink + if (pEntry->DllBase == pBase) + { + RemoveEntryList( &pEntry->InLoadOrderLinks ); + RemoveEntryList( &pEntry->InInitializationOrderLinks ); + RemoveEntryList( &pEntry->InMemoryOrderLinks ); + RemoveEntryList( &pEntry->HashLinks ); + + break; + } + } + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + DPRINT( "BlackBone: %s: Exception, Code: 0x%X\n", __FUNCTION__, GetExceptionCode() ); + } + + return status; +} + +/// +/// Get exported function address +/// +/// Module base +/// Function name or ordinal +/// Target process for user module +/// Dll name for api schema +/// Found address, NULL if not found +PVOID BBGetModuleExport( IN PVOID pBase, IN PCCHAR name_ord, IN PEPROCESS pProcess, IN PUNICODE_STRING baseName ) +{ + PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)pBase; + PIMAGE_NT_HEADERS32 pNtHdr32 = NULL; + PIMAGE_NT_HEADERS64 pNtHdr64 = NULL; + PIMAGE_EXPORT_DIRECTORY pExport = NULL; + ULONG expSize = 0; + ULONG_PTR pAddress = 0; + + ASSERT( pBase != NULL ); + if (pBase == NULL) + return NULL; + + /// Not a PE file + if (pDosHdr->e_magic != IMAGE_DOS_SIGNATURE) + return NULL; + + pNtHdr32 = (PIMAGE_NT_HEADERS32)((PUCHAR)pBase + pDosHdr->e_lfanew); + pNtHdr64 = (PIMAGE_NT_HEADERS64)((PUCHAR)pBase + pDosHdr->e_lfanew); + + // Not a PE file + if (pNtHdr32->Signature != IMAGE_NT_SIGNATURE) + return NULL; + + // 64 bit image + if (pNtHdr32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) + { + pExport = (PIMAGE_EXPORT_DIRECTORY)(pNtHdr64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + (ULONG_PTR)pBase); + expSize = pNtHdr64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; + } + // 32 bit image + else + { + pExport = (PIMAGE_EXPORT_DIRECTORY)(pNtHdr32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + (ULONG_PTR)pBase); + expSize = pNtHdr32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; + } + + PUSHORT pAddressOfOrds = (PUSHORT)(pExport->AddressOfNameOrdinals + (ULONG_PTR)pBase); + PULONG pAddressOfNames = (PULONG)(pExport->AddressOfNames + (ULONG_PTR)pBase); + PULONG pAddressOfFuncs = (PULONG)(pExport->AddressOfFunctions + (ULONG_PTR)pBase); + + for (ULONG i = 0; i < pExport->NumberOfFunctions; ++i) + { + USHORT OrdIndex = 0xFFFF; + PCHAR pName = NULL; + + // Find by index + if ((ULONG_PTR)name_ord <= 0xFFFF) + { + OrdIndex = (USHORT)i; + } + // Find by name + else if ((ULONG_PTR)name_ord > 0xFFFF && i < pExport->NumberOfNames) + { + pName = (PCHAR)(pAddressOfNames[i] + (ULONG_PTR)pBase); + OrdIndex = pAddressOfOrds[i]; + } + // Weird params + else + return NULL; + + if (((ULONG_PTR)name_ord <= 0xFFFF && (USHORT)((ULONG_PTR)name_ord) == OrdIndex + pExport->Base) || + ((ULONG_PTR)name_ord > 0xFFFF && strcmp( pName, name_ord ) == 0)) + { + pAddress = pAddressOfFuncs[OrdIndex] + (ULONG_PTR)pBase; + + // Check forwarded export + if (pAddress >= (ULONG_PTR)pExport && pAddress <= (ULONG_PTR)pExport + expSize) + { + WCHAR strbuf[256] = { 0 }; + ANSI_STRING forwarder = { 0 }; + ANSI_STRING import = { 0 }; + + UNICODE_STRING uForwarder = { 0 }; + ULONG delimIdx = 0; + PVOID forwardBase = NULL; + PVOID result = NULL; + + // System image, not supported + if (pProcess == NULL) + return NULL; + + RtlInitAnsiString( &forwarder, (PCSZ)pAddress ); + RtlInitEmptyUnicodeString( &uForwarder, strbuf, sizeof( strbuf ) ); + + RtlAnsiStringToUnicodeString( &uForwarder, &forwarder, FALSE ); + for (ULONG j = 0; j < uForwarder.Length / sizeof( WCHAR ); j++) + { + if (uForwarder.Buffer[j] == L'.') + { + uForwarder.Length = (USHORT)(j * sizeof( WCHAR )); + uForwarder.Buffer[j] = L'\0'; + delimIdx = j; + break; + } + } + + // Get forward function name/ordinal + RtlInitAnsiString( &import, forwarder.Buffer + delimIdx + 1 ); + RtlAppendUnicodeToString( &uForwarder, L".dll" ); + + // + // Check forwarded module + // + UNICODE_STRING resolved = { 0 }; + UNICODE_STRING resolvedName = { 0 }; + BBResolveImagePath( NULL, pProcess, KApiShemaOnly, &uForwarder, baseName, &resolved ); + BBStripPath( &resolved, &resolvedName ); + + forwardBase = BBGetUserModule( pProcess, &resolvedName, PsGetProcessWow64Process( pProcess ) != NULL ); + result = BBGetModuleExport( forwardBase, import.Buffer, pProcess, &resolvedName ); + RtlFreeUnicodeString( &resolved ); + + return result; + } + + break; + } + } + + return (PVOID)pAddress; +} + +/// +/// Check if thread does not satisfy APC requirements +/// +/// Thread to check +/// /// If TRUE - check Wow64 TEB +/// If TRUE - BBLookupProcessThread should skip thread +BOOLEAN BBSkipThread( IN PETHREAD pThread, IN BOOLEAN isWow64 ) +{ + PUCHAR pTeb64 = PsGetThreadTeb( pThread ); + if (!pTeb64) + return TRUE; + + // Skip GUI treads. APC to GUI thread causes ZwUserGetMessage to fail + // TEB64 + 0x78 = Win32ThreadInfo + if (*(PULONG64)(pTeb64 + 0x78) != 0) + return TRUE; + + // Skip threads with no ActivationContext + // Skip threads with no TLS pointer + if (isWow64) + { + PUCHAR pTeb32 = pTeb64 + 0x2000; + + // TEB32 + 0x1A8 = ActivationContextStackPointer + if (*(PULONG32)(pTeb32 + 0x1A8) == 0) + return TRUE; + + // TEB64 + 0x2C = ThreadLocalStoragePointer + if (*(PULONG32)(pTeb32 + 0x2C) == 0) + return TRUE; + } + else + { + // TEB64 + 0x2C8 = ActivationContextStackPointer + if (*(PULONG64)(pTeb64 + 0x2C8) == 0) + return TRUE; + + // TEB64 + 0x58 = ThreadLocalStoragePointer + if (*(PULONG64)(pTeb64 + 0x58) == 0) + return TRUE; + } + + return FALSE; +} + +/// +/// Find first thread of the target process +/// +/// Target process +/// Found thread. Thread object reference count is increased by 1 +/// Status code +NTSTATUS BBLookupProcessThread( IN PEPROCESS pProcess, OUT PETHREAD* ppThread ) +{ + NTSTATUS status = STATUS_SUCCESS; + HANDLE pid = PsGetProcessId( pProcess ); + PVOID pBuf = ExAllocatePoolWithTag( NonPagedPool, 1024 * 1024, BB_POOL_TAG ); + PSYSTEM_PROCESS_INFO pInfo = (PSYSTEM_PROCESS_INFO)pBuf; + + ASSERT( ppThread != NULL ); + if (ppThread == NULL) + return STATUS_INVALID_PARAMETER; + + if (!pInfo) + { + DPRINT( "BlackBone: %s: Failed to allocate memory for process list\n", __FUNCTION__ ); + return STATUS_NO_MEMORY; + } + + // Get the process thread list + status = ZwQuerySystemInformation( SystemProcessInformation, pInfo, 1024 * 1024, NULL ); + if (!NT_SUCCESS( status )) + { + ExFreePoolWithTag( pBuf, BB_POOL_TAG ); + return status; + } + + // Find target thread + if (NT_SUCCESS( status )) + { + status = STATUS_NOT_FOUND; + for (;;) + { + if (pInfo->UniqueProcessId == pid) + { + status = STATUS_SUCCESS; + break; + } + else if (pInfo->NextEntryOffset) + pInfo = (PSYSTEM_PROCESS_INFO)((PUCHAR)pInfo + pInfo->NextEntryOffset); + else + break; + } + } + + BOOLEAN wow64 = PsGetProcessWow64Process( pProcess ) != NULL; + + // Reference target thread + if (NT_SUCCESS( status )) + { + status = STATUS_NOT_FOUND; + + // Get first thread + for (ULONG i = 0; i < pInfo->NumberOfThreads; i++) + { + // Skip current thread + if (/*pInfo->Threads[i].WaitReason == Suspended || + pInfo->Threads[i].ThreadState == 5 ||*/ + pInfo->Threads[i].ClientId.UniqueThread == PsGetCurrentThreadId()) + { + continue; + } + + status = PsLookupThreadByThreadId( pInfo->Threads[i].ClientId.UniqueThread, ppThread ); + + // Skip specific threads + if (*ppThread && BBSkipThread( *ppThread, wow64 )) + { + ObDereferenceObject( *ppThread ); + *ppThread = NULL; + continue; + } + + break; + } + } + else + DPRINT( "BlackBone: %s: Failed to locate process\n", __FUNCTION__ ); + + if (pBuf) + ExFreePoolWithTag( pBuf, BB_POOL_TAG ); + + // No suitable thread + if (!*ppThread) + status = STATUS_NOT_FOUND; + + return status; +} + +/// +/// Create new thread in the target process +/// Must be running in target process context +/// +/// Thread start address +/// Thread argument +/// Thread creation flags +/// If set to TRUE - wait for thread completion +/// Thread exit status +/// Status code +NTSTATUS BBExecuteInNewThread( + IN PVOID pBaseAddress, + IN PVOID pParam, + IN ULONG flags, + IN BOOLEAN wait, + OUT PNTSTATUS pExitStatus + ) +{ + HANDLE hThread = NULL; + OBJECT_ATTRIBUTES ob = { 0 }; + + InitializeObjectAttributes( &ob, NULL, OBJ_KERNEL_HANDLE, NULL, NULL ); + + NTSTATUS status = ZwCreateThreadEx( + &hThread, THREAD_QUERY_LIMITED_INFORMATION, &ob, + ZwCurrentProcess(), pBaseAddress, pParam, flags, + 0, 0x1000, 0x100000, NULL + ); + + // Wait for completion + if (NT_SUCCESS( status ) && wait != FALSE) + { + // Force 60 sec timeout + LARGE_INTEGER timeout = { 0 }; + timeout.QuadPart = -(60ll * 10 * 1000 * 1000); + + status = ZwWaitForSingleObject( hThread, TRUE, &timeout ); + if (NT_SUCCESS( status )) + { + THREAD_BASIC_INFORMATION info = { 0 }; + ULONG bytes = 0; + + status = ZwQueryInformationThread( hThread, ThreadBasicInformation, &info, sizeof( info ), &bytes ); + if (NT_SUCCESS( status ) && pExitStatus) + { + *pExitStatus = info.ExitStatus; + } + else if (!NT_SUCCESS( status )) + { + DPRINT( "BlackBone: %s: ZwQueryInformationThread failed with status 0x%X\n", __FUNCTION__, status ); + } + } + else + DPRINT( "BlackBone: %s: ZwWaitForSingleObject failed with status 0x%X\n", __FUNCTION__, status ); + } + else + DPRINT( "BlackBone: %s: ZwCreateThreadEx failed with status 0x%X\n", __FUNCTION__, status ); + + if (hThread) + ZwClose( hThread ); + + return status; +} + +/// +/// Queue user-mode APC to the target thread +/// +/// Target thread +/// APC function +/// Argument 1 +/// Argument 2 +/// Argument 3 +/// If TRUE - force delivery by issuing special kernel APC +/// Status code +NTSTATUS BBQueueUserApc( + IN PETHREAD pThread, + IN PVOID pUserFunc, + IN PVOID Arg1, + IN PVOID Arg2, + IN PVOID Arg3, + IN BOOLEAN bForce + ) +{ + ASSERT( pThread != NULL ); + if (pThread == NULL) + return STATUS_INVALID_PARAMETER; + + // Allocate APC + PKAPC pPrepareApc = NULL; + PKAPC pInjectApc = ExAllocatePoolWithTag( NonPagedPool, sizeof( KAPC ), BB_POOL_TAG ); + + if (pInjectApc == NULL) + { + DPRINT( "BlackBone: %s: Failed to allocate APC\n", __FUNCTION__ ); + return STATUS_NO_MEMORY; + } + + // Actual APC + KeInitializeApc( + pInjectApc, (PKTHREAD)pThread, + OriginalApcEnvironment, &KernelApcInjectCallback, + NULL, (PKNORMAL_ROUTINE)(ULONG_PTR)pUserFunc, UserMode, Arg1 + ); + + // Setup force-delivery APC + if (bForce) + { + pPrepareApc = ExAllocatePoolWithTag( NonPagedPool, sizeof( KAPC ), BB_POOL_TAG ); + KeInitializeApc( + pPrepareApc, (PKTHREAD)pThread, + OriginalApcEnvironment, &KernelApcPrepareCallback, + NULL, NULL, KernelMode, NULL + ); + } + + // Insert APC + if (KeInsertQueueApc( pInjectApc, Arg2, Arg3, 0 )) + { + if (bForce && pPrepareApc) + KeInsertQueueApc( pPrepareApc, NULL, NULL, 0 ); + + return STATUS_SUCCESS; + } + else + { + DPRINT( "BlackBone: %s: Failed to insert APC\n", __FUNCTION__ ); + + ExFreePoolWithTag( pInjectApc, BB_POOL_TAG ); + + if (pPrepareApc) + ExFreePoolWithTag( pPrepareApc, BB_POOL_TAG ); + + return STATUS_NOT_CAPABLE; + } +} + +// +// Injection APC routines +// +VOID KernelApcPrepareCallback( + PKAPC Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArgument2 + ) +{ + UNREFERENCED_PARAMETER( NormalRoutine ); + UNREFERENCED_PARAMETER( NormalContext ); + UNREFERENCED_PARAMETER( SystemArgument1 ); + UNREFERENCED_PARAMETER( SystemArgument2 ); + + //DPRINT( "BlackBone: %s: Called\n", __FUNCTION__ ); + + // Alert current thread + KeTestAlertThread( UserMode ); + ExFreePoolWithTag( Apc, BB_POOL_TAG ); +} + +VOID KernelApcInjectCallback( + PKAPC Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArgument2 + ) +{ + UNREFERENCED_PARAMETER( SystemArgument1 ); + UNREFERENCED_PARAMETER( SystemArgument2 ); + + //DPRINT( "BlackBone: %s: Called. NormalRoutine = 0x%p\n", __FUNCTION__, *NormalRoutine ); + + // Skip execution + if (PsIsThreadTerminating( PsGetCurrentThread() )) + *NormalRoutine = NULL; + + // Fix Wow64 APC + if (PsGetCurrentProcessWow64Process() != NULL) + PsWrapApcWow64Thread( NormalContext, (PVOID*)NormalRoutine ); + + ExFreePoolWithTag( Apc, BB_POOL_TAG ); +} + +/// +/// System worker thread that performs actual mapping +/// +/// Path to the driver - PUNICODE_STRING type +/// Status code +NTSTATUS BBMapWorker( IN PVOID pArg ) +{ + NTSTATUS status = STATUS_SUCCESS; + HANDLE hFile = NULL; + PUNICODE_STRING pPath = (PUNICODE_STRING)pArg; + OBJECT_ATTRIBUTES obAttr = { 0 }; + IO_STATUS_BLOCK statusBlock = { 0 }; + PVOID fileData = NULL; + PIMAGE_NT_HEADERS pNTHeader = NULL; + PVOID imageSection = NULL; + PMDL pMDL = NULL; + FILE_STANDARD_INFORMATION fileInfo = { 0 }; + + InitializeObjectAttributes( &obAttr, pPath, OBJ_KERNEL_HANDLE, NULL, NULL ); + + // Open driver file + status = ZwCreateFile( + &hFile, FILE_READ_DATA | SYNCHRONIZE, &obAttr, + &statusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, + FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 + ); + + if (!NT_SUCCESS( status )) + { + DPRINT( "BlackBone: %s: Failed to open '%wZ'. Status: 0x%X\n", __FUNCTION__, pPath, status ); + PsTerminateSystemThread( status ); + return status; + } + + // Allocate memory for file contents + status = ZwQueryInformationFile( hFile, &statusBlock, &fileInfo, sizeof( fileInfo ), FileStandardInformation ); + if (NT_SUCCESS( status )) + fileData = ExAllocatePoolWithTag( PagedPool, fileInfo.EndOfFile.QuadPart, BB_POOL_TAG ); + else + DPRINT( "BlackBone: %s: Failed to get '%wZ' size. Status: 0x%X\n", __FUNCTION__, pPath, status ); + + // Get file contents + status = ZwReadFile( hFile, NULL, NULL, NULL, &statusBlock, fileData, fileInfo.EndOfFile.LowPart, NULL, NULL ); + if (NT_SUCCESS( status )) + { + pNTHeader = RtlImageNtHeader( fileData ); + if (!pNTHeader) + { + DPRINT( "BlackBone: %s: Failed to obtaint NT Header for '%wZ'\n", __FUNCTION__, pPath ); + status = STATUS_INVALID_IMAGE_FORMAT; + } + } + else + DPRINT( "BlackBone: %s: Failed to read '%wZ'. Status: 0x%X\n", __FUNCTION__, pPath, status ); + + ZwClose( hFile ); + + if (NT_SUCCESS( status )) + { + // + // Allocate memory from System PTEs + // + PHYSICAL_ADDRESS start = { 0 }, end = { 0 }; + end.QuadPart = MAXULONG64; + + pMDL = MmAllocatePagesForMdl( start, end, start, pNTHeader->OptionalHeader.SizeOfImage ); + imageSection = MmGetSystemAddressForMdlSafe( pMDL, NormalPagePriority ); + + if (NT_SUCCESS( status ) && imageSection) + { + // Copy header + RtlCopyMemory( imageSection, fileData, pNTHeader->OptionalHeader.SizeOfHeaders ); + + // Copy sections + for (PIMAGE_SECTION_HEADER pSection = (PIMAGE_SECTION_HEADER)(pNTHeader + 1); + pSection < (PIMAGE_SECTION_HEADER)(pNTHeader + 1) + pNTHeader->FileHeader.NumberOfSections; + pSection++) + { + RtlCopyMemory( + (PUCHAR)imageSection + pSection->VirtualAddress, + (PUCHAR)fileData + pSection->PointerToRawData, + pSection->SizeOfRawData + ); + } + + // Relocate image + status = LdrRelocateImage( imageSection, STATUS_SUCCESS, STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT ); + if (!NT_SUCCESS( status )) + DPRINT( "BlackBone: %s: Failed to relocate image '%wZ'. Status: 0x%X\n", __FUNCTION__, pPath, status ); + + // Fill IAT + if (NT_SUCCESS( status )) + status = BBResolveImageRefs( imageSection, TRUE, NULL, FALSE, NULL, 0 ); + } + else + { + DPRINT( "BlackBone: %s: Failed to allocate memory for image '%wZ'\n", __FUNCTION__, pPath ); + status = STATUS_MEMORY_NOT_ALLOCATED; + } + } + + // SEH support + /*if (NT_SUCCESS( status )) + { + //NTSTATUS( NTAPI* RtlInsertInvertedFunctionTable )(PVOID, SIZE_T) = (NTSTATUS( *)(PVOID, SIZE_T))((ULONG_PTR)GetKernelBase( NULL ) + 0x9B0A8); + NTSTATUS( NTAPI* RtlInsertInvertedFunctionTable )(PVOID, PVOID, SIZE_T) = (NTSTATUS( *)(PVOID, PVOID, SIZE_T))((ULONG_PTR)GetKernelBase( NULL ) + 0x11E4C0); + RtlInsertInvertedFunctionTable((PUCHAR)GetKernelBase( NULL ) + 0x1ED450, imageSection, pNTHeader->OptionalHeader.SizeOfImage ); + }*/ + + // Initialize kernel security cookie + if (NT_SUCCESS( status )) + BBCreateCookie( imageSection ); + + // Call entry point + if (NT_SUCCESS( status ) && pNTHeader->OptionalHeader.AddressOfEntryPoint) + { + PDRIVER_INITIALIZE pEntryPoint = (PDRIVER_INITIALIZE)((ULONG_PTR)imageSection + pNTHeader->OptionalHeader.AddressOfEntryPoint); + pEntryPoint( NULL, NULL ); + } + + // Wipe header + if (NT_SUCCESS( status ) && imageSection) + RtlZeroMemory( imageSection, pNTHeader->OptionalHeader.SizeOfHeaders ); + + // Erase info about allocated region + if (pMDL) + { + // Free image memory in case of failure + if(!NT_SUCCESS( status )) + MmFreePagesFromMdl( pMDL ); + + ExFreePool( pMDL ); + } + + if (fileData) + ExFreePoolWithTag( fileData, BB_POOL_TAG ); + + if (NT_SUCCESS( status )) + DPRINT( "BlackBone: %s: Successfully mapped '%wZ' at 0x%p\n", __FUNCTION__, pPath, imageSection ); + + PsTerminateSystemThread( status ); + return status; +} + +/// +/// Manually map driver into system space +/// +/// Fully qualified native path to the driver +/// Status code +NTSTATUS BBMMapDriver( IN PUNICODE_STRING pPath ) +{ + HANDLE hThread = NULL; + CLIENT_ID clientID = { 0 }; + OBJECT_ATTRIBUTES obAttr = { 0 }; + PETHREAD pThread = NULL; + OBJECT_HANDLE_INFORMATION handleInfo = { 0 }; + + InitializeObjectAttributes( &obAttr, NULL, OBJ_KERNEL_HANDLE, NULL, NULL ); + + ASSERT( pPath != NULL ); + if (pPath == NULL) + return STATUS_INVALID_PARAMETER; + + NTSTATUS status = PsCreateSystemThread( &hThread, THREAD_ALL_ACCESS, &obAttr, NULL, &clientID, &BBMapWorker, pPath ); + if (!NT_SUCCESS( status )) + { + DPRINT( "BlackBone: %s: Failed to create worker thread. Status: 0x%X\n", __FUNCTION__, status ); + return status; + } + + // Wait on worker thread + status = ObReferenceObjectByHandle( hThread, THREAD_ALL_ACCESS, *PsThreadType, KernelMode, &pThread, &handleInfo ); + if (NT_SUCCESS( status )) + { + THREAD_BASIC_INFORMATION info = { 0 }; + ULONG bytes = 0; + + status = KeWaitForSingleObject( pThread, Executive, KernelMode, TRUE, NULL ); + status = ZwQueryInformationThread( hThread, ThreadBasicInformation, &info, sizeof( info ), &bytes ); + if (NT_SUCCESS( status )); + status = info.ExitStatus; + } + + if (pThread) + ObDereferenceObject( pThread ); + + return status; +} diff --git a/third/Blackbone/src/BlackBoneDrv/Loader.h b/third/Blackbone/src/BlackBoneDrv/Loader.h new file mode 100644 index 0000000000000000000000000000000000000000..667aa5c7635747b89ca22233cfbdab7f390cea49 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/Loader.h @@ -0,0 +1,289 @@ +#pragma once + +#include "Imports.h" +#include "NativeStructs.h" + +// Module type +typedef enum _ModType +{ + mt_mod32, // 64 bit module + mt_mod64, // 32 bit module + mt_default, // type is deduced from target process + mt_unknown // Failed to detect type +} ModType; + +// Image name resolve flags +typedef enum _ResolveFlags +{ + KApiShemaOnly = 1, + KSkipSxS = 2, + KFullPath = 4, +} ResolveFlags; + +/// +/// Module info +/// +typedef struct _MODULE_DATA +{ + LIST_ENTRY link; // List link + PUCHAR baseAddress; // Base image address in target process + PUCHAR localBase; // Base image address in system space + UNICODE_STRING name; // File name + UNICODE_STRING fullPath; // Full file path + SIZE_T size; // Size of image + ModType type; // Module type + enum KMmapFlags flags; // Flags + BOOLEAN manual; // Image is manually mapped + BOOLEAN initialized; // DllMain was already called +} MODULE_DATA, *PMODULE_DATA; + + +/// +/// User-mode memory region +/// +typedef struct _USER_CONTEXT +{ + UCHAR code[0x1000]; // Code buffer + union + { + UNICODE_STRING ustr; + UNICODE_STRING32 ustr32; + }; + wchar_t buffer[0x400]; // Buffer for unicode string + + + // Activation context data + union + { + ACTCTXW actx; + ACTCTXW32 actx32; + }; + HANDLE hCTX; + ULONG hCookie; + + PVOID ptr; // Tmp data + union + { + NTSTATUS status; // Last execution status + PVOID retVal; // Function return value + ULONG retVal32; // Function return value + }; + + //UCHAR tlsBuf[0x100]; +} USER_CONTEXT, *PUSER_CONTEXT; + +/// +/// Manual map context +/// +typedef struct _MMAP_CONTEXT +{ + PEPROCESS pProcess; // Target process + PVOID pWorkerBuf; // Worker thread code buffer + HANDLE hWorker; // Worker thread handle + PETHREAD pWorker; // Worker thread object + LIST_ENTRY modules; // Manual module list + PUSER_CONTEXT userMem; // Tmp buffer in user space + HANDLE hSync; // APC sync handle + PKEVENT pSync; // APC sync object + PVOID pSetEvent; // ZwSetEvent address + PVOID pLoadImage; // LdrLoadDll address + BOOLEAN tlsInitialized; // Static TLS was initialized + BOOLEAN noThreads; // No threads should be created +} MMAP_CONTEXT, *PMMAP_CONTEXT; + +/// +/// Initialize loader stuff +/// +/// Any valid system module +/// Status code +NTSTATUS BBInitLdrData( IN PKLDR_DATA_TABLE_ENTRY pThisModule ); + +/// +/// Get address of a system module +/// Either 'pName' or 'pAddress' is required to perform search +/// +/// Base name of the image (e.g. hal.dll) +/// Address inside module +/// Found loader entry. NULL if nothing found +PKLDR_DATA_TABLE_ENTRY BBGetSystemModule( IN PUNICODE_STRING pName, IN PVOID pAddress ); + +/// +/// Get module base address by name +/// +/// Target process +/// Nodule name to search for +/// If TRUE - search in 32-bit PEB +/// Found address, NULL if not found +PVOID BBGetUserModule( IN PEPROCESS pProcess, IN PUNICODE_STRING ModuleName, IN BOOLEAN isWow64 ); + +/// +/// Unlink user-mode module from Loader lists +/// +/// Target process +/// Module base +/// If TRUE - unlink from PEB32 Loader, otherwise use PEB64 +/// Status code +NTSTATUS BBUnlinkFromLoader( IN PEPROCESS pProcess, IN PVOID pBase, IN BOOLEAN isWow64 ); + +/// +/// Get exported function address +/// +/// Module base +/// Function name or ordinal +/// Target process for user module +/// Found address, NULL if not found +PVOID BBGetModuleExport( IN PVOID pBase, IN PCCHAR name_ord, IN PEPROCESS pProcess, IN PUNICODE_STRING modName ); + +/// +/// Map new user module +/// +/// Target process +/// Image path +/// Image buffer +/// Image buffer size +/// Buffer has image memory layout +/// Mapping flags +/// Init routine RVA +/// Init argument +/// Mapped image data +/// Status code +NTSTATUS BBMapUserImage( + IN PEPROCESS pProcess, + IN PUNICODE_STRING path, + IN PVOID buffer, IN ULONG_PTR size, + IN BOOLEAN asImage, + IN enum KMmapFlags flags, + IN ULONG initRVA, + IN PWCH initArg, + OUT PMODULE_DATA pImage + ); + +/// +/// Resolve import table and load missing dependencies +/// +/// Target image base +/// If TRUE - image is driver +/// Target process +/// Iamge is 32bit image +/// Manual map context +/// Status code +NTSTATUS BBResolveImageRefs( + IN PVOID pImageBase, + IN BOOLEAN systemImage, + IN PEPROCESS pProcess, + IN BOOLEAN wow64Image, + IN PMMAP_CONTEXT pContext, + IN enum KMmapFlags flags + ); + +/// +/// Resolve image name to fully qualified path +/// +/// Loader context +/// Target process. Must be running in the context of this process +/// Flags +/// Image name to resolve +/// Base image name for API SET translation +/// Resolved image path +/// Status code +NTSTATUS BBResolveImagePath( + IN PMMAP_CONTEXT pContext, + IN PEPROCESS pProcess, + IN ResolveFlags flags, + IN PUNICODE_STRING path, + IN PUNICODE_STRING baseImage, + OUT PUNICODE_STRING resolved + ); + +/// +/// Find first thread of the target process +/// +/// Target process. +/// Found thread. Thread object reference count is increased by 1 +/// Status code +NTSTATUS BBLookupProcessThread( IN PEPROCESS pProcess, OUT PETHREAD* ppThread ); + +/// +/// Create new thread in the target process +/// +/// Thread start address +/// Thread argument +/// Thread creation flags +/// If set to TRUE - wait for thread completion +/// Thread exit status +/// Status code +NTSTATUS BBExecuteInNewThread( + IN PVOID pBaseAddress, + IN PVOID pParam, + IN ULONG flags, + IN BOOLEAN wait, + OUT PNTSTATUS pExitStatus + ); + +/// +/// Queue user-mode APC to the target thread +/// +/// Target thread +/// APC function +/// Argument 1 +/// Argument 2 +/// Argument 3 +/// If TRUE - force delivery by issuing special kernel APC +/// Status code +NTSTATUS BBQueueUserApc( + IN PETHREAD pThread, + IN PVOID pUserFunc, + IN PVOID Arg1, + IN PVOID Arg2, + IN PVOID Arg3, + BOOLEAN bForce + ); + + +/// +/// Manually map driver into system space +/// +/// Fully qualified native path to the driver +/// Status code +NTSTATUS BBMMapDriver( IN PUNICODE_STRING pPath ); + +PIMAGE_BASE_RELOCATION +LdrProcessRelocationBlockLongLong( + IN ULONG_PTR VA, + IN ULONG SizeOfBlock, + IN PUSHORT NextOffset, + IN LONGLONG Diff + ); + +NTSTATUS +LdrRelocateImage ( + IN PVOID NewBase, + IN NTSTATUS Success, + IN NTSTATUS Conflict, + IN NTSTATUS Invalid + ); + +NTSTATUS +LdrRelocateImageWithBias( + IN PVOID NewBase, + IN LONGLONG AdditionalBias, + IN NTSTATUS Success, + IN NTSTATUS Conflict, + IN NTSTATUS Invalid + ); + +PIMAGE_BASE_RELOCATION +LdrProcessRelocationBlock( + IN ULONG_PTR VA, + IN ULONG SizeOfBlock, + IN PUSHORT NextOffset, + IN LONG_PTR Diff + ); + +PIMAGE_BASE_RELOCATION +LdrProcessRelocationBlockLongLong( + IN ULONG_PTR VA, + IN ULONG SizeOfBlock, + IN PUSHORT NextOffset, + IN LONGLONG Diff + ); \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/MMap.c b/third/Blackbone/src/BlackBoneDrv/MMap.c new file mode 100644 index 0000000000000000000000000000000000000000..fe6138d5d6fb5bd686031d77ac1e53583be1a97e --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/MMap.c @@ -0,0 +1,1951 @@ +#include "Loader.h" +#include "Private.h" +#include "Routines.h" +#include "BlackBoneDef.h" +#include "Utils.h" +#include "apiset.h" +#include + +#define IMAGE32(hdr) (hdr->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) +#define IMAGE64(hdr) (hdr->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) + +#define HEADER_VAL_T(hdr, val) (IMAGE64(hdr) ? ((PIMAGE_NT_HEADERS64)hdr)->OptionalHeader.val : ((PIMAGE_NT_HEADERS32)hdr)->OptionalHeader.val) +#define THUNK_VAL_T(hdr, ptr, val) (IMAGE64(hdr) ? ((PIMAGE_THUNK_DATA64)ptr)->val : ((PIMAGE_THUNK_DATA32)ptr)->val) +#define TLS_VAL_T(hdr, ptr, val) (IMAGE64(hdr) ? ((PIMAGE_TLS_DIRECTORY64)ptr)->val : ((PIMAGE_TLS_DIRECTORY32)ptr)->val) +#define CFG_DIR_VAL_T(hdr, dir, val) (IMAGE64(hdr) ? ((PIMAGE_LOAD_CONFIG_DIRECTORY64)dir)->val : ((PIMAGE_LOAD_CONFIG_DIRECTORY32)dir)->val) + +#if defined (_WIN10_) +typedef PAPI_SET_VALUE_ENTRY_10 PAPISET_VALUE_ENTRY; +typedef PAPI_SET_VALUE_ARRAY_10 PAPISET_VALUE_ARRAY; +typedef PAPI_SET_NAMESPACE_ENTRY_10 PAPISET_NAMESPACE_ENTRY; +typedef PAPI_SET_NAMESPACE_ARRAY_10 PAPISET_NAMESPACE_ARRAY; +#elif defined (_WIN81_) +typedef PAPI_SET_VALUE_ENTRY PAPISET_VALUE_ENTRY; +typedef PAPI_SET_VALUE_ARRAY PAPISET_VALUE_ARRAY; +typedef PAPI_SET_NAMESPACE_ENTRY PAPISET_NAMESPACE_ENTRY; +typedef PAPI_SET_NAMESPACE_ARRAY PAPISET_NAMESPACE_ARRAY; +#else +typedef PAPI_SET_VALUE_ENTRY_V2 PAPISET_VALUE_ENTRY; +typedef PAPI_SET_VALUE_ARRAY_V2 PAPISET_VALUE_ARRAY; +typedef PAPI_SET_NAMESPACE_ENTRY_V2 PAPISET_NAMESPACE_ENTRY; +typedef PAPI_SET_NAMESPACE_ARRAY_V2 PAPISET_NAMESPACE_ARRAY; +#endif + +PLIST_ENTRY PsLoadedModuleList; +extern DYNAMIC_DATA dynData; + +/// +/// Map new module or return existing +/// +/// Target process +/// Image path +/// Image buffer +/// Image buffer size +/// Buffer has image memory layout +/// Mapping flags +/// Manual map context +/// Mapped image data +/// Status code +NTSTATUS BBFindOrMapModule( + IN PEPROCESS pProcess, + IN PUNICODE_STRING path, + IN PVOID buffer, IN ULONG_PTR size, + IN BOOLEAN asImage, + IN KMmapFlags flags, + IN PMMAP_CONTEXT pContext, + OUT PMODULE_DATA pImage + ); + +/// +/// Try to resolve image via API SET map +/// +/// Target process. Must be run in the context of this process +/// Name to resolve +/// Parent image name +/// Resolved name if any +/// Status code +NTSTATUS BBResolveApiSet( IN PEPROCESS pProcess, IN PUNICODE_STRING name, IN PUNICODE_STRING baseImage, OUT PUNICODE_STRING resolved ); + +/// +///Try to resolve image via SxS isolation +/// +/// Loader context. +/// Name to resolve +/// Resolved name if any +/// Status code +NTSTATUS BBResolveSxS( IN PMMAP_CONTEXT pContext, IN PUNICODE_STRING name, OUT PUNICODE_STRING resolved ); + +/// +/// Call module initialization routines +/// +/// Map context +/// If TRUE - TLS callbacks will no be invoked +/// Status code +NTSTATUS BBCallInitializers( IN PMMAP_CONTEXT pContext, IN BOOLEAN noTLS ); + +/// +/// Call TLS callbacks +/// +/// Loader context +/// Target image base +void BBCallTlsInitializers( IN PMMAP_CONTEXT pContext, IN PVOID imageBase ); + +/// +/// Create activation context +/// +/// Manifest path +/// Target file is a PE image +/// Manifest ID +/// Loader context +/// Status code +NTSTATUS BBPrepareACTX( IN PUNICODE_STRING pPath, IN BOOLEAN asImage, IN LONG manifestID, IN PMMAP_CONTEXT pContext ); + +/// +/// Create exception table for x64 image +/// +/// Loader context +/// Image base +/// Status code +NTSTATUS BBCreateExceptionTable64( IN PMMAP_CONTEXT pContext, IN PVOID imageBase ); + +/// +/// Setup image security cookie +/// +/// Image base +/// Status code +NTSTATUS BBCreateCookie( IN PVOID imageBase ); + +/// +/// Load image from disk into system memory +/// +/// Image path +/// Mapped base +/// Status code +NTSTATUS BBLoadLocalImage( IN PUNICODE_STRING path, OUT PVOID* pBase ); + +/// +/// Create worker thread for user-mode calls +/// +/// Map context +/// Status code +NTSTATUS BBCreateWorkerThread( IN PMMAP_CONTEXT pContext ); + +/// +/// Find suitable thread to be used as worker for user-mode calls +/// +/// Map context +/// Status code +NTSTATUS BBFindWokerThread( IN PMMAP_CONTEXT pContext ); + +/// +/// Call arbitrary function +/// +/// Perform call in a separate thread +/// Loader context +/// Routine to call. +/// Number of arguments. +/// Arguments +/// Status code +NTSTATUS BBCallRoutine( IN BOOLEAN newThread, IN PMMAP_CONTEXT pContext, IN PVOID pRoutine, IN INT argc, ... ); + +/// +/// Find existing module in the list +/// +/// Module list +/// Module name +/// Module type +/// Module info address; NULL if not found +PMODULE_DATA BBLookupMappedModule( IN PLIST_ENTRY pList, IN PUNICODE_STRING pName, IN ModType type ); + +/// +/// Get memory protection form section characteristics +/// +/// Characteristics +/// Set to TRUE if DEP is disabled. This will omit creation of executable pages +/// Memory protection value +ULONG BBCastSectionProtection( IN ULONG characteristics, IN BOOLEAN noDEP ); + +/// +/// Get image manifest data +/// +/// Image base +/// Manifest size +/// Manifest ID +/// Manifest data pointer or NULL if no manifest +PVOID BBImageManifest( IN PVOID pImageBase, OUT PULONG_PTR pSize, OUT PLONG pID ); + +/// +/// Translate RVA address to VA +/// +/// RVA +/// Image is mapped using image memory layout +/// Image base +/// Translated address +PVOID BBRvaToVa( IN ULONG rva, IN BOOLEAN MappedAsImage, IN IN PVOID imageBase ); + +#pragma alloc_text(PAGE, BBMapUserImage) +#pragma alloc_text(PAGE, BBFindOrMapModule) +#pragma alloc_text(PAGE, BBResolveImageRefs) +#pragma alloc_text(PAGE, BBResolveApiSet) +#pragma alloc_text(PAGE, BBResolveSxS) +#pragma alloc_text(PAGE, BBResolveImagePath) +#pragma alloc_text(PAGE, BBCallInitializers) +#pragma alloc_text(PAGE, BBPrepareACTX) +#pragma alloc_text(PAGE, BBCreateExceptionTable64) +#pragma alloc_text(PAGE, BBCreateCookie) +#pragma alloc_text(PAGE, BBLoadLocalImage) +#pragma alloc_text(PAGE, BBCreateWorkerThread) +#pragma alloc_text(PAGE, BBCallRoutine) +#pragma alloc_text(PAGE, BBLookupMappedModule) +#pragma alloc_text(PAGE, BBCastSectionProtection) +#pragma alloc_text(PAGE, BBImageManifest) +#pragma alloc_text(PAGE, BBRvaToVa) + +/// +/// Map new user module +/// +/// Target process +/// Image path +/// Image buffer +/// Image buffer size +/// Buffer has image memory layout +/// Mapping flags +/// Init routine RVA +/// Init argument +/// Mapped image data +/// Status code +NTSTATUS BBMapUserImage( + IN PEPROCESS pProcess, + IN PUNICODE_STRING path, + IN PVOID buffer, IN ULONG_PTR size, + IN BOOLEAN asImage, + IN KMmapFlags flags, + IN ULONG initRVA, + IN PWCH initArg, + OUT PMODULE_DATA pImage + ) +{ + NTSTATUS status = STATUS_SUCCESS; + MMAP_CONTEXT context = { 0 }; + + ASSERT( pProcess != NULL ); + if (pProcess == NULL) + { + DPRINT( "BlackBone: %s: No process provided\n", __FUNCTION__ ); + return STATUS_INVALID_PARAMETER; + } + + context.pProcess = pProcess; + InitializeListHead( &context.modules ); + + DPRINT( "BlackBone: %s: Mapping image '%wZ' with flags 0x%X\n", __FUNCTION__, path, flags ); + + // Create or find worker thread + context.noThreads = (flags & KNoThreads) != 0; + status = context.noThreads ? BBFindWokerThread( &context ) : BBCreateWorkerThread( &context ); + if (NT_SUCCESS( status )) + { + SIZE_T mapSize = 0x2000; + status = ZwAllocateVirtualMemory( ZwCurrentProcess(), &context.userMem, 0, &mapSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + } + + // Create sync event + if (NT_SUCCESS( status )) + { + OBJECT_ATTRIBUTES eventAttr = { 0 }; + InitializeObjectAttributes( &eventAttr, 0, 0, 0, 0 ); + status = ZwCreateEvent( &context.hSync, EVENT_ALL_ACCESS, &eventAttr, NotificationEvent, FALSE ); + if (NT_SUCCESS( status )) + status = ObReferenceObjectByHandle( context.hSync, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode, &context.pSync, NULL ); + + if (!NT_SUCCESS( status )) + DPRINT( "BlackBone: %s: Failed to create sync event. Status 0x%X\n", __FUNCTION__, status ); + + UNICODE_STRING ustrNtdll; + RtlUnicodeStringInit( &ustrNtdll, L"ntdll.dll" ); + + PVOID pNtdll = BBGetUserModule( context.pProcess, &ustrNtdll, PsGetProcessWow64Process( pProcess ) != NULL ); + + context.pSetEvent = BBGetModuleExport( pNtdll, "NtSetEvent", pProcess, NULL ); + context.pLoadImage = BBGetModuleExport( pNtdll, "LdrLoadDll", pProcess, NULL ); + } + + // Map module + if (NT_SUCCESS( status )) + status = BBFindOrMapModule( pProcess, path, buffer, size, asImage, flags, &context, pImage ); + + // Enable exceptions for WOW64 process + if (NT_SUCCESS( status ) && !(flags & KNoExceptions)) + { + if (dynData.KExecOpt != 0) + { + PKEXECUTE_OPTIONS pExecOpt = (PKEXECUTE_OPTIONS)((PUCHAR)pProcess + dynData.KExecOpt); + + pExecOpt->Flags.ImageDispatchEnable = 1; + pExecOpt->Flags.ExecuteDispatchEnable = 1; + pExecOpt->Flags.Permanent = 1; + } + else + DPRINT( "BlackBone: %s: Invalid KEXECUTE_OPTIONS offset\n", __FUNCTION__ ); + } + + // Rebase process + if (NT_SUCCESS( status ) && flags & KRebaseProcess) + { + PPEB pPeb = (PPEB)PsGetProcessPeb( pProcess ); + PPEB32 pPeb32 = (PPEB32)PsGetProcessWow64Process( pProcess ); + + pPeb->ImageBaseAddress = pImage->baseAddress; + if (pPeb32) + pPeb32->ImageBaseAddress = (ULONG)(ULONG_PTR)pImage->baseAddress; + } + + // Run module initializers + if (NT_SUCCESS( status )) + { + __try{ + status = BBCallInitializers( &context, (flags & KNoTLS) != 0 ); + } + __except (EXCEPTION_EXECUTE_HANDLER) { + status = GetExceptionCode(); + DPRINT( "BlackBone: %s: Exception during initialization phase.Exception code 0x%X\n", __FUNCTION__, status ); + } + } + + // Run user initializer + if (NT_SUCCESS( status ) && initRVA != 0) + { + PVOID pInitRoutine = (PUCHAR)pImage->baseAddress + initRVA; + memcpy( context.userMem->buffer, initArg, 512 * sizeof( WCHAR ) ); + BBCallRoutine( FALSE, &context, pInitRoutine, 1, context.userMem->buffer ); + } + + // + // Cleanup + // + + // Event + if (context.pSync) + ObDereferenceObject( context.pSync ); + + if (context.hSync && !BBCheckProcessTermination( PsGetCurrentProcess() )) + ZwClose( context.hSync ); + + // Worker thread + if (context.pWorker) + ObDereferenceObject( context.pWorker ); + + if (context.hWorker) + { + LARGE_INTEGER timeout = { 0 }; + timeout.QuadPart = -(10ll * 10 * 1000); // 10 ms + ZwTerminateThread( context.hWorker, 0 ); + ZwWaitForSingleObject( context.hWorker, TRUE, &timeout ); + ZwClose( context.hWorker ); + } + + // Worker code buffer + if (context.pWorkerBuf) + { + SIZE_T mapSize = 0; + ZwFreeVirtualMemory( ZwCurrentProcess(), &context.pWorkerBuf, &mapSize, MEM_RELEASE ); + } + + // Code buffer + if (context.userMem) + { + SIZE_T mapSize = 0; + ZwFreeVirtualMemory( ZwCurrentProcess(), &context.userMem, &mapSize, MEM_RELEASE ); + } + + // Cleanup module list + while (!IsListEmpty( &context.modules )) + { + PVOID pListEntry = context.modules.Flink; + PMODULE_DATA pEntry = (PMODULE_DATA)CONTAINING_RECORD( pListEntry, MODULE_DATA, link ); + + RemoveHeadList( &context.modules ); + + RtlFreeUnicodeString( &pEntry->fullPath ); + ExFreePoolWithTag( pListEntry, BB_POOL_TAG ); + } + + return status; +} + +/// +/// Map new module or return existing +/// +/// Target process +/// Image path +/// Image buffer +/// Image buffer size +/// Buffer has image memory layout +/// Mapping flags +/// Manual map context +/// Mapped image data +/// Status code +NTSTATUS BBFindOrMapModule( + IN PEPROCESS pProcess, + IN PUNICODE_STRING path, + IN PVOID buffer, IN ULONG_PTR size, + IN BOOLEAN asImage, + IN KMmapFlags flags, + IN PMMAP_CONTEXT pContext, + OUT PMODULE_DATA pImage + ) +{ + NTSTATUS status = STATUS_SUCCESS; + PMODULE_DATA pLocalImage = NULL; + PIMAGE_NT_HEADERS pHeaders = NULL; + BOOLEAN wow64 = PsGetProcessWow64Process( pProcess ) != NULL; + + UNREFERENCED_PARAMETER( size ); + + // Allocate image context record + pLocalImage = ExAllocatePoolWithTag( PagedPool, sizeof( MODULE_DATA ), BB_POOL_TAG ); + RtlZeroMemory( pLocalImage, sizeof( MODULE_DATA ) ); + + BBSafeInitString( &pLocalImage->fullPath, path ); + BBStripPath( &pLocalImage->fullPath, &pLocalImage->name ); + pLocalImage->flags = flags; + + // Check if image is already loaded + pLocalImage->type = wow64 ? mt_mod32 : mt_mod64; + PMODULE_DATA pFoundMod = BBLookupMappedModule( &pContext->modules, &pLocalImage->name, pLocalImage->type ); + if (pFoundMod != NULL) + { + RtlFreeUnicodeString( &pLocalImage->fullPath ); + ExFreePoolWithTag( pLocalImage, BB_POOL_TAG ); + + *pImage = *pFoundMod; + return STATUS_SUCCESS; + } + + DPRINT( "BlackBone: %s: Loading image %wZ\n", __FUNCTION__, &pLocalImage->fullPath ); + + // Load image info + if (buffer == NULL) + { + status = BBLoadLocalImage( path, &pLocalImage->localBase ); + asImage = FALSE; + } + else + pLocalImage->localBase = buffer; + + // Validate PE + if (NT_SUCCESS( status )) + { + pHeaders = RtlImageNtHeader( pLocalImage->localBase ); + if (!pHeaders) + status = STATUS_INVALID_IMAGE_FORMAT; + } + + // Prepare activation context + if (!(flags & KNoSxS) && NT_SUCCESS( status )) + { + LONG manifestID = 0; + ULONG_PTR manifestSize = 0; + PVOID pManifest = BBImageManifest( pLocalImage->localBase, &manifestSize, &manifestID ); + if (pManifest && manifestID != 0) + { + // Save manifest into tmp file + if (buffer != NULL) + { + UNICODE_STRING manifestPathNt = { 0 }; + UNICODE_STRING manifestPath = { 0 }; + NTSTATUS status2 = STATUS_SUCCESS; + HANDLE hFile = NULL; + OBJECT_ATTRIBUTES obAttr = { 0 }; + IO_STATUS_BLOCK statusBlock = { 0 }; + + BBSafeAllocateString( &manifestPath, 512 ); + RtlInitUnicodeString( &manifestPathNt, L"\\SystemRoot\\Temp\\BBImage.manifest" ); + InitializeObjectAttributes( &obAttr, &manifestPathNt, OBJ_KERNEL_HANDLE, NULL, NULL ); + + status2 = ZwCreateFile( + &hFile, FILE_WRITE_DATA | DELETE | SYNCHRONIZE, &obAttr, + &statusBlock, NULL, FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ, FILE_SUPERSEDE, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 + ); + + if (NT_SUCCESS( status2 )) + { + status2 = ZwWriteFile( hFile, NULL, NULL, NULL, &statusBlock, pManifest, (ULONG)manifestSize, NULL, NULL ); + ZwClose( hFile ); + } + + if (NT_SUCCESS( status2 )) + { + // Cast path + RtlUnicodeStringPrintf( &manifestPath, L"%ls\\%ls", SharedUserData->NtSystemRoot, L"\\Temp\\BBImage.manifest" ); + BBPrepareACTX( &manifestPath, FALSE, manifestID, pContext ); + } + else + DPRINT( "BlackBone: %s: Failed to create temporary manifest. Status code: 0x%X\n", __FUNCTION__, status2 ); + + ZwDeleteFile( &obAttr ); + RtlFreeUnicodeString( &manifestPath ); + } + else + BBPrepareACTX( path, TRUE, manifestID, pContext ); + } + } + + + // Allocate memory in target process + if (NT_SUCCESS( status )) + { + // Allocate physical memory + if (flags & KHideVAD) + { + ALLOCATE_FREE_MEMORY request = { 0 }; + ALLOCATE_FREE_MEMORY_RESULT mapResult = { 0 }; + + request.pid = (ULONG)(ULONG_PTR)PsGetProcessId( pProcess ); + request.allocate = TRUE; + request.physical = TRUE; + request.protection = PAGE_EXECUTE_READWRITE; + request.size = HEADER_VAL_T( pHeaders, SizeOfImage ); + + status = BBAllocateFreePhysical( pProcess, &request, &mapResult ); + if (NT_SUCCESS( status )) + { + pLocalImage->baseAddress = (PUCHAR)mapResult.address; + pLocalImage->size = mapResult.size; + } + } + else + { + pLocalImage->baseAddress = (PUCHAR)HEADER_VAL_T( pHeaders, ImageBase ); + pLocalImage->size = HEADER_VAL_T( pHeaders, SizeOfImage ); + status = ZwAllocateVirtualMemory( ZwCurrentProcess(), &pLocalImage->baseAddress, 0, &pLocalImage->size, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + + // Retry with arbitrary base + if (!NT_SUCCESS( status )) + { + pLocalImage->baseAddress = NULL; + pLocalImage->size = HEADER_VAL_T( pHeaders, SizeOfImage ); + status = ZwAllocateVirtualMemory( ZwCurrentProcess(), &pLocalImage->baseAddress, 0, &pLocalImage->size, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + } + } + } + + // Copy image memory + if (NT_SUCCESS( status )) + { + // Copy header + RtlCopyMemory( pLocalImage->baseAddress, pLocalImage->localBase, HEADER_VAL_T( pHeaders, SizeOfHeaders ) ); + + // + // Copy sections + // + PIMAGE_SECTION_HEADER pFirstSection = (PIMAGE_SECTION_HEADER)(pHeaders + 1); + if (IMAGE32( pHeaders )) + pFirstSection = (PIMAGE_SECTION_HEADER)((PIMAGE_NT_HEADERS32)pHeaders + 1); + + for (PIMAGE_SECTION_HEADER pSection = pFirstSection; + pSection < pFirstSection + pHeaders->FileHeader.NumberOfSections; + pSection++) + { + // Skip invalid sections + if (!(pSection->Characteristics & (IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE)) || + pSection->SizeOfRawData == 0) + { + continue; + } + + RtlCopyMemory( + pLocalImage->baseAddress + pSection->VirtualAddress, + pLocalImage->localBase + pSection->PointerToRawData, + pSection->SizeOfRawData + ); + } + } + + // Relocate image + if (NT_SUCCESS( status )) + { + status = LdrRelocateImage( pLocalImage->baseAddress, STATUS_SUCCESS, STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT ); + if (!NT_SUCCESS( status )) + DPRINT( "BlackBone: %s: Failed to relocate image '%wZ'. Status: 0x%X\n", __FUNCTION__, path, status ); + } + + InsertHeadList( &pContext->modules, &pLocalImage->link ); + + // Resolve imports + if (NT_SUCCESS( status )) + status = BBResolveImageRefs( pLocalImage->baseAddress, FALSE, pProcess, IMAGE32( pHeaders ), pContext, flags ); + + // Set image memory protection + if (NT_SUCCESS( status )) + { + if (flags & KHideVAD) + { + status = BBProtectVAD( pProcess, (ULONG_PTR)pLocalImage->baseAddress, MM_ZERO_ACCESS ); + } + else + { + SIZE_T tmpSize = 0; + + // Protect header + tmpSize = HEADER_VAL_T( pHeaders, SizeOfHeaders ); + status = ZwProtectVirtualMemory( ZwCurrentProcess(), &pLocalImage->baseAddress, &tmpSize, PAGE_READONLY, NULL ); + + // + // Protect sections + // + PIMAGE_SECTION_HEADER pFirstSection = (PIMAGE_SECTION_HEADER)(pHeaders + 1); + if (IMAGE32( pHeaders )) + pFirstSection = (PIMAGE_SECTION_HEADER)((PIMAGE_NT_HEADERS32)pHeaders + 1); + + for (PIMAGE_SECTION_HEADER pSection = pFirstSection; + pSection < pFirstSection + pHeaders->FileHeader.NumberOfSections; + pSection++) + { + ULONG prot = BBCastSectionProtection( pSection->Characteristics, FALSE /*!(flags & KNoExceptions) && wow64*/ ); + PUCHAR pAddr = pLocalImage->baseAddress + pSection->VirtualAddress; + tmpSize = pSection->Misc.VirtualSize; + + // Decommit pages with NO_ACCESS protection + if (prot != PAGE_NOACCESS) + status |= ZwProtectVirtualMemory( ZwCurrentProcess(), &pAddr, &tmpSize, prot, NULL ); + else + ZwFreeVirtualMemory( ZwCurrentProcess(), &pAddr, &tmpSize, MEM_DECOMMIT ); + } + } + } + + // Setup security cookie + if (NT_SUCCESS( status )) + BBCreateCookie( pLocalImage->baseAddress ); + + // Enable SEH support for x64 image + if (!(flags & KNoExceptions) && NT_SUCCESS( status ) && wow64 == FALSE) + BBCreateExceptionTable64( pContext, pLocalImage->baseAddress ); + + // + // Cleanup + // + + + // Free system-space image memory + if (pLocalImage->localBase) + { + ExFreePoolWithTag( pLocalImage->localBase, BB_POOL_TAG ); + pLocalImage->localBase = NULL; + } + + if (NT_SUCCESS( status )) + { + // Copy image info + if (pImage) + *pImage = *pLocalImage; + } + else if (pLocalImage) + { + // Remove entry from list + RemoveEntryList( &pLocalImage->link ); + + // Delete remote image + if (pLocalImage->baseAddress) + { + if (flags & KHideVAD) + { + ALLOCATE_FREE_MEMORY request = { 0 }; + ALLOCATE_FREE_MEMORY_RESULT mapResult = { 0 }; + + request.pid = (ULONG)(ULONG_PTR)PsGetProcessId( pProcess ); + request.allocate = FALSE; + request.physical = TRUE; + + BBAllocateFreePhysical( pProcess, &request, &mapResult ); + } + else + { + SIZE_T tmpSize = 0; + ZwFreeVirtualMemory( ZwCurrentProcess(), &pLocalImage->baseAddress, &tmpSize, MEM_RELEASE ); + } + } + + RtlFreeUnicodeString( &pLocalImage->fullPath ); + ExFreePoolWithTag( pLocalImage, BB_POOL_TAG ); + } + + return status; +} + +/// +/// Resolve import table and load missing dependencies +/// +/// Target image base +/// If TRUE - image is driver +/// Target process +/// Iamge is 32bit image +/// Manual map context +/// Status code +NTSTATUS BBResolveImageRefs( + IN PVOID pImageBase, + IN BOOLEAN systemImage, + IN PEPROCESS pProcess, + IN BOOLEAN wow64Image, + IN PMMAP_CONTEXT pContext, + IN KMmapFlags flags + ) +{ + NTSTATUS status = STATUS_SUCCESS; + ULONG impSize = 0; + PIMAGE_NT_HEADERS pHeader = RtlImageNtHeader( pImageBase ); + PIMAGE_IMPORT_DESCRIPTOR pImportTbl = RtlImageDirectoryEntryToData( pImageBase, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &impSize ); + + // No import libs + if (pImportTbl == NULL) + return STATUS_SUCCESS; + + for (; pImportTbl->Name && NT_SUCCESS( status ); ++pImportTbl) + { + PVOID pThunk = ((PUCHAR)pImageBase + (pImportTbl->OriginalFirstThunk ? pImportTbl->OriginalFirstThunk : pImportTbl->FirstThunk)); + UNICODE_STRING ustrImpDll = { 0 }; + UNICODE_STRING resolved = { 0 }; + UNICODE_STRING resolvedName = { 0 }; + ANSI_STRING strImpDll = { 0 }; + ULONG IAT_Index = 0; + PCCHAR impFunc = NULL; + union + { + PVOID address; + PKLDR_DATA_TABLE_ENTRY ldrEntry; + } pModule = { 0 }; + + RtlInitAnsiString( &strImpDll, (PCHAR)pImageBase + pImportTbl->Name ); + RtlAnsiStringToUnicodeString( &ustrImpDll, &strImpDll, TRUE ); + + // Resolve image name + if(!systemImage) + { + status = BBResolveImagePath( pContext, pProcess, 0, &ustrImpDll, NULL, &resolved ); + BBStripPath( &resolved, &resolvedName ); + + // Something went terribly wrong + if (status == STATUS_UNHANDLED_EXCEPTION) + { + RtlFreeUnicodeString( &ustrImpDll ); + RtlFreeUnicodeString( &resolved ); + + return STATUS_NOT_FOUND; + } + } + else + { + BBSafeInitString( &resolved, &ustrImpDll ); + } + + // Get import module + pModule.address = systemImage ? BBGetSystemModule( &ustrImpDll, NULL ) : BBGetUserModule( pProcess, &resolvedName, wow64Image ); + + // Load missing import + if (!pModule.address && !systemImage) + { + if (flags & KManualImports) + { + MODULE_DATA modData = { 0 }; + + status = BBFindOrMapModule( pProcess, &resolved, NULL, 0, FALSE, flags | KNoSxS, pContext, &modData ); + if (NT_SUCCESS( status )) + pModule.address = modData.baseAddress; + } + else + { + DPRINT( "BlackBone: %s: Loading missing import %wZ\n", __FUNCTION__, &resolved ); + + if (IMAGE64( pHeader )) + { + RtlInitEmptyUnicodeString( &pContext->userMem->ustr, pContext->userMem->buffer, sizeof( pContext->userMem->buffer ) ); + RtlCopyUnicodeString( &pContext->userMem->ustr, &resolvedName ); + } + else + { + pContext->userMem->ustr32.Buffer = (ULONG)(ULONG_PTR)pContext->userMem->buffer; + pContext->userMem->ustr32.MaximumLength = sizeof( pContext->userMem->buffer ); + pContext->userMem->ustr32.Length = resolvedName.Length; + + RtlZeroMemory( pContext->userMem->buffer, sizeof( pContext->userMem->buffer ) ); + memcpy( pContext->userMem->buffer, resolvedName.Buffer, resolvedName.Length ); + } + + // Invoke LdrLoadDll + pContext->userMem->status = STATUS_SUCCESS; + + // Calling LdrLoadDll in worker thread breaks further APC delivery, so use new thread + BBCallRoutine( !pContext->noThreads, pContext, pContext->pLoadImage, 4, NULL, NULL, &pContext->userMem->ustr, &pContext->userMem->ptr ); + pModule.address = pContext->userMem->ptr; + if (!pModule.address) + status = pContext->userMem->status; + } + } + + // Failed to load + if (!pModule.address) + { + DPRINT( "BlackBone: %s: Failed to load import '%wZ'. Status code: 0x%X\n", __FUNCTION__, ustrImpDll, status ); + RtlFreeUnicodeString( &ustrImpDll ); + RtlFreeUnicodeString( &resolved ); + + return STATUS_NOT_FOUND; + } + + while (THUNK_VAL_T( pHeader, pThunk, u1.AddressOfData )) + { + PIMAGE_IMPORT_BY_NAME pAddressTable = (PIMAGE_IMPORT_BY_NAME)((PUCHAR)pImageBase + THUNK_VAL_T( pHeader, pThunk, u1.AddressOfData )); + PVOID pFunc = NULL; + + // import by name + if (THUNK_VAL_T( pHeader, pThunk, u1.AddressOfData ) < (IMAGE64( pHeader ) ? IMAGE_ORDINAL_FLAG64 : IMAGE_ORDINAL_FLAG32) && + pAddressTable->Name[0]) + { + impFunc = pAddressTable->Name; + } + // import by ordinal + else + { + impFunc = (PCCHAR)(THUNK_VAL_T( pHeader, pThunk, u1.AddressOfData ) & 0xFFFF); + } + + pFunc = BBGetModuleExport( + systemImage ? pModule.ldrEntry->DllBase : pModule.address, + impFunc, + systemImage ? NULL : pContext->pProcess, + &resolved + ); + + // No export found + if (!pFunc) + { + if (THUNK_VAL_T( pHeader, pThunk, u1.AddressOfData ) < (IMAGE64( pHeader ) ? IMAGE_ORDINAL_FLAG64 : IMAGE_ORDINAL_FLAG32) && pAddressTable->Name[0]) + DPRINT( "BlackBone: %s: Failed to resolve import '%wZ' : '%s'\n", __FUNCTION__, ustrImpDll, pAddressTable->Name ); + else + DPRINT( "BlackBone: %s: Failed to resolve import '%wZ' : '%d'\n", __FUNCTION__, ustrImpDll, THUNK_VAL_T( pHeader, pThunk, u1.AddressOfData ) & 0xFFFF ); + + status = STATUS_NOT_FOUND; + break; + } + + if(IMAGE64( pHeader )) + { + // Save address to IAT + if (pImportTbl->FirstThunk) + *(PULONG_PTR)((PUCHAR)pImageBase + pImportTbl->FirstThunk + IAT_Index) = (ULONG_PTR)pFunc; + // Save address to OrigianlFirstThunk + else + *(PULONG_PTR)((PUCHAR)pImageBase + THUNK_VAL_T( pHeader, pThunk, u1.AddressOfData )) = (ULONG_PTR)pFunc; + } + else + { + // Save address to IAT + if (pImportTbl->FirstThunk) + *(PULONG)((PUCHAR)pImageBase + pImportTbl->FirstThunk + IAT_Index) = (ULONG)(ULONG_PTR)pFunc; + // Save address to OrigianlFirstThunk + else + *(PULONG)((PUCHAR)pImageBase + THUNK_VAL_T( pHeader, pThunk, u1.AddressOfData )) = (ULONG)(ULONG_PTR)pFunc; + } + + // Go to next entry + pThunk = (PUCHAR)pThunk + (IMAGE64( pHeader ) ? sizeof( IMAGE_THUNK_DATA64 ) : sizeof( IMAGE_THUNK_DATA32 )); + IAT_Index += (IMAGE64( pHeader ) ? sizeof( ULONGLONG ) : sizeof( ULONG )); + } + + RtlFreeUnicodeString( &ustrImpDll ); + RtlFreeUnicodeString( &resolved ); + } + + return status; +} + + +/// +/// Try to resolve image via API SET map +/// +/// Target process. Must be run in the context of this process +/// Name to resolve +/// Parent image name +/// Resolved name if any +/// Status code +NTSTATUS BBResolveApiSet( + IN PEPROCESS pProcess, + IN PUNICODE_STRING name, + IN PUNICODE_STRING baseImage, + OUT PUNICODE_STRING resolved + ) +{ + NTSTATUS status = STATUS_NOT_FOUND; + PPEB32 pPeb32 = (PPEB32)PsGetProcessWow64Process( pProcess ); + PPEB pPeb = PsGetProcessPeb( pProcess ); + PAPISET_NAMESPACE_ARRAY pApiSetMap = (PAPISET_NAMESPACE_ARRAY)(pPeb32 != NULL ? (PVOID)pPeb32->ApiSetMap : pPeb->ApiSetMap); + + // Invalid name + if ( name == NULL || name->Length < 4 * sizeof(WCHAR) || name->Buffer == NULL || + (memcmp( name->Buffer, L"api-", 4 ) != 0 && memcmp( name->Buffer, L"ext-", 4 ) != 0)) + return STATUS_NOT_FOUND; + + // Iterate api set map + for (ULONG i = 0; i < pApiSetMap->Count; i++) + { + PAPISET_NAMESPACE_ENTRY pDescriptor = NULL; + PAPISET_VALUE_ARRAY pHostArray = NULL; + wchar_t apiNameBuf[255] = { 0 }; + UNICODE_STRING apiName = { 0 }; + +#ifdef _WIN10_ + pDescriptor = (PAPISET_NAMESPACE_ENTRY)((PUCHAR)pApiSetMap + pApiSetMap->End + i * sizeof( API_SET_NAMESPACE_ENTRY_10 )); + pHostArray = (PAPISET_VALUE_ARRAY)((PUCHAR)pApiSetMap + pApiSetMap->Start + sizeof( API_SET_VALUE_ARRAY_10 ) * pDescriptor->Size); + + memcpy( apiNameBuf, (PUCHAR)pApiSetMap + pHostArray->NameOffset, pHostArray->NameLength ); +#else + pDescriptor = pApiSetMap->Array + i; + memcpy( apiNameBuf, (PUCHAR)pApiSetMap + pDescriptor->NameOffset, pDescriptor->NameLength ); +#endif + RtlUnicodeStringInit( &apiName, apiNameBuf ); + + // Check if this is a target api + if (BBSafeSearchString( name, &apiName, TRUE ) >= 0) + { + PAPISET_VALUE_ENTRY pHost = NULL; + wchar_t apiHostNameBuf[255] = { 0 }; + UNICODE_STRING apiHostName = { 0 }; + +#ifdef _WIN10_ + pHost = (PAPISET_VALUE_ENTRY)((PUCHAR)pApiSetMap + pHostArray->DataOffset); +#else + pHostArray = (PAPISET_VALUE_ARRAY)((PUCHAR)pApiSetMap + pDescriptor->DataOffset); + pHost = pHostArray->Array; +#endif + // Sanity check + if (pHostArray->Count < 1) + return STATUS_NOT_FOUND; + + memcpy( apiHostNameBuf, (PUCHAR)pApiSetMap + pHost->ValueOffset, pHost->ValueLength ); + RtlUnicodeStringInit( &apiHostName, apiHostNameBuf ); + + // No base name redirection + if (pHostArray->Count == 1 || baseImage == NULL || baseImage->Buffer[0] == 0) + { + BBSafeInitString( resolved, &apiHostName ); + return STATUS_SUCCESS; + } + // Redirect accordingly to base name + else + { + UNICODE_STRING baseImageName = { 0 }; + BBStripPath( baseImage, &baseImageName ); + + if (RtlCompareUnicodeString( &apiHostName, &baseImageName, TRUE ) == 0) + { + memset( apiHostNameBuf, 0, sizeof( apiHostNameBuf ) ); + memcpy( apiHostNameBuf, (PUCHAR)pApiSetMap + pHost[1].ValueOffset, pHost[1].ValueLength ); + RtlCreateUnicodeString( resolved, apiHostNameBuf ); + return STATUS_SUCCESS; + } + else + { + BBSafeInitString( resolved, &apiHostName ); + return STATUS_SUCCESS; + } + } + } + } + + return status; +} + +/// +///Try to resolve image via SxS isolation +/// +/// Loader context. +/// Name to resolve +/// Resolved name if any +/// Status code +NTSTATUS BBResolveSxS( + IN PMMAP_CONTEXT pContext, + IN PUNICODE_STRING name, + OUT PUNICODE_STRING resolved + ) +{ + NTSTATUS status = STATUS_NOT_FOUND; + UNICODE_STRING ustrNtdll = { 0 }; + BOOLEAN wow64 = PsGetProcessWow64Process( pContext->pProcess ) != NULL; + + typedef struct _STRIBG_BUF + { + union + { + UNICODE_STRING name1; + UNICODE_STRING32 name132; + }; + union + { + UNICODE_STRING name2; + UNICODE_STRING32 name232; + }; + union + { + UNICODE_STRING origName; + UNICODE_STRING32 origName32; + }; + union + { + PUNICODE_STRING pResolved; + ULONG pResolved32; + }; + wchar_t origBuf[0x100]; + wchar_t staticBuf[0x200]; + } STRIBG_BUF, *PSTRIBG_BUF; + + PSTRIBG_BUF pStringBuf = (PSTRIBG_BUF)pContext->userMem->buffer; + + RtlUnicodeStringInit( &ustrNtdll, L"ntdll.dll" ); + + PVOID hNtdll = BBGetUserModule( pContext->pProcess, &ustrNtdll, wow64 ); + PVOID pQueryName = BBGetModuleExport( hNtdll, "RtlDosApplyFileIsolationRedirection_Ustr", pContext->pProcess, NULL ); + + if (pQueryName == NULL) + { + DPRINT( "BlackBone: %s: Failed to get RtlDosApplyFileIsolationRedirection_Ustr\n", __FUNCTION__ ); + return STATUS_NOT_FOUND; + } + + RtlZeroMemory( pStringBuf->origBuf, sizeof( pStringBuf->origBuf ) ); + RtlZeroMemory( pStringBuf->staticBuf, sizeof( pStringBuf->staticBuf ) ); + + // Fill params + memcpy( pStringBuf->origBuf, name->Buffer, name->Length ); + if (wow64) + { + pStringBuf->origName32.Buffer = (ULONG)(ULONG_PTR)pStringBuf->origBuf; + pStringBuf->origName32.MaximumLength = sizeof( pStringBuf->origBuf ); + pStringBuf->origName32.Length = name->Length; + + pStringBuf->name132.Buffer = (ULONG)(ULONG_PTR)pStringBuf->staticBuf; + pStringBuf->name132.MaximumLength = sizeof( pStringBuf->staticBuf ); + pStringBuf->name132.Length = 0; + + pStringBuf->name232.Buffer = 0; + pStringBuf->name232.Length = pStringBuf->name232.MaximumLength = 0; + } + else + { + RtlInitUnicodeString( &pStringBuf->origName, pStringBuf->origBuf ); + RtlInitEmptyUnicodeString( &pStringBuf->name1, pStringBuf->staticBuf, sizeof( pStringBuf->staticBuf ) ); + RtlInitEmptyUnicodeString( &pStringBuf->name2, NULL, 0 ); + } + + + // Prevent some unpredictable shit + __try + { + // RtlDosApplyFileIsolationRedirection_Ustr + status = BBCallRoutine( + FALSE, pContext, pQueryName, 9, + (PVOID)TRUE, &pStringBuf->origName, NULL, + &pStringBuf->name1, &pStringBuf->name2, &pStringBuf->pResolved, + NULL, NULL, NULL + ); + + if (NT_SUCCESS( status ) && NT_SUCCESS( pContext->userMem->status )) + { + if (wow64) + { + ULONG tmp = ((PUNICODE_STRING32)pStringBuf->pResolved32)->Buffer; + pStringBuf->pResolved = &pStringBuf->name1; + pStringBuf->pResolved->Buffer = (PWCH)tmp; + } + + RtlDowncaseUnicodeString( resolved, pStringBuf->pResolved, TRUE ); + // TODO: name2 cleanup + } + + return NT_SUCCESS( status ) ? pContext->userMem->status : status; + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + DPRINT( "BlackBone: %s: Exception. Code: 0x%X\n", __FUNCTION__, GetExceptionCode() ); + return STATUS_UNHANDLED_EXCEPTION; + } +} + +/// +/// Resolve image name to fully qualified path +/// +/// Loader context +/// Target process. Must be running in the context of this process +/// Flags +/// Image name to resolve +/// Base image name for API SET translation +/// Resolved image path +/// Status code +NTSTATUS BBResolveImagePath( + IN PMMAP_CONTEXT pContext, + IN PEPROCESS pProcess, + IN ResolveFlags flags, + IN PUNICODE_STRING path, + IN PUNICODE_STRING baseImage, + OUT PUNICODE_STRING resolved + ) +{ + NTSTATUS status = STATUS_SUCCESS; + UNICODE_STRING pathLow = { 0 }; + UNICODE_STRING filename = { 0 }; + UNICODE_STRING fullResolved = { 0 }; + + UNREFERENCED_PARAMETER( baseImage ); + + ASSERT( pProcess != NULL && path != NULL && resolved != NULL ); + if (pProcess == NULL || path == NULL || resolved == NULL) + { + DPRINT( "BlackBone: %s: Missing parameter\n", __FUNCTION__ ); + return STATUS_INVALID_PARAMETER; + } + + RtlDowncaseUnicodeString( &pathLow, path, TRUE ); + BBStripPath( &pathLow, &filename ); + + // API Schema + if (NT_SUCCESS( BBResolveApiSet( pProcess, &filename, baseImage, resolved ) )) + { + BBSafeAllocateString( &fullResolved, 512 ); + + // Perpend system directory + if (PsGetProcessWow64Process( pProcess ) != NULL) + RtlUnicodeStringCatString( &fullResolved, L"\\SystemRoot\\syswow64\\" ); + else + RtlUnicodeStringCatString( &fullResolved, L"\\SystemRoot\\system32\\" ); + + RtlUnicodeStringCat( &fullResolved, resolved ); + RtlFreeUnicodeString( resolved ); + RtlFreeUnicodeString( &pathLow ); + + //DPRINT( "BlackBone: %s: Resolved image '%wZ' to '%wZ' by ApiSetSchema\n", __FUNCTION__, path, fullResolved ); + + *resolved = fullResolved; + return STATUS_SUCCESS; + } + + // Api schema only + if (flags & KApiShemaOnly) + goto skip; + + if (flags & KSkipSxS) + goto SkipSxS; + + // SxS + status = BBResolveSxS( pContext, &filename, resolved ); + if (pContext && NT_SUCCESS( status )) + { + BBSafeAllocateString( &fullResolved, 1024 ); + RtlUnicodeStringCatString( &fullResolved, L"\\??\\" ); + RtlUnicodeStringCat( &fullResolved, resolved ); + + RtlFreeUnicodeString( resolved ); + RtlFreeUnicodeString( &pathLow ); + + *resolved = fullResolved; + return STATUS_SUCCESS; + } + else if (status == STATUS_UNHANDLED_EXCEPTION) + { + *resolved = pathLow; + return status; + } + else + status = STATUS_SUCCESS; + +SkipSxS: + BBSafeAllocateString( &fullResolved, 0x400 ); + + // + // Executable directory + // + ULONG bytes = 0; + if (NT_SUCCESS( ZwQueryInformationProcess( ZwCurrentProcess(), ProcessImageFileName, fullResolved.Buffer + 0x100, 0x200, &bytes ) )) + { + PUNICODE_STRING pPath = (PUNICODE_STRING)(fullResolved.Buffer + 0x100); + UNICODE_STRING parentDir = { 0 }; + BBStripFilename( pPath, &parentDir ); + + RtlCopyUnicodeString( &fullResolved, &parentDir ); + RtlUnicodeStringCatString( &fullResolved, L"\\" ); + RtlUnicodeStringCat( &fullResolved, &filename ); + + if (NT_SUCCESS( BBFileExists( &fullResolved ) )) + { + RtlFreeUnicodeString( resolved ); + RtlFreeUnicodeString( &pathLow ); + + *resolved = fullResolved; + return STATUS_SUCCESS; + } + } + + fullResolved.Length = 0; + RtlZeroMemory( fullResolved.Buffer, 0x400 ); + + // + // System directory + // + if (PsGetProcessWow64Process( pProcess ) != NULL) + RtlUnicodeStringCatString( &fullResolved, L"\\SystemRoot\\SysWOW64\\" ); + else + RtlUnicodeStringCatString( &fullResolved, L"\\SystemRoot\\System32\\" ); + + RtlUnicodeStringCat( &fullResolved, &filename ); + if (NT_SUCCESS( BBFileExists( &fullResolved ) )) + { + RtlFreeUnicodeString( resolved ); + RtlFreeUnicodeString( &pathLow ); + + *resolved = fullResolved; + return STATUS_SUCCESS; + } + + RtlFreeUnicodeString( &fullResolved ); + + // Nothing found +skip: + *resolved = pathLow; + return status; +} + +/// +/// Call module initialization routines +/// +/// Map context +/// If TRUE - TLS callbacks will no be invoked +/// Status code +NTSTATUS BBCallInitializers( IN PMMAP_CONTEXT pContext, IN BOOLEAN noTLS ) +{ + for (PLIST_ENTRY pListEntry = pContext->modules.Flink; pListEntry != &pContext->modules; pListEntry = pListEntry->Flink) + { + PMODULE_DATA pEntry = (PMODULE_DATA)CONTAINING_RECORD( pListEntry, MODULE_DATA, link ); + if (pEntry->initialized) + continue; + + DPRINT( "BlackBone: %s: Calling '%wZ' initializer\n", __FUNCTION__, pEntry->name ); + + PIMAGE_NT_HEADERS pHeaders = RtlImageNtHeader( pEntry->baseAddress ); + + if (noTLS == FALSE) + BBCallTlsInitializers( pContext, pEntry->baseAddress ); + + NTSTATUS status = STATUS_SUCCESS; + if (HEADER_VAL_T( pHeaders, AddressOfEntryPoint )) + { + PUCHAR entrypoint = pEntry->baseAddress + HEADER_VAL_T( pHeaders, AddressOfEntryPoint ); + status = BBCallRoutine( FALSE, pContext, entrypoint, 3, pEntry->baseAddress, (PVOID)1, NULL ); + } + + // Check if process is terminating + if (status != STATUS_SUCCESS && BBCheckProcessTermination( PsGetCurrentProcess() )) + { + DPRINT( "BlackBone: %s: Process is terminating, map aborted\n", __FUNCTION__ ); + return STATUS_PROCESS_IS_TERMINATING; + } + + // + // Wipe discardable sections + // + PIMAGE_SECTION_HEADER pFirstSection = (PIMAGE_SECTION_HEADER)(pHeaders + 1); + if (IMAGE32( pHeaders )) + pFirstSection = (PIMAGE_SECTION_HEADER)((PIMAGE_NT_HEADERS32)pHeaders + 1); + + for (PIMAGE_SECTION_HEADER pSection = pFirstSection; + pSection < pFirstSection + pHeaders->FileHeader.NumberOfSections; + pSection++) + { + if (!(pSection->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)) + continue; + + PVOID pBase = (PUCHAR)pEntry->baseAddress + pSection->VirtualAddress; + SIZE_T secSize = pSection->Misc.VirtualSize; + + if (pEntry->flags & KHideVAD) + { + RtlZeroMemory( pBase, secSize ); + } + else + { + if (NT_SUCCESS( ZwProtectVirtualMemory( ZwCurrentProcess(), &pBase, &secSize, PAGE_READWRITE, NULL ) )) + RtlZeroMemory( pBase, secSize ); + + ZwProtectVirtualMemory( ZwCurrentProcess(), &pBase, &secSize, PAGE_NOACCESS, NULL ); + ZwFreeVirtualMemory( ZwCurrentProcess(), &pBase, &secSize, MEM_DECOMMIT ); + } + } + + // Wipe header + if (pEntry->flags & KWipeHeader) + { + SIZE_T hdrSize = HEADER_VAL_T( pHeaders, SizeOfHeaders ); + + if (pEntry->flags & KHideVAD) + { + RtlZeroMemory( pEntry->baseAddress, hdrSize ); + } + else + { + PVOID pBase = pEntry->baseAddress; + if (NT_SUCCESS( ZwProtectVirtualMemory( ZwCurrentProcess(), &pBase, &hdrSize, PAGE_READWRITE, NULL ) )) + { + RtlZeroMemory( pEntry->baseAddress, hdrSize ); + ZwProtectVirtualMemory( ZwCurrentProcess(), &pBase, &hdrSize, PAGE_READONLY, NULL ); + } + else + DPRINT( "BlackBone: %s: Failed to wipe image header\n", __FUNCTION__ ); + } + } + + pEntry->initialized = TRUE; + } + + return STATUS_SUCCESS; +} + +/// +/// Call TLS callbacks +/// +/// Loader context +/// Target image base +void BBCallTlsInitializers( IN PMMAP_CONTEXT pContext, IN PVOID imageBase ) +{ + ULONG size = 0; + PIMAGE_NT_HEADERS pHeaders = RtlImageNtHeader( imageBase ); + if (!pHeaders) + return; + + // No TLS directory + PVOID pTLS = RtlImageDirectoryEntryToData( imageBase, TRUE, IMAGE_DIRECTORY_ENTRY_TLS, &size ); + if (!pTLS) + return; + + // Prepare static TLS a bit + // Still not compatible with LdrpQueueDeferredTlsData in Win8.1, but I'm tired of this shit + if (!pContext->tlsInitialized && TLS_VAL_T( pHeaders, pTLS, StartAddressOfRawData ) != 0) + { + PVOID pTLSMem = NULL; + SIZE_T tlsSize = 0x1000; + + if (NT_SUCCESS( ZwAllocateVirtualMemory( ZwCurrentProcess(), &pTLSMem, 0, &tlsSize, MEM_COMMIT, PAGE_READWRITE ) )) + { + PUCHAR pTeb64 = PsGetThreadTeb( pContext->pWorker ); + + // WOW64 + if (PsGetProcessWow64Process( pContext->pProcess ) != NULL) + { + // TEB32 is 2 pages after TEB64 + *(PULONG)(pTeb64 + 0x2000 + 0x2C) = (ULONG)(ULONG_PTR)pTLSMem; + *(PULONG)pTLSMem = (ULONG)TLS_VAL_T( pHeaders, pTLS, StartAddressOfRawData ); + } + // Native + else + { + *(PVOID*)(pTeb64 + 0x58) = pTLSMem; + *(PULONGLONG)pTLSMem = TLS_VAL_T( pHeaders, pTLS, StartAddressOfRawData ); + } + + DPRINT( "BlackBone: %s: Static TLS buffer: 0x%p\n", __FUNCTION__, pTLSMem ); + pContext->tlsInitialized = TRUE; + } + } + + for ( PUCHAR pCallback = (PUCHAR)TLS_VAL_T( pHeaders, pTLS, AddressOfCallBacks ); + ((IMAGE64( pHeaders ) ? *(PULONGLONG)pCallback : *(PULONG)pCallback)) != 0; + pCallback += IMAGE64( pHeaders ) ? sizeof( ULONGLONG ) : sizeof( ULONG )) + { + ULONG_PTR callback = IMAGE64( pHeaders ) ? *(PULONGLONG)pCallback : *(PULONG)pCallback; + BBCallRoutine( FALSE, pContext, (PVOID)callback, 3, imageBase, (PVOID)1, NULL ); + } +} + +/// +/// Create activation context +/// +/// Manifest path +/// Target file is a PE image +/// Manifest ID +/// Loader context +/// Status code +NTSTATUS BBPrepareACTX( IN PUNICODE_STRING pPath, IN BOOLEAN asImage, IN LONG manifestID, IN PMMAP_CONTEXT pContext ) +{ + NTSTATUS status = STATUS_SUCCESS; + UNICODE_STRING ustrKernel = { 0 }, ustrNtdll = { 0 }; + BOOLEAN wow64 = PsGetProcessWow64Process( pContext->pProcess ) != NULL; + + RtlUnicodeStringInit( &ustrKernel, L"kernel32.dll" ); + RtlUnicodeStringInit( &ustrNtdll, L"ntdll.dll" ); + + PVOID pCreateActCtxW = BBGetModuleExport( + BBGetUserModule( pContext->pProcess, &ustrKernel, wow64 ), + "CreateActCtxW", pContext->pProcess, NULL + ); + + if (!pCreateActCtxW) + { + DPRINT( "BlackBone: %s: Failed to get CreateActCtxW address\n", __FUNCTION__ ); + status = STATUS_NOT_FOUND; + } + + PVOID pActivateCtx = BBGetModuleExport( + BBGetUserModule( pContext->pProcess, &ustrNtdll, wow64 ), + "RtlActivateActivationContext", pContext->pProcess, NULL + ); + + if (!pActivateCtx) + { + DPRINT( "BlackBone: %s: Failed to get RtlActivateActivationContext address\n", __FUNCTION__ ); + status = STATUS_NOT_FOUND; + } + + // Generate activation context + if (NT_SUCCESS( status )) + { + RtlZeroMemory( pContext->userMem->buffer, sizeof( pContext->userMem->buffer ) ); + memcpy( pContext->userMem->buffer, pPath->Buffer, pPath->Length ); + + if (wow64 != FALSE) + { + RtlZeroMemory( &pContext->userMem->actx32, sizeof( pContext->userMem->actx32 ) ); + + pContext->userMem->actx32.cbSize = sizeof( ACTCTXW32 ); + pContext->userMem->actx32.lpSource = (ULONG)(ULONG_PTR)pContext->userMem->buffer; + if (asImage) + { + pContext->userMem->actx32.lpSource += 4 * sizeof( wchar_t ); + pContext->userMem->actx32.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID; + pContext->userMem->actx32.lpResourceName = (ULONG)(ULONG_PTR)MAKEINTRESOURCEW( manifestID ); + } + + BBCallRoutine( FALSE, pContext, pCreateActCtxW, 1, &pContext->userMem->actx32 ); + } + else + { + RtlZeroMemory( &pContext->userMem->actx, sizeof( pContext->userMem->actx ) ); + + pContext->userMem->actx.cbSize = sizeof( ACTCTXW ); + pContext->userMem->actx.lpSource = pContext->userMem->buffer; + if (asImage) + { + pContext->userMem->actx.lpSource += 4; + pContext->userMem->actx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID; + pContext->userMem->actx.lpResourceName = MAKEINTRESOURCEW( manifestID ); + } + + BBCallRoutine( FALSE, pContext, pCreateActCtxW, 1, &pContext->userMem->actx ); + } + + if (pContext->userMem->retVal32 != 0xFFFFFFFF) + { + pContext->userMem->hCTX = wow64 ? (PVOID)pContext->userMem->retVal32 : pContext->userMem->retVal; + } + else + { + DPRINT( "BlackBone: %s: CreateActCtxW failed\n", __FUNCTION__ ); + status = STATUS_SXS_CANT_GEN_ACTCTX; + } + } + + // Activate context + if (NT_SUCCESS( status )) + { + BBCallRoutine( FALSE, pContext, pActivateCtx, 3, NULL, pContext->userMem->hCTX, &pContext->userMem->hCookie ); + if (!NT_SUCCESS( pContext->userMem->status )) + { + DPRINT( "BlackBone: %s: RtlActivateActivationContext failed with code 0x%X\n", __FUNCTION__, pContext->userMem->status ); + status = pContext->userMem->status; + } + } + + return status; +} + +/// +/// Create exception table for x64 image +/// +/// Loader context +/// Image base +/// Status code +NTSTATUS BBCreateExceptionTable64( IN PMMAP_CONTEXT pContext, IN PVOID imageBase ) +{ + NTSTATUS status = STATUS_SUCCESS; + ULONG dirSize = 0; + _PIMAGE_RUNTIME_FUNCTION_ENTRY pExpTable = (_PIMAGE_RUNTIME_FUNCTION_ENTRY)RtlImageDirectoryEntryToData( + imageBase, TRUE, IMAGE_DIRECTORY_ENTRY_EXCEPTION, &dirSize + ); + + // Invoke RtlAddFunctionTable + if (pExpTable) + { + UNICODE_STRING ustrNtdll = { 0 }; + BOOLEAN wow64 = PsGetProcessWow64Process( pContext->pProcess ) != NULL; + + RtlUnicodeStringInit( &ustrNtdll, L"ntdll.dll" ); + + PVOID pAddTable = BBGetModuleExport( + BBGetUserModule( pContext->pProcess, &ustrNtdll, wow64 ), + "RtlAddFunctionTable", pContext->pProcess, NULL + ); + + if (!pAddTable) + { + DPRINT( "BlackBone: %s: Failed to get RtlAddFunctionTable address\n", __FUNCTION__ ); + return STATUS_NOT_FOUND; + } + + status = BBCallRoutine( FALSE, pContext, pAddTable, 3, pExpTable, (PVOID)(dirSize / sizeof( _IMAGE_RUNTIME_FUNCTION_ENTRY )), imageBase ); + if (NT_SUCCESS( status )) + { + if (pContext->userMem->retVal32 == FALSE) + DPRINT( "BlackBone: %s: RtlAddFunctionTable failed\n", __FUNCTION__ ); + } + else + DPRINT( "BlackBone: %s: Failed co call RtlAddFunctionTable. Status code: 0x%X\n", __FUNCTION__, status ); + + return status; + } + + return status; +} + +/// +/// Setup image security cookie +/// +/// Image base +/// Status code +NTSTATUS BBCreateCookie( IN PVOID imageBase ) +{ + NTSTATUS status = STATUS_SUCCESS; + PIMAGE_NT_HEADERS pHeader = RtlImageNtHeader( imageBase ); + if (pHeader) + { + ULONG cfgSize = 0; + PVOID pCfgDir = RtlImageDirectoryEntryToData( imageBase, TRUE, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &cfgSize ); + + // TODO: implement proper cookie algorithm + if (pCfgDir && CFG_DIR_VAL_T( pHeader, pCfgDir, SecurityCookie )) + { + ULONG seed = (ULONG)(ULONG_PTR)imageBase ^ (ULONG)((ULONG_PTR)imageBase >> 32); + ULONG_PTR cookie = (ULONG_PTR)imageBase ^ RtlRandomEx( &seed ); + + // SecurityCookie value must be rebased by this moment + if (IMAGE64( pHeader )) + *(PULONG_PTR)CFG_DIR_VAL_T( pHeader, pCfgDir, SecurityCookie ) = cookie; + else + *(PULONG)CFG_DIR_VAL_T( pHeader, pCfgDir, SecurityCookie ) = (ULONG)cookie; + } + } + else + status = STATUS_INVALID_IMAGE_FORMAT; + + return status; +} + +/// +/// Load image from disk into system memory +/// +/// Image path +/// Mapped base +/// Status code +NTSTATUS BBLoadLocalImage( IN PUNICODE_STRING path, OUT PVOID* pBase ) +{ + NTSTATUS status = STATUS_SUCCESS; + HANDLE hFile = NULL; + OBJECT_ATTRIBUTES obAttr = { 0 }; + IO_STATUS_BLOCK statusBlock = { 0 }; + FILE_STANDARD_INFORMATION fileInfo = { 0 }; + + ASSERT( path != NULL && pBase != NULL ); + if (path == NULL || pBase == NULL) + { + DPRINT( "BlackBone: %s: No image path or output base\n", __FUNCTION__ ); + return STATUS_INVALID_PARAMETER; + } + + InitializeObjectAttributes( &obAttr, path, OBJ_KERNEL_HANDLE, NULL, NULL ); + + // Open image file + status = ZwCreateFile( + &hFile, FILE_READ_DATA | SYNCHRONIZE, &obAttr, + &statusBlock, NULL, FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 + ); + + if (!NT_SUCCESS( status )) + { + DPRINT( "BlackBone: %s: Failed to open '%wZ'. Status: 0x%X\n", __FUNCTION__, path, status ); + return status; + } + + // Allocate memory for file contents + status = ZwQueryInformationFile( hFile, &statusBlock, &fileInfo, sizeof( fileInfo ), FileStandardInformation ); + if (NT_SUCCESS( status )) + *pBase = ExAllocatePoolWithTag( PagedPool, fileInfo.EndOfFile.QuadPart, BB_POOL_TAG ); + else + DPRINT( "BlackBone: %s: Failed to get '%wZ' size. Status: 0x%X\n", __FUNCTION__, path, status ); + + // Get file contents + status = ZwReadFile( hFile, NULL, NULL, NULL, &statusBlock, *pBase, fileInfo.EndOfFile.LowPart, NULL, NULL ); + if (NT_SUCCESS( status )) + { + PIMAGE_NT_HEADERS pNTHeader = RtlImageNtHeader( *pBase ); + if (!pNTHeader) + { + DPRINT( "BlackBone: %s: Failed to obtaint NT Header for '%wZ'\n", __FUNCTION__, path ); + status = STATUS_INVALID_IMAGE_FORMAT; + } + } + else + DPRINT( "BlackBone: %s: Failed to read '%wZ'. Status: 0x%X\n", __FUNCTION__, path, status ); + + ZwClose( hFile ); + + if (!NT_SUCCESS( status ) && *pBase) + ExFreePoolWithTag( *pBase, BB_POOL_TAG ); + + return status; +} + +/// +/// Create worker thread for user-mode calls +/// +/// Map context +/// Status code +NTSTATUS BBCreateWorkerThread( IN PMMAP_CONTEXT pContext ) +{ + NTSTATUS status = STATUS_SUCCESS; + SIZE_T codeSize = 0x1000; + ASSERT( pContext != NULL ); + if (pContext == NULL) + return STATUS_INVALID_PARAMETER; + + pContext->pWorkerBuf = NULL; + status = ZwAllocateVirtualMemory( ZwCurrentProcess(), &pContext->pWorkerBuf, 0, &codeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + if (NT_SUCCESS( status )) + { + PUCHAR pBuf = pContext->pWorkerBuf; + UNICODE_STRING ustrNtdll; + BOOLEAN wow64 = PsGetProcessWow64Process( pContext->pProcess ) != NULL; + + RtlUnicodeStringInit( &ustrNtdll, L"ntdll.dll" ); + + PVOID pNtDelayExec = BBGetModuleExport( + BBGetUserModule( pContext->pProcess, &ustrNtdll, wow64 ), + "NtDelayExecution", pContext->pProcess, NULL + ); + + if (pNtDelayExec) + { + OBJECT_ATTRIBUTES obattr = { 0 }; + PLARGE_INTEGER pDelay = (PLARGE_INTEGER)(pBuf + 0x100); + pDelay->QuadPart = -(5ll * 10 * 1000); + ULONG ofst = 0; + + if (wow64) + { + *(PUCHAR)(pBuf + ofst) = 0x68; // push pDelay + *(PULONG)(pBuf + ofst + 1) = (ULONG)(ULONG_PTR)pDelay; // + ofst += 5; + + *(PUSHORT)(pBuf + ofst) = 0x016A; // push TRUE + ofst += 2; + + *(PUCHAR)(pBuf + ofst) = 0xB8; // mov eax, pFn + *(PULONG)(pBuf + ofst + 1) = (ULONG)(ULONG_PTR)pNtDelayExec;// + ofst += 5; + + *(PUSHORT)(pBuf + ofst) = 0xD0FF; // call eax + ofst += 2; + + *(PUSHORT)(pBuf + ofst) = 0xF0EB; // jmp + ofst += 2; + } + else + { + *(PUSHORT)(pBuf + ofst) = 0xB948; // mov rcx, TRUE + *(PULONG_PTR)(pBuf + ofst + 2) = TRUE; // + ofst += 10; + + *(PUSHORT)(pBuf + ofst) = 0xBA48; // mov rdx, pDelay + *(PVOID*)(pBuf + ofst + 2) = pDelay; // + ofst += 10; + + *(PUSHORT)(pBuf + ofst) = 0xB848; // mov rax, pNtDelayExec + *(PVOID*)(pBuf + ofst + 2) = pNtDelayExec; // + ofst += 10; + + *(PUSHORT)(pBuf + ofst) = 0xD0FF; // call rax + ofst += 2; + + *(PUSHORT)(pBuf + ofst) = 0xDEEB; // jmp + ofst += 2; + } + + InitializeObjectAttributes( &obattr, NULL, OBJ_KERNEL_HANDLE, NULL, NULL ); + status = ZwCreateThreadEx( + &pContext->hWorker, THREAD_ALL_ACCESS, &obattr, + ZwCurrentProcess(), pContext->pWorkerBuf, NULL, 0, + 0, 0x1000, 0x100000, NULL + ); + + if (NT_SUCCESS( status )) + ObReferenceObjectByHandle( pContext->hWorker, THREAD_ALL_ACCESS, *PsThreadType, KernelMode, &pContext->pWorker, NULL ); + } + else + { + status = STATUS_NOT_FOUND; + } + } + + return status; +} + +/// +/// Find suitable thread to be used as worker for user-mode calls +/// +/// Map context +/// Status code +NTSTATUS BBFindWokerThread( IN PMMAP_CONTEXT pContext ) +{ + return BBLookupProcessThread( pContext->pProcess, &pContext->pWorker ); +} + +/// +/// Call arbitrary function +/// +/// Perform call in a separate thread +/// Loader context +/// Routine to call. +/// Number of arguments. +/// Arguments +/// Status code +NTSTATUS BBCallRoutine( IN BOOLEAN newThread, IN PMMAP_CONTEXT pContext, IN PVOID pRoutine, IN INT argc, ... ) +{ + NTSTATUS status = STATUS_SUCCESS; + va_list vl; + BOOLEAN wow64 = PsGetProcessWow64Process( pContext->pProcess ) != NULL; + + va_start( vl, argc ); + ULONG ofst = GenPrologueT( wow64, pContext->userMem->code ); + ofst += GenCallTV( wow64, pContext->userMem->code + ofst, pRoutine, argc, vl ); + ofst += GenSyncT( wow64, pContext->userMem->code + ofst, &pContext->userMem->status, pContext->pSetEvent, pContext->hSync ); + ofst += GenEpilogueT( wow64, pContext->userMem->code + ofst, argc * sizeof( ULONG ) ); + + if (newThread) + { + status = BBExecuteInNewThread( pContext->userMem->code, NULL, 0/*THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER*/, TRUE, NULL ); + } + else + { + KeResetEvent( pContext->pSync ); + status = BBQueueUserApc( pContext->pWorker, pContext->userMem->code, NULL, NULL, NULL, pContext->noThreads ); + if (NT_SUCCESS( status )) + { + LARGE_INTEGER timeout = { 0 }; + timeout.QuadPart = -(10ll * 10 * 1000 * 1000); // 10s + + status = KeWaitForSingleObject( pContext->pSync, Executive, UserMode, TRUE, &timeout ); + + timeout.QuadPart = -(1ll * 10 * 1000); // 1ms + KeDelayExecutionThread( KernelMode, TRUE, &timeout ); + } + } + + va_end( vl ); + + return status; +} + +/// +/// Find existing module in the list +/// +/// Module list +/// Module name +/// Module type +/// Module info address; NULL if not found +PMODULE_DATA BBLookupMappedModule( IN PLIST_ENTRY pList, IN PUNICODE_STRING pName, IN ModType type ) +{ + // Sanity check + ASSERT( pList != NULL && pName != NULL ); + if (pList == NULL || pName == NULL) + return NULL; + + if (IsListEmpty( pList )) + return NULL; + + // Walk list + for (PLIST_ENTRY pListEntry = pList->Flink; pListEntry != pList; pListEntry = pListEntry->Flink) + { + PMODULE_DATA pEntry = (PMODULE_DATA)CONTAINING_RECORD( pListEntry, MODULE_DATA, link ); + if (type == pEntry->type && RtlCompareUnicodeString( &pEntry->name, pName, TRUE ) == 0) + return pEntry; + } + + return NULL; +} + +/// +/// Get memory protection form section characteristics +/// +/// Characteristics +/// Set to TRUE if DEP is disabled. This will omit creation of executable pages +/// Memory protection value +ULONG BBCastSectionProtection( IN ULONG characteristics, IN BOOLEAN noDEP ) +{ + ULONG dwResult = PAGE_NOACCESS; + + if (characteristics & IMAGE_SCN_MEM_DISCARDABLE) + { + dwResult = PAGE_NOACCESS; + } + else if (characteristics & IMAGE_SCN_MEM_EXECUTE) + { + if (characteristics & IMAGE_SCN_MEM_WRITE) + dwResult = noDEP ? PAGE_READWRITE : PAGE_EXECUTE_READWRITE; + else if (characteristics & IMAGE_SCN_MEM_READ) + dwResult = noDEP ? PAGE_READONLY : PAGE_EXECUTE_READ; + else + dwResult = noDEP ? PAGE_READONLY : PAGE_EXECUTE; + } + else + { + if (characteristics & IMAGE_SCN_MEM_WRITE) + dwResult = PAGE_READWRITE; + else if (characteristics & IMAGE_SCN_MEM_READ) + dwResult = PAGE_READONLY; + else + dwResult = PAGE_NOACCESS; + } + + return dwResult; +} + +/// +/// Get image manifest data +/// +/// Image base +/// Manifest size +/// Manifest ID +/// Manifest data pointer or NULL if no manifest +PVOID BBImageManifest( IN PVOID pImageBase, OUT PULONG_PTR pSize, OUT PLONG pID ) +{ + ULONG secSize = 0; + + ASSERT( pImageBase != NULL && pSize != NULL && pID != NULL ); + if (pImageBase == NULL || pSize == NULL || pID == NULL) + return NULL; + + // 3 levels of pointers to nodes + IMAGE_RESOURCE_DIRECTORY_ENTRY *pDirNode1 = NULL; + IMAGE_RESOURCE_DIRECTORY_ENTRY *pDirNode2 = NULL; + IMAGE_RESOURCE_DIRECTORY_ENTRY *pDirNode3 = NULL; + + // 3 levels of nodes + IMAGE_RESOURCE_DIRECTORY *pDirNodePtr1 = NULL; + IMAGE_RESOURCE_DIRECTORY *pDirNodePtr2 = NULL; + IMAGE_RESOURCE_DIRECTORY *pDirNodePtr3 = NULL; + + // resource entry data + IMAGE_RESOURCE_DATA_ENTRY *pDataNode = NULL; + + size_t ofst_1 = 0; // first level nodes offset + size_t ofst_2 = 0; // second level nodes offset + size_t ofst_3 = 0; // third level nodes offset + + // Get section base + PUCHAR secBase = RtlImageDirectoryEntryToData( pImageBase, FALSE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &secSize ); + if (secBase == NULL) + { + *pSize = 0; + *pID = 0; + return NULL; + } + + pDirNodePtr1 = (PIMAGE_RESOURCE_DIRECTORY)secBase; + ofst_1 += sizeof( IMAGE_RESOURCE_DIRECTORY ); + + // first-level nodes + for (int i = 0; i < pDirNodePtr1->NumberOfIdEntries + pDirNodePtr1->NumberOfNamedEntries; ++i) + { + pDirNode1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(secBase + ofst_1); + + // Not a manifest directory + if (!pDirNode1->DataIsDirectory || pDirNode1->Id != 0x18) + { + ofst_1 += sizeof( IMAGE_RESOURCE_DIRECTORY_ENTRY ); + continue; + } + + pDirNodePtr2 = (PIMAGE_RESOURCE_DIRECTORY)(secBase + pDirNode1->OffsetToDirectory); + ofst_2 = pDirNode1->OffsetToDirectory + sizeof( IMAGE_RESOURCE_DIRECTORY ); + + // second-level nodes + for (int j = 0; j < pDirNodePtr2->NumberOfIdEntries + pDirNodePtr2->NumberOfNamedEntries; ++j) + { + pDirNode2 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(secBase + ofst_2); + + if (!pDirNode2->DataIsDirectory) + { + ofst_2 += sizeof( IMAGE_RESOURCE_DIRECTORY_ENTRY ); + continue; + } + + // Check if this is a valid manifest resource + if (pDirNode2->Id == 1 || pDirNode2->Id == 2 || pDirNode2->Id == 3) + { + pDirNodePtr3 = (PIMAGE_RESOURCE_DIRECTORY)(secBase + pDirNode2->OffsetToDirectory); + ofst_3 = pDirNode2->OffsetToDirectory + sizeof( IMAGE_RESOURCE_DIRECTORY ); + pDirNode3 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(secBase + ofst_3); + pDataNode = (PIMAGE_RESOURCE_DATA_ENTRY)(secBase + pDirNode3->OffsetToData); + + *pID = pDirNode2->Id; + *pSize = pDataNode->Size; + + return BBRvaToVa( pDataNode->OffsetToData, FALSE, pImageBase ); + } + + ofst_2 += sizeof( IMAGE_RESOURCE_DIRECTORY_ENTRY ); + } + + ofst_1 += sizeof( IMAGE_RESOURCE_DIRECTORY_ENTRY ); + } + + return NULL; +} + +/// +/// Translate RVA address to VA +/// +/// RVA +/// Image is mapped using image memory layout +/// Image base +/// Translated address +PVOID BBRvaToVa( IN ULONG rva, IN BOOLEAN MappedAsImage, IN PVOID imageBase ) +{ + // Simple offset + if (MappedAsImage) + return (PUCHAR)imageBase + rva; + + PIMAGE_NT_HEADERS pHeader = RtlImageNtHeader( imageBase ); + if (pHeader) + { + PIMAGE_SECTION_HEADER pFirstSection = (PIMAGE_SECTION_HEADER)(pHeader + 1); + if (IMAGE32( pHeader )) + pFirstSection = (PIMAGE_SECTION_HEADER)((PIMAGE_NT_HEADERS32)pHeader + 1); + + for (PIMAGE_SECTION_HEADER pSection = pFirstSection; + pSection < pFirstSection + pHeader->FileHeader.NumberOfSections; + pSection++) + { + if (rva >= pSection->VirtualAddress && rva < pSection->VirtualAddress + pSection->Misc.VirtualSize) + return (PUCHAR)imageBase + pSection->PointerToRawData + (rva - pSection->VirtualAddress); + } + } + + return NULL; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/NativeEnums.h b/third/Blackbone/src/BlackBoneDrv/NativeEnums.h new file mode 100644 index 0000000000000000000000000000000000000000..6dfd0dac7d66162b843edf4d1dc4405587b32014 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/NativeEnums.h @@ -0,0 +1,218 @@ +#pragma once + +typedef enum _MEMORY_INFORMATION_CLASS_EX +{ + MemoryBasicInformationEx = 0, + MemoryWorkingSetInformation = 1, + MemoryMappedFilenameInformation = 2, + MemoryRegionInformation = 3, + MemoryWorkingSetExInformation = 4, +} MEMORY_INFORMATION_CLASS_EX; + +typedef enum _PS_PROTECTED_SIGNER +{ + PsProtectedSignerNone = 0, + PsProtectedSignerAuthenticode = 1, + PsProtectedSignerCodeGen = 2, + PsProtectedSignerAntimalware = 3, + PsProtectedSignerLsa = 4, + PsProtectedSignerWindows = 5, + PsProtectedSignerWinTcb = 6, + PsProtectedSignerMax = 7 +} PS_PROTECTED_SIGNER; + +typedef enum _PS_PROTECTED_TYPE +{ + PsProtectedTypeNone = 0, + PsProtectedTypeProtectedLight = 1, + PsProtectedTypeProtected = 2, + PsProtectedTypeMax = 3 +} PS_PROTECTED_TYPE; + +typedef enum _SYSTEM_INFORMATION_CLASS +{ + SystemBasicInformation = 0x0, + SystemProcessorInformation = 0x1, + SystemPerformanceInformation = 0x2, + SystemTimeOfDayInformation = 0x3, + SystemPathInformation = 0x4, + SystemProcessInformation = 0x5, + SystemCallCountInformation = 0x6, + SystemDeviceInformation = 0x7, + SystemProcessorPerformanceInformation = 0x8, + SystemFlagsInformation = 0x9, + SystemCallTimeInformation = 0xa, + SystemModuleInformation = 0xb, + SystemLocksInformation = 0xc, + SystemStackTraceInformation = 0xd, + SystemPagedPoolInformation = 0xe, + SystemNonPagedPoolInformation = 0xf, + SystemHandleInformation = 0x10, + SystemObjectInformation = 0x11, + SystemPageFileInformation = 0x12, + SystemVdmInstemulInformation = 0x13, + SystemVdmBopInformation = 0x14, + SystemFileCacheInformation = 0x15, + SystemPoolTagInformation = 0x16, + SystemInterruptInformation = 0x17, + SystemDpcBehaviorInformation = 0x18, + SystemFullMemoryInformation = 0x19, + SystemLoadGdiDriverInformation = 0x1a, + SystemUnloadGdiDriverInformation = 0x1b, + SystemTimeAdjustmentInformation = 0x1c, + SystemSummaryMemoryInformation = 0x1d, + SystemMirrorMemoryInformation = 0x1e, + SystemPerformanceTraceInformation = 0x1f, + SystemObsolete0 = 0x20, + SystemExceptionInformation = 0x21, + SystemCrashDumpStateInformation = 0x22, + SystemKernelDebuggerInformation = 0x23, + SystemContextSwitchInformation = 0x24, + SystemRegistryQuotaInformation = 0x25, + SystemExtendServiceTableInformation = 0x26, + SystemPrioritySeperation = 0x27, + SystemVerifierAddDriverInformation = 0x28, + SystemVerifierRemoveDriverInformation = 0x29, + SystemProcessorIdleInformation = 0x2a, + SystemLegacyDriverInformation = 0x2b, + SystemCurrentTimeZoneInformation = 0x2c, + SystemLookasideInformation = 0x2d, + SystemTimeSlipNotification = 0x2e, + SystemSessionCreate = 0x2f, + SystemSessionDetach = 0x30, + SystemSessionInformation = 0x31, + SystemRangeStartInformation = 0x32, + SystemVerifierInformation = 0x33, + SystemVerifierThunkExtend = 0x34, + SystemSessionProcessInformation = 0x35, + SystemLoadGdiDriverInSystemSpace = 0x36, + SystemNumaProcessorMap = 0x37, + SystemPrefetcherInformation = 0x38, + SystemExtendedProcessInformation = 0x39, + SystemRecommendedSharedDataAlignment = 0x3a, + SystemComPlusPackage = 0x3b, + SystemNumaAvailableMemory = 0x3c, + SystemProcessorPowerInformation = 0x3d, + SystemEmulationBasicInformation = 0x3e, + SystemEmulationProcessorInformation = 0x3f, + SystemExtendedHandleInformation = 0x40, + SystemLostDelayedWriteInformation = 0x41, + SystemBigPoolInformation = 0x42, + SystemSessionPoolTagInformation = 0x43, + SystemSessionMappedViewInformation = 0x44, + SystemHotpatchInformation = 0x45, + SystemObjectSecurityMode = 0x46, + SystemWatchdogTimerHandler = 0x47, + SystemWatchdogTimerInformation = 0x48, + SystemLogicalProcessorInformation = 0x49, + SystemWow64SharedInformationObsolete = 0x4a, + SystemRegisterFirmwareTableInformationHandler = 0x4b, + SystemFirmwareTableInformation = 0x4c, + SystemModuleInformationEx = 0x4d, + SystemVerifierTriageInformation = 0x4e, + SystemSuperfetchInformation = 0x4f, + SystemMemoryListInformation = 0x50, + SystemFileCacheInformationEx = 0x51, + SystemThreadPriorityClientIdInformation = 0x52, + SystemProcessorIdleCycleTimeInformation = 0x53, + SystemVerifierCancellationInformation = 0x54, + SystemProcessorPowerInformationEx = 0x55, + SystemRefTraceInformation = 0x56, + SystemSpecialPoolInformation = 0x57, + SystemProcessIdInformation = 0x58, + SystemErrorPortInformation = 0x59, + SystemBootEnvironmentInformation = 0x5a, + SystemHypervisorInformation = 0x5b, + SystemVerifierInformationEx = 0x5c, + SystemTimeZoneInformation = 0x5d, + SystemImageFileExecutionOptionsInformation = 0x5e, + SystemCoverageInformation = 0x5f, + SystemPrefetchPatchInformation = 0x60, + SystemVerifierFaultsInformation = 0x61, + SystemSystemPartitionInformation = 0x62, + SystemSystemDiskInformation = 0x63, + SystemProcessorPerformanceDistribution = 0x64, + SystemNumaProximityNodeInformation = 0x65, + SystemDynamicTimeZoneInformation = 0x66, + SystemCodeIntegrityInformation = 0x67, + SystemProcessorMicrocodeUpdateInformation = 0x68, + SystemProcessorBrandString = 0x69, + SystemVirtualAddressInformation = 0x6a, + SystemLogicalProcessorAndGroupInformation = 0x6b, + SystemProcessorCycleTimeInformation = 0x6c, + SystemStoreInformation = 0x6d, + SystemRegistryAppendString = 0x6e, + SystemAitSamplingValue = 0x6f, + SystemVhdBootInformation = 0x70, + SystemCpuQuotaInformation = 0x71, + SystemNativeBasicInformation = 0x72, + SystemErrorPortTimeouts = 0x73, + SystemLowPriorityIoInformation = 0x74, + SystemBootEntropyInformation = 0x75, + SystemVerifierCountersInformation = 0x76, + SystemPagedPoolInformationEx = 0x77, + SystemSystemPtesInformationEx = 0x78, + SystemNodeDistanceInformation = 0x79, + SystemAcpiAuditInformation = 0x7a, + SystemBasicPerformanceInformation = 0x7b, + SystemQueryPerformanceCounterInformation = 0x7c, + SystemSessionBigPoolInformation = 0x7d, + SystemBootGraphicsInformation = 0x7e, + SystemScrubPhysicalMemoryInformation = 0x7f, + SystemBadPageInformation = 0x80, + SystemProcessorProfileControlArea = 0x81, + SystemCombinePhysicalMemoryInformation = 0x82, + SystemEntropyInterruptTimingInformation = 0x83, + SystemConsoleInformation = 0x84, + SystemPlatformBinaryInformation = 0x85, + SystemThrottleNotificationInformation = 0x86, + SystemHypervisorProcessorCountInformation = 0x87, + SystemDeviceDataInformation = 0x88, + SystemDeviceDataEnumerationInformation = 0x89, + SystemMemoryTopologyInformation = 0x8a, + SystemMemoryChannelInformation = 0x8b, + SystemBootLogoInformation = 0x8c, + SystemProcessorPerformanceInformationEx = 0x8d, + SystemSpare0 = 0x8e, + SystemSecureBootPolicyInformation = 0x8f, + SystemPageFileInformationEx = 0x90, + SystemSecureBootInformation = 0x91, + SystemEntropyInterruptTimingRawInformation = 0x92, + SystemPortableWorkspaceEfiLauncherInformation = 0x93, + SystemFullProcessInformation = 0x94, + SystemKernelDebuggerInformationEx = 0x95, + SystemBootMetadataInformation = 0x96, + SystemSoftRebootInformation = 0x97, + SystemElamCertificateInformation = 0x98, + SystemOfflineDumpConfigInformation = 0x99, + SystemProcessorFeaturesInformation = 0x9a, + SystemRegistryReconciliationInformation = 0x9b, + MaxSystemInfoClass = 0x9c, +} SYSTEM_INFORMATION_CLASS; + +typedef enum _KAPC_ENVIRONMENT +{ + OriginalApcEnvironment, + AttachedApcEnvironment, + CurrentApcEnvironment, + InsertApcEnvironment +} KAPC_ENVIRONMENT, *PKAPC_ENVIRONMENT; + +typedef enum _MI_VAD_TYPE +{ + VadNone, + VadDevicePhysicalMemory, + VadImageMap, + VadAwe, + VadWriteWatch, + VadLargePages, + VadRotatePhysical, + VadLargePageSection +} MI_VAD_TYPE, *PMI_VAD_TYPE; + +typedef enum _MMSYSTEM_PTE_POOL_TYPE +{ + SystemPteSpace, + NonPagedPoolExpansion, + MaximumPtePoolTypes +} MMSYSTEM_PTE_POOL_TYPE; \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/NativeStructs.h b/third/Blackbone/src/BlackBoneDrv/NativeStructs.h new file mode 100644 index 0000000000000000000000000000000000000000..f16e717720c3f7ff112647dc5419d7fce7dea8c2 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/NativeStructs.h @@ -0,0 +1,965 @@ +#pragma once + +#include "PEStructs.h" + +#ifdef _WIN10_ +#include "NativeStructs10.h" +#elif _WIN81_ +#include "NativeStructs81.h" +#elif _WIN8_ +#include "NativeStructs8.h" +#elif _WIN7_ +#include "NativeStructs7.h" +#else +#error Unsupported OS build version +#endif + +#define MAKEINTRESOURCEW(i) ((PWCH)((ULONG_PTR)((USHORT)(i)))) + +typedef struct _SYSTEM_SERVICE_DESCRIPTOR_TABLE +{ + PULONG_PTR ServiceTableBase; + PULONG ServiceCounterTableBase; + ULONG_PTR NumberOfServices; + PUCHAR ParamTableBase; +} SYSTEM_SERVICE_DESCRIPTOR_TABLE, *PSYSTEM_SERVICE_DESCRIPTOR_TABLE; + +typedef union _PS_PROTECTION +{ + UCHAR Level; + struct + { + int Type : 3; + int Audit : 1; + int Signer : 4; + } Flags; +} PS_PROTECTION, *PPS_PROTECTION; + +typedef union _KEXECUTE_OPTIONS +{ + struct + { + int ExecuteDisable : 1; // 0x01 + int ExecuteEnable : 1; // 0x02 + int DisableThunkEmulation : 1; // 0x04 + int Permanent : 1; // 0x08 + int ExecuteDispatchEnable : 1; // 0x10 + int ImageDispatchEnable : 1; // 0x20 + int DisableExceptionChainValidation : 1; // 0x40 + int Spare : 1; + } Flags; + + UCHAR ExecuteOptions; +} KEXECUTE_OPTIONS, *PKEXECUTE_OPTIONS; + +typedef struct _EPROCESS_FLAGS2 +{ + unsigned int JobNotReallyActive : 1; + unsigned int AccountingFolded : 1; + unsigned int NewProcessReported : 1; + unsigned int ExitProcessReported : 1; + unsigned int ReportCommitChanges : 1; + unsigned int LastReportMemory : 1; + unsigned int ForceWakeCharge : 1; + unsigned int CrossSessionCreate : 1; + unsigned int NeedsHandleRundown : 1; + unsigned int RefTraceEnabled : 1; + unsigned int DisableDynamicCode : 1; + unsigned int EmptyJobEvaluated : 1; + unsigned int DefaultPagePriority : 3; + unsigned int PrimaryTokenFrozen : 1; + unsigned int ProcessVerifierTarget : 1; + unsigned int StackRandomizationDisabled : 1; + unsigned int AffinityPermanent : 1; + unsigned int AffinityUpdateEnable : 1; + unsigned int PropagateNode : 1; + unsigned int ExplicitAffinity : 1; + unsigned int ProcessExecutionState : 2; + unsigned int DisallowStrippedImages : 1; + unsigned int HighEntropyASLREnabled : 1; + unsigned int ExtensionPointDisable : 1; + unsigned int ForceRelocateImages : 1; + unsigned int ProcessStateChangeRequest : 2; + unsigned int ProcessStateChangeInProgress : 1; + unsigned int DisallowWin32kSystemCalls : 1; +} EPROCESS_FLAGS2, *PEPROCESS_FLAGS2; + +typedef struct _MITIGATION_FLAGS +{ + unsigned int ControlFlowGuardEnabled : 1; + unsigned int ControlFlowGuardExportSuppressionEnabled : 1; + unsigned int ControlFlowGuardStrict : 1; + unsigned int DisallowStrippedImages : 1; + unsigned int ForceRelocateImages : 1; + unsigned int HighEntropyASLREnabled : 1; + unsigned int StackRandomizationDisabled : 1; + unsigned int ExtensionPointDisable : 1; + unsigned int DisableDynamicCode : 1; + unsigned int DisableDynamicCodeAllowOptOut : 1; + unsigned int DisableDynamicCodeAllowRemoteDowngrade : 1; + unsigned int AuditDisableDynamicCode : 1; + unsigned int DisallowWin32kSystemCalls : 1; + unsigned int AuditDisallowWin32kSystemCalls : 1; + unsigned int EnableFilteredWin32kAPIs : 1; + unsigned int AuditFilteredWin32kAPIs : 1; + unsigned int DisableNonSystemFonts : 1; + unsigned int AuditNonSystemFontLoading : 1; + unsigned int PreferSystem32Images : 1; + unsigned int ProhibitRemoteImageMap : 1; + unsigned int AuditProhibitRemoteImageMap : 1; + unsigned int ProhibitLowILImageMap : 1; + unsigned int AuditProhibitLowILImageMap : 1; + unsigned int SignatureMitigationOptIn : 1; + unsigned int AuditBlockNonMicrosoftBinaries : 1; + unsigned int AuditBlockNonMicrosoftBinariesAllowStore : 1; + unsigned int LoaderIntegrityContinuityEnabled : 1; + unsigned int AuditLoaderIntegrityContinuity : 1; + unsigned int EnableModuleTamperingProtection : 1; + unsigned int EnableModuleTamperingProtectionNoInherit : 1; + unsigned int RestrictIndirectBranchPrediction; + unsigned int IsolateSecurityDomain; +} MITIGATION_FLAGS, *PMITIGATION_FLAGS; + +typedef union _EXHANDLE +{ + struct + { + int TagBits : 2; + int Index : 30; + } u; + void * GenericHandleOverlay; + ULONG_PTR Value; +} EXHANDLE, *PEXHANDLE; + +#pragma warning(disable : 4214 4201) + +#pragma pack(push, 1) +typedef struct _POOL_HEADER // Size=16 +{ + union + { + struct + { + unsigned long PreviousSize : 8; // Size=4 Offset=0 BitOffset=0 BitCount=8 + unsigned long PoolIndex : 8; // Size=4 Offset=0 BitOffset=8 BitCount=8 + unsigned long BlockSize : 8; // Size=4 Offset=0 BitOffset=16 BitCount=8 + unsigned long PoolType : 8; // Size=4 Offset=0 BitOffset=24 BitCount=8 + }; + unsigned long Ulong1; // Size=4 Offset=0 + }; + unsigned long PoolTag; // Size=4 Offset=4 + union + { + struct _EPROCESS * ProcessBilled; // Size=8 Offset=8 + struct + { + unsigned short AllocatorBackTraceIndex; // Size=2 Offset=8 + unsigned short PoolTagHash; // Size=2 Offset=10 + }; + }; +} POOL_HEADER, *PPOOL_HEADER; +#pragma pack(pop) + +typedef struct _HANDLE_TABLE_ENTRY // Size=16 +{ + union + { + ULONG_PTR VolatileLowValue; // Size=8 Offset=0 + ULONG_PTR LowValue; // Size=8 Offset=0 + struct _HANDLE_TABLE_ENTRY_INFO * InfoTable; // Size=8 Offset=0 + struct + { + ULONG_PTR Unlocked : 1; // Size=8 Offset=0 BitOffset=0 BitCount=1 + ULONG_PTR RefCnt : 16; // Size=8 Offset=0 BitOffset=1 BitCount=16 + ULONG_PTR Attributes : 3; // Size=8 Offset=0 BitOffset=17 BitCount=3 + ULONG_PTR ObjectPointerBits : 44; // Size=8 Offset=0 BitOffset=20 BitCount=44 + }; + }; + union + { + ULONG_PTR HighValue; // Size=8 Offset=8 + struct _HANDLE_TABLE_ENTRY * NextFreeHandleEntry; // Size=8 Offset=8 + union _EXHANDLE LeafHandleValue; // Size=8 Offset=8 + struct + { + ULONG GrantedAccessBits : 25; // Size=4 Offset=8 BitOffset=0 BitCount=25 + ULONG NoRightsUpgrade : 1; // Size=4 Offset=8 BitOffset=25 BitCount=1 + ULONG Spare : 6; // Size=4 Offset=8 BitOffset=26 BitCount=6 + }; + }; + ULONG TypeInfo; // Size=4 Offset=12 +} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY; + + + +typedef struct _OBJECT_HEADER // Size=56 +{ + ULONG_PTR PointerCount; // Size=8 Offset=0 + union + { + ULONG_PTR HandleCount; // Size=8 Offset=8 + void * NextToFree; // Size=8 Offset=8 + }; + void* Lock; // Size=8 Offset=16 + UCHAR TypeIndex; // Size=1 Offset=24 + union + { + UCHAR TraceFlags; // Size=1 Offset=25 + struct + { + UCHAR DbgRefTrace : 1; // Size=1 Offset=25 BitOffset=0 BitCount=1 + UCHAR DbgTracePermanent : 1; // Size=1 Offset=25 BitOffset=1 BitCount=1 + }; + }; + UCHAR InfoMask; // Size=1 Offset=26 + union + { + UCHAR Flags; // Size=1 Offset=27 + struct + { + UCHAR NewObject : 1; // Size=1 Offset=27 BitOffset=0 BitCount=1 + UCHAR KernelObject : 1; // Size=1 Offset=27 BitOffset=1 BitCount=1 + UCHAR KernelOnlyAccess : 1; // Size=1 Offset=27 BitOffset=2 BitCount=1 + UCHAR ExclusiveObject : 1; // Size=1 Offset=27 BitOffset=3 BitCount=1 + UCHAR PermanentObject : 1; // Size=1 Offset=27 BitOffset=4 BitCount=1 + UCHAR DefaultSecurityQuota : 1; // Size=1 Offset=27 BitOffset=5 BitCount=1 + UCHAR SingleHandleEntry : 1; // Size=1 Offset=27 BitOffset=6 BitCount=1 + UCHAR DeletedInline : 1; // Size=1 Offset=27 BitOffset=7 BitCount=1 + }; + }; + ULONG Spare; // Size=4 Offset=28 + union + { + struct _OBJECT_CREATE_INFORMATION * ObjectCreateInfo; // Size=8 Offset=32 + void * QuotaBlockCharged; // Size=8 Offset=32 + }; + void * SecurityDescriptor; // Size=8 Offset=40 + struct _QUAD Body; // Size=8 Offset=48 +} OBJECT_HEADER, *POBJECT_HEADER; + +typedef union _EX_FAST_REF // Size=8 +{ + void * Object; + struct + { + unsigned __int64 RefCnt : 4; + }; + unsigned __int64 Value; +} EX_FAST_REF, *PEX_FAST_REF; + +typedef struct _CONTROL_AREA // Size=120 +{ + struct _SEGMENT * Segment; + struct _LIST_ENTRY ListHead; + unsigned __int64 NumberOfSectionReferences; + unsigned __int64 NumberOfPfnReferences; + unsigned __int64 NumberOfMappedViews; + unsigned __int64 NumberOfUserReferences; + unsigned long f1; + unsigned long f2; + EX_FAST_REF FilePointer; + // Other fields +} CONTROL_AREA, *PCONTROL_AREA; + +typedef struct _SUBSECTION // Size=56 +{ + PCONTROL_AREA ControlArea; + // Other fields +} SUBSECTION, *PSUBSECTION; + +typedef struct _MEMORY_BASIC_INFORMATION_EX +{ + PVOID BaseAddress; + PVOID AllocationBase; + ULONG AllocationProtect; + SIZE_T RegionSize; + ULONG State; + ULONG Protect; + ULONG Type; +} MEMORY_BASIC_INFORMATION_EX, *PMEMORY_BASIC_INFORMATION_EX; + +typedef struct _SYSTEM_CALL_COUNT_INFORMATION +{ + ULONG Length; + ULONG NumberOfTables; + ULONG limits[2]; + } SYSTEM_CALL_COUNT_INFORMATION, *PSYSTEM_CALL_COUNT_INFORMATION; + +typedef struct _SYSTEM_THREAD_INFORMATION +{ + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER CreateTime; + ULONG WaitTime; + PVOID StartAddress; + CLIENT_ID ClientId; + KPRIORITY Priority; + LONG BasePriority; + ULONG ContextSwitches; + ULONG ThreadState; + KWAIT_REASON WaitReason; +}SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION; + +typedef struct _THREAD_BASIC_INFORMATION +{ + NTSTATUS ExitStatus; + PVOID TebBaseAddress; + CLIENT_ID ClientId; + ULONG_PTR AffinityMask; + LONG Priority; + LONG BasePriority; +} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; + +typedef struct _SYSTEM_PROCESS_INFO +{ + ULONG NextEntryOffset; + ULONG NumberOfThreads; + LARGE_INTEGER WorkingSetPrivateSize; + ULONG HardFaultCount; + ULONG NumberOfThreadsHighWatermark; + ULONGLONG CycleTime; + LARGE_INTEGER CreateTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; + UNICODE_STRING ImageName; + KPRIORITY BasePriority; + HANDLE UniqueProcessId; + HANDLE InheritedFromUniqueProcessId; + ULONG HandleCount; + ULONG SessionId; + ULONG_PTR UniqueProcessKey; + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; + SIZE_T PrivatePageCount; + LARGE_INTEGER ReadOperationCount; + LARGE_INTEGER WriteOperationCount; + LARGE_INTEGER OtherOperationCount; + LARGE_INTEGER ReadTransferCount; + LARGE_INTEGER WriteTransferCount; + LARGE_INTEGER OtherTransferCount; + SYSTEM_THREAD_INFORMATION Threads[1]; +}SYSTEM_PROCESS_INFO, *PSYSTEM_PROCESS_INFO; + +#pragma warning(disable : 4214) +typedef struct _MMPTE_HARDWARE64 +{ + ULONGLONG Valid : 1; + ULONGLONG Dirty1 : 1; + ULONGLONG Owner : 1; + ULONGLONG WriteThrough : 1; + ULONGLONG CacheDisable : 1; + ULONGLONG Accessed : 1; + ULONGLONG Dirty : 1; + ULONGLONG LargePage : 1; + ULONGLONG Global : 1; + ULONGLONG CopyOnWrite : 1; + ULONGLONG Unused : 1; + ULONGLONG Write : 1; + ULONGLONG PageFrameNumber : 36; + ULONGLONG reserved1 : 4; + ULONGLONG SoftwareWsIndex : 11; + ULONGLONG NoExecute : 1; +} MMPTE_HARDWARE64, *PMMPTE_HARDWARE64; + +typedef struct _MMPTE +{ + union + { + ULONG_PTR Long; + MMPTE_HARDWARE64 Hard; + } u; +} MMPTE; +typedef MMPTE *PMMPTE; + +#pragma warning(default : 4214) + +typedef struct _NT_PROC_THREAD_ATTRIBUTE_ENTRY +{ + ULONG Attribute; // PROC_THREAD_ATTRIBUTE_XXX + SIZE_T Size; + ULONG_PTR Value; + ULONG Unknown; +} NT_PROC_THREAD_ATTRIBUTE_ENTRY, *NT_PPROC_THREAD_ATTRIBUTE_ENTRY; + +typedef struct _NT_PROC_THREAD_ATTRIBUTE_LIST +{ + ULONG Length; + NT_PROC_THREAD_ATTRIBUTE_ENTRY Entry[1]; +} NT_PROC_THREAD_ATTRIBUTE_LIST, *PNT_PROC_THREAD_ATTRIBUTE_LIST; + + +typedef struct _RTL_PROCESS_MODULE_INFORMATION +{ + HANDLE Section; // Not filled in + PVOID MappedBase; + PVOID ImageBase; + ULONG ImageSize; + ULONG Flags; + USHORT LoadOrderIndex; + USHORT InitOrderIndex; + USHORT LoadCount; + USHORT OffsetToFileName; + UCHAR FullPathName[MAXIMUM_FILENAME_LENGTH]; +} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; + +typedef struct _RTL_PROCESS_MODULES +{ + ULONG NumberOfModules; + RTL_PROCESS_MODULE_INFORMATION Modules[1]; +} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; + +#pragma warning(disable : 4214) +typedef union _MEMORY_WORKING_SET_EX_BLOCK +{ + ULONG_PTR Flags; + struct + { + ULONG_PTR Valid : 1; + ULONG_PTR ShareCount : 3; + ULONG_PTR Win32Protection : 11; + ULONG_PTR Shared : 1; + ULONG_PTR Node : 6; + ULONG_PTR Locked : 1; + ULONG_PTR LargePage : 1; + ULONG_PTR Reserved : 7; + ULONG_PTR Bad : 1; + +#if defined(_WIN64) + ULONG_PTR ReservedUlong : 32; +#endif + }; +} MEMORY_WORKING_SET_EX_BLOCK, *PMEMORY_WORKING_SET_EX_BLOCK; + +typedef struct _MEMORY_WORKING_SET_EX_INFORMATION +{ + PVOID VirtualAddress; + MEMORY_WORKING_SET_EX_BLOCK VirtualAttributes; +} MEMORY_WORKING_SET_EX_INFORMATION, *PMEMORY_WORKING_SET_EX_INFORMATION; + +#pragma warning(default : 4214) + + +typedef struct _PEB_LDR_DATA +{ + ULONG Length; + UCHAR Initialized; + PVOID SsHandle; + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; +} PEB_LDR_DATA, *PPEB_LDR_DATA; + +typedef struct _LDR_DATA_TABLE_ENTRY +{ + LIST_ENTRY InLoadOrderLinks; + LIST_ENTRY InMemoryOrderLinks; + LIST_ENTRY InInitializationOrderLinks; + PVOID DllBase; + PVOID EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + USHORT LoadCount; + USHORT TlsIndex; + LIST_ENTRY HashLinks; + ULONG TimeDateStamp; +} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; + + +typedef struct _PEB +{ + UCHAR InheritedAddressSpace; + UCHAR ReadImageFileExecOptions; + UCHAR BeingDebugged; + UCHAR BitField; + PVOID Mutant; + PVOID ImageBaseAddress; + PPEB_LDR_DATA Ldr; + PVOID ProcessParameters; + PVOID SubSystemData; + PVOID ProcessHeap; + PVOID FastPebLock; + PVOID AtlThunkSListPtr; + PVOID IFEOKey; + PVOID CrossProcessFlags; + PVOID KernelCallbackTable; + ULONG SystemReserved; + ULONG AtlThunkSListPtr32; + PVOID ApiSetMap; +} PEB, *PPEB; + +typedef struct _PEB_LDR_DATA32 +{ + ULONG Length; + UCHAR Initialized; + ULONG SsHandle; + LIST_ENTRY32 InLoadOrderModuleList; + LIST_ENTRY32 InMemoryOrderModuleList; + LIST_ENTRY32 InInitializationOrderModuleList; +} PEB_LDR_DATA32, *PPEB_LDR_DATA32; + +typedef struct _LDR_DATA_TABLE_ENTRY32 +{ + LIST_ENTRY32 InLoadOrderLinks; + LIST_ENTRY32 InMemoryOrderLinks; + LIST_ENTRY32 InInitializationOrderLinks; + ULONG DllBase; + ULONG EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING32 FullDllName; + UNICODE_STRING32 BaseDllName; + ULONG Flags; + USHORT LoadCount; + USHORT TlsIndex; + LIST_ENTRY32 HashLinks; + ULONG TimeDateStamp; +} LDR_DATA_TABLE_ENTRY32, *PLDR_DATA_TABLE_ENTRY32; + +typedef struct _PEB32 +{ + UCHAR InheritedAddressSpace; + UCHAR ReadImageFileExecOptions; + UCHAR BeingDebugged; + UCHAR BitField; + ULONG Mutant; + ULONG ImageBaseAddress; + ULONG Ldr; + ULONG ProcessParameters; + ULONG SubSystemData; + ULONG ProcessHeap; + ULONG FastPebLock; + ULONG AtlThunkSListPtr; + ULONG IFEOKey; + ULONG CrossProcessFlags; + ULONG UserSharedInfoPtr; + ULONG SystemReserved; + ULONG AtlThunkSListPtr32; + ULONG ApiSetMap; +} PEB32, *PPEB32; + +typedef struct _WOW64_PROCESS +{ + PPEB32 Wow64; +} WOW64_PROCESS, *PWOW64_PROCESS; + +typedef union _WOW64_APC_CONTEXT +{ + struct + { + ULONG Apc32BitContext; + ULONG Apc32BitRoutine; + }; + + PVOID Apc64BitContext; + +} WOW64_APC_CONTEXT, *PWOW64_APC_CONTEXT; + +typedef struct _NON_PAGED_DEBUG_INFO +{ + USHORT Signature; + USHORT Flags; + ULONG Size; + USHORT Machine; + USHORT Characteristics; + ULONG TimeDateStamp; + ULONG CheckSum; + ULONG SizeOfImage; + ULONGLONG ImageBase; +} NON_PAGED_DEBUG_INFO, *PNON_PAGED_DEBUG_INFO; + +typedef struct _KLDR_DATA_TABLE_ENTRY +{ + LIST_ENTRY InLoadOrderLinks; + PVOID ExceptionTable; + ULONG ExceptionTableSize; + // ULONG padding on IA64 + PVOID GpValue; + PNON_PAGED_DEBUG_INFO NonPagedDebugInfo; + PVOID DllBase; + PVOID EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + USHORT LoadCount; + USHORT __Unused5; + PVOID SectionPointer; + ULONG CheckSum; + // ULONG padding on IA64 + PVOID LoadedImports; + PVOID PatchInformation; +} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY; + + +// +// This structure is used by the debugger for all targets +// It is the same size as DBGKD_DATA_HEADER on all systems +// +typedef struct _DBGKD_DEBUG_DATA_HEADER64 { + + // + // Link to other blocks + // + + LIST_ENTRY64 List; + + // + // This is a unique tag to identify the owner of the block. + // If your component only uses one pool tag, use it for this, too. + // + + ULONG OwnerTag; + + // + // This must be initialized to the size of the data block, + // including this structure. + // + + ULONG Size; + +} DBGKD_DEBUG_DATA_HEADER64, *PDBGKD_DEBUG_DATA_HEADER64; + + +// +// This structure is the same size on all systems. The only field +// which must be translated by the debugger is Header.List. +// + +// +// DO NOT ADD OR REMOVE FIELDS FROM THE MIDDLE OF THIS STRUCTURE!!! +// +// If you remove a field, replace it with an "unused" placeholder. +// Do not reuse fields until there has been enough time for old debuggers +// and extensions to age out. +// +typedef struct _KDDEBUGGER_DATA64 { + + DBGKD_DEBUG_DATA_HEADER64 Header; + + // + // Base address of kernel image + // + + ULONG64 KernBase; + + // + // DbgBreakPointWithStatus is a function which takes an argument + // and hits a breakpoint. This field contains the address of the + // breakpoint instruction. When the debugger sees a breakpoint + // at this address, it may retrieve the argument from the first + // argument register, or on x86 the eax register. + // + + ULONG64 BreakpointWithStatus; // address of breakpoint + + // + // Address of the saved context record during a bugcheck + // + // N.B. This is an automatic in KeBugcheckEx's frame, and + // is only valid after a bugcheck. + // + + ULONG64 SavedContext; + + // + // help for walking stacks with user callbacks: + // + + // + // The address of the thread structure is provided in the + // WAIT_STATE_CHANGE packet. This is the offset from the base of + // the thread structure to the pointer to the kernel stack frame + // for the currently active usermode callback. + // + + USHORT ThCallbackStack; // offset in thread data + + // + // these values are offsets into that frame: + // + + USHORT NextCallback; // saved pointer to next callback frame + USHORT FramePointer; // saved frame pointer + + // + // pad to a quad boundary + // + USHORT PaeEnabled; + + // + // Address of the kernel callout routine. + // + + ULONG64 KiCallUserMode; // kernel routine + + // + // Address of the usermode entry point for callbacks. + // + + ULONG64 KeUserCallbackDispatcher; // address in ntdll + + + // + // Addresses of various kernel data structures and lists + // that are of interest to the kernel debugger. + // + + ULONG64 PsLoadedModuleList; + ULONG64 PsActiveProcessHead; + ULONG64 PspCidTable; + + ULONG64 ExpSystemResourcesList; + ULONG64 ExpPagedPoolDescriptor; + ULONG64 ExpNumberOfPagedPools; + + ULONG64 KeTimeIncrement; + ULONG64 KeBugCheckCallbackListHead; + ULONG64 KiBugcheckData; + + ULONG64 IopErrorLogListHead; + + ULONG64 ObpRootDirectoryObject; + ULONG64 ObpTypeObjectType; + + ULONG64 MmSystemCacheStart; + ULONG64 MmSystemCacheEnd; + ULONG64 MmSystemCacheWs; + + ULONG64 MmPfnDatabase; + ULONG64 MmSystemPtesStart; + ULONG64 MmSystemPtesEnd; + ULONG64 MmSubsectionBase; + ULONG64 MmNumberOfPagingFiles; + + ULONG64 MmLowestPhysicalPage; + ULONG64 MmHighestPhysicalPage; + ULONG64 MmNumberOfPhysicalPages; + + ULONG64 MmMaximumNonPagedPoolInBytes; + ULONG64 MmNonPagedSystemStart; + ULONG64 MmNonPagedPoolStart; + ULONG64 MmNonPagedPoolEnd; + + ULONG64 MmPagedPoolStart; + ULONG64 MmPagedPoolEnd; + ULONG64 MmPagedPoolInformation; + ULONG64 MmPageSize; + + ULONG64 MmSizeOfPagedPoolInBytes; + + ULONG64 MmTotalCommitLimit; + ULONG64 MmTotalCommittedPages; + ULONG64 MmSharedCommit; + ULONG64 MmDriverCommit; + ULONG64 MmProcessCommit; + ULONG64 MmPagedPoolCommit; + ULONG64 MmExtendedCommit; + + ULONG64 MmZeroedPageListHead; + ULONG64 MmFreePageListHead; + ULONG64 MmStandbyPageListHead; + ULONG64 MmModifiedPageListHead; + ULONG64 MmModifiedNoWritePageListHead; + ULONG64 MmAvailablePages; + ULONG64 MmResidentAvailablePages; + + ULONG64 PoolTrackTable; + ULONG64 NonPagedPoolDescriptor; + + ULONG64 MmHighestUserAddress; + ULONG64 MmSystemRangeStart; + ULONG64 MmUserProbeAddress; + + ULONG64 KdPrintCircularBuffer; + ULONG64 KdPrintCircularBufferEnd; + ULONG64 KdPrintWritePointer; + ULONG64 KdPrintRolloverCount; + + ULONG64 MmLoadedUserImageList; + + // NT 5.1 Addition + + ULONG64 NtBuildLab; + ULONG64 KiNormalSystemCall; + + // NT 5.0 hotfix addition + + ULONG64 KiProcessorBlock; + ULONG64 MmUnloadedDrivers; + ULONG64 MmLastUnloadedDriver; + ULONG64 MmTriageActionTaken; + ULONG64 MmSpecialPoolTag; + ULONG64 KernelVerifier; + ULONG64 MmVerifierData; + ULONG64 MmAllocatedNonPagedPool; + ULONG64 MmPeakCommitment; + ULONG64 MmTotalCommitLimitMaximum; + ULONG64 CmNtCSDVersion; + + // NT 5.1 Addition + + ULONG64 MmPhysicalMemoryBlock; + ULONG64 MmSessionBase; + ULONG64 MmSessionSize; + ULONG64 MmSystemParentTablePage; + + // Server 2003 addition + + ULONG64 MmVirtualTranslationBase; + + USHORT OffsetKThreadNextProcessor; + USHORT OffsetKThreadTeb; + USHORT OffsetKThreadKernelStack; + USHORT OffsetKThreadInitialStack; + + USHORT OffsetKThreadApcProcess; + USHORT OffsetKThreadState; + USHORT OffsetKThreadBStore; + USHORT OffsetKThreadBStoreLimit; + + USHORT SizeEProcess; + USHORT OffsetEprocessPeb; + USHORT OffsetEprocessParentCID; + USHORT OffsetEprocessDirectoryTableBase; + + USHORT SizePrcb; + USHORT OffsetPrcbDpcRoutine; + USHORT OffsetPrcbCurrentThread; + USHORT OffsetPrcbMhz; + + USHORT OffsetPrcbCpuType; + USHORT OffsetPrcbVendorString; + USHORT OffsetPrcbProcStateContext; + USHORT OffsetPrcbNumber; + + USHORT SizeEThread; + + ULONG64 KdPrintCircularBufferPtr; + ULONG64 KdPrintBufferSize; + + ULONG64 KeLoaderBlock; + + USHORT SizePcr; + USHORT OffsetPcrSelfPcr; + USHORT OffsetPcrCurrentPrcb; + USHORT OffsetPcrContainedPrcb; + + USHORT OffsetPcrInitialBStore; + USHORT OffsetPcrBStoreLimit; + USHORT OffsetPcrInitialStack; + USHORT OffsetPcrStackLimit; + + USHORT OffsetPrcbPcrPage; + USHORT OffsetPrcbProcStateSpecialReg; + USHORT GdtR0Code; + USHORT GdtR0Data; + + USHORT GdtR0Pcr; + USHORT GdtR3Code; + USHORT GdtR3Data; + USHORT GdtR3Teb; + + USHORT GdtLdt; + USHORT GdtTss; + USHORT Gdt64R3CmCode; + USHORT Gdt64R3CmTeb; + + ULONG64 IopNumTriageDumpDataBlocks; + ULONG64 IopTriageDumpDataBlocks; + + // Longhorn addition + + ULONG64 VfCrashDataBlock; + ULONG64 MmBadPagesDetected; + ULONG64 MmZeroedPageSingleBitErrorsDetected; + + // Windows 7 addition + + ULONG64 EtwpDebuggerData; + USHORT OffsetPrcbContext; + + // Windows 8 addition + + USHORT OffsetPrcbMaxBreakpoints; + USHORT OffsetPrcbMaxWatchpoints; + + ULONG OffsetKThreadStackLimit; + ULONG OffsetKThreadStackBase; + ULONG OffsetKThreadQueueListEntry; + ULONG OffsetEThreadIrpList; + + USHORT OffsetPrcbIdleThread; + USHORT OffsetPrcbNormalDpcState; + USHORT OffsetPrcbDpcStack; + USHORT OffsetPrcbIsrStack; + + USHORT SizeKDPC_STACK_FRAME; + + // Windows 8.1 Addition + + USHORT OffsetKPriQueueThreadListHead; + USHORT OffsetKThreadWaitReason; + + // Windows 10 RS1 Addition + + USHORT Padding; + ULONG64 PteBase; + + // Windows 10 RS5 Addition + + ULONG64 RetpolineStubFunctionTable; + ULONG RetpolineStubFunctionTableSize; + ULONG RetpolineStubOffset; + ULONG RetpolineStubSize; + +} KDDEBUGGER_DATA64, *PKDDEBUGGER_DATA64; + + +typedef struct _DUMP_HEADER +{ + ULONG Signature; + ULONG ValidDump; + ULONG MajorVersion; + ULONG MinorVersion; + ULONG_PTR DirectoryTableBase; + ULONG_PTR PfnDataBase; + PLIST_ENTRY PsLoadedModuleList; + PLIST_ENTRY PsActiveProcessHead; + ULONG MachineImageType; + ULONG NumberProcessors; + ULONG BugCheckCode; + ULONG_PTR BugCheckParameter1; + ULONG_PTR BugCheckParameter2; + ULONG_PTR BugCheckParameter3; + ULONG_PTR BugCheckParameter4; + CHAR VersionUser[32]; + struct _KDDEBUGGER_DATA64 *KdDebuggerDataBlock; +} DUMP_HEADER, *PDUMP_HEADER; +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, Signature ) == 0 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, ValidDump ) == 4 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, MajorVersion ) == 8 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, MinorVersion ) == 0xc ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, DirectoryTableBase ) == 0x10 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, PfnDataBase ) == 0x18 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, PsLoadedModuleList ) == 0x20 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, PsActiveProcessHead ) == 0x28 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, MachineImageType ) == 0x30 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, NumberProcessors ) == 0x34 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckCode ) == 0x38 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckParameter1 ) == 0x40 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckParameter2 ) == 0x48 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckParameter3 ) == 0x50 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckParameter4 ) == 0x58 ); +C_ASSERT( FIELD_OFFSET( DUMP_HEADER, KdDebuggerDataBlock ) == 0x80 ); + +extern KDDEBUGGER_DATA64 g_KdBlock; \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/NativeStructs10.h b/third/Blackbone/src/BlackBoneDrv/NativeStructs10.h new file mode 100644 index 0000000000000000000000000000000000000000..9d1f3cbaad10c5eb3ef55eb87bc1ae428d05b6bf --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/NativeStructs10.h @@ -0,0 +1,193 @@ +#pragma once + +// +// Native structures W10 technical preview x64, build 9841 +// +#pragma warning(disable : 4214 4201) +#pragma pack(push, 1) + +typedef struct _MM_AVL_NODE // Size=24 +{ + struct _MM_AVL_NODE * LeftChild; // Size=8 Offset=0 + struct _MM_AVL_NODE * RightChild; // Size=8 Offset=8 + + union ___unnamed1666 // Size=8 + { + struct + { + __int64 Balance : 2; // Size=8 Offset=0 BitOffset=0 BitCount=2 + }; + struct _MM_AVL_NODE * Parent; // Size=8 Offset=0 + } u1; +} MM_AVL_NODE, *PMM_AVL_NODE, *PMMADDRESS_NODE; + +typedef struct _RTL_AVL_TREE // Size=8 +{ + PMM_AVL_NODE BalancedRoot; + void * NodeHint; + unsigned __int64 NumberGenericTableElements; +} RTL_AVL_TREE, *PRTL_AVL_TREE, MM_AVL_TABLE, *PMM_AVL_TABLE; + +union _EX_PUSH_LOCK // Size=8 +{ + struct + { + unsigned __int64 Locked : 1; // Size=8 Offset=0 BitOffset=0 BitCount=1 + unsigned __int64 Waiting : 1; // Size=8 Offset=0 BitOffset=1 BitCount=1 + unsigned __int64 Waking : 1; // Size=8 Offset=0 BitOffset=2 BitCount=1 + unsigned __int64 MultipleShared : 1; // Size=8 Offset=0 BitOffset=3 BitCount=1 + unsigned __int64 Shared : 60; // Size=8 Offset=0 BitOffset=4 BitCount=60 + }; + unsigned __int64 Value; // Size=8 Offset=0 + void * Ptr; // Size=8 Offset=0 +}; + +struct _MMVAD_FLAGS // Size=4 +{ + unsigned long VadType: 3; // Size=4 Offset=0 BitOffset=0 BitCount=3 + unsigned long Protection: 5; // Size=4 Offset=0 BitOffset=3 BitCount=5 + unsigned long PreferredNode: 6; // Size=4 Offset=0 BitOffset=8 BitCount=6 + unsigned long NoChange: 1; // Size=4 Offset=0 BitOffset=14 BitCount=1 + unsigned long PrivateMemory: 1; // Size=4 Offset=0 BitOffset=15 BitCount=1 + unsigned long Teb: 1; // Size=4 Offset=0 BitOffset=16 BitCount=1 + unsigned long PrivateFixup: 1; // Size=4 Offset=0 BitOffset=17 BitCount=1 + unsigned long ManySubsections: 1; // Size=4 Offset=0 BitOffset=18 BitCount=1 + unsigned long Spare: 12; // Size=4 Offset=0 BitOffset=19 BitCount=12 + unsigned long DeleteInProgress: 1; // Size=4 Offset=0 BitOffset=31 BitCount=1 +}; +struct _MMVAD_FLAGS1 // Size=4 +{ + unsigned long CommitCharge : 31; // Size=4 Offset=0 BitOffset=0 BitCount=31 + unsigned long MemCommit : 1; // Size=4 Offset=0 BitOffset=31 BitCount=1 +}; + +struct _MMVAD_FLAGS2 // Size=4 +{ + unsigned long FileOffset : 24; // Size=4 Offset=0 BitOffset=0 BitCount=24 + unsigned long Large : 1; // Size=4 Offset=0 BitOffset=24 BitCount=1 + unsigned long TrimBehind : 1; // Size=4 Offset=0 BitOffset=25 BitCount=1 + unsigned long Inherit : 1; // Size=4 Offset=0 BitOffset=26 BitCount=1 + unsigned long CopyOnWrite : 1; // Size=4 Offset=0 BitOffset=27 BitCount=1 + unsigned long NoValidationNeeded : 1; // Size=4 Offset=0 BitOffset=28 BitCount=1 + unsigned long Spare : 3; // Size=4 Offset=0 BitOffset=29 BitCount=3 +}; + +struct _MI_VAD_SEQUENTIAL_INFO // Size=8 +{ + unsigned __int64 Length : 12; // Size=8 Offset=0 BitOffset=0 BitCount=12 + unsigned __int64 Vpn : 52; // Size=8 Offset=0 BitOffset=12 BitCount=52 +}; + +union ___unnamed1951 // Size=4 +{ + unsigned long LongFlags; // Size=4 Offset=0 + struct _MMVAD_FLAGS VadFlags; // Size=4 Offset=0 +}; + +union ___unnamed1952 // Size=4 +{ + unsigned long LongFlags1; // Size=4 Offset=0 + struct _MMVAD_FLAGS1 VadFlags1; // Size=4 Offset=0 +}; + +union ___unnamed2047 // Size=4 +{ + unsigned long LongFlags2; // Size=4 Offset=0 + struct _MMVAD_FLAGS2 VadFlags2; // Size=4 Offset=0 +}; + +union ___unnamed2048 // Size=8 +{ + struct _MI_VAD_SEQUENTIAL_INFO SequentialVa; // Size=8 Offset=0 + struct _MMEXTEND_INFO * ExtendedInfo; // Size=8 Offset=0 +}; + +typedef struct _MMVAD_SHORT // Size=64 +{ + union + { + struct _RTL_BALANCED_NODE VadNode; // Size=24 Offset=0 + struct _MMVAD_SHORT * NextVad; // Size=8 Offset=0 + }; + unsigned long StartingVpn; // Size=4 Offset=24 + unsigned long EndingVpn; // Size=4 Offset=28 + unsigned char StartingVpnHigh; // Size=1 Offset=32 + unsigned char EndingVpnHigh; // Size=1 Offset=33 + unsigned char CommitChargeHigh; // Size=1 Offset=34 + unsigned char SpareNT64VadUChar; // Size=1 Offset=35 + long ReferenceCount; // Size=4 Offset=36 + union _EX_PUSH_LOCK PushLock; // Size=8 Offset=40 + union ___unnamed1951 u; // Size=4 Offset=48 + union ___unnamed1952 u1; // Size=4 Offset=52 + struct _MI_VAD_EVENT_BLOCK * EventList; // Size=8 Offset=56 +} MMVAD_SHORT, *PMMVAD_SHORT; + + +typedef struct _MMVAD // Size=128 +{ + struct _MMVAD_SHORT Core; // Size=64 Offset=0 + union ___unnamed2047 u2; // Size=4 Offset=64 + unsigned long pad0; // Size=4 Offset=68 + struct _SUBSECTION * Subsection; // Size=8 Offset=72 + struct _MMPTE * FirstPrototypePte; // Size=8 Offset=80 + struct _MMPTE * LastContiguousPte; // Size=8 Offset=88 + struct _LIST_ENTRY ViewLinks; // Size=16 Offset=96 + struct _EPROCESS * VadsProcess; // Size=8 Offset=112 + union ___unnamed2048 u4; // Size=8 Offset=120 + struct _FILE_OBJECT * FileObject; // Size=8 Offset=128 +} MMVAD, *PMMVAD; +#pragma pack(pop) + +typedef struct _HANDLE_TABLE +{ + ULONG NextHandleNeedingPool; + long ExtraInfoPages; + LONG_PTR TableCode; + PEPROCESS QuotaProcess; + LIST_ENTRY HandleTableList; + ULONG UniqueProcessId; + ULONG Flags; + EX_PUSH_LOCK HandleContentionEvent; + EX_PUSH_LOCK HandleTableLock; + // More fields here... +} HANDLE_TABLE, *PHANDLE_TABLE; + +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; +} 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]; +} API_SET_NAMESPACE_ARRAY_10, *PAPI_SET_NAMESPACE_ARRAY_10; + +#pragma warning(default : 4214 4201) + +#define GET_VAD_ROOT(Table) Table->BalancedRoot \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/NativeStructs7.h b/third/Blackbone/src/BlackBoneDrv/NativeStructs7.h new file mode 100644 index 0000000000000000000000000000000000000000..531e61f0b9c3138051f7fa232f2b28cdb4d5127d --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/NativeStructs7.h @@ -0,0 +1,176 @@ +#pragma once + +// +// Native structures W7 x64 SP1 +// +#pragma warning(disable : 4214 4201) + +struct _MMVAD_FLAGS // Size=8 +{ + unsigned __int64 CommitCharge: 51; // Size=8 Offset=0 BitOffset=0 BitCount=51 + unsigned __int64 NoChange: 1; // Size=8 Offset=0 BitOffset=51 BitCount=1 + unsigned __int64 VadType: 3; // Size=8 Offset=0 BitOffset=52 BitCount=3 + unsigned __int64 MemCommit: 1; // Size=8 Offset=0 BitOffset=55 BitCount=1 + unsigned __int64 Protection: 5; // Size=8 Offset=0 BitOffset=56 BitCount=5 + unsigned __int64 Spare: 2; // Size=8 Offset=0 BitOffset=61 BitCount=2 + unsigned __int64 PrivateMemory: 1; // Size=8 Offset=0 BitOffset=63 BitCount=1 +}; + +struct _MMVAD_FLAGS3 // Size=8 +{ + unsigned __int64 PreferredNode: 6; // Size=8 Offset=0 BitOffset=0 BitCount=6 + unsigned __int64 Teb: 1; // Size=8 Offset=0 BitOffset=6 BitCount=1 + unsigned __int64 Spare: 1; // Size=8 Offset=0 BitOffset=7 BitCount=1 + unsigned __int64 SequentialAccess: 1; // Size=8 Offset=0 BitOffset=8 BitCount=1 + unsigned __int64 LastSequentialTrim: 15; // Size=8 Offset=0 BitOffset=9 BitCount=15 + unsigned __int64 Spare2: 8; // Size=8 Offset=0 BitOffset=24 BitCount=8 + unsigned __int64 LargePageCreating: 1; // Size=8 Offset=0 BitOffset=32 BitCount=1 + unsigned __int64 Spare3: 31; // Size=8 Offset=0 BitOffset=33 BitCount=31 +}; + +struct _MMVAD_FLAGS2 // Size=4 +{ + unsigned int FileOffset: 24; // Size=4 Offset=0 BitOffset=0 BitCount=24 + unsigned int SecNoChange: 1; // Size=4 Offset=0 BitOffset=24 BitCount=1 + unsigned int OneSecured: 1; // Size=4 Offset=0 BitOffset=25 BitCount=1 + unsigned int MultipleSecured: 1; // Size=4 Offset=0 BitOffset=26 BitCount=1 + unsigned int Spare: 1; // Size=4 Offset=0 BitOffset=27 BitCount=1 + unsigned int LongVad: 1; // Size=4 Offset=0 BitOffset=28 BitCount=1 + unsigned int ExtendableFile: 1; // Size=4 Offset=0 BitOffset=29 BitCount=1 + unsigned int Inherit: 1; // Size=4 Offset=0 BitOffset=30 BitCount=1 + unsigned int CopyOnWrite: 1; // Size=4 Offset=0 BitOffset=31 BitCount=1 +}; + +struct _MMSECURE_FLAGS // Size=4 +{ + unsigned long ReadOnly: 1; // Size=4 Offset=0 BitOffset=0 BitCount=1 + unsigned long NoWrite: 1; // Size=4 Offset=0 BitOffset=1 BitCount=1 + unsigned long Spare: 10; // Size=4 Offset=0 BitOffset=2 BitCount=10 +}; + +union ___unnamed710 // Size=8 +{ + struct + { + __int64 Balance: 2; // Size=8 Offset=0 BitOffset=0 BitCount=2 + }; + struct _MMADDRESS_NODE * Parent; // Size=8 Offset=0 +}; + +union ___unnamed712 // Size=8 +{ + unsigned __int64 LongFlags; // Size=8 Offset=0 + struct _MMVAD_FLAGS VadFlags; // Size=8 Offset=0 +}; +union ___unnamed713 // Size=8 +{ + unsigned __int64 LongFlags3; // Size=8 Offset=0 + struct _MMVAD_FLAGS3 VadFlags3; // Size=8 Offset=0 +}; + +union ___unnamed715 // Size=4 +{ + unsigned long LongFlags2; // Size=4 Offset=0 + struct _MMVAD_FLAGS2 VadFlags2; // Size=4 Offset=0 +}; + +union ___unnamed1322 // Size=8 +{ + struct _MMSECURE_FLAGS Flags; // Size=4 Offset=0 + void * StartVa; // Size=8 Offset=0 +}; + +struct _MMADDRESS_LIST // Size=16 +{ + union ___unnamed1322 u1; // Size=8 Offset=0 + void * EndVa; // Size=8 Offset=8 +}; + +union ___unnamed1319 // Size=16 +{ + struct _LIST_ENTRY List; // Size=16 Offset=0 + struct _MMADDRESS_LIST Secured; // Size=16 Offset=0 +}; + +union ___unnamed1320 // Size=8 +{ + struct _MMBANKED_SECTION * Banked; // Size=8 Offset=0 + struct _MMEXTEND_INFO * ExtendedInfo; // Size=8 Offset=0 +}; + +typedef struct _MMADDRESS_NODE // Size=40 +{ + union ___unnamed710 u1; + struct _MMADDRESS_NODE * LeftChild; // Size=8 Offset=8 + struct _MMADDRESS_NODE * RightChild; // Size=8 Offset=16 + unsigned __int64 StartingVpn; // Size=8 Offset=24 + unsigned __int64 EndingVpn; // Size=8 Offset=32 + +} MMADDRESS_NODE, *PMMADDRESS_NODE, *PMM_AVL_NODE; + +typedef struct _MM_AVL_TABLE // Size=64 +{ + struct _MMADDRESS_NODE BalancedRoot; // Size=40 Offset=0 + struct + { + unsigned __int64 DepthOfTree: 5; // Size=8 Offset=40 BitOffset=0 BitCount=5 + unsigned __int64 Unused: 3; // Size=8 Offset=40 BitOffset=5 BitCount=3 + unsigned __int64 NumberGenericTableElements: 56; // Size=8 Offset=40 BitOffset=8 BitCount=56 + }; + void * NodeHint; // Size=8 Offset=48 + void * NodeFreeHint; // Size=8 Offset=56 + +} MM_AVL_TABLE, *PMM_AVL_TABLE; + +typedef struct _MMVAD_SHORT // Size=64 +{ + union ___unnamed710 u1; // Size=8 Offset=0 + struct _MMVAD * LeftChild; // Size=8 Offset=8 + struct _MMVAD * RightChild; // Size=8 Offset=16 + unsigned __int64 StartingVpn; // Size=8 Offset=24 + unsigned __int64 EndingVpn; // Size=8 Offset=32 + union ___unnamed712 u; // Size=8 Offset=40 + void * PushLock; // Size=8 Offset=48 + union ___unnamed713 u5; // Size=8 Offset=56 +} MMVAD_SHORT, *PMMVAD_SHORT; + +typedef struct _MMVAD // Size=120 +{ + MMVAD_SHORT vadShort; + union ___unnamed715 u2; // Size=4 Offset=64 + unsigned long pad0; // Size=4 Offset=68 + struct _SUBSECTION * Subsection; // Size=8 Offset=72 + struct _MMPTE * FirstPrototypePte; // Size=8 Offset=80 + struct _MMPTE * LastContiguousPte; // Size=8 Offset=88 + struct _LIST_ENTRY ViewLinks; // Size=16 Offset=96 + struct _EPROCESS * VadsProcess; // Size=8 Offset=112 +} MMVAD, *PMMVAD; + +typedef struct _MMVAD_LONG // Size=144 +{ + MMVAD vad; + union ___unnamed1319 u3; // Size=16 Offset=120 + union ___unnamed1320 u4; // Size=8 Offset=136 +} MMVAD_LONG, *PMMVAD_LONG; + +typedef struct _HANDLE_TABLE +{ + ULONG_PTR TableCode; + struct _EPROCESS *QuotaProcess; + HANDLE UniqueProcessId; + void* HandleLock; + struct _LIST_ENTRY HandleTableList; + EX_PUSH_LOCK HandleContentionEvent; + struct _HANDLE_TRACE_DEBUG_INFO *DebugInfo; + int ExtraInfoPages; + ULONG Flags; + ULONG FirstFreeHandle; + struct _HANDLE_TABLE_ENTRY *LastFreeHandleEntry; + ULONG HandleCount; + ULONG NextHandleNeedingPool; + // More fields here... +} HANDLE_TABLE, *PHANDLE_TABLE; + +#pragma warning(default : 4214 4201) + +#define GET_VAD_ROOT(Table) &Table->BalancedRoot \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/NativeStructs8.h b/third/Blackbone/src/BlackBoneDrv/NativeStructs8.h new file mode 100644 index 0000000000000000000000000000000000000000..0998fd790cc4ce1394dda54df700f951faf6e6f6 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/NativeStructs8.h @@ -0,0 +1,155 @@ +#pragma once + +// +// Native structures W8 x64 +// +#pragma warning(disable : 4214 4201) + +struct _MMVAD_FLAGS // Size=4 +{ + unsigned long VadType: 3; // Size=4 Offset=0 BitOffset=0 BitCount=3 + unsigned long Protection: 5; // Size=4 Offset=0 BitOffset=3 BitCount=5 + unsigned long PreferredNode: 6; // Size=4 Offset=0 BitOffset=8 BitCount=6 + unsigned long NoChange: 1; // Size=4 Offset=0 BitOffset=14 BitCount=1 + unsigned long PrivateMemory: 1; // Size=4 Offset=0 BitOffset=15 BitCount=1 + unsigned long Teb: 1; // Size=4 Offset=0 BitOffset=16 BitCount=1 + unsigned long PrivateFixup: 1; // Size=4 Offset=0 BitOffset=17 BitCount=1 + unsigned long Spare: 13; // Size=4 Offset=0 BitOffset=18 BitCount=13 + unsigned long DeleteInProgress: 1; // Size=4 Offset=0 BitOffset=31 BitCount=1 +}; + +struct _MMVAD_FLAGS1 // Size=4 +{ + unsigned long CommitCharge: 31; // Size=4 Offset=0 BitOffset=0 BitCount=31 + unsigned long MemCommit: 1; // Size=4 Offset=0 BitOffset=31 BitCount=1 +}; + +struct _MMVAD_FLAGS2 // Size=4 +{ + unsigned long FileOffset: 24; // Size=4 Offset=0 BitOffset=0 BitCount=24 + unsigned long Large: 1; // Size=4 Offset=0 BitOffset=24 BitCount=1 + unsigned long TrimBehind: 1; // Size=4 Offset=0 BitOffset=25 BitCount=1 + unsigned long Inherit: 1; // Size=4 Offset=0 BitOffset=26 BitCount=1 + unsigned long CopyOnWrite: 1; // Size=4 Offset=0 BitOffset=27 BitCount=1 + unsigned long NoValidationNeeded: 1; // Size=4 Offset=0 BitOffset=28 BitCount=1 + unsigned long Spare: 3; // Size=4 Offset=0 BitOffset=29 BitCount=3 +}; + +struct _MMVAD_FLAGS3 // Size=8 +{ + unsigned __int64 PreferredNode: 6; // Size=8 Offset=0 BitOffset=0 BitCount=6 + unsigned __int64 Teb: 1; // Size=8 Offset=0 BitOffset=6 BitCount=1 + unsigned __int64 Spare: 1; // Size=8 Offset=0 BitOffset=7 BitCount=1 + unsigned __int64 SequentialAccess: 1; // Size=8 Offset=0 BitOffset=8 BitCount=1 + unsigned __int64 LastSequentialTrim: 15; // Size=8 Offset=0 BitOffset=9 BitCount=15 + unsigned __int64 Spare2: 8; // Size=8 Offset=0 BitOffset=24 BitCount=8 + unsigned __int64 LargePageCreating: 1; // Size=8 Offset=0 BitOffset=32 BitCount=1 + unsigned __int64 Spare3: 31; // Size=8 Offset=0 BitOffset=33 BitCount=31 +}; + +struct _MMSECURE_FLAGS // Size=4 +{ + unsigned long ReadOnly: 1; // Size=4 Offset=0 BitOffset=0 BitCount=1 + unsigned long NoWrite: 1; // Size=4 Offset=0 BitOffset=1 BitCount=1 + unsigned long Spare: 10; // Size=4 Offset=0 BitOffset=2 BitCount=10 +}; + +struct _MI_VAD_SEQUENTIAL_INFO // Size=8 +{ + unsigned __int64 Length: 12; // Size=8 Offset=0 BitOffset=0 BitCount=12 + unsigned __int64 Vpn: 52; // Size=8 Offset=0 BitOffset=12 BitCount=52 +}; + +union ___unnamed1666 // Size=8 +{ + struct + { + __int64 Balance: 2; // Size=8 Offset=0 BitOffset=0 BitCount=2 + }; + struct _MM_AVL_NODE * Parent; // Size=8 Offset=0 +}; + +union ___unnamed1784 // Size=4 +{ + unsigned long LongFlags; // Size=4 Offset=0 + struct _MMVAD_FLAGS VadFlags; // Size=4 Offset=0 +}; +union ___unnamed1785 // Size=4 +{ + unsigned long LongFlags1; // Size=4 Offset=0 + struct _MMVAD_FLAGS1 VadFlags1; // Size=4 Offset=0 +}; + +union ___unnamed1883 // Size=4 +{ + unsigned long LongFlags2; // Size=4 Offset=0 + struct _MMVAD_FLAGS2 VadFlags2; // Size=4 Offset=0 +}; + +union ___unnamed1885 // Size=8 +{ + struct _MI_VAD_SEQUENTIAL_INFO SequentialVa; // Size=8 Offset=0 + struct _MMEXTEND_INFO * ExtendedInfo; // Size=8 Offset=0 +}; + +typedef struct _MM_AVL_NODE // Size=24 +{ + union ___unnamed1666 u1; // Size=8 Offset=0 + struct _MM_AVL_NODE * LeftChild; // Size=8 Offset=8 + struct _MM_AVL_NODE * RightChild; // Size=8 Offset=16 +} MM_AVL_NODE, *PMM_AVL_NODE, *PMMADDRESS_NODE; + +typedef struct _MM_AVL_TABLE // Size=48 +{ + struct _MM_AVL_NODE BalancedRoot; // Size=24 Offset=0 + struct + { + unsigned __int64 DepthOfTree: 5; // Size=8 Offset=24 BitOffset=0 BitCount=5 + unsigned __int64 TableType: 3; // Size=8 Offset=24 BitOffset=5 BitCount=3 + unsigned __int64 NumberGenericTableElements: 56; // Size=8 Offset=24 BitOffset=8 BitCount=56 + }; + void * NodeHint; // Size=8 Offset=32 + void * NodeFreeHint; // Size=8 Offset=40 +} MM_AVL_TABLE, *PMM_AVL_TABLE; + +typedef struct _MMVAD_SHORT // Size=64 +{ + struct _MM_AVL_NODE VadNode; // Size=24 Offset=0 + unsigned long StartingVpn; // Size=4 Offset=24 + unsigned long EndingVpn; // Size=4 Offset=28 + void * PushLock; // Size=8 Offset=32 + union ___unnamed1784 u; // Size=4 Offset=40 + union ___unnamed1785 u1; // Size=4 Offset=44 + struct _MI_VAD_EVENT_BLOCK * EventList; // Size=8 Offset=48 + long ReferenceCount; // Size=4 Offset=56 +} MMVAD_SHORT, *PMMVAD_SHORT; + +typedef struct _MMVAD // Size=128 +{ + struct _MMVAD_SHORT Core; // Size=64 Offset=0 + union ___unnamed1883 u2; // Size=4 Offset=64 + struct _SUBSECTION * Subsection; // Size=8 Offset=72 + struct _MMPTE * FirstPrototypePte; // Size=8 Offset=80 + struct _MMPTE * LastContiguousPte; // Size=8 Offset=88 + struct _LIST_ENTRY ViewLinks; // Size=16 Offset=96 + struct _EPROCESS * VadsProcess; // Size=8 Offset=112 + union ___unnamed1885 u4; // Size=8 Offset=120 +} MMVAD, *PMMVAD; + +typedef struct _HANDLE_TABLE +{ + ULONG NextHandleNeedingPool; + long ExtraInfoPages; + ULONG_PTR TableCode; + struct _EPROCESS * QuotaProcess; + LIST_ENTRY HandleTableList; + ULONG UniqueProcessId; + ULONG Flags; + EX_PUSH_LOCK HandleContentionEvent; + EX_PUSH_LOCK HandleTableLock; + // More fields here... +} HANDLE_TABLE, *PHANDLE_TABLE; + +#pragma warning(default : 4214 4201) + +#define GET_VAD_ROOT(Table) (Table->BalancedRoot.RightChild) \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/NativeStructs81.h b/third/Blackbone/src/BlackBoneDrv/NativeStructs81.h new file mode 100644 index 0000000000000000000000000000000000000000..f8a5dbf2547fc4586c57ea01def162baaaeb632e --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/NativeStructs81.h @@ -0,0 +1,153 @@ +#pragma once + +// +// Native structures W8.1 x64 +// +#pragma warning(disable : 4214 4201) +#pragma pack(push, 1) + +typedef struct _MM_AVL_NODE // Size=24 +{ + struct _MM_AVL_NODE * LeftChild; // Size=8 Offset=0 + struct _MM_AVL_NODE * RightChild; // Size=8 Offset=8 + + union ___unnamed1666 // Size=8 + { + struct + { + __int64 Balance : 2; // Size=8 Offset=0 BitOffset=0 BitCount=2 + }; + struct _MM_AVL_NODE * Parent; // Size=8 Offset=0 + } u1; +} MM_AVL_NODE, *PMM_AVL_NODE, *PMMADDRESS_NODE; + +typedef struct _RTL_AVL_TREE // Size=8 +{ + PMM_AVL_NODE BalancedRoot; // Size=8 Offset=0 + void * NodeHint; // Size=8 Offset=1504 + unsigned __int64 NumberGenericTableElements; // Size=8 Offset=1512 +} RTL_AVL_TREE, *PRTL_AVL_TREE, *PMM_AVL_TABLE; + +union _EX_PUSH_LOCK // Size=8 +{ + struct + { + unsigned __int64 Locked : 1; // Size=8 Offset=0 BitOffset=0 BitCount=1 + unsigned __int64 Waiting : 1; // Size=8 Offset=0 BitOffset=1 BitCount=1 + unsigned __int64 Waking : 1; // Size=8 Offset=0 BitOffset=2 BitCount=1 + unsigned __int64 MultipleShared : 1; // Size=8 Offset=0 BitOffset=3 BitCount=1 + unsigned __int64 Shared : 60; // Size=8 Offset=0 BitOffset=4 BitCount=60 + }; + unsigned __int64 Value; // Size=8 Offset=0 + void * Ptr; // Size=8 Offset=0 +}; + +struct _MMVAD_FLAGS // Size=4 +{ + unsigned long VadType : 3; // Size=4 Offset=0 BitOffset=0 BitCount=3 + unsigned long Protection : 5; // Size=4 Offset=0 BitOffset=3 BitCount=5 + unsigned long PreferredNode : 6; // Size=4 Offset=0 BitOffset=8 BitCount=6 + unsigned long NoChange : 1; // Size=4 Offset=0 BitOffset=14 BitCount=1 + unsigned long PrivateMemory : 1; // Size=4 Offset=0 BitOffset=15 BitCount=1 + unsigned long Teb : 1; // Size=4 Offset=0 BitOffset=16 BitCount=1 + unsigned long PrivateFixup : 1; // Size=4 Offset=0 BitOffset=17 BitCount=1 + unsigned long Spare : 13; // Size=4 Offset=0 BitOffset=18 BitCount=13 + unsigned long DeleteInProgress : 1; // Size=4 Offset=0 BitOffset=31 BitCount=1 +}; +struct _MMVAD_FLAGS1 // Size=4 +{ + unsigned long CommitCharge : 31; // Size=4 Offset=0 BitOffset=0 BitCount=31 + unsigned long MemCommit : 1; // Size=4 Offset=0 BitOffset=31 BitCount=1 +}; + +struct _MMVAD_FLAGS2 // Size=4 +{ + unsigned long FileOffset : 24; // Size=4 Offset=0 BitOffset=0 BitCount=24 + unsigned long Large : 1; // Size=4 Offset=0 BitOffset=24 BitCount=1 + unsigned long TrimBehind : 1; // Size=4 Offset=0 BitOffset=25 BitCount=1 + unsigned long Inherit : 1; // Size=4 Offset=0 BitOffset=26 BitCount=1 + unsigned long CopyOnWrite : 1; // Size=4 Offset=0 BitOffset=27 BitCount=1 + unsigned long NoValidationNeeded : 1; // Size=4 Offset=0 BitOffset=28 BitCount=1 + unsigned long Spare : 3; // Size=4 Offset=0 BitOffset=29 BitCount=3 +}; + +struct _MI_VAD_SEQUENTIAL_INFO // Size=8 +{ + unsigned __int64 Length : 12; // Size=8 Offset=0 BitOffset=0 BitCount=12 + unsigned __int64 Vpn : 52; // Size=8 Offset=0 BitOffset=12 BitCount=52 +}; + +union ___unnamed1859 // Size=4 +{ + unsigned long LongFlags; // Size=4 Offset=0 + struct _MMVAD_FLAGS VadFlags; // Size=4 Offset=0 +}; +union ___unnamed1860 // Size=4 +{ + unsigned long LongFlags1; // Size=4 Offset=0 + struct _MMVAD_FLAGS1 VadFlags1; // Size=4 Offset=0 +}; + +union ___unnamed1956 // Size=4 +{ + unsigned long LongFlags2; // Size=4 Offset=0 + struct _MMVAD_FLAGS2 VadFlags2; // Size=4 Offset=0 +}; + +union ___unnamed1957 // Size=8 +{ + struct _MI_VAD_SEQUENTIAL_INFO SequentialVa; // Size=8 Offset=0 + struct _MMEXTEND_INFO * ExtendedInfo; // Size=8 Offset=0 +}; + +typedef struct _MMVAD_SHORT // Size=64 +{ + union + { + struct _MM_AVL_NODE VadNode; // Size=24 Offset=0 + struct _MMVAD_SHORT * NextVad; // Size=8 Offset=0 + }; + unsigned long StartingVpn; // Size=4 Offset=24 + unsigned long EndingVpn; // Size=4 Offset=28 + unsigned char StartingVpnHigh; // Size=1 Offset=32 + unsigned char EndingVpnHigh; // Size=1 Offset=33 + unsigned char CommitChargeHigh; // Size=1 Offset=34 + unsigned char LargeImageBias; // Size=1 Offset=35 + long ReferenceCount; // Size=4 Offset=36 + union _EX_PUSH_LOCK PushLock; // Size=8 Offset=40 + union ___unnamed1859 u; // Size=4 Offset=48 + union ___unnamed1860 u1; // Size=4 Offset=52 + struct _MI_VAD_EVENT_BLOCK * EventList; // Size=8 Offset=56 +} MMVAD_SHORT, *PMMVAD_SHORT; + +typedef struct _MMVAD // Size=128 +{ + struct _MMVAD_SHORT Core; // Size=64 Offset=0 + union ___unnamed1956 u2; // Size=4 Offset=64 + unsigned long pad0; // Size=4 Offset=68 + struct _SUBSECTION * Subsection; // Size=8 Offset=72 + struct _MMPTE * FirstPrototypePte; // Size=8 Offset=80 + struct _MMPTE * LastContiguousPte; // Size=8 Offset=88 + struct _LIST_ENTRY ViewLinks; // Size=16 Offset=96 + struct _EPROCESS * VadsProcess; // Size=8 Offset=112 + union ___unnamed1957 u4; // Size=8 Offset=120 +} MMVAD, *PMMVAD; +#pragma pack(pop) + +typedef struct _HANDLE_TABLE +{ + ULONG NextHandleNeedingPool; + long ExtraInfoPages; + LONG_PTR TableCode; + struct _EPROCESS * QuotaProcess; + LIST_ENTRY HandleTableList; + ULONG UniqueProcessId; + ULONG Flags; + EX_PUSH_LOCK HandleContentionEvent; + EX_PUSH_LOCK HandleTableLock; + // More fields here... +} HANDLE_TABLE, *PHANDLE_TABLE; + +#pragma warning(default : 4214 4201) + +#define GET_VAD_ROOT(Table) Table->BalancedRoot \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/NotifyRoutine.c b/third/Blackbone/src/BlackBoneDrv/NotifyRoutine.c new file mode 100644 index 0000000000000000000000000000000000000000..9a12c18089210fb1c6f96fe85367080cf8c1f06a --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/NotifyRoutine.c @@ -0,0 +1,50 @@ +#include "Remap.h" +#include "BlackBoneDrv.h" +#include "Routines.h" + +#pragma alloc_text(PAGE, BBProcessNotify) + + +/// +/// Process termination handler +/// +/// Parent PID +/// PID +/// TRUE if process was created +VOID BBProcessNotify( IN HANDLE ParentId, IN HANDLE ProcessId, IN BOOLEAN Create ) +{ + UNREFERENCED_PARAMETER( ParentId ); + PPROCESS_MAP_ENTRY pProcessEntry = NULL; + PMEM_PHYS_PROCESS_ENTRY pPhysProcessEntry = NULL; + + if (Create == FALSE) + { + pPhysProcessEntry = BBLookupPhysProcessEntry( ProcessId ); + if (pPhysProcessEntry != NULL) + { + DPRINT( "BlackBone: %s: Target process %u shutdown. Physical memory Cleanup\n", __FUNCTION__, ProcessId ); + BBCleanupProcessPhysEntry( pPhysProcessEntry, TRUE ); + } + + KeAcquireGuardedMutex( &g_globalLock ); + + pProcessEntry = BBLookupProcessEntry( ProcessId, FALSE ); + + // Target process shutdown + if (pProcessEntry != NULL) + { + DPRINT( "BlackBone: %s: Target process %u shutdown. Cleanup\n", __FUNCTION__, pProcessEntry->target.pid ); + BBCleanupProcessEntry( pProcessEntry ); + } + else + { + pProcessEntry = BBLookupProcessEntry( ProcessId, TRUE ); + + // Host process shutdown + if (pProcessEntry != NULL) + BBCleanupHostProcess( pProcessEntry ); + } + + KeReleaseGuardedMutex( &g_globalLock ); + } +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/PEStructs.h b/third/Blackbone/src/BlackBoneDrv/PEStructs.h new file mode 100644 index 0000000000000000000000000000000000000000..f17c7e652f587fe3fd9363774924c17e2f103ef8 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/PEStructs.h @@ -0,0 +1,551 @@ +#pragma once +#include "NativeEnums.h" +#include + + +#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define IMAGE_NT_SIGNATURE 0x00004550 // PE00 + +#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b +#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory +// IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage) +#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP +#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory +#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers +#define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table +#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors +#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor + +#define IMAGE_REL_BASED_ABSOLUTE 0 +#define IMAGE_REL_BASED_HIGH 1 +#define IMAGE_REL_BASED_LOW 2 +#define IMAGE_REL_BASED_HIGHLOW 3 +#define IMAGE_REL_BASED_HIGHADJ 4 +#define IMAGE_REL_BASED_MIPS_JMPADDR 5 +#define IMAGE_REL_BASED_SECTION 6 +#define IMAGE_REL_BASED_REL32 7 +#define IMAGE_REL_BASED_MIPS_JMPADDR16 9 +#define IMAGE_REL_BASED_IA64_IMM64 9 +#define IMAGE_REL_BASED_DIR64 10 + +#define IMAGE_SIZEOF_BASE_RELOCATION 8 + + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved external references). +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. +#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 // Aggressively trim working set +#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 // App can handle >2gb addresses +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. +#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file +#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 // If Image is on removable media, copy and run from the swap file. +#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 // If Image is on Net, copy and run from the swap file. +#define IMAGE_FILE_SYSTEM 0x1000 // System File. +#define IMAGE_FILE_DLL 0x2000 // File is a DLL. +#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 // File should only be run on a UP machine +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. + +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386. +#define IMAGE_FILE_MACHINE_R3000 0x0162 // MIPS little-endian, 0x160 big-endian +#define IMAGE_FILE_MACHINE_R4000 0x0166 // MIPS little-endian +#define IMAGE_FILE_MACHINE_R10000 0x0168 // MIPS little-endian +#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 // MIPS little-endian WCE v2 +#define IMAGE_FILE_MACHINE_ALPHA 0x0184 // Alpha_AXP +#define IMAGE_FILE_MACHINE_SH3 0x01a2 // SH3 little-endian +#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 +#define IMAGE_FILE_MACHINE_SH3E 0x01a4 // SH3E little-endian +#define IMAGE_FILE_MACHINE_SH4 0x01a6 // SH4 little-endian +#define IMAGE_FILE_MACHINE_SH5 0x01a8 // SH5 +#define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian +#define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian +#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian +#define IMAGE_FILE_MACHINE_AM33 0x01d3 +#define IMAGE_FILE_MACHINE_POWERPC 0x01F0 // IBM PowerPC Little-Endian +#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 +#define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64 +#define IMAGE_FILE_MACHINE_MIPS16 0x0266 // MIPS +#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64 +#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 // MIPS +#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 // MIPS +#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64 +#define IMAGE_FILE_MACHINE_TRICORE 0x0520 // Infineon +#define IMAGE_FILE_MACHINE_CEF 0x0CEF +#define IMAGE_FILE_MACHINE_EBC 0x0EBC // EFI Byte Code +#define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8) +#define IMAGE_FILE_MACHINE_M32R 0x9041 // M32R little-endian +#define IMAGE_FILE_MACHINE_CEE 0xC0EE + +#define IMAGE_ORDINAL_FLAG64 0x8000000000000000 +#define IMAGE_ORDINAL_FLAG32 0x80000000 +#define IMAGE_ORDINAL64(Ordinal) (Ordinal & 0xffff) +#define IMAGE_ORDINAL32(Ordinal) (Ordinal & 0xffff) +#define IMAGE_SNAP_BY_ORDINAL64(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG64) != 0) +#define IMAGE_SNAP_BY_ORDINAL32(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG32) != 0) + +// +// Section characteristics. +// +// IMAGE_SCN_TYPE_REG 0x00000000 // Reserved. +// IMAGE_SCN_TYPE_DSECT 0x00000001 // Reserved. +// IMAGE_SCN_TYPE_NOLOAD 0x00000002 // Reserved. +// IMAGE_SCN_TYPE_GROUP 0x00000004 // Reserved. +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved. +// IMAGE_SCN_TYPE_COPY 0x00000010 // Reserved. + +#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code. +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data. +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data. + +#define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved. +#define IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information. +// IMAGE_SCN_TYPE_OVER 0x00000400 // Reserved. +#define IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image. +#define IMAGE_SCN_LNK_COMDAT 0x00001000 // Section contents comdat. +// 0x00002000 // Reserved. +// IMAGE_SCN_MEM_PROTECTED - Obsolete 0x00004000 +#define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000 // Reset speculative exceptions handling bits in the TLB entries for this section. +#define IMAGE_SCN_GPREL 0x00008000 // Section content can be accessed relative to GP +#define IMAGE_SCN_MEM_FARDATA 0x00008000 +// IMAGE_SCN_MEM_SYSHEAP - Obsolete 0x00010000 +#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 +#define IMAGE_SCN_MEM_16BIT 0x00020000 +#define IMAGE_SCN_MEM_LOCKED 0x00040000 +#define IMAGE_SCN_MEM_PRELOAD 0x00080000 + +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 // +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 // +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 // +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 // +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 // Default alignment if no others are specified. +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 // +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 // +#define IMAGE_SCN_ALIGN_128BYTES 0x00800000 // +#define IMAGE_SCN_ALIGN_256BYTES 0x00900000 // +#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000 // +#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000 // +#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000 // +#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000 // +#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000 // +// Unused 0x00F00000 +#define IMAGE_SCN_ALIGN_MASK 0x00F00000 + +#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 // Section contains extended relocations. +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded. +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable. +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable. +#define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable. +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable. +#define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable. +#define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable. + +typedef struct _IMAGE_DOS_HEADER +{ + USHORT e_magic; + USHORT e_cblp; + USHORT e_cp; + USHORT e_crlc; + USHORT e_cparhdr; + USHORT e_minalloc; + USHORT e_maxalloc; + USHORT e_ss; + USHORT e_sp; + USHORT e_csum; + USHORT e_ip; + USHORT e_cs; + USHORT e_lfarlc; + USHORT e_ovno; + USHORT e_res[4]; + USHORT e_oemid; + USHORT e_oeminfo; + USHORT e_res2[10]; + LONG e_lfanew; +} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +typedef struct _IMAGE_SECTION_HEADER +{ + UCHAR Name[8]; + union + { + ULONG PhysicalAddress; + ULONG VirtualSize; + } Misc; + ULONG VirtualAddress; + ULONG SizeOfRawData; + ULONG PointerToRawData; + ULONG PointerToRelocations; + ULONG PointerToLinenumbers; + USHORT NumberOfRelocations; + USHORT NumberOfLinenumbers; + ULONG Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +typedef struct _IMAGE_FILE_HEADER // Size=20 +{ + USHORT Machine; + USHORT NumberOfSections; + ULONG TimeDateStamp; + ULONG PointerToSymbolTable; + ULONG NumberOfSymbols; + USHORT SizeOfOptionalHeader; + USHORT Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +typedef struct _IMAGE_DATA_DIRECTORY +{ + ULONG VirtualAddress; + ULONG Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +typedef struct _IMAGE_OPTIONAL_HEADER64 +{ + USHORT Magic; + UCHAR MajorLinkerVersion; + UCHAR MinorLinkerVersion; + ULONG SizeOfCode; + ULONG SizeOfInitializedData; + ULONG SizeOfUninitializedData; + ULONG AddressOfEntryPoint; + ULONG BaseOfCode; + ULONGLONG ImageBase; + ULONG SectionAlignment; + ULONG FileAlignment; + USHORT MajorOperatingSystemVersion; + USHORT MinorOperatingSystemVersion; + USHORT MajorImageVersion; + USHORT MinorImageVersion; + USHORT MajorSubsystemVersion; + USHORT MinorSubsystemVersion; + ULONG Win32VersionValue; + ULONG SizeOfImage; + ULONG SizeOfHeaders; + ULONG CheckSum; + USHORT Subsystem; + USHORT DllCharacteristics; + ULONGLONG SizeOfStackReserve; + ULONGLONG SizeOfStackCommit; + ULONGLONG SizeOfHeapReserve; + ULONGLONG SizeOfHeapCommit; + ULONG LoaderFlags; + ULONG NumberOfRvaAndSizes; + struct _IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64; + +typedef struct _IMAGE_OPTIONAL_HEADER32 +{ + // + // Standard fields. + // + + USHORT Magic; + UCHAR MajorLinkerVersion; + UCHAR MinorLinkerVersion; + ULONG SizeOfCode; + ULONG SizeOfInitializedData; + ULONG SizeOfUninitializedData; + ULONG AddressOfEntryPoint; + ULONG BaseOfCode; + ULONG BaseOfData; + + // + // NT additional fields. + // + + ULONG ImageBase; + ULONG SectionAlignment; + ULONG FileAlignment; + USHORT MajorOperatingSystemVersion; + USHORT MinorOperatingSystemVersion; + USHORT MajorImageVersion; + USHORT MinorImageVersion; + USHORT MajorSubsystemVersion; + USHORT MinorSubsystemVersion; + ULONG Win32VersionValue; + ULONG SizeOfImage; + ULONG SizeOfHeaders; + ULONG CheckSum; + USHORT Subsystem; + USHORT DllCharacteristics; + ULONG SizeOfStackReserve; + ULONG SizeOfStackCommit; + ULONG SizeOfHeapReserve; + ULONG SizeOfHeapCommit; + ULONG LoaderFlags; + ULONG NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; + +typedef struct _IMAGE_NT_HEADERS64 +{ + ULONG Signature; + struct _IMAGE_FILE_HEADER FileHeader; + struct _IMAGE_OPTIONAL_HEADER64 OptionalHeader; +} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64; + +typedef struct _IMAGE_NT_HEADERS +{ + ULONG Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER32 OptionalHeader; +} IMAGE_NT_HEADERS; + +typedef struct _IMAGE_EXPORT_DIRECTORY { + ULONG Characteristics; + ULONG TimeDateStamp; + USHORT MajorVersion; + USHORT MinorVersion; + ULONG Name; + ULONG Base; + ULONG NumberOfFunctions; + ULONG NumberOfNames; + ULONG AddressOfFunctions; // RVA from base of image + ULONG AddressOfNames; // RVA from base of image + ULONG AddressOfNameOrdinals; // RVA from base of image +} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; + +typedef struct _IMAGE_BASE_RELOCATION { + ULONG VirtualAddress; + ULONG SizeOfBlock; + // USHORT TypeOffset[1]; +} IMAGE_BASE_RELOCATION; +typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION; + +typedef struct _IMAGE_IMPORT_BY_NAME { + USHORT Hint; + CHAR Name[1]; +} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; + + +// warning C4201: nonstandard extension used : nameless struct/union +#pragma warning (disable : 4201) + +typedef struct _IMAGE_IMPORT_DESCRIPTOR +{ + union { + ULONG Characteristics; // 0 for terminating null import descriptor + ULONG OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) + }; + ULONG TimeDateStamp; // 0 if not bound, + // -1 if bound, and real date\time stamp + // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) + // O.W. date/time stamp of DLL bound to (Old BIND) + + ULONG ForwarderChain; // -1 if no forwarders + ULONG Name; + ULONG FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) +} IMAGE_IMPORT_DESCRIPTOR; +typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR; + + +typedef struct _IMAGE_THUNK_DATA64 +{ + union + { + ULONGLONG ForwarderString; // PBYTE + ULONGLONG Function; // PULONG + ULONGLONG Ordinal; + ULONGLONG AddressOfData; // PIMAGE_IMPORT_BY_NAME + } u1; +} IMAGE_THUNK_DATA64; +typedef IMAGE_THUNK_DATA64 * PIMAGE_THUNK_DATA64; + +typedef struct _IMAGE_THUNK_DATA32 +{ + union + { + ULONG ForwarderString; // PBYTE + ULONG Function; // PULONG + ULONG Ordinal; + ULONG AddressOfData; // PIMAGE_IMPORT_BY_NAME + } u1; +} IMAGE_THUNK_DATA32; +typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32; + +typedef struct _IMAGE_RESOURCE_DIRECTORY { + ULONG Characteristics; + ULONG TimeDateStamp; + USHORT MajorVersion; + USHORT MinorVersion; + USHORT NumberOfNamedEntries; + USHORT NumberOfIdEntries; + // IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[]; +} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY; + +typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { + union { + struct { + INT NameOffset : 31; + INT NameIsString : 1; + } DUMMYSTRUCTNAME; + ULONG Name; + USHORT Id; + } DUMMYUNIONNAME; + union { + ULONG OffsetToData; + struct { + INT OffsetToDirectory : 31; + INT DataIsDirectory : 1; + } DUMMYSTRUCTNAME2; + } DUMMYUNIONNAME2; +} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY; + +typedef struct _IMAGE_RESOURCE_DATA_ENTRY { + ULONG OffsetToData; + ULONG Size; + ULONG CodePage; + ULONG Reserved; +} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY; + +typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY { + ULONG BeginAddress; + ULONG EndAddress; + union { + ULONG UnwindInfoAddress; + ULONG UnwindData; + } DUMMYUNIONNAME; +} _IMAGE_RUNTIME_FUNCTION_ENTRY, *_PIMAGE_RUNTIME_FUNCTION_ENTRY; + +typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32 { + ULONG Size; + ULONG TimeDateStamp; + USHORT MajorVersion; + USHORT MinorVersion; + ULONG GlobalFlagsClear; + ULONG GlobalFlagsSet; + ULONG CriticalSectionDefaultTimeout; + ULONG DeCommitFreeBlockThreshold; + ULONG DeCommitTotalFreeThreshold; + ULONG LockPrefixTable; // VA + ULONG MaximumAllocationSize; + ULONG VirtualMemoryThreshold; + ULONG ProcessHeapFlags; + ULONG ProcessAffinityMask; + USHORT CSDVersion; + USHORT Reserved1; + ULONG EditList; // VA + ULONG SecurityCookie; // VA + ULONG SEHandlerTable; // VA + ULONG SEHandlerCount; + ULONG GuardCFCheckFunctionPointer; // VA + ULONG Reserved2; + ULONG GuardCFFunctionTable; // VA + ULONG GuardCFFunctionCount; + ULONG GuardFlags; +} IMAGE_LOAD_CONFIG_DIRECTORY32, *PIMAGE_LOAD_CONFIG_DIRECTORY32; + +typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64 { + ULONG Size; + ULONG TimeDateStamp; + USHORT MajorVersion; + USHORT MinorVersion; + ULONG GlobalFlagsClear; + ULONG GlobalFlagsSet; + ULONG CriticalSectionDefaultTimeout; + ULONGLONG DeCommitFreeBlockThreshold; + ULONGLONG DeCommitTotalFreeThreshold; + ULONGLONG LockPrefixTable; // VA + ULONGLONG MaximumAllocationSize; + ULONGLONG VirtualMemoryThreshold; + ULONGLONG ProcessAffinityMask; + ULONG ProcessHeapFlags; + USHORT CSDVersion; + USHORT Reserved1; + ULONGLONG EditList; // VA + ULONGLONG SecurityCookie; // VA + ULONGLONG SEHandlerTable; // VA + ULONGLONG SEHandlerCount; + ULONGLONG GuardCFCheckFunctionPointer; // VA + ULONGLONG Reserved2; + ULONGLONG GuardCFFunctionTable; // VA + ULONGLONG GuardCFFunctionCount; + ULONG GuardFlags; +} IMAGE_LOAD_CONFIG_DIRECTORY64, *PIMAGE_LOAD_CONFIG_DIRECTORY64; + +typedef struct _IMAGE_TLS_DIRECTORY64 { + ULONGLONG StartAddressOfRawData; + ULONGLONG EndAddressOfRawData; + ULONGLONG AddressOfIndex; // PULONG + ULONGLONG AddressOfCallBacks; // PIMAGE_TLS_CALLBACK *; + ULONG SizeOfZeroFill; + union { + ULONG Characteristics; + struct { + INT Reserved0 : 20; + INT Alignment : 4; + INT Reserved1 : 8; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + +} IMAGE_TLS_DIRECTORY64; + +typedef IMAGE_TLS_DIRECTORY64 * PIMAGE_TLS_DIRECTORY64; + +typedef struct _IMAGE_TLS_DIRECTORY32 { + ULONG StartAddressOfRawData; + ULONG EndAddressOfRawData; + ULONG AddressOfIndex; // PULONG + ULONG AddressOfCallBacks; // PIMAGE_TLS_CALLBACK * + ULONG SizeOfZeroFill; + union { + ULONG Characteristics; + struct { + INT Reserved0 : 20; + INT Alignment : 4; + INT Reserved1 : 8; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + +} IMAGE_TLS_DIRECTORY32; +typedef IMAGE_TLS_DIRECTORY32 * PIMAGE_TLS_DIRECTORY32; + + +#define ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID (0x00000001) +#define ACTCTX_FLAG_LANGID_VALID (0x00000002) +#define ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID (0x00000004) +#define ACTCTX_FLAG_RESOURCE_NAME_VALID (0x00000008) +#define ACTCTX_FLAG_SET_PROCESS_DEFAULT (0x00000010) +#define ACTCTX_FLAG_APPLICATION_NAME_VALID (0x00000020) +#define ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF (0x00000040) +#define ACTCTX_FLAG_HMODULE_VALID (0x00000080) + +typedef struct tagACTCTXW +{ + ULONG cbSize; + ULONG dwFlags; + PWCH lpSource; + USHORT wProcessorArchitecture; + USHORT wLangId; + PWCH lpAssemblyDirectory; + PWCH lpResourceName; + PWCH lpApplicationName; + PVOID hModule; +} ACTCTXW, *PACTCTXW; + +typedef struct tagACTCTXW32 +{ + ULONG cbSize; + ULONG dwFlags; + ULONG lpSource; + USHORT wProcessorArchitecture; + USHORT wLangId; + ULONG lpAssemblyDirectory; + ULONG lpResourceName; + ULONG lpApplicationName; + ULONG hModule; +} ACTCTXW32, *PACTCTXW32; + +#pragma warning (default : 4201) \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/Private.c b/third/Blackbone/src/BlackBoneDrv/Private.c new file mode 100644 index 0000000000000000000000000000000000000000..3e76136189d5de640252d00dea84344bde8573c5 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/Private.c @@ -0,0 +1,575 @@ +#include "Private.h" +#include "Utils.h" +#include + +#pragma alloc_text(PAGE, ExpLookupHandleTableEntry) +#pragma alloc_text(PAGE, GetKernelBase) +#pragma alloc_text(PAGE, GetSSDTBase) +#pragma alloc_text(PAGE, GetSSDTEntry) +#pragma alloc_text(PAGE, GetPTEForVA) +#pragma alloc_text(PAGE, InitializeStopProcessors) +#pragma alloc_text(PAGE, StopProcessors) +#pragma alloc_text(PAGE, StartProcessors) +#pragma alloc_text(PAGE, AllocateInDiscardedMemory) + +extern DYNAMIC_DATA dynData; + +PVOID g_KernelBase = NULL; +ULONG g_KernelSize = 0; +PSYSTEM_SERVICE_DESCRIPTOR_TABLE g_SSDT = NULL; +KDDEBUGGER_DATA64 g_KdBlock = {0}; + +MMPTE ValidKernelPte = +{ + MM_PTE_VALID_MASK | + MM_PTE_WRITE_MASK | + MM_PTE_GLOBAL_MASK | + MM_PTE_DIRTY_MASK | + MM_PTE_ACCESS_MASK +}; + +/// +/// Initialize debugger block g_KdBlock +/// +VOID InitializeDebuggerBlock() +{ + CONTEXT context = { 0 }; + context.ContextFlags = CONTEXT_FULL; + RtlCaptureContext( &context ); + + PDUMP_HEADER dumpHeader = ExAllocatePool( NonPagedPool, DUMP_BLOCK_SIZE ); + if (dumpHeader) + { + KeCapturePersistentThreadState( &context, NULL, 0, 0, 0, 0, 0, dumpHeader ); + RtlCopyMemory( &g_KdBlock, (PUCHAR)dumpHeader + KDDEBUGGER_DATA_OFFSET, sizeof( g_KdBlock ) ); + + ExFreePool( dumpHeader ); + } +} + +/// +/// Lookup handle in the process handle table +/// +/// Handle table +/// Handle to search for +/// Found entry, NULL if nothing found +PHANDLE_TABLE_ENTRY ExpLookupHandleTableEntry( IN PHANDLE_TABLE HandleTable, IN EXHANDLE tHandle ) +{ + ULONG_PTR TableCode = HandleTable->TableCode & 3; + if (tHandle.Value >= HandleTable->NextHandleNeedingPool) + return NULL; + + tHandle.Value &= 0xFFFFFFFFFFFFFFFC; + +#if defined ( _WIN10_ ) + if (TableCode != 0) + { + if (TableCode == 1) + { + return (PHANDLE_TABLE_ENTRY)(*(ULONG_PTR*)(HandleTable->TableCode + 8 * (tHandle.Value >> 11) - 1) + 4 * (tHandle.Value & 0x7FC)); + } + else + { + ULONG_PTR tmp = tHandle.Value >> 11; + return (PHANDLE_TABLE_ENTRY)(*(ULONG_PTR*)(*(ULONG_PTR*)(HandleTable->TableCode + 8 * (tHandle.Value >> 21) - 2) + 8 * (tmp & 0x3FF)) + 4 * (tHandle.Value & 0x7FC)); + } + } + else + { + return (PHANDLE_TABLE_ENTRY)(HandleTable->TableCode + 4 * tHandle.Value); + } +#elif defined ( _WIN7_ ) + ULONG_PTR Diff = HandleTable->TableCode - TableCode; + + if (TableCode != 0) + { + if (TableCode == 1) + { + return (PHANDLE_TABLE_ENTRY)(*(ULONG_PTR*)(Diff + ((tHandle.Value - tHandle.Value & 0x7FC) >> 9)) + 4 * (tHandle.Value & 0x7FC)); + } + else + { + ULONG_PTR tmp = (tHandle.Value - tHandle.Value & 0x7FC) >> 9; + return (PHANDLE_TABLE_ENTRY)(*(ULONG_PTR*)(*(ULONG_PTR*)(Diff + ((tHandle.Value - tmp - tmp & 0xFFF) >> 10)) + (tmp & 0xFFF)) + 4 * (tHandle.Value & 0x7FC)); + } + } + else + { + return (PHANDLE_TABLE_ENTRY)(Diff + 4 * tHandle.Value); + } +#else + if (TableCode != 0) + { + if (TableCode == 1) + { + return (PHANDLE_TABLE_ENTRY)(*(ULONG_PTR*)(HandleTable->TableCode + 8 * (tHandle.Value >> 10) - 1) + 4 * (tHandle.Value & 0x3FF)); + } + else + { + ULONG_PTR tmp = tHandle.Value >> 10; + return (PHANDLE_TABLE_ENTRY)(*(ULONG_PTR*)(*(ULONG_PTR*)(HandleTable->TableCode + 8 * (tHandle.Value >> 19) - 2) + 8 * (tmp & 0x1FF)) + 4 * (tHandle.Value & 0x3FF)); + } + } + else + { + return (PHANDLE_TABLE_ENTRY)(HandleTable->TableCode + 4 * tHandle.Value); + } +#endif +} + + +/// +/// Get ntoskrnl base address +/// +/// Size of module +/// Found address, NULL if not found +PVOID GetKernelBase( OUT PULONG pSize ) +{ + NTSTATUS status = STATUS_SUCCESS; + ULONG bytes = 0; + PRTL_PROCESS_MODULES pMods = NULL; + PVOID checkPtr = NULL; + UNICODE_STRING routineName; + + // Already found + if (g_KernelBase != NULL) + { + if (pSize) + *pSize = g_KernelSize; + return g_KernelBase; + } + + RtlUnicodeStringInit( &routineName, L"NtOpenFile" ); + + checkPtr = MmGetSystemRoutineAddress( &routineName ); + if (checkPtr == NULL) + return NULL; + + // Protect from UserMode AV + status = ZwQuerySystemInformation( SystemModuleInformation, 0, bytes, &bytes ); + if (bytes == 0) + { + DPRINT( "BlackBone: %s: Invalid SystemModuleInformation size\n", __FUNCTION__ ); + return NULL; + } + + pMods = (PRTL_PROCESS_MODULES)ExAllocatePoolWithTag( NonPagedPool, bytes, BB_POOL_TAG ); + RtlZeroMemory( pMods, bytes ); + + status = ZwQuerySystemInformation( SystemModuleInformation, pMods, bytes, &bytes ); + + if (NT_SUCCESS( status )) + { + PRTL_PROCESS_MODULE_INFORMATION pMod = pMods->Modules; + + for (ULONG i = 0; i < pMods->NumberOfModules; i++) + { + // System routine is inside module + if (checkPtr >= pMod[i].ImageBase && + checkPtr < (PVOID)((PUCHAR)pMod[i].ImageBase + pMod[i].ImageSize)) + { + g_KernelBase = pMod[i].ImageBase; + g_KernelSize = pMod[i].ImageSize; + if (pSize) + *pSize = g_KernelSize; + break; + } + } + } + + if (pMods) + ExFreePoolWithTag( pMods, BB_POOL_TAG ); + + return g_KernelBase; +} + +/// +/// Gets SSDT base - KiServiceTable +/// +/// SSDT base, NULL if not found +PSYSTEM_SERVICE_DESCRIPTOR_TABLE GetSSDTBase() +{ + PUCHAR ntosBase = GetKernelBase( NULL ); + + // Already found + if (g_SSDT != NULL) + return g_SSDT; + + if (!ntosBase) + return NULL; + + PIMAGE_NT_HEADERS pHdr = RtlImageNtHeader( ntosBase ); + PIMAGE_SECTION_HEADER pFirstSec = (PIMAGE_SECTION_HEADER)(pHdr + 1); + for (PIMAGE_SECTION_HEADER pSec = pFirstSec; pSec < pFirstSec + pHdr->FileHeader.NumberOfSections; pSec++) + { + // Non-paged, non-discardable, readable sections + // Probably still not fool-proof enough... + if (pSec->Characteristics & IMAGE_SCN_MEM_NOT_PAGED && + pSec->Characteristics & IMAGE_SCN_MEM_EXECUTE && + !(pSec->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) && + (*(PULONG)pSec->Name != 'TINI') && + (*(PULONG)pSec->Name != 'EGAP')) + { + PVOID pFound = NULL; + + // KiSystemServiceRepeat pattern + UCHAR pattern[] = "\x4c\x8d\x15\xcc\xcc\xcc\xcc\x4c\x8d\x1d\xcc\xcc\xcc\xcc\xf7"; + NTSTATUS status = BBSearchPattern( pattern, 0xCC, sizeof( pattern ) - 1, ntosBase + pSec->VirtualAddress, pSec->Misc.VirtualSize, &pFound ); + if (NT_SUCCESS( status )) + { + g_SSDT = (PSYSTEM_SERVICE_DESCRIPTOR_TABLE)((PUCHAR)pFound + *(PULONG)((PUCHAR)pFound + 3) + 7); + //DPRINT( "BlackBone: %s: KeSystemServiceDescriptorTable = 0x%p\n", __FUNCTION__, g_SSDT ); + return g_SSDT; + } + } + } + + return NULL; +} + +/// +/// Gets the SSDT entry address by index. +/// +/// Service index +/// Found service address, NULL if not found +PVOID GetSSDTEntry( IN ULONG index ) +{ + ULONG size = 0; + PSYSTEM_SERVICE_DESCRIPTOR_TABLE pSSDT = GetSSDTBase(); + PVOID pBase = GetKernelBase( &size ); + + if (pSSDT && pBase) + { + // Index range check + if (index > pSSDT->NumberOfServices) + return NULL; + + return (PUCHAR)pSSDT->ServiceTableBase + (((PLONG)pSSDT->ServiceTableBase)[index] >> 4); + } + + return NULL; +} + +/// +/// Get page hardware PTE. +/// Address must be valid, otherwise bug check is imminent +/// +/// Target address +/// Found PTE +PMMPTE GetPTEForVA( IN PVOID pAddress ) +{ + if (dynData.ver >= WINVER_10_RS1) + { + // Check if large page + PMMPTE pPDE = (PMMPTE)(((((ULONG_PTR)pAddress >> PDI_SHIFT) << PTE_SHIFT) & 0x3FFFFFF8ull) + dynData.DYN_PDE_BASE); + if (pPDE->u.Hard.LargePage) + return pPDE; + + return (PMMPTE)(((((ULONG_PTR)pAddress >> PTI_SHIFT) << PTE_SHIFT) & 0x7FFFFFFFF8ull) + dynData.DYN_PTE_BASE); + } + else + { + // Check if large page + PMMPTE pPDE = MiGetPdeAddress( pAddress ); + if (pPDE->u.Hard.LargePage) + return pPDE; + + return MiGetPteAddress( pAddress ); + } +} + +VOID DpcRoutine( KDPC *pDpc, void *pContext, void *pArg1, void *pArg2 ) +{ + KIRQL Irql; + PNOPPROCINFO Info = (PNOPPROCINFO)pContext; + + UNREFERENCED_PARAMETER( pDpc ); + UNREFERENCED_PARAMETER( pArg1 ); + UNREFERENCED_PARAMETER( pArg2 ); + + InterlockedIncrement( &Info->DPCCount ); + do + { + __nop(); + } while (Info->ActiveCores != Info->DPCCount); + + KeRaiseIrql( HIGH_LEVEL, &Irql ); + do + { + __nop(); + } while (!Info->IsCodeExecuted); + + InterlockedDecrement( &Info->DPCCount ); + KeLowerIrql( Irql ); +} + +/// +/// Initialize structure for processor start/stop +/// +/// >Processors data +VOID InitializeStopProcessors( OUT NOPPROCINFO* Info ) +{ + KAFFINITY aff = 0; + RtlZeroMemory( Info, sizeof( NOPPROCINFO ) ); + + Info->Cores = KeQueryActiveProcessorCount( &aff ); + + if (Info->Cores > 1) + { + for (ULONG i = 0; i < Info->Cores; i++) + { + KeInitializeDpc( &Info->DpcTraps[i], DpcRoutine, Info ); + KeSetImportanceDpc( &Info->DpcTraps[i], LowImportance ); + KeSetTargetProcessorDpc( &Info->DpcTraps[i], (CCHAR)i ); + } + } +} + +/// +/// Stall all but current active processors +/// +/// Processors data +VOID StopProcessors( IN NOPPROCINFO* Info ) +{ + ULONG CurrentProcessor; + KAFFINITY ActiveProcessors; + + if (Info->Cores > 1) + { + Info->SavedPriority = KeSetPriorityThread( KeGetCurrentThread(), HIGH_PRIORITY ); + ActiveProcessors = KeQueryActiveProcessors(); + + KeRaiseIrql( DISPATCH_LEVEL, &Info->SavedIrql ); + + CurrentProcessor = KeGetCurrentProcessorNumber(); + Info->ActiveCores = Info->DPCCount = 0; + + for (ULONG i = 0; i < Info->Cores; i++) + { + if ((i != CurrentProcessor) && ((ActiveProcessors & (1ull << i)) != 0)) + { + InterlockedIncrement( &Info->ActiveCores ); + KeInsertQueueDpc( &Info->DpcTraps[i], &Info, 0 ); + } + } + + KeLowerIrql( Info->SavedIrql ); + + do + { + __nop(); + } while (Info->ActiveCores != Info->DPCCount); + + KeRaiseIrql( HIGH_LEVEL, &Info->SavedIrql ); + } + else + KeRaiseIrql( HIGH_LEVEL, &Info->SavedIrql ); +}; + +/// +/// Resume all stopped active processors +/// +/// Processors data +VOID StartProcessors( IN NOPPROCINFO* Info ) +{ + if (Info->Cores > 1) + { + InterlockedExchange( &Info->IsCodeExecuted, 1 ); + KeLowerIrql( Info->SavedIrql ); + + do + { + __nop(); + } while (Info->DPCCount > 0); + + KeSetPriorityThread( KeGetCurrentThread(), Info->SavedPriority ); + } + else + KeLowerIrql( Info->SavedIrql ); +} + +/// +/// Allocate memory in one of the ntoskrnl discarded section +/// +/// Block size to allocate +/// Allocated address +/// Status code +NTSTATUS AllocateInDiscardedMemory( IN ULONG size, OUT PVOID* ppFoundBase ) +{ + ASSERT( ppFoundBase != NULL ); + if (ppFoundBase == NULL) + return STATUS_INVALID_PARAMETER; + + // Ensure MiAllocateDriverPage address is valid + if (dynData.MiAllocPage == 0) + return STATUS_INVALID_ADDRESS; + + PVOID pBase = GetKernelBase( NULL ); + fnMiAllocateDriverPage MiAllocateDriverPage = (fnMiAllocateDriverPage)((ULONG_PTR)pBase + dynData.MiAllocPage); + + PIMAGE_NT_HEADERS pNTOSHdr = RtlImageNtHeader( pBase ); + if (!pNTOSHdr) + return STATUS_INVALID_IMAGE_FORMAT; + + // Walk ntoskrnl section + PIMAGE_SECTION_HEADER pFirstSection = (PIMAGE_SECTION_HEADER)(pNTOSHdr + 1); + PIMAGE_SECTION_HEADER pLastSection = pFirstSection + pNTOSHdr->FileHeader.NumberOfSections; + + for (PIMAGE_SECTION_HEADER pSection = pLastSection - 1; pSection >= pFirstSection; --pSection) + { + // Find first suitable discarded section + if (pSection->Characteristics & IMAGE_SCN_MEM_DISCARDABLE && (ULONG_PTR)PAGE_ALIGN( pSection->Misc.VirtualSize ) >= size) + { + // TODO: implement some randomization for starting address + PVOID pSectionBase = (PUCHAR)pBase + pSection->VirtualAddress; + + // I don't care about large pages + // If image was mapped using large pages bugcheck is imminent + ULONG_PTR TotalPTEs = BYTES_TO_PAGES( size ); + PMMPTE pStartPTE = MiGetPteAddress( pSectionBase ); + PMMPTE pEndPTE = pStartPTE + TotalPTEs; + MMPTE TempPTE = ValidKernelPte; + + // Allocate physical pages for PTEs + for (PMMPTE pPTE = pStartPTE; pPTE < pEndPTE; ++pPTE) + { + PVOID VA = MiGetVirtualAddressMappedByPte( pPTE ); + + // Already allocated + if (MI_IS_PHYSICAL_ADDRESS( VA )) + { + //DPRINT( "BlackBone: %s: VA 0x%p is already backed by PFN: 0x%p\n", __FUNCTION__, VA, pPTE->u.Hard.PageFrameNumber ); + continue; + } + + PFN_NUMBER pfn = MiAllocateDriverPage( pPTE ); + if (pfn == 0) + { + DPRINT( "BlackBone: %s: Failed to allocate physical page for PTE 0x%p\n", __FUNCTION__, pPTE ); + return STATUS_NO_MEMORY; + } + else + { + //DPRINT( "BlackBone: %s: VA 0x%p now backed by PFN: 0x%p; PTE: 0x%p\n", __FUNCTION__, VA, pfn, pPTE ); + TempPTE.u.Hard.PageFrameNumber = pfn; + *pPTE = TempPTE; + } + } + + *ppFoundBase = pSectionBase; + return STATUS_SUCCESS; + } + } + + return STATUS_NOT_FOUND; +} + + + +#if defined(_WIN8_) || defined (_WIN7_) + +NTSTATUS +NTAPI +ZwProtectVirtualMemory( + IN HANDLE ProcessHandle, + IN OUT PVOID* BaseAddress, + IN OUT SIZE_T* NumberOfBytesToProtect, + IN ULONG NewAccessProtection, + OUT PULONG OldAccessProtection + ) +{ + NTSTATUS status = STATUS_SUCCESS; + + fnNtProtectVirtualMemory NtProtectVirtualMemory = (fnNtProtectVirtualMemory)(ULONG_PTR)GetSSDTEntry( dynData.NtProtectIndex ); + if (NtProtectVirtualMemory) + { + // + // If previous mode is UserMode, addresses passed into NtProtectVirtualMemory must be in user-mode space + // Switching to KernelMode allows usage of kernel-mode addresses + // + PUCHAR pPrevMode = (PUCHAR)PsGetCurrentThread() + dynData.PrevMode; + UCHAR prevMode = *pPrevMode; + PVOID BaseCopy = NULL; + SIZE_T SizeCopy = 0; + *pPrevMode = KernelMode; + + if (BaseAddress) + BaseCopy = *BaseAddress; + + if (NumberOfBytesToProtect) + SizeCopy = *NumberOfBytesToProtect; + + status = NtProtectVirtualMemory( ProcessHandle, &BaseCopy, &SizeCopy, NewAccessProtection, OldAccessProtection ); + + *pPrevMode = prevMode; + } + else + status = STATUS_NOT_FOUND; + + return status; +} +#endif + +NTSTATUS +NTAPI +ZwCreateThreadEx( + OUT PHANDLE hThread, + IN ACCESS_MASK DesiredAccess, + IN PVOID ObjectAttributes, + IN HANDLE ProcessHandle, + IN PVOID lpStartAddress, + IN PVOID lpParameter, + IN ULONG Flags, + IN SIZE_T StackZeroBits, + IN SIZE_T SizeOfStackCommit, + IN SIZE_T SizeOfStackReserve, + IN PNT_PROC_THREAD_ATTRIBUTE_LIST AttributeList + ) +{ + NTSTATUS status = STATUS_SUCCESS; + + fnNtCreateThreadEx NtCreateThreadEx = (fnNtCreateThreadEx)(ULONG_PTR)GetSSDTEntry( dynData.NtCreateThdIndex ); + if (NtCreateThreadEx) + { + // + // If previous mode is UserMode, addresses passed into ZwCreateThreadEx must be in user-mode space + // Switching to KernelMode allows usage of kernel-mode addresses + // + PUCHAR pPrevMode = (PUCHAR)PsGetCurrentThread() + dynData.PrevMode; + UCHAR prevMode = *pPrevMode; + *pPrevMode = KernelMode; + + status = NtCreateThreadEx( + hThread, DesiredAccess, ObjectAttributes, + ProcessHandle, lpStartAddress, lpParameter, + Flags, StackZeroBits, SizeOfStackCommit, + SizeOfStackReserve, AttributeList + ); + + *pPrevMode = prevMode; + } + else + status = STATUS_NOT_FOUND; + + return status; +} + +NTSTATUS NTAPI ZwTerminateThread( IN HANDLE ThreadHandle, IN NTSTATUS ExitStatus ) +{ + NTSTATUS status = STATUS_SUCCESS; + + fnNtTerminateThread NtTerminateThread = (fnNtTerminateThread)(ULONG_PTR)GetSSDTEntry( dynData.NtTermThdIndex ); + if (NtTerminateThread) + { + PUCHAR pPrevMode = (PUCHAR)PsGetCurrentThread() + dynData.PrevMode; + UCHAR prevMode = *pPrevMode; + *pPrevMode = KernelMode; + + status = NtTerminateThread( ThreadHandle, ExitStatus ); + *pPrevMode = prevMode; + } + else + status = STATUS_NOT_FOUND; + + return status; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/Private.h b/third/Blackbone/src/BlackBoneDrv/Private.h new file mode 100644 index 0000000000000000000000000000000000000000..6bd29977ad01eb96b02061cc61e940db2105dc53 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/Private.h @@ -0,0 +1,353 @@ +#pragma once + +#include "Imports.h" + +//#ifdef DBG +#define DPRINT(format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, format, __VA_ARGS__) +//#else +//#define DPRINT(...) +//#endif + +#define BB_POOL_TAG 'enoB' + + +#define ObpAccessProtectCloseBit 0x2000000 + +// +// PTE protection values +// +#define MM_ZERO_ACCESS 0 +#define MM_READONLY 1 +#define MM_EXECUTE 2 +#define MM_EXECUTE_READ 3 +#define MM_READWRITE 4 +#define MM_WRITECOPY 5 +#define MM_EXECUTE_READWRITE 6 +#define MM_EXECUTE_WRITECOPY 7 + +#define MM_PTE_VALID_MASK 0x1 +#define MM_PTE_WRITE_MASK 0x800 +#define MM_PTE_OWNER_MASK 0x4 +#define MM_PTE_WRITE_THROUGH_MASK 0x8 +#define MM_PTE_CACHE_DISABLE_MASK 0x10 +#define MM_PTE_ACCESS_MASK 0x20 +#define MM_PTE_DIRTY_MASK 0x42 +#define MM_PTE_LARGE_PAGE_MASK 0x80 +#define MM_PTE_GLOBAL_MASK 0x100 +#define MM_PTE_COPY_ON_WRITE_MASK 0x200 +#define MM_PTE_PROTOTYPE_MASK 0x400 +#define MM_PTE_TRANSITION_MASK 0x800 + +#define VIRTUAL_ADDRESS_BITS 48 +#define VIRTUAL_ADDRESS_MASK ((((ULONG_PTR)1) << VIRTUAL_ADDRESS_BITS) - 1) + +#define THREAD_CREATE_FLAGS_CREATE_SUSPENDED 0x00000001 +#define THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH 0x00000002 +#define THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER 0x00000004 + +#define MI_SYSTEM_RANGE_START (ULONG_PTR)(0xFFFF080000000000) // start of system space + +#define EX_ADDITIONAL_INFO_SIGNATURE (ULONG_PTR)(-2) + +#define KI_USER_SHARED_DATA 0xFFFFF78000000000UI64 + +#define SharedUserData ((KUSER_SHARED_DATA * const)KI_USER_SHARED_DATA) + +#ifndef PTE_SHIFT +#define PTE_SHIFT 3 +#endif +#ifndef PTI_SHIFT +#define PTI_SHIFT 12 +#endif +#ifndef PDI_SHIFT +#define PDI_SHIFT 21 +#endif +#ifndef PPI_SHIFT +#define PPI_SHIFT 30 +#endif +#ifndef PXI_SHIFT +#define PXI_SHIFT 39 +#endif + +#ifndef PXE_BASE +#define PXE_BASE 0xFFFFF6FB7DBED000UI64 +#endif +#ifndef PXE_SELFMAP +#define PXE_SELFMAP 0xFFFFF6FB7DBEDF68UI64 +#endif +#ifndef PPE_BASE +#define PPE_BASE 0xFFFFF6FB7DA00000UI64 +#endif +#ifndef PDE_BASE +#define PDE_BASE 0xFFFFF6FB40000000UI64 +#endif +#ifndef PTE_BASE +#define PTE_BASE 0xFFFFF68000000000UI64 +#endif + +#ifndef _WIN64 +#define KDDEBUGGER_DATA_OFFSET 0x1068 +#else +#define KDDEBUGGER_DATA_OFFSET 0x2080 +#endif + +#ifndef _WIN64 +#define DUMP_BLOCK_SIZE 0x20000 +#else +#define DUMP_BLOCK_SIZE 0x40000 +#endif + +#define PHYSICAL_ADDRESS_BITS 40 + +#define ObpDecodeGrantedAccess( Access ) \ + ((Access)& ~ObpAccessProtectCloseBit) + +#define ObpDecodeObject( Object ) (PVOID)(((LONG_PTR)Object >> 0x10) & ~(ULONG_PTR)0xF) + +#define PTE_PER_PAGE 512 +#define PDE_PER_PAGE 512 +#define PPE_PER_PAGE 512 +#define PXE_PER_PAGE 512 + +#define PPI_MASK (PPE_PER_PAGE - 1) +#define PXI_MASK (PXE_PER_PAGE - 1) + +#define MiGetPxeOffset(va) \ + ((ULONG)(((ULONG_PTR)(va) >> PXI_SHIFT) & PXI_MASK)) + +#define MiGetPxeAddress(va) \ + ((PMMPTE)PXE_BASE + MiGetPxeOffset(va)) + +#define MiGetPpeAddress(va) \ + ((PMMPTE)(((((ULONG_PTR)(va) & VIRTUAL_ADDRESS_MASK) >> PPI_SHIFT) << PTE_SHIFT) + PPE_BASE)) + +#define MiGetPdeAddress(va) \ + ((PMMPTE)(((((ULONG_PTR)(va) & VIRTUAL_ADDRESS_MASK) >> PDI_SHIFT) << PTE_SHIFT) + PDE_BASE)) + +#define MiGetPteAddress(va) \ + ((PMMPTE)(((((ULONG_PTR)(va) & VIRTUAL_ADDRESS_MASK) >> PTI_SHIFT) << PTE_SHIFT) + PTE_BASE)) + +#define VA_SHIFT (63 - 47) // address sign extend shift count + +#define MiGetVirtualAddressMappedByPte(PTE) \ + ((PVOID)((LONG_PTR)(((LONG_PTR)(PTE) - PTE_BASE) << (PAGE_SHIFT + VA_SHIFT - PTE_SHIFT)) >> VA_SHIFT)) + +#define MI_IS_PHYSICAL_ADDRESS(Va) \ + ((MiGetPxeAddress(Va)->u.Hard.Valid == 1) && \ + (MiGetPpeAddress(Va)->u.Hard.Valid == 1) && \ + ((MiGetPdeAddress(Va)->u.Long & 0x81) == 0x81) || (MiGetPteAddress(Va)->u.Hard.Valid == 1)) + +#define ExpIsValidObjectEntry(Entry) \ + ( (Entry != NULL) && (Entry->LowValue != 0) && (Entry->HighValue != EX_ADDITIONAL_INFO_SIGNATURE) ) + +// Workaround for compiler warning +#define FN_CAST(T, p) (T)(ULONG_PTR)p +#define FN_CAST_V(p) (PVOID)(ULONG_PTR)p + +// Get SSDT index from function pointer +#define SSDTIndex(pfn) *(PULONG)((ULONG_PTR)pfn + 0x15) + +typedef ULONG WIN32_PROTECTION_MASK; +typedef PULONG PWIN32_PROTECTION_MASK; + +typedef enum _WinVer +{ + WINVER_7 = 0x0610, + WINVER_7_SP1 = 0x0611, + WINVER_8 = 0x0620, + WINVER_81 = 0x0630, + WINVER_10 = 0x0A00, + WINVER_10_RS1 = 0x0A01, // Anniversary update + WINVER_10_RS2 = 0x0A02, // Creators update + WINVER_10_RS3 = 0x0A03, // Fall creators update + WINVER_10_RS4 = 0x0A04, // Spring creators update + WINVER_10_RS5 = 0x0A05, // October 2018 update +} WinVer; + +extern PLIST_ENTRY PsLoadedModuleList; +extern MMPTE ValidKernelPte; + +/// +/// OS-dependent stuff +/// +typedef struct _DYNAMIC_DATA +{ + WinVer ver; // OS version + ULONG buildNo; // OS build revision + BOOLEAN correctBuild; // OS kernel build number is correct and supported + + ULONG KExecOpt; // KPROCESS::ExecuteOptions + ULONG Protection; // EPROCESS::Protection + ULONG EProcessFlags2; // EPROCESS::Flags2 + ULONG ObjTable; // EPROCESS::ObjectTable + ULONG VadRoot; // EPROCESS::VadRoot + ULONG NtProtectIndex; // NtProtectVirtualMemory SSDT index + ULONG NtCreateThdIndex; // NtCreateThreadEx SSDT index + ULONG NtTermThdIndex; // NtTerminateThread SSDT index + ULONG PrevMode; // KTHREAD::PreviousMode + ULONG ExitStatus; // ETHREAD::ExitStatus + ULONG MiAllocPage; // MiAllocateDriverPage offset + ULONG ExRemoveTable; // Ex(p)RemoveHandleTable offset + + ULONG_PTR DYN_PDE_BASE; // Win10 AU+ relocated PDE base VA + ULONG_PTR DYN_PTE_BASE; // Win10 AU+ relocated PTE base VA +} DYNAMIC_DATA, *PDYNAMIC_DATA; + + +typedef struct _NOPPROCINFO +{ + KDPC DpcTraps[MAXIMUM_PROCESSORS]; + LONG ActiveCores; + LONG DPCCount; + ULONG Cores; + KIRQL SavedIrql; + KPRIORITY SavedPriority; + LONG IsCodeExecuted; +}NOPPROCINFO, *PNOPPROCINFO; + +typedef NTSTATUS( NTAPI* fnNtCreateThreadEx ) + ( + OUT PHANDLE hThread, + IN ACCESS_MASK DesiredAccess, + IN PVOID ObjectAttributes, + IN HANDLE ProcessHandle, + IN PVOID lpStartAddress, + IN PVOID lpParameter, + IN ULONG Flags, + IN SIZE_T StackZeroBits, + IN SIZE_T SizeOfStackCommit, + IN SIZE_T SizeOfStackReserve, + OUT PVOID lpBytesBuffer + ); + +typedef PFN_NUMBER( NTAPI* fnMiAllocateDriverPage )(IN PMMPTE pPTE); +typedef NTSTATUS( NTAPI* fnNtTerminateThread)( IN HANDLE ThreadHandle, IN NTSTATUS ExitStatus ); +typedef NTSTATUS( NTAPI* fnExRemoveHandleTable )(IN PHANDLE_TABLE pTable); + +#if defined(_WIN8_) || defined (_WIN7_) + +typedef NTSTATUS( NTAPI* fnNtProtectVirtualMemory ) + ( + IN HANDLE ProcessHandle, + IN PVOID* BaseAddress, + IN SIZE_T* NumberOfBytesToProtect, + IN ULONG NewAccessProtection, + OUT PULONG OldAccessProtection + ); + +NTSTATUS +NTAPI +ZwProtectVirtualMemory( + IN HANDLE ProcessHandle, + IN OUT PVOID* BaseAddress, + IN OUT SIZE_T* NumberOfBytesToProtect, + IN ULONG NewAccessProtection, + OUT PULONG OldAccessProtection + ); + + +#else +NTSYSAPI +NTSTATUS +NTAPI +ZwProtectVirtualMemory( + IN HANDLE ProcessHandle, + IN OUT PVOID* BaseAddress, + IN OUT SIZE_T* NumberOfBytesToProtect, + IN ULONG NewAccessProtection, + OUT PULONG OldAccessProtection + ); + +#endif + +#ifdef _WIN81_ + +NTSYSAPI +PVOID +NTAPI +RtlAvlRemoveNode( + IN PRTL_AVL_TREE pTree, + IN PMMADDRESS_NODE pNode + ); + +#endif + +ULONG +NTAPI +KeCapturePersistentThreadState( + IN PCONTEXT Context, + IN PKTHREAD Thread, + IN ULONG BugCheckCode, + IN ULONG BugCheckParameter1, + IN ULONG BugCheckParameter2, + IN ULONG BugCheckParameter3, + IN ULONG BugCheckParameter4, + OUT PVOID VirtualAddress +); + +/// +/// Initialize debugger block g_KdBlock +/// +VOID InitializeDebuggerBlock(); + +/// +/// Lookup handle in the process handle table +/// +/// Handle table +/// Handle to search for +/// Found entry, NULL if nothing found +PHANDLE_TABLE_ENTRY ExpLookupHandleTableEntry( IN PHANDLE_TABLE HandleTable, IN EXHANDLE tHandle ); + +/// +/// Get ntoskrnl base address +/// +/// Size of module +/// Found address, NULL if not found +PVOID GetKernelBase( OUT PULONG pSize ); + +/// +/// Gets SSDT base - KiSystemServiceTable +/// +/// SSDT base, NULL if not found +PSYSTEM_SERVICE_DESCRIPTOR_TABLE GetSSDTBase(); + +/// +/// Gets the SSDT entry address by index. +/// +/// Service index +/// Found service address, NULL if not found +PVOID GetSSDTEntry( IN ULONG index ); + +/// +/// Get page hardware PTE +/// Address must be valid, otherwise bug check is imminent +/// +/// Target address +/// Found PTE +PMMPTE GetPTEForVA( IN PVOID pAddress ); + +/// +/// Initialize structure for processor start/stop +/// +/// >Processors data +VOID InitializeStopProcessors( OUT NOPPROCINFO* Info ); + +/// +/// Stall all but current active processors +/// +/// Processors data +VOID StopProcessors( IN NOPPROCINFO* Info ); + +/// +/// Resume all stopped active processors +/// +/// Processors data +VOID StartProcessors( IN NOPPROCINFO* Info ); + +/// +/// Allocate memory in one of the ntoskrnl discarded section +/// +/// Block size to allocate +/// Allocated address +/// Status code +NTSTATUS AllocateInDiscardedMemory( IN ULONG size, OUT PVOID* ppFoundBase ); diff --git a/third/Blackbone/src/BlackBoneDrv/Remap.c b/third/Blackbone/src/BlackBoneDrv/Remap.c new file mode 100644 index 0000000000000000000000000000000000000000..33cd640ed7c22d380db0d18e1618afbb82676e40 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/Remap.c @@ -0,0 +1,1342 @@ +#include "Remap.h" +#include "Utils.h" +#include + +RTL_AVL_TABLE g_ProcessPageTables; // Mapping table +KGUARDED_MUTEX g_globalLock; // ProcessPageTables mutex + +/// +/// Walk region list and create MDL for each region +/// +/// Target process +/// Region list +/// Status code +NTSTATUS BBPrepareMDLList( IN PEPROCESS pProcess, IN PLIST_ENTRY pList ); + +/// +/// Build MDL for memory region +/// +/// Target process +/// Region data +/// Status code +NTSTATUS BBPrepareMDLListEntry( IN PEPROCESS pProcess, IN PMAP_ENTRY pEntry ); + +/// +/// Map locked physical pages into caller process +/// +/// Region list +/// If set to FALSE, warning will be printed if region is already mapped +/// Status code +NTSTATUS BBMapRegionListIntoCurrentProcess( IN PLIST_ENTRY pList, IN BOOLEAN noWarning ); + +/// +/// Map locked physical pages into caller process +/// +/// Memory region +/// Last mapped region +/// Status code +NTSTATUS BBMapRegionIntoCurrentProcess( IN PMAP_ENTRY pEntry, IN PMAP_ENTRY pPrevEntry ); + + +/// +/// Allocate kernel page from NonPaged pool and build MDL for it +/// +/// Resulting address +/// Resulting MDL +/// Status code +NTSTATUS BBAllocateSharedPage( OUT PVOID* pPage, OUT PMDL* pResultMDL ); + +/// +/// Map kernel page into current process address space +/// +/// Page MDL +/// Mapped address +/// Status code +NTSTATUS BBMapSharedPage( IN PMDL pMDL, OUT PVOID* pResult ); + +/// +/// Consolidate adjacent memory regions +/// +/// Region list +/// Status code +NTSTATUS BBConsolidateRegionList( IN PLIST_ENTRY pList ); + +/// +/// Process section object pages +/// Function will attempt to trigger copy-on-write for underlying pages to convert them into private +/// If copy-on-write fails, region will be then mapped as read-only +/// +/// Target process +/// Region data +/// Status code +NTSTATUS BBHandleSharedRegion( IN PEPROCESS pProcess, IN PMAP_ENTRY pEntry ); + +/// +/// Unmap memory region, release corresponding MDL, and remove region form list +/// +/// Region data +/// Process data +/// Status code +NTSTATUS BBUnmapRegionEntry( IN PMAP_ENTRY pPageEntry, IN PPROCESS_MAP_ENTRY pFoundEntry ); + +// +// Lookup routines +// + +/// +/// Find memory region containing at least one byte from specific region +/// +/// Region list to search in +/// Base of region to find +/// Size of the region to find +/// Status code +PMAP_ENTRY BBFindPageEntry( IN PLIST_ENTRY pList, IN ULONG_PTR baseAddress, IN ULONG_PTR size ); + +// +// Cleanup routines +// + +/// +/// Unmap pages, destroy MDLs, remove entry from list +/// +/// TRUE indicates that function is executed +/// in the context of host process and pages can be safely unmapped +/// Region list +VOID BBCleanupPageList( IN BOOLEAN attached, IN PLIST_ENTRY pList ); + +/// +/// Close handle if process isn't in signaled state +/// +/// Process object +/// Handle +/// KernelMode or UserMode handle +/// Status code +NTSTATUS BBSafeHandleClose( IN PEPROCESS pProcess, IN HANDLE handle, IN KPROCESSOR_MODE mode ); + +#pragma alloc_text(PAGE, BBBuildProcessRegionListForRange) +#pragma alloc_text(PAGE, BBPrepareMDLList) +#pragma alloc_text(PAGE, BBPrepareMDLListEntry) +#pragma alloc_text(PAGE, BBMapRegionListIntoCurrentProcess) +#pragma alloc_text(PAGE, BBMapRegionIntoCurrentProcess) + +#pragma alloc_text(PAGE, BBAllocateSharedPage) +#pragma alloc_text(PAGE, BBMapSharedPage) +#pragma alloc_text(PAGE, BBConsolidateRegionList) +#pragma alloc_text(PAGE, BBHandleSharedRegion) +#pragma alloc_text(PAGE, BBUnmapRegionEntry) + +#pragma alloc_text(PAGE, BBMapMemory) +#pragma alloc_text(PAGE, BBMapMemoryRegion) +#pragma alloc_text(PAGE, BBUnmapMemory) +#pragma alloc_text(PAGE, BBUnmapMemoryRegion) + +#pragma alloc_text(PAGE, BBGetRequiredRemapOutputSize) + +#pragma alloc_text(PAGE, BBLookupProcessEntry) +#pragma alloc_text(PAGE, BBFindPageEntry) + +#pragma alloc_text(PAGE, BBCleanupProcessTable) +#pragma alloc_text(PAGE, BBCleanupProcessEntry) +#pragma alloc_text(PAGE, BBCleanupHostProcess) +#pragma alloc_text(PAGE, BBCleanupPageList) +#pragma alloc_text(PAGE, BBSafeHandleClose) + +#pragma alloc_text(PAGE, AvlCompare) +#pragma alloc_text(PAGE, AvlAllocate) +#pragma alloc_text(PAGE, AvlFree) + + + +/* +*/ +RTL_GENERIC_COMPARE_RESULTS AvlCompare( IN RTL_AVL_TABLE *Table, IN PVOID FirstStruct, IN PVOID SecondStruct ) +{ + UNREFERENCED_PARAMETER( Table ); + PPROCESS_MAP_ENTRY pFirstEntry = (PPROCESS_MAP_ENTRY)FirstStruct; + PPROCESS_MAP_ENTRY pSecondEntry = (PPROCESS_MAP_ENTRY)SecondStruct; + + // Find by target + if (pFirstEntry->target.pid != 0 && pSecondEntry->target.pid != 0) + { + if (pFirstEntry->target.pid == pSecondEntry->target.pid) + return GenericEqual; + + if (pSecondEntry->target.pid > pFirstEntry->target.pid) + return GenericGreaterThan; + + return GenericLessThan; + } + // Find by Host + else + { + if (pFirstEntry->host.pid == pSecondEntry->host.pid) + return GenericEqual; + + if (pSecondEntry->host.pid > pFirstEntry->host.pid) + return GenericGreaterThan; + + return GenericLessThan; + } +} + +/* +*/ +PVOID AvlAllocate( IN RTL_AVL_TABLE *Table, IN CLONG ByteSize ) +{ + UNREFERENCED_PARAMETER( Table ); + return ExAllocatePoolWithTag( PagedPool, ByteSize, BB_POOL_TAG ); +} + +/* +*/ +VOID AvlFree( IN RTL_AVL_TABLE *Table, IN PVOID Buffer ) +{ + UNREFERENCED_PARAMETER( Table ); + ExFreePoolWithTag( Buffer, BB_POOL_TAG ); +} + +/// +/// Enumerate committed, accessible, non-guarded memory regions +/// +/// Region list +/// Region start +/// Region end +/// If set to FALSE, section objects will be excluded from list +/// Status code +NTSTATUS BBBuildProcessRegionListForRange( IN PLIST_ENTRY pList, IN ULONG_PTR start, IN ULONG_PTR end, IN BOOLEAN mapSections ) +{ + NTSTATUS status = STATUS_SUCCESS; + MEMORY_BASIC_INFORMATION mbi = { 0 }; + SIZE_T length = 0; + ULONG_PTR memptr = 0; + PMAP_ENTRY pEntry = NULL; + + for (memptr = start; memptr < end; memptr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize) + { + status = ZwQueryVirtualMemory( ZwCurrentProcess(), (PVOID)memptr, MemoryBasicInformationEx, &mbi, sizeof( mbi ), &length ); + + if (!NT_SUCCESS( status )) + { + DPRINT( "BlackBone: %s: ZwQueryVirtualMemory for address 0x%p returned status 0x%X\n", __FUNCTION__, memptr, status ); + + // STATUS_INVALID_PARAMETER is a normal status for last secured VAD under Win7 + return status == STATUS_INVALID_PARAMETER ? STATUS_SUCCESS : status; + } + // Skip non-committed, no-access and guard pages + else if (mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS && !(mbi.Protect & PAGE_GUARD)) + { + // Ignore shared memory if required + if (mbi.Type != MEM_PRIVATE && !mapSections) + continue; + + pEntry = ExAllocatePoolWithTag( PagedPool, sizeof( MAP_ENTRY ), BB_POOL_TAG ); + if (pEntry == NULL) + { + DPRINT( "BlackBone: %s: Failed to allocate memory for Remap descriptor\n", __FUNCTION__ ); + BBCleanupPageList( FALSE, pList ); + return STATUS_NO_MEMORY; + } + + pEntry->mem = mbi; + pEntry->newPtr = 0; + pEntry->pMdl = NULL; + pEntry->locked = FALSE; + pEntry->shared = mbi.Type != MEM_PRIVATE; + + InsertTailList( pList, &pEntry->link ); + } + } + + //if (NT_SUCCESS( status )) + //status = BBConsolidateRegionList( pList ); + + return status; +} + + +/// +/// Consolidate adjacent memory regions +/// +/// Region list +/// Status code +NTSTATUS BBConsolidateRegionList( IN PLIST_ENTRY pList ) +{ + NTSTATUS status = STATUS_SUCCESS; + + for (PLIST_ENTRY pListEntry = pList->Flink; pListEntry != pList; ) + { + PMAP_ENTRY pNextEntry = NULL; + PMAP_ENTRY pEntry = CONTAINING_RECORD( pListEntry, MAP_ENTRY, link ); + + // End of list + if (pListEntry->Flink == pList) + break; + + pNextEntry = CONTAINING_RECORD( pListEntry->Flink, MAP_ENTRY, link ); + + // Consolidate only non-mapped entries. Both entries must have same sharing flags + if (pEntry->pMdl == NULL && pNextEntry->pMdl == NULL && pEntry->shared == pNextEntry->shared) + { + // Regions are adjacent + if ((PUCHAR)pEntry->mem.BaseAddress + pEntry->mem.RegionSize == pNextEntry->mem.BaseAddress) + { + pEntry->mem.RegionSize += pNextEntry->mem.RegionSize; + RemoveEntryList( &pNextEntry->link ); + } + else + pListEntry = pListEntry->Flink; + } + else + pListEntry = pListEntry->Flink; + } + + return status; +} + + + +/// +/// Unmap memory region, release corresponding MDL, and remove region form list +/// +/// Region data +/// Process data +/// Status code +NTSTATUS BBUnmapRegionEntry( IN PMAP_ENTRY pPageEntry, IN PPROCESS_MAP_ENTRY pFoundEntry ) +{ + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER( pFoundEntry ); + + // MDL is valid + if (pPageEntry->pMdl) + { + // If MDL is mapped + if (pPageEntry->newPtr) + { + DPRINT( "BlackBone: %s: Unmapping region at 0x%p from process %u\n", __FUNCTION__, pPageEntry->newPtr, pFoundEntry->target.pid ); + MmUnmapLockedPages( (PVOID)pPageEntry->newPtr, pPageEntry->pMdl ); + pPageEntry->newPtr = 0; + } + + if (pPageEntry->locked) + MmUnlockPages( pPageEntry->pMdl ); + + IoFreeMdl( pPageEntry->pMdl ); + } + + RemoveEntryList( &pPageEntry->link ); + ExFreePoolWithTag( pPageEntry, BB_POOL_TAG ); + + return status; +} + +/// +/// Process section object pages +/// Function will attempt to trigger copy-on-write for underlying pages to convert them into private +/// If copy-on-write fails, region will be then mapped as read-only +/// +/// Target process +/// Region data +/// Status code +NTSTATUS BBHandleSharedRegion( IN PEPROCESS pProcess, IN PMAP_ENTRY pEntry ) +{ + NTSTATUS status = STATUS_SUCCESS; + + MEMORY_BASIC_INFORMATION mbi = { 0 }; + SIZE_T length = 0; + ULONG_PTR memptr = 0; + + // Iterate underlying memory regions + for (memptr = (ULONG_PTR)pEntry->mem.BaseAddress; + memptr < (ULONG_PTR)pEntry->mem.BaseAddress + pEntry->mem.RegionSize; + memptr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize) + { + PVOID pBase = NULL; + SIZE_T size = 0; + MEMORY_WORKING_SET_EX_INFORMATION wsInfo = { 0 }; + ULONG oldProt = 0; + BOOLEAN writable = FALSE; + + status = ZwQueryVirtualMemory( ZwCurrentProcess(), (PVOID)memptr, MemoryBasicInformation, &mbi, sizeof( mbi ), &length ); + if (!NT_SUCCESS( status )) + { + DPRINT( "BlackBone: %s: ZwQueryVirtualMemory for address 0x%p failed, status 0x%X\n", __FUNCTION__, memptr, status ); + return status; + } + + // Check if region has SEC_NO_CHANGE attribute + PMMVAD_SHORT pVad = { 0 }; + if (NT_SUCCESS( BBFindVAD( pProcess, (ULONG_PTR)mbi.BaseAddress, &pVad ) ) && pVad != NULL) + { + // Can't change region protection + if (pVad->u.VadFlags.NoChange) + { + return STATUS_SHARING_VIOLATION; + } + } + + writable = (mbi.Protect & (PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE)); + pBase = mbi.BaseAddress; + size = (SIZE_T)mbi.RegionSize; + + // Make readonly pages writable + if (writable || NT_SUCCESS( status = ZwProtectVirtualMemory( ZwCurrentProcess(), &pBase, &size, PAGE_EXECUTE_READWRITE, &oldProt ) )) + { + BOOLEAN failed = FALSE; + + // Touch pages to trigger copy-on-write and create private copies + // This is crucial to prevent changes on section pages + __try + { + ProbeForWrite( mbi.BaseAddress, mbi.RegionSize, PAGE_SIZE ); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + DPRINT( "BlackBone: %s: Exception while touching address 0x%p\n", __FUNCTION__, mbi.BaseAddress ); + failed = TRUE; + } + + // Restore protection + if (writable == FALSE) + ZwProtectVirtualMemory( ZwCurrentProcess(), &pBase, &size, oldProt, &oldProt ); + + if (failed) + return STATUS_SHARING_VIOLATION; + + // If region was writable, it's safe to map shared pages + if (writable) + continue; + + // + // Ensure pages were made private + // + for (ULONG_PTR pPage = (ULONG_PTR)mbi.BaseAddress; pPage < (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize; pPage += PAGE_SIZE) + { + RtlZeroMemory( &wsInfo, sizeof( wsInfo ) ); + + wsInfo.VirtualAddress = (PVOID)pPage; + + // Check page 'shared' flag + if (NT_SUCCESS( ZwQueryVirtualMemory( ZwCurrentProcess(), NULL, MemoryWorkingSetExInformation, &wsInfo, sizeof( wsInfo ), &length ) ) && + wsInfo.VirtualAttributes.Shared) + { + DPRINT( "BlackBone: %s: Page at address 0x%p is still shared!", __FUNCTION__, pPage ); + return STATUS_SHARING_VIOLATION; + } + } + } + else + { + if(status != STATUS_SECTION_PROTECTION) + DPRINT( "BlackBone: %s: Failed to alter protection of region at 0x%p, status 0x%X\n", __FUNCTION__, mbi.BaseAddress, status ); + + return status; + } + } + + return status; +} + + +/// +/// Build MDL for memory region +/// +/// Region data +/// Status code +NTSTATUS BBPrepareMDLListEntry( IN PEPROCESS pProcess, IN OUT PMAP_ENTRY pEntry ) +{ + NTSTATUS status = STATUS_SUCCESS; + + ASSERT( pEntry != NULL ); + if (pEntry == NULL) + return STATUS_INVALID_PARAMETER; + + // Handle shared pages + if (pEntry->shared != FALSE && !NT_SUCCESS( BBHandleSharedRegion( pProcess, pEntry ) )) + pEntry->readonly = TRUE; + else + pEntry->readonly = FALSE; + + pEntry->pMdl = IoAllocateMdl( pEntry->mem.BaseAddress, (ULONG)pEntry->mem.RegionSize, FALSE, FALSE, NULL ); + + if (pEntry->pMdl == NULL) + { + DPRINT( "BlackBone: %s: Failed to allocate MDL for address 0x%p\n", __FUNCTION__, pEntry->mem.BaseAddress ); + return STATUS_NO_MEMORY; + } + + __try + { + MmProbeAndLockPages( pEntry->pMdl, UserMode, IoReadAccess ); + pEntry->locked = TRUE; + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + DPRINT( "BlackBone: %s: Exception in MmProbeAndLockPages. Base = 0x%p\n", __FUNCTION__, pEntry->mem.BaseAddress ); + IoFreeMdl( pEntry->pMdl ); + pEntry->pMdl = NULL; + } + + return status; +} + + +/// +/// Walk region list and create MDL for each region +/// +/// Region list +/// Target process +/// Status code +NTSTATUS BBPrepareMDLList( IN PEPROCESS pProcess, IN PLIST_ENTRY pList ) +{ + NTSTATUS status = STATUS_SUCCESS; + PMAP_ENTRY pEntry = NULL; + + for (PLIST_ENTRY pListEntry = pList->Flink; pListEntry != pList; pListEntry = pListEntry->Flink) + { + pEntry = CONTAINING_RECORD( pListEntry, MAP_ENTRY, link ); + if (pEntry->pMdl == NULL) + BBPrepareMDLListEntry( pProcess, pEntry ); + } + + return status; +} + + +/// +/// Map locked physical pages into caller process +/// +/// Memory region +/// Last mapped region +/// Status code +NTSTATUS BBMapRegionIntoCurrentProcess( IN PMAP_ENTRY pEntry, IN PMAP_ENTRY pPrevEntry ) +{ + NTSTATUS status = STATUS_SUCCESS; + UNREFERENCED_PARAMETER( pPrevEntry ); + + ASSERT( pEntry != NULL ); + if (pEntry == NULL) + return STATUS_INVALID_PARAMETER; + + // Try to map at original address + __try { + pEntry->newPtr = (ULONG_PTR)MmMapLockedPagesSpecifyCache( + pEntry->pMdl, UserMode, MmCached, pEntry->mem.BaseAddress, FALSE, NormalPagePriority + ); + } + __except (EXCEPTION_EXECUTE_HANDLER) { } + + // Try to map immediately after previous entry + if (pEntry->newPtr == 0 && pPrevEntry != NULL && pPrevEntry->newPtr != 0) + { + __try { + pEntry->newPtr = (ULONG_PTR)MmMapLockedPagesSpecifyCache( + pEntry->pMdl, UserMode, MmCached, (PVOID)(pPrevEntry->newPtr + pPrevEntry->mem.RegionSize), FALSE, NormalPagePriority + ); + } + __except (EXCEPTION_EXECUTE_HANDLER) { } + } + + // Map at arbitrary available location + if (pEntry->newPtr == 0) + { + __try { + pEntry->newPtr = (ULONG_PTR)MmMapLockedPagesSpecifyCache( pEntry->pMdl, UserMode, MmCached, NULL, FALSE, NormalPagePriority ); + } + __except (EXCEPTION_EXECUTE_HANDLER) { } + } + + if (pEntry->newPtr != 0) + { + //if (pEntry->newPtr != pEntry->originalPtr) + //DPRINT( "BlackBone: %s: Remapped 0x%p --> 0x%p\n", __FUNCTION__, pEntry->originalPtr, pEntry->newPtr ); + + // Update region protection only for the sake of NtQueryVirtualMemory + // It has no other effect because real protection is determined by underlying PTEs + BBProtectVAD( PsGetCurrentProcess(), pEntry->newPtr, pEntry->readonly ? MM_READONLY : MM_EXECUTE_READWRITE ); + + // ZwProtectVirtualMemory can't update protection of pages that represent Physical View + // So PTEs are updated directly + for (ULONG_PTR pAdress = pEntry->newPtr; pAdress < pEntry->newPtr + pEntry->mem.RegionSize; pAdress += PAGE_SIZE) + { + PMMPTE pPTE = GetPTEForVA( (PVOID)pAdress ); + + if (pEntry->readonly) + pPTE->u.Hard.Dirty1 = pPTE->u.Hard.Write = 0; + else + pPTE->u.Hard.NoExecute = 0; + } + } + else + { + DPRINT( "BlackBone: %s: Failed to map region at adress 0x%p\n", __FUNCTION__, pEntry->mem.BaseAddress ); + status = STATUS_NONE_MAPPED; + } + + return status; +} + + +/// +/// Map memory regions into caller process +/// +/// Region list +/// If set to FALSE, warning will be printed if region is already mapped +/// Status code +NTSTATUS BBMapRegionListIntoCurrentProcess( IN PLIST_ENTRY pList, IN BOOLEAN noWarning ) +{ + NTSTATUS status = STATUS_SUCCESS; + PMAP_ENTRY pEntry = NULL, pPrevEntry = NULL; + + for (PLIST_ENTRY pListEntry = pList->Flink; pListEntry != pList; pListEntry = pListEntry->Flink) + { + pEntry = CONTAINING_RECORD( pListEntry, MAP_ENTRY, link ); + + // Skip already mapped entries + if (pEntry->newPtr != 0) + { + if (noWarning == FALSE) + DPRINT( "BlackBone: %s: Warning! Region 0x%p already mapped to 0x%p\n", __FUNCTION__, pEntry->mem.BaseAddress, pEntry->newPtr ); + + continue; + } + + // Non-locked pages can't be mapped + if (pEntry->pMdl && pEntry->locked) + status |= BBMapRegionIntoCurrentProcess( pEntry, pPrevEntry ); + else + DPRINT( "BlackBone: %s: No valid MDL for address 0x%p. Either not allocated or not locked\n", __FUNCTION__, pEntry->mem.BaseAddress ); + + pPrevEntry = pEntry; + } + + return status; +} + + +/// +/// Allocate kernel page from NonPaged pool and build MDL for it +/// +/// Resulting address +/// Resulting MDL +/// Status code +NTSTATUS BBAllocateSharedPage( OUT PVOID* pPage, OUT PMDL* pResultMDL ) +{ + NTSTATUS status = STATUS_SUCCESS; + + ASSERT( pPage != NULL && pResultMDL != NULL ); + if (pPage == NULL || pResultMDL == NULL) + return STATUS_INVALID_PARAMETER; + + *pPage = ExAllocatePoolWithTag( NonPagedPool, PAGE_SIZE, BB_POOL_TAG ); + if (*pPage) + { + // Cleanup buffer before mapping it into UserMode to prevent exposure of kernel data + RtlZeroMemory( *pPage, PAGE_SIZE ); + + *pResultMDL = IoAllocateMdl( *pPage, PAGE_SIZE, FALSE, FALSE, NULL ); + if (*pResultMDL) + MmBuildMdlForNonPagedPool( *pResultMDL ); + } + else + { + DPRINT( "BlackBone: %s: Failed to allocate kernel page\n", __FUNCTION__ ); + status = STATUS_MEMORY_NOT_ALLOCATED; + } + + return status; +} + + +/// +/// Map kernel page into current process address space +/// +/// Page MDL +/// Mapped address +/// Status code +NTSTATUS BBMapSharedPage( IN PMDL pMDL, OUT PVOID* pResult ) +{ + NTSTATUS status = STATUS_SUCCESS; + + ASSERT( pMDL != NULL && pResult != NULL ); + if (pMDL == NULL || pResult == NULL) + return STATUS_INVALID_PARAMETER; + + __try + { + // Map into user space + *pResult = MmMapLockedPagesSpecifyCache( pMDL, UserMode, MmCached, NULL, FALSE, NormalPagePriority ); + if (*pResult) + { + //DPRINT( "BlackBone: %s: Shared page at 0x%p\n", __FUNCTION__, *pResult ); + + // Make executable + BBProtectVAD( PsGetCurrentProcess(), (ULONG_PTR)*pResult, MM_EXECUTE_READWRITE ); + GetPTEForVA( *pResult )->u.Hard.NoExecute = 0; + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + } + + if (*pResult == NULL) + { + DPRINT( "BlackBone: %s: Failed to map kernel page\n", __FUNCTION__ ); + status = STATUS_NOT_MAPPED_DATA; + } + + + return status; + +} + + +/// +/// Map entire address space of target process into current +/// Subsequent calls won't map any additional regions, only return info about existing mapping +/// +/// Mapping params +/// Mapped context +/// Status code +NTSTATUS BBMapMemory( IN PMAP_MEMORY pRemap, OUT PPROCESS_MAP_ENTRY* ppEntry ) +{ + NTSTATUS status = STATUS_SUCCESS; + PEPROCESS pProcess = NULL; + PROCESS_MAP_ENTRY processEntry = { 0 }; + PPROCESS_MAP_ENTRY pFoundEntry = NULL; + BOOLEAN newEntry = FALSE; + + // Sanity checks + // Can't remap self + if ((HANDLE)pRemap->pid == PsGetCurrentProcessId()) + return STATUS_INVALID_PARAMETER; + + processEntry.target.pid = (HANDLE)pRemap->pid; + + KeAcquireGuardedMutex( &g_globalLock ); + + status = PsLookupProcessByProcessId( processEntry.target.pid, &pProcess ); + if (!NT_SUCCESS( status )) + { + DPRINT( "BlackBone: %s: Failed to find process with PID %u\n", __FUNCTION__, processEntry.target.pid ); + + KeReleaseGuardedMutex( &g_globalLock ); + return status; + } + + // Process in signaled state, abort any operations + if (BBCheckProcessTermination( pProcess )) + { + DPRINT( "BlackBone: %s: Process %u is terminating. Abort\n", __FUNCTION__, processEntry.target.pid ); + + ObDereferenceObject( pProcess ); + KeReleaseGuardedMutex( &g_globalLock ); + return STATUS_PROCESS_IS_TERMINATING; + } + + pFoundEntry = (PPROCESS_MAP_ENTRY)RtlInsertElementGenericTableAvl( &g_ProcessPageTables, &processEntry, sizeof( processEntry ), &newEntry ); + if (newEntry != FALSE) + { + InitializeListHead( &pFoundEntry->pageList ); + + // Allocate shared Page + status = BBAllocateSharedPage( &pFoundEntry->pSharedPage, &pFoundEntry->pMDLShared ); + + if (NT_SUCCESS( status )) + { + KAPC_STATE apc; + IO_STATUS_BLOCK ioStatusBlock = { 0 }; + + KeStackAttachProcess( pProcess, &apc ); + status = BBBuildProcessRegionListForRange( + &pFoundEntry->pageList, (ULONG_PTR)MM_LOWEST_USER_ADDRESS, + (ULONG_PTR)MM_HIGHEST_USER_ADDRESS, pRemap->mapSections + ); + + if (NT_SUCCESS( status )) + status = BBPrepareMDLList( pProcess, &pFoundEntry->pageList ); + + // Map shared page into target process + if (NT_SUCCESS( status )) + status = BBMapSharedPage( pFoundEntry->pMDLShared, &pFoundEntry->target.sharedPage ); + + // Open pipe endpoint + if (NT_SUCCESS( status ) && pRemap->pipeName[0] != L'\0') + { + WCHAR wbuf[64] = { 0 }; + UNICODE_STRING pipeName = { 0 }; + pipeName.Buffer = wbuf; + pipeName.MaximumLength = sizeof( wbuf ); + + NTSTATUS pipeStatus = RtlUnicodeStringPrintf( &pipeName, L"\\??\\pipe\\%ls", pRemap->pipeName ); + if (NT_SUCCESS( pipeStatus )) + { + OBJECT_ATTRIBUTES attr = { 0 }; + InitializeObjectAttributes( &attr, &pipeName, OBJ_CASE_INSENSITIVE, NULL, NULL ); + pipeStatus = ZwOpenFile( &pFoundEntry->targetPipe, GENERIC_WRITE, &attr, &ioStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, 0 ); + } + + if (!NT_SUCCESS( pipeStatus )) + DPRINT( "BlackBone: %s: Remap pipe failed with status 0x%X\n", __FUNCTION__, pipeStatus ); + } + + KeUnstackDetachProcess( &apc ); + } + } + else + { + DPRINT( "BlackBone: %s: Found mapping entry for process %u\n", __FUNCTION__, pFoundEntry->target.pid ); + + // Caller is not Host and Host still exists + // Do not allow remapping into new process + if (pFoundEntry->host.pid != PsGetCurrentProcessId() && pFoundEntry->host.pid != NULL) + { + DPRINT( "BlackBone: %s: Host process %u still exists. Cannot map into new process\n", __FUNCTION__, pFoundEntry->host.pid ); + status = STATUS_ADDRESS_ALREADY_EXISTS; + } + } + + // Update host process + if (NT_SUCCESS( status ) && (newEntry || pFoundEntry->host.pid == NULL)) + { + // Map memory + BBMapRegionListIntoCurrentProcess( &pFoundEntry->pageList, FALSE ); + + // Map shared page into Host process + BBMapSharedPage( pFoundEntry->pMDLShared, &pFoundEntry->host.sharedPage ); + + pFoundEntry->host.pid = PsGetCurrentProcessId(); + } + + if (ppEntry) + *ppEntry = pFoundEntry; + + if (pProcess) + ObDereferenceObject( pProcess ); + + // Remove entry if something went wrong + if (!NT_SUCCESS( status ) && status != STATUS_ADDRESS_ALREADY_EXISTS) + BBCleanupProcessEntry(pFoundEntry); + + KeReleaseGuardedMutex( &g_globalLock ); + + return status; +} + +/// +/// Map specific memory region +/// +/// Region data +/// Mapping results +/// Status code +NTSTATUS BBMapMemoryRegion( IN PMAP_MEMORY_REGION pRegion, OUT PMAP_MEMORY_REGION_RESULT pResult ) +{ + NTSTATUS status = STATUS_SUCCESS; + ULONG pageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES( pRegion->base, pRegion->size ); + PROCESS_MAP_ENTRY processEntry = { 0 }; + PPROCESS_MAP_ENTRY pFoundEntry = NULL; + PEPROCESS pProcess = NULL; + BOOLEAN newEntry = FALSE; + BOOLEAN alreadyExists = FALSE; + ULONG_PTR removedBase = 0; + ULONG removedSize = 0; + + // Don't allow remapping of kernel addresses + if (pRegion->base >= (ULONGLONG)MM_HIGHEST_USER_ADDRESS || pRegion->base + pRegion->size > (ULONGLONG)MM_HIGHEST_USER_ADDRESS) + { + DPRINT( "BlackBone: %s: Invalid address range: 0x%p - 0x%p\n", __FUNCTION__, pRegion->base, pRegion->base + pRegion->size ); + return STATUS_INVALID_ADDRESS; + } + + KeAcquireGuardedMutex( &g_globalLock ); + + // Align on page boundaries + pRegion->base = (ULONGLONG)PAGE_ALIGN( pRegion->base ); + pRegion->size = pageCount << PAGE_SHIFT; + + processEntry.target.pid = (HANDLE)pRegion->pid; + processEntry.host.pid = PsGetCurrentProcessId(); + + status = PsLookupProcessByProcessId( processEntry.target.pid, &pProcess ); + if (!NT_SUCCESS( status )) + { + DPRINT( "BlackBone: %s: Failed to find process 0x%u\n", __FUNCTION__, processEntry.target.pid ); + KeReleaseGuardedMutex( &g_globalLock ); + return status; + } + + // Process in signaled state, abort any operations + if (BBCheckProcessTermination( pProcess )) + { + DPRINT( "BlackBone: %s: Process %u is terminating. Abort\n", __FUNCTION__, processEntry.target.pid ); + + ObDereferenceObject( pProcess ); + KeReleaseGuardedMutex( &g_globalLock ); + return STATUS_PROCESS_IS_TERMINATING; + } + + // Store or retrieve context + pFoundEntry = (PPROCESS_MAP_ENTRY)RtlInsertElementGenericTableAvl( &g_ProcessPageTables, &processEntry, sizeof( processEntry ), &newEntry ); + if (newEntry != FALSE) + { + DPRINT( "BlackBone: %s: Process entry 0x%u was not found, creating new\n", __FUNCTION__, processEntry.target.pid ); + InitializeListHead( &pFoundEntry->pageList ); + + // Allocate shared Page + status = BBAllocateSharedPage( &pFoundEntry->pSharedPage, &pFoundEntry->pMDLShared ); + } + else + { + PMAP_ENTRY pPageEntry = NULL; + + // Does not allow call from non-original process + if (pFoundEntry->host.pid != PsGetCurrentProcessId() && pFoundEntry->host.pid != NULL) + { + DPRINT( "BlackBone: %s: Call from non-original process not supported\n", __FUNCTION__ ); + status = STATUS_INVALID_PARAMETER; + } + + // Conflicting region + // Target region isn't considered conflicting if it completely fits into existing + // TODO: Find source of the problem + pPageEntry = BBFindPageEntry( &pFoundEntry->pageList, pRegion->base, pRegion->size ); + if (pPageEntry) + { + if (pRegion->base < (ULONGLONG)pPageEntry->mem.BaseAddress || + pRegion->base + pRegion->size > (ULONGLONG)pPageEntry->mem.BaseAddress + pPageEntry->mem.RegionSize) + { + DPRINT( + "BlackBone: %s: Target region 0%p - 0x%p conficts with existing: 0x%p - 0x%p\n", __FUNCTION__, + pRegion->base, pRegion->base + pRegion->size, + pPageEntry->mem.BaseAddress, (ULONGLONG)pPageEntry->mem.BaseAddress + pPageEntry->mem.RegionSize + ); + + // Unmap conflicting region + removedBase = (ULONG_PTR)pPageEntry->mem.BaseAddress; + removedSize = (ULONG)pPageEntry->mem.RegionSize; + + status = BBUnmapRegionEntry( pPageEntry, pFoundEntry ); + } + else + alreadyExists = TRUE; + } + } + + // Map region if required + if (alreadyExists == FALSE && NT_SUCCESS( status )) + { + KAPC_STATE apc; + + // Allocate MDLs and lock pages + KeStackAttachProcess( pProcess, &apc ); + status = BBBuildProcessRegionListForRange( &pFoundEntry->pageList, pRegion->base, pRegion->base + pRegion->size, TRUE ); + + if (NT_SUCCESS( status )) + status = BBPrepareMDLList( pProcess, &pFoundEntry->pageList ); + + // Map shared page into target process + if (NT_SUCCESS( status ) && newEntry) + status = BBMapSharedPage( pFoundEntry->pMDLShared, &pFoundEntry->target.sharedPage ); + + KeUnstackDetachProcess( &apc ); + + // Map shared page into Host process + if (NT_SUCCESS( status ) && newEntry) + status = BBMapSharedPage( pFoundEntry->pMDLShared, &pFoundEntry->host.sharedPage ); + + if (NT_SUCCESS( status )) + status = BBMapRegionListIntoCurrentProcess( &pFoundEntry->pageList, TRUE ); + } + + if (pProcess) + ObDereferenceObject( pProcess ); + + // Fill result + if (NT_SUCCESS( status ) && pResult) + { + // FIXME: + // Target region could be divided into several smaller ones + // This function will return only first found + PMAP_ENTRY pEntry = BBFindPageEntry( &pFoundEntry->pageList, pRegion->base, pRegion->size ); + if (pEntry) + { + DPRINT( "BlackBone: %s: Updated 0x%p --> 0x%p\n", __FUNCTION__, pEntry->mem.BaseAddress, pEntry->newPtr ); + + pResult->originalPtr = (ULONGLONG)pEntry->mem.BaseAddress; + pResult->newPtr = pEntry->newPtr; + pResult->removedPtr = removedBase; + pResult->size = (ULONG)pEntry->mem.RegionSize; + pResult->removedSize = removedSize; + } + } + + // Remove entry if something goes wrong + if (!NT_SUCCESS( status )) + BBCleanupProcessEntry( pFoundEntry ); + + KeReleaseGuardedMutex( &g_globalLock ); + + return status; +} + +/// +/// Unmap any mapped memory from host and target processes +/// +/// Request params +/// Status code +NTSTATUS BBUnmapMemory( IN PUNMAP_MEMORY pUnmap ) +{ + NTSTATUS status = STATUS_SUCCESS; + PPROCESS_MAP_ENTRY pFoundEntry = NULL; + + KeAcquireGuardedMutex( &g_globalLock ); + + pFoundEntry = BBLookupProcessEntry( (HANDLE)pUnmap->pid, FALSE ); + if (pFoundEntry == NULL) + { + DPRINT( "BlackBone: %s: Process entry with PID %u was not found\n", __FUNCTION__, pUnmap->pid ); + status = STATUS_NOT_FOUND; + } + else + { + DPRINT( "BlackBone: %s: BBUnmapMemory cleanup for PID %u\n", __FUNCTION__, pUnmap->pid ); + BBCleanupProcessEntry( pFoundEntry ); + } + + KeReleaseGuardedMutex( &g_globalLock ); + + return status; +} + +/// +/// Unmap specific memory region +/// +/// Region info +/// Status ode +NTSTATUS BBUnmapMemoryRegion( IN PUNMAP_MEMORY_REGION pRegion ) +{ + NTSTATUS status = STATUS_SUCCESS; + PPROCESS_MAP_ENTRY pFoundEntry = NULL; + PMAP_ENTRY pPageEntry = NULL; + PEPROCESS pProcess = NULL; + ULONG pageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(pRegion->base, pRegion->size); + + // Sanity check + if (pRegion->base >= (ULONGLONG)MM_HIGHEST_USER_ADDRESS || pRegion->base + pRegion->size > (ULONGLONG)MM_HIGHEST_USER_ADDRESS) + return STATUS_INVALID_ADDRESS; + + KeAcquireGuardedMutex( &g_globalLock ); + + status = PsLookupProcessByProcessId( (HANDLE)pRegion->pid, &pProcess ); + if (!NT_SUCCESS( status )) + { + DPRINT( "BlackBone: %s: Failed to find process 0x%u\n", __FUNCTION__, pRegion->pid ); + KeReleaseGuardedMutex( &g_globalLock ); + return status; + } + + // Process in signaled state, abort any operations + if (BBCheckProcessTermination( pProcess )) + { + DPRINT( "BlackBone: %s: Process %u is terminating. Abort\n", __FUNCTION__, pRegion->pid ); + + ObDereferenceObject( pProcess ); + KeReleaseGuardedMutex( &g_globalLock ); + return STATUS_PROCESS_IS_TERMINATING; + } + + pFoundEntry = BBLookupProcessEntry( (HANDLE)pRegion->pid, FALSE ); + if (pFoundEntry == NULL) + { + DPRINT( "BlackBone: %s: Process entry for process %u was not found\n", __FUNCTION__, pRegion->pid ); + status = STATUS_NOT_FOUND; + } + else + { + // Does not allow call from non-original process + if (pFoundEntry->host.pid != PsGetCurrentProcessId()) + { + DPRINT( "BlackBone: %s: Call from non-original process not supported\n", __FUNCTION__ ); + status = STATUS_INVALID_PARAMETER; + } + else + { + // Align on page boundaries + pRegion->base = (ULONGLONG)PAGE_ALIGN( pRegion->base ); + pRegion->size = pageCount << PAGE_SHIFT; + + pPageEntry = BBFindPageEntry( &pFoundEntry->pageList, pRegion->base, pRegion->size ); + if (pPageEntry) + { + status = BBUnmapRegionEntry( pPageEntry, pFoundEntry ); + } + else + { + DPRINT( "BlackBone: %s: Map entry for address 0x%p was not found\n", __FUNCTION__, pRegion->base ); + status = STATUS_INVALID_ADDRESS; + } + } + } + + if (pProcess) + ObDereferenceObject( pProcess ); + + KeReleaseGuardedMutex( &g_globalLock ); + + return status; +} + + +/// +/// Unmap pages, destroy MDLs, remove entry from list +/// +/// TRUE indicates that function is executed +/// in the context of host process and pages can be safely unmapped +/// Region list +VOID BBCleanupPageList( IN BOOLEAN attached, IN PLIST_ENTRY pList ) +{ + // No work required + if (pList == NULL || IsListEmpty( pList )) + return; + + while (!IsListEmpty( pList )) + { + PMAP_ENTRY pEntry = CONTAINING_RECORD( pList->Flink, MAP_ENTRY, link ); + + if (pEntry->pMdl) + { + // If MDL is mapped and we are in the context of corresponding process + if (attached && pEntry->newPtr) + MmUnmapLockedPages( (PVOID)pEntry->newPtr, pEntry->pMdl ); + + if (pEntry->locked) + MmUnlockPages( pEntry->pMdl ); + + IoFreeMdl( pEntry->pMdl ); + } + + RemoveHeadList( pList ); + ExFreePoolWithTag( pEntry, BB_POOL_TAG ); + } +} + + +/// +/// Close handle if process isn't in signaled state +/// +/// Process object +/// Handle +/// KernelMode or UserMode handle +/// Status code +NTSTATUS BBSafeHandleClose( IN PEPROCESS pProcess, IN HANDLE handle, IN KPROCESSOR_MODE mode ) +{ + ASSERT( pProcess != NULL ); + if (pProcess == NULL) + return STATUS_INVALID_PARAMETER; + + // + // If process is in signaled state, ObjectTable is already NULL + // Thus is will lead to crash in ObCloseHandle->ExpLookupHandleTableEntry + // + if (BBCheckProcessTermination( pProcess )) + return STATUS_PROCESS_IS_TERMINATING; + + return ObCloseHandle( handle, mode ); +} + + +/// +/// Unmap all regions, delete MDLs, close handles, remove entry from table +/// +/// Process entry +VOID BBCleanupProcessEntry( IN PPROCESS_MAP_ENTRY pProcessEntry ) +{ + KAPC_STATE apc; + PEPROCESS pTargetProc = NULL, pHostProc = NULL; + ATTACHED_CONTEXT context = ContextNone; + + ASSERT( pProcessEntry != NULL ); + if (pProcessEntry == NULL) + return; + + if (PsGetCurrentProcessId() == pProcessEntry->host.pid) + context = ContextHost; + else if (PsGetCurrentProcessId() == pProcessEntry->target.pid) + context = ContextTarget; + + // Unmap from Host + if (context == ContextHost || NT_SUCCESS( PsLookupProcessByProcessId( pProcessEntry->host.pid, &pHostProc ) )) + { + if (context != ContextHost) + KeStackAttachProcess( pHostProc, &apc ); + + if (pProcessEntry->host.sharedPage) + MmUnmapLockedPages( pProcessEntry->host.sharedPage, pProcessEntry->pMDLShared ); + + BBCleanupPageList( TRUE, &pProcessEntry->pageList ); + + if (context != ContextHost) + KeUnstackDetachProcess( &apc ); + + if (pHostProc) + ObDereferenceObject( pHostProc ); + } + + // Unmap from target + if (context == ContextTarget || NT_SUCCESS( PsLookupProcessByProcessId( pProcessEntry->target.pid, &pTargetProc ) )) + { + if (context != ContextTarget) + KeStackAttachProcess( pTargetProc, &apc ); + + BBSafeHandleClose( context == ContextTarget ? IoGetCurrentProcess() : pTargetProc, pProcessEntry->targetPipe, UserMode ); + + if (pProcessEntry->target.sharedPage) + MmUnmapLockedPages( pProcessEntry->target.sharedPage, pProcessEntry->pMDLShared ); + + if (context != ContextTarget) + KeUnstackDetachProcess( &apc ); + + if (pTargetProc) + ObDereferenceObject( pTargetProc ); + } + + // Free shared page + if (pProcessEntry->pSharedPage) + { + if (pProcessEntry->pMDLShared) + { + IoFreeMdl( pProcessEntry->pMDLShared ); + pProcessEntry->pMDLShared = NULL; + } + + ExFreePoolWithTag( pProcessEntry->pSharedPage, BB_POOL_TAG ); + pProcessEntry->pSharedPage = NULL; + } + + // Make sure page list is cleaned up even if there is no Host process + BBCleanupPageList( FALSE, &pProcessEntry->pageList ); + RtlDeleteElementGenericTableAvl( &g_ProcessPageTables, pProcessEntry ); +} + + +/// +/// Unmap any mapped pages from host process +/// +/// Process entry +VOID BBCleanupHostProcess( IN PPROCESS_MAP_ENTRY pProcessEntry ) +{ + ASSERT( pProcessEntry != NULL ); + if (pProcessEntry == NULL) + return; + + DPRINT( "BlackBone: %s: Host process %u shutdown. Cleanup\n", __FUNCTION__, pProcessEntry->host.pid ); + + for (PLIST_ENTRY pListEntry = pProcessEntry->pageList.Flink; pListEntry != &pProcessEntry->pageList; pListEntry = pListEntry->Flink) + { + PMAP_ENTRY pEntry = CONTAINING_RECORD( pListEntry, MAP_ENTRY, link ); + if (pEntry->newPtr) + { + MmUnmapLockedPages( (PVOID)pEntry->newPtr, pEntry->pMdl ); + pEntry->newPtr = 0; + } + } + + // + // Unmap kernel shared page + // + if (pProcessEntry->pSharedPage && + pProcessEntry->pMDLShared && + pProcessEntry->host.sharedPage) + { + MmUnmapLockedPages( (PVOID)pProcessEntry->host.sharedPage, pProcessEntry->pMDLShared ); + pProcessEntry->host.sharedPage = 0; + } + + // Set host process as none + pProcessEntry->host.pid = 0; +} + + +/// +/// Clear global process map table +/// +VOID BBCleanupProcessTable() +{ + KeAcquireGuardedMutex( &g_globalLock ); + + while (!RtlIsGenericTableEmptyAvl( &g_ProcessPageTables )) + BBCleanupProcessEntry( (PPROCESS_MAP_ENTRY)RtlEnumerateGenericTableAvl( &g_ProcessPageTables, TRUE ) ); + + KeReleaseGuardedMutex( &g_globalLock ); +} + + +/// +/// Search process entry in list by PID +/// +/// PID. +/// If set to TRUE, pid is treated as host PID +/// Found entry, NULL in not found +PPROCESS_MAP_ENTRY BBLookupProcessEntry( IN HANDLE pid, IN BOOLEAN asHost ) +{ + PROCESS_MAP_ENTRY entry = { 0 }; + + if (asHost) + entry.host.pid = pid; + else + entry.target.pid = pid; + + return RtlLookupElementGenericTableAvl( &g_ProcessPageTables, &entry ); +} + + +/// +/// Find memory region containing at least one byte from specific region +/// +/// Region list to search in +/// Base of region to find +/// Size of the region to find +/// Status code +PMAP_ENTRY BBFindPageEntry( IN PLIST_ENTRY pList, IN ULONG_PTR baseAddress, IN ULONG_PTR size ) +{ + // Test if target region overlaps with any existing one + for (PLIST_ENTRY pListEntry = pList->Flink; pListEntry != pList; pListEntry = pListEntry->Flink) + { + PMAP_ENTRY pEntry = CONTAINING_RECORD( pListEntry, MAP_ENTRY, link ); + + if (baseAddress >= (ULONG_PTR)pEntry->mem.BaseAddress && + baseAddress < (ULONG_PTR)pEntry->mem.BaseAddress + pEntry->mem.RegionSize) + { + return pEntry; + } + + if (baseAddress + size >= (ULONG_PTR)pEntry->mem.BaseAddress && + baseAddress + size < (ULONG_PTR)pEntry->mem.BaseAddress + pEntry->mem.RegionSize) + { + return pEntry; + } + } + + return NULL; +} + +/// +/// Calculate size required to store mapping info +/// +/// Mapped regions list +/// Resulting size +/// Status code +NTSTATUS BBGetRequiredRemapOutputSize( IN PLIST_ENTRY pList, OUT PULONG_PTR pSize ) +{ + NTSTATUS status = STATUS_SUCCESS; + ULONG_PTR size = sizeof( MAP_MEMORY_RESULT ) - sizeof( MAP_MEMORY_RESULT_ENTRY ); + + for (PLIST_ENTRY pListEntry = pList->Flink; pListEntry != pList; pListEntry = pListEntry->Flink) + size += sizeof( MAP_MEMORY_RESULT_ENTRY ); + + if (pSize) + *pSize = size; + + return status; +} + diff --git a/third/Blackbone/src/BlackBoneDrv/Remap.h b/third/Blackbone/src/BlackBoneDrv/Remap.h new file mode 100644 index 0000000000000000000000000000000000000000..184625cd7a3461fd8d383b8a505c80e1eaca6aca --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/Remap.h @@ -0,0 +1,138 @@ +#pragma once + +#include "Private.h" +#include "VadRoutines.h" +#include "BlackBoneDef.h" + +typedef enum _ATTACHED_CONTEXT +{ + ContextNone, // Running in system context + ContextHost, // Running in the context of host process + ContextTarget, // Running in the context of target process +} ATTACHED_CONTEXT; + +/// +/// Process-specific data +/// +typedef struct _PROCESS_CONTEXT +{ + HANDLE pid; // Process ID + PVOID sharedPage; // Address of kernel shared page +} PROCESS_CONTEXT, *PPROCESS_CONTEXT; + + +/// +/// Target - host correspondence +/// +typedef struct _PROCESS_MAP_ENTRY +{ + PROCESS_CONTEXT host; // Hosting process context + PROCESS_CONTEXT target; // Target process context + + PVOID pSharedPage; // Address of kernel-shared page allocated from non-paged pool + PMDL pMDLShared; // MDL of kernel-shared page + + HANDLE targetPipe; // Hook pipe handle in target process + + LIST_ENTRY pageList; // List of REMAP_ENTRY structures +} PROCESS_MAP_ENTRY, *PPROCESS_MAP_ENTRY; + + +/// +/// Mapped memory region info +/// +typedef struct _MAP_ENTRY +{ + LIST_ENTRY link; // Linked list link + MEMORY_BASIC_INFORMATION mem; // Original memory info + + ULONG_PTR newPtr; // Mapped memory address in host process + PMDL pMdl; // Region MDL entry + BOOLEAN locked; // MDL is locked + BOOLEAN shared; // Regions has shared pages + BOOLEAN readonly; // Region must be mapped as readonly +} MAP_ENTRY, *PMAP_ENTRY; + +extern DYNAMIC_DATA dynData; +extern RTL_AVL_TABLE g_ProcessPageTables; +extern KGUARDED_MUTEX g_globalLock; + +/// +/// Map entire address space of target process into current +/// +/// Mapping params +/// Mapped context +/// Status code +NTSTATUS BBMapMemory( IN PMAP_MEMORY pRemap, OUT PPROCESS_MAP_ENTRY* ppEntry ); + +/// +/// Map specific memory region +/// +/// Region data +/// Mapping results +/// Status code +NTSTATUS BBMapMemoryRegion( IN PMAP_MEMORY_REGION pRegion, OUT PMAP_MEMORY_REGION_RESULT pResult ); + +/// +/// Unmap any mapped memory from host and target processes +/// +/// Request params +/// Status code +NTSTATUS BBUnmapMemory( IN PUNMAP_MEMORY pUnmap ); + +/// +/// Unmap specific memory region +/// +/// Region info +/// Status ode +NTSTATUS BBUnmapMemoryRegion( IN PUNMAP_MEMORY_REGION pRegion ); + +/// +/// Calculate size required to store mapping info +/// +/// Mapped regions list +/// Resulting size +/// Status code +NTSTATUS BBGetRequiredRemapOutputSize( IN PLIST_ENTRY pList, OUT PULONG_PTR pSize ); + +/// +/// Enumerate committed, accessible, non-guarded memory regions +/// +/// Region list +/// Region start +/// Region end +/// If set to FALSE, section objects will be excluded from list +/// Status code +NTSTATUS BBBuildProcessRegionListForRange( IN PLIST_ENTRY pList, IN ULONG_PTR start, IN ULONG_PTR end, IN BOOLEAN mapSections ); + +/// +/// Search process entry in list by PID +/// +/// PID. +/// If set to TRUE, pid is treated as host PID +/// Found entry, NULL in not found +PPROCESS_MAP_ENTRY BBLookupProcessEntry( IN HANDLE pid, IN BOOLEAN asHost ); + +/// +/// Unmap all regions, delete MDLs, close handles, remove entry from table +/// +/// Process entry +VOID BBCleanupProcessEntry( IN PPROCESS_MAP_ENTRY pProcessEntry ); + +/// +/// Clear global process map table +/// +VOID BBCleanupProcessTable(); + +/// +/// Unmap any mapped pages from host process +/// +/// Process entry +VOID BBCleanupHostProcess( IN PPROCESS_MAP_ENTRY pProcessEntry ); + +// +// AVL table routines +// +RTL_GENERIC_COMPARE_RESULTS AvlCompare( IN RTL_AVL_TABLE *Table, IN PVOID FirstStruct, IN PVOID SecondStruct ); +PVOID AvlAllocate( IN RTL_AVL_TABLE *Table, IN CLONG ByteSize ); +VOID AvlFree( IN RTL_AVL_TABLE *Table, IN PVOID Buffer ); \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/Routines.c b/third/Blackbone/src/BlackBoneDrv/Routines.c new file mode 100644 index 0000000000000000000000000000000000000000..6d9a38ba70b28e98e7f27c25694087bf63e35ce3 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/Routines.c @@ -0,0 +1,936 @@ +#include "BlackBoneDrv.h" +#include "Routines.h" +#include "Utils.h" +#include + +LIST_ENTRY g_PhysProcesses; +PVOID g_kernelPage = NULL; // Trampoline buffer page +LONG g_trIndex = 0; // Trampoline global index + +/// +/// Find allocated memory region entry +/// +/// Region list +/// Region base +/// Found entry, NULL if not found +PMEM_PHYS_ENTRY BBLookupPhysMemEntry( IN PLIST_ENTRY pList, IN PVOID pBase ); +VOID BBWriteTrampoline( IN PUCHAR place, IN PVOID pfn ); +BOOLEAN BBHandleCallback( +#if !defined(_WIN7_) + IN PHANDLE_TABLE HandleTable, +#endif + IN PHANDLE_TABLE_ENTRY HandleTableEntry, + IN HANDLE Handle, + IN PVOID EnumParameter + ); + +#pragma alloc_text(PAGE, BBDisableDEP) +#pragma alloc_text(PAGE, BBSetProtection) +#pragma alloc_text(PAGE, BBHandleCallback) +#pragma alloc_text(PAGE, BBGrantAccess) +#pragma alloc_text(PAGE, BBCopyMemory) +#pragma alloc_text(PAGE, BBAllocateFreeMemory) +#pragma alloc_text(PAGE, BBAllocateFreePhysical) +#pragma alloc_text(PAGE, BBProtectMemory) +#pragma alloc_text(PAGE, BBWriteTrampoline) +#pragma alloc_text(PAGE, BBHookSSDT) + +#pragma alloc_text(PAGE, BBLookupPhysProcessEntry) +#pragma alloc_text(PAGE, BBLookupPhysMemEntry) + +#pragma alloc_text(PAGE, BBCleanupPhysMemEntry) +#pragma alloc_text(PAGE, BBCleanupProcessPhysEntry) +#pragma alloc_text(PAGE, BBCleanupProcessPhysList) + +/// +/// Disable process DEP +/// Has no effect on native x64 process +/// +/// Request params +/// Status code +NTSTATUS BBDisableDEP( IN PDISABLE_DEP pData ) +{ + NTSTATUS status = STATUS_SUCCESS; + PEPROCESS pProcess = NULL; + + status = PsLookupProcessByProcessId( (HANDLE)pData->pid, &pProcess ); + if (NT_SUCCESS( status )) + { + if (dynData.KExecOpt != 0) + { + PKEXECUTE_OPTIONS pExecOpt = (PKEXECUTE_OPTIONS)((PUCHAR)pProcess + dynData.KExecOpt); + + // Reset all flags + pExecOpt->ExecuteOptions = 0; + + pExecOpt->Flags.ExecuteEnable = 1; // + pExecOpt->Flags.ImageDispatchEnable = 1; // Disable all checks + pExecOpt->Flags.ExecuteDispatchEnable = 1; // + } + else + { + DPRINT( "BlackBone: %s: Invalid _KEXECUTE_OPTIONS offset\n", __FUNCTION__ ); + status = STATUS_INVALID_ADDRESS; + } + } + else + DPRINT( "BlackBone: %s: PsLookupProcessByProcessId failed with status 0x%X\n", __FUNCTION__, status ); + + if (pProcess) + ObDereferenceObject( pProcess ); + + return status; +} + +/// +/// Enable/disable process protection flag +/// +/// Request params +/// Status code +NTSTATUS BBSetProtection( IN PSET_PROC_PROTECTION pProtection ) +{ + NTSTATUS status = STATUS_SUCCESS; + PEPROCESS pProcess = NULL; + + status = PsLookupProcessByProcessId( (HANDLE)pProtection->pid, &pProcess ); + if (NT_SUCCESS( status )) + { + if (dynData.Protection != 0) + { + PUCHAR pValue = (PUCHAR)pProcess + dynData.Protection; + + // Win7 + if (dynData.ver <= WINVER_7_SP1) + { + if (pProtection->protection == Policy_Enable) + *(PULONG)pValue |= 1 << 0xB; + else if (pProtection->protection == Policy_Disable) + *(PULONG)pValue &= ~(1 << 0xB); + } + // Win8 + else if (dynData.ver == WINVER_8) + { + if (pProtection->protection != Policy_Keep) + *pValue = pProtection->protection; + } + // Win8.1 + else if (dynData.ver >= WINVER_81) + { + // Protection + if (pProtection->protection == Policy_Disable) + { + *pValue = 0; + } + else if(pProtection->protection == Policy_Enable) + { + PS_PROTECTION protBuf = { 0 }; + + protBuf.Flags.Signer = PsProtectedSignerWinTcb; + protBuf.Flags.Type = PsProtectedTypeProtected; + *pValue = protBuf.Level; + } + + // Dynamic code + if (pProtection->dynamicCode != Policy_Keep && dynData.EProcessFlags2 != 0) + { + if (dynData.ver >= WINVER_10_RS3) + { + PMITIGATION_FLAGS pFlags2 = (PMITIGATION_FLAGS)((PUCHAR)pProcess + dynData.EProcessFlags2); + pFlags2->DisableDynamicCode = pProtection->dynamicCode; + } + else + { + PEPROCESS_FLAGS2 pFlags2 = (PEPROCESS_FLAGS2)((PUCHAR)pProcess + dynData.EProcessFlags2); + pFlags2->DisableDynamicCode = pProtection->dynamicCode; + } + + } + + // Binary signature + if (pProtection->signature != Policy_Keep) + { + PSE_SIGNING_LEVEL pSignLevel = (PSE_SIGNING_LEVEL)((PUCHAR)pProcess + dynData.Protection - 2); + PSE_SIGNING_LEVEL pSignLevelSection = (PSE_SIGNING_LEVEL)((PUCHAR)pProcess + dynData.Protection - 1); + + if(pProtection->signature == Policy_Enable) + *pSignLevel = *pSignLevelSection = SE_SIGNING_LEVEL_MICROSOFT; + else + *pSignLevel = *pSignLevelSection = SE_SIGNING_LEVEL_UNCHECKED; + } + } + else + status = STATUS_NOT_SUPPORTED; + } + else + { + DPRINT( "BlackBone: %s: Invalid protection flag offset\n", __FUNCTION__ ); + status = STATUS_INVALID_ADDRESS; + } + } + else + DPRINT( "BlackBone: %s: PsLookupProcessByProcessId failed with status 0x%X\n", __FUNCTION__, status ); + + if (pProcess) + ObDereferenceObject( pProcess ); + + return status; +} + +/// +/// Handle enumeration callback +/// +/// Process handle table +/// Handle entry +/// Handle value +/// User context +/// TRUE when desired handle is found +BOOLEAN BBHandleCallback( +#if !defined(_WIN7_) + IN PHANDLE_TABLE HandleTable, +#endif + IN PHANDLE_TABLE_ENTRY HandleTableEntry, + IN HANDLE Handle, + IN PVOID EnumParameter + ) +{ + + BOOLEAN result = FALSE; + ASSERT( EnumParameter ); + + if (EnumParameter != NULL) + { + PHANDLE_GRANT_ACCESS pAccess = (PHANDLE_GRANT_ACCESS)EnumParameter; + if (Handle == (HANDLE)pAccess->handle) + { + if (ExpIsValidObjectEntry( HandleTableEntry )) + { + // Update access + HandleTableEntry->GrantedAccessBits = pAccess->access; + result = TRUE; + } + else + DPRINT( "BlackBone: %s: 0x%X:0x%X handle is invalid\n. HandleEntry = 0x%p", + __FUNCTION__, pAccess->pid, pAccess->handle, HandleTableEntry + ); + } + } + +#if !defined(_WIN7_) + // Release implicit locks + _InterlockedExchangeAdd8( (char*)&HandleTableEntry->VolatileLowValue, 1 ); // Set Unlocked flag to 1 + if (HandleTable != NULL && HandleTable->HandleContentionEvent) + ExfUnblockPushLock( &HandleTable->HandleContentionEvent, NULL ); +#endif + + return result; +} + +/// +/// Change handle granted access +/// +/// Request params +/// Status code +NTSTATUS BBGrantAccess( IN PHANDLE_GRANT_ACCESS pAccess ) +{ + NTSTATUS status = STATUS_SUCCESS; + PEPROCESS pProcess = NULL; + + // Validate dynamic offset + if (dynData.ObjTable == 0) + { + DPRINT( "BlackBone: %s: Invalid ObjTable address\n", __FUNCTION__ ); + return STATUS_INVALID_ADDRESS; + } + + status = PsLookupProcessByProcessId( (HANDLE)pAccess->pid, &pProcess ); + if (NT_SUCCESS( status ) && BBCheckProcessTermination( pProcess )) + status = STATUS_PROCESS_IS_TERMINATING; + + if (NT_SUCCESS( status )) + { + PHANDLE_TABLE pTable = *(PHANDLE_TABLE*)((PUCHAR)pProcess + dynData.ObjTable); + BOOLEAN found = ExEnumHandleTable( pTable, &BBHandleCallback, pAccess, NULL ); + if (found == FALSE) + status = STATUS_NOT_FOUND; + } + else + DPRINT( "BlackBone: %s: PsLookupProcessByProcessId failed with status 0x%X\n", __FUNCTION__, status ); + + if (pProcess) + ObDereferenceObject( pProcess ); + + return status; +} + +/// +/// Change handle granted access +/// +/// Request params +/// Status code +NTSTATUS BBUnlinkHandleTable( IN PUNLINK_HTABLE pUnlink ) +{ + NTSTATUS status = STATUS_SUCCESS; + PEPROCESS pProcess = NULL; + + // Validate dynamic offset + if (dynData.ExRemoveTable == 0 || dynData.ObjTable == 0) + { + DPRINT( "BlackBone: %s: Invalid ExRemoveTable/ObjTable address\n", __FUNCTION__ ); + return STATUS_INVALID_ADDRESS; + } + + // Validate build + if (dynData.correctBuild == FALSE) + { + DPRINT( "BlackBone: %s: Unsupported kernel build version\n", __FUNCTION__ ); + return STATUS_INVALID_KERNEL_INFO_VERSION; + } + + status = PsLookupProcessByProcessId( (HANDLE)pUnlink->pid, &pProcess ); + if (NT_SUCCESS( status )) + { + PHANDLE_TABLE pTable = *(PHANDLE_TABLE*)((PUCHAR)pProcess + dynData.ObjTable); + + // Unlink process handle table + fnExRemoveHandleTable ExRemoveHandleTable = (fnExRemoveHandleTable)((ULONG_PTR)GetKernelBase( NULL ) + dynData.ExRemoveTable); + //DPRINT( "BlackBone: %s: ExRemoveHandleTable address 0x%p. Object Table offset: 0x%X\n", + // __FUNCTION__, ExRemoveHandleTable, dynData.ObjTable ); + + ExRemoveHandleTable( pTable ); + } + else + DPRINT( "BlackBone: %s: PsLookupProcessByProcessId failed with status 0x%X\n", __FUNCTION__, status ); + + if (pProcess) + ObDereferenceObject( pProcess ); + + return status; +} + +/// +/// Read/write process memory +/// +/// Request params +/// Status code +NTSTATUS BBCopyMemory( IN PCOPY_MEMORY pCopy ) +{ + NTSTATUS status = STATUS_SUCCESS; + PEPROCESS pProcess = NULL, pSourceProc = NULL, pTargetProc = NULL; + PVOID pSource = NULL, pTarget = NULL; + + status = PsLookupProcessByProcessId( (HANDLE)pCopy->pid, &pProcess ); + + if (NT_SUCCESS( status )) + { + SIZE_T bytes = 0; + + // Write + if (pCopy->write != FALSE) + { + pSourceProc = PsGetCurrentProcess(); + pTargetProc = pProcess; + pSource = (PVOID)pCopy->localbuf; + pTarget = (PVOID)pCopy->targetPtr; + } + // Read + else + { + pSourceProc = pProcess; + pTargetProc = PsGetCurrentProcess(); + pSource = (PVOID)pCopy->targetPtr; + pTarget = (PVOID)pCopy->localbuf; + } + + status = MmCopyVirtualMemory( pSourceProc, pSource, pTargetProc, pTarget, pCopy->size, KernelMode, &bytes ); + } + else + DPRINT( "BlackBone: %s: PsLookupProcessByProcessId failed with status 0x%X\n", __FUNCTION__, status ); + + if (pProcess) + ObDereferenceObject( pProcess ); + + return status; +} + +/// +/// Allocate/Free process memory +/// +/// Request params. +/// Allocated region info. +/// Status code +NTSTATUS BBAllocateFreeMemory( IN PALLOCATE_FREE_MEMORY pAllocFree, OUT PALLOCATE_FREE_MEMORY_RESULT pResult ) +{ + NTSTATUS status = STATUS_SUCCESS; + PEPROCESS pProcess = NULL; + + ASSERT( pResult != NULL ); + if (pResult == NULL) + return STATUS_INVALID_PARAMETER; + + status = PsLookupProcessByProcessId( (HANDLE)pAllocFree->pid, &pProcess ); + if (NT_SUCCESS( status )) + { + KAPC_STATE apc; + PVOID base = (PVOID)pAllocFree->base; + ULONG_PTR size = pAllocFree->size; + + KeStackAttachProcess( pProcess, &apc ); + + if (pAllocFree->allocate) + { + if (pAllocFree->physical != FALSE) + { + status = BBAllocateFreePhysical( pProcess, pAllocFree, pResult ); + } + else + { + status = ZwAllocateVirtualMemory( ZwCurrentProcess(), &base, 0, &size, pAllocFree->type, pAllocFree->protection ); + pResult->address = (ULONGLONG)base; + pResult->size = size; + } + } + else + { + MI_VAD_TYPE vadType = VadNone; + BBGetVadType( pProcess, pAllocFree->base, &vadType ); + + if (vadType == VadDevicePhysicalMemory) + status = BBAllocateFreePhysical( pProcess, pAllocFree, pResult ); + else + status = ZwFreeVirtualMemory( ZwCurrentProcess(), &base, &size, pAllocFree->type ); + } + + KeUnstackDetachProcess( &apc ); + } + else + DPRINT( "BlackBone: %s: PsLookupProcessByProcessId failed with status 0x%X\n", __FUNCTION__, status ); + + if (pProcess) + ObDereferenceObject( pProcess ); + + return status; +} + +/// +/// Allocate kernel memory and map into User space. Or free previously allocated memory +/// +/// Target process object +/// Request params. +/// Allocated region info. +/// Status code +NTSTATUS BBAllocateFreePhysical( IN PEPROCESS pProcess, IN PALLOCATE_FREE_MEMORY pAllocFree, OUT PALLOCATE_FREE_MEMORY_RESULT pResult ) +{ + NTSTATUS status = STATUS_SUCCESS; + PVOID pRegionBase = NULL; + PMDL pMDL = NULL; + + ASSERT( pProcess != NULL && pResult != NULL ); + if (pProcess == NULL || pResult == NULL) + return STATUS_INVALID_PARAMETER; + + // MDL doesn't support regions this large + if (pAllocFree->size > 0xFFFFFFFF) + { + DPRINT( "BlackBone: %s: Region size if too big: 0x%p\n", __FUNCTION__, pAllocFree->size ); + return STATUS_INVALID_PARAMETER; + } + + // Align on page boundaries + pAllocFree->base = (ULONGLONG)PAGE_ALIGN( pAllocFree->base ); + pAllocFree->size = ADDRESS_AND_SIZE_TO_SPAN_PAGES( pAllocFree->base, pAllocFree->size ) << PAGE_SHIFT; + + // Allocate + if (pAllocFree->allocate != FALSE) + { + PMMVAD_SHORT pVad = NULL; + if (pAllocFree->base != 0 && BBFindVAD( pProcess, pAllocFree->base, &pVad ) != STATUS_NOT_FOUND) + return STATUS_ALREADY_COMMITTED; + + pRegionBase = ExAllocatePoolWithTag( NonPagedPool, pAllocFree->size, BB_POOL_TAG ); + if (!pRegionBase) + return STATUS_NO_MEMORY; + + // Cleanup buffer before mapping it into UserMode to prevent exposure of kernel data + RtlZeroMemory( pRegionBase, pAllocFree->size ); + + pMDL = IoAllocateMdl( pRegionBase, (ULONG)pAllocFree->size, FALSE, FALSE, NULL ); + if (pMDL == NULL) + { + ExFreePoolWithTag( pRegionBase, BB_POOL_TAG ); + return STATUS_NO_MEMORY; + } + + MmBuildMdlForNonPagedPool( pMDL ); + + // Map at original base + __try { + pResult->address = (ULONGLONG)MmMapLockedPagesSpecifyCache( + pMDL, UserMode, MmCached, (PVOID)pAllocFree->base, FALSE, NormalPagePriority + ); + } + __except (EXCEPTION_EXECUTE_HANDLER) { } + + // Map at any suitable + if (pResult->address == 0 && pAllocFree->base != 0) + { + __try { + pResult->address = (ULONGLONG)MmMapLockedPagesSpecifyCache( + pMDL, UserMode, MmCached, NULL, FALSE, NormalPagePriority + ); + } + __except (EXCEPTION_EXECUTE_HANDLER) { } + } + + if (pResult->address) + { + PMEM_PHYS_PROCESS_ENTRY pEntry = NULL; + PMEM_PHYS_ENTRY pMemEntry = NULL; + + pResult->size = pAllocFree->size; + + // Set initial protection + BBProtectVAD( pProcess, pResult->address, BBConvertProtection( pAllocFree->protection, FALSE ) ); + + // Make pages executable + if (pAllocFree->protection & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE)) + { + for (ULONG_PTR pAdress = pResult->address; pAdress < pResult->address + pResult->size; pAdress += PAGE_SIZE) + GetPTEForVA( (PVOID)pAdress )->u.Hard.NoExecute = 0; + } + + // Add to list + pEntry = BBLookupPhysProcessEntry( (HANDLE)pAllocFree->pid ); + if (pEntry == NULL) + { + pEntry = ExAllocatePoolWithTag( PagedPool, sizeof( MEM_PHYS_PROCESS_ENTRY ), BB_POOL_TAG ); + pEntry->pid = (HANDLE)pAllocFree->pid; + + InitializeListHead( &pEntry->pVadList ); + InsertTailList( &g_PhysProcesses, &pEntry->link ); + } + + pMemEntry = ExAllocatePoolWithTag( PagedPool, sizeof( MEM_PHYS_ENTRY ), BB_POOL_TAG ); + + pMemEntry->pMapped = (PVOID)pResult->address; + pMemEntry->pMDL = pMDL; + pMemEntry->ptr = pRegionBase; + pMemEntry->size = pAllocFree->size; + + InsertTailList( &pEntry->pVadList, &pMemEntry->link ); + } + else + { + // Failed, cleanup + IoFreeMdl( pMDL ); + ExFreePoolWithTag( pRegionBase, BB_POOL_TAG ); + + status = STATUS_NONE_MAPPED; + } + } + // Free + else + { + PMEM_PHYS_PROCESS_ENTRY pEntry = BBLookupPhysProcessEntry( (HANDLE)pAllocFree->pid ); + + if (pEntry != NULL) + { + PMEM_PHYS_ENTRY pMemEntry = BBLookupPhysMemEntry( &pEntry->pVadList, (PVOID)pAllocFree->base ); + + if (pMemEntry != NULL) + BBCleanupPhysMemEntry( pMemEntry, TRUE ); + else + status = STATUS_NOT_FOUND; + } + else + status = STATUS_NOT_FOUND; + } + + return status; +} + +/// +/// Change process memory protection +/// +/// Request params +/// Status code +NTSTATUS BBProtectMemory( IN PPROTECT_MEMORY pProtect ) +{ + NTSTATUS status = STATUS_SUCCESS; + PEPROCESS pProcess = NULL; + + status = PsLookupProcessByProcessId( (HANDLE)pProtect->pid, &pProcess ); + if (NT_SUCCESS( status )) + { + KAPC_STATE apc; + MI_VAD_TYPE vadType = VadNone; + PVOID base = (PVOID)pProtect->base; + SIZE_T size = (SIZE_T)pProtect->size; + ULONG oldProt = 0; + + KeStackAttachProcess( pProcess, &apc ); + + // Handle physical allocations + status = BBGetVadType( pProcess, pProtect->base, &vadType ); + if (NT_SUCCESS( status )) + { + if (vadType == VadDevicePhysicalMemory) + { + // Align on page boundaries + pProtect->base = (ULONGLONG)PAGE_ALIGN( pProtect->base ); + pProtect->size = ADDRESS_AND_SIZE_TO_SPAN_PAGES( pProtect->base, pProtect->size ) << PAGE_SHIFT; + + status = BBProtectVAD( pProcess, pProtect->base, BBConvertProtection( pProtect->newProtection, FALSE ) ); + + // Update PTE + for (ULONG_PTR pAdress = pProtect->base; pAdress < pProtect->base + pProtect->size; pAdress += PAGE_SIZE) + { + PMMPTE pPTE = GetPTEForVA( (PVOID)pAdress ); + + // Executable + if (pProtect->newProtection & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) + pPTE->u.Hard.NoExecute = 0; + + // Read-only + if (pProtect->newProtection & (PAGE_READONLY | PAGE_EXECUTE | PAGE_EXECUTE_READ)) + pPTE->u.Hard.Dirty1 = pPTE->u.Hard.Write = 0; + } + } + else + status = ZwProtectVirtualMemory( ZwCurrentProcess(), &base, &size, pProtect->newProtection, &oldProt ); + } + + KeUnstackDetachProcess( &apc ); + } + else + DPRINT( "BlackBone: %s: PsLookupProcessByProcessId failed with status 0x%X\n", __FUNCTION__, status ); + + if (pProcess) + ObDereferenceObject( pProcess ); + + return status; +} + +/// +/// Hide VAD containing target address +/// +/// Address info +/// Status code +NTSTATUS BBHideVAD( IN PHIDE_VAD pData ) +{ + NTSTATUS status = STATUS_SUCCESS; + PEPROCESS pProcess = NULL; + + status = PsLookupProcessByProcessId( (HANDLE)pData->pid, &pProcess ); + if (NT_SUCCESS( status )) + status = BBUnlinkVAD( pProcess, pData->base ); + else + DPRINT( "BlackBone: %s: PsLookupProcessByProcessId failed with status 0x%X\n", __FUNCTION__, status ); + + if (pProcess) + ObDereferenceObject( pProcess ); + + return status; +} + +/// +/// Enumerate committed, accessible, non-guarded memory regions +/// +/// Target process ID +/// Result +/// Status code +NTSTATUS BBEnumMemRegions( IN PENUM_REGIONS pData, OUT PENUM_REGIONS_RESULT pResult ) +{ + NTSTATUS status = STATUS_SUCCESS; + PEPROCESS pProcess = NULL; + LIST_ENTRY memList; + ULONG totalCount = 0; + + ASSERT( pResult != NULL && pData != NULL && pData->pid != 0 ); + if (pResult == NULL || pData == NULL || pData->pid == 0) + return STATUS_INVALID_PARAMETER; + + InitializeListHead( &memList ); + + status = PsLookupProcessByProcessId( (HANDLE)pData->pid, &pProcess ); + if (NT_SUCCESS( status )) + { + KAPC_STATE apc; + KeStackAttachProcess( pProcess, &apc ); + status = BBBuildProcessRegionListForRange( &memList, (ULONG_PTR)MM_LOWEST_USER_ADDRESS, (ULONG_PTR)MM_HIGHEST_USER_ADDRESS, TRUE ); + KeUnstackDetachProcess( &apc ); + } + + if (NT_SUCCESS( status )) + { + for (PLIST_ENTRY pListEntry = memList.Flink; pListEntry != &memList; pListEntry = pListEntry->Flink, totalCount++); + + // Not enough memory + if (pResult->count < totalCount) + { + pResult->count = totalCount; + status = STATUS_BUFFER_TOO_SMALL; + } + // Copy from list to array + else + { + ULONG i = 0; + pResult->count = totalCount; + for (PLIST_ENTRY pListEntry = memList.Flink; pListEntry != &memList; pListEntry = pListEntry->Flink, i++) + { + PMEMORY_BASIC_INFORMATION pMem = &CONTAINING_RECORD( pListEntry, MAP_ENTRY, link )->mem; + pResult->regions[i].AllocationBase = (ULONGLONG)pMem->AllocationBase; + pResult->regions[i].AllocationProtect = pMem->AllocationProtect; + pResult->regions[i].BaseAddress = (ULONGLONG)pMem->BaseAddress; + pResult->regions[i].Protect = pMem->Protect; + pResult->regions[i].RegionSize = pMem->RegionSize; + pResult->regions[i].State = pMem->State; + pResult->regions[i].Type = pMem->Type; + } + } + } + + // Cleanup list + while (!IsListEmpty( &memList )) + { + PMAP_ENTRY ptr = CONTAINING_RECORD( memList.Flink, MAP_ENTRY, link ); + RemoveEntryList( &ptr->link ); + ExFreePoolWithTag( ptr, BB_POOL_TAG ); + } + + if (pProcess) + ObDereferenceObject( pProcess ); + + return status; +} + +/// +/// Create hook trampoline +/// +/// Trampoline address +/// Function pointer +VOID BBWriteTrampoline( IN PUCHAR place, IN PVOID pfn ) +{ + if (!place || !pfn) + return; + + // jmp [rip + 0] + ULONGLONG cr0 = __readcr0(); + __writecr0( cr0 & 0xFFFEFFFF ); + *(PUSHORT)place = 0x25FF; + *(PULONG)(place + 2) = 0; + *(PVOID**)(place + 6) = pfn; + __writecr0( cr0 ); +} + +PVOID BBFindTrampolineSpace( IN PVOID lowest ) +{ + ASSERT( lowest != NULL ); + if (lowest == NULL) + return NULL; + + const ULONG size = sizeof( USHORT ) + sizeof( ULONG ) + sizeof( PVOID ); + PUCHAR ntosBase = GetKernelBase( NULL ); + if (!ntosBase) + return NULL; + + PIMAGE_NT_HEADERS pHdr = RtlImageNtHeader( ntosBase ); + PIMAGE_SECTION_HEADER pFirstSec = (PIMAGE_SECTION_HEADER)(pHdr + 1); + for (PIMAGE_SECTION_HEADER pSec = pFirstSec; pSec < pFirstSec + pHdr->FileHeader.NumberOfSections; pSec++) + { + // First appropriate section + if ((PUCHAR)lowest < ntosBase + pSec->VirtualAddress || (PUCHAR)lowest < ntosBase + pSec->VirtualAddress + (ULONG_PTR)PAGE_ALIGN( pSec->Misc.VirtualSize )) + { + if (pSec->Characteristics & IMAGE_SCN_MEM_EXECUTE && + !(pSec->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) && + (*(PULONG)pSec->Name != 'TINI')) + { + ULONG_PTR offset = 0; + if((PUCHAR)lowest >= ntosBase + pSec->VirtualAddress) + offset = (PUCHAR)lowest - ntosBase - pSec->VirtualAddress; + + for (ULONG_PTR i = offset, bytes = 0; i < (ULONG_PTR)PAGE_ALIGN( pSec->Misc.VirtualSize - size ); i++) + { + // int3, nop, or inside unused section space + if (ntosBase[pSec->VirtualAddress + i] == 0xCC || ntosBase[pSec->VirtualAddress + i] == 0x90 || i > pSec->Misc.VirtualSize - size) + bytes++; + else + bytes = 0; + + if (bytes >= size) + return &ntosBase[pSec->VirtualAddress + i - bytes + 1]; + } + } + } + } + + return NULL; +} + +/// +/// Hook SSDT entry +/// +/// SSDT index to hook +/// Hook function +/// Original function pointer +/// Status code +NTSTATUS BBHookSSDT( IN ULONG index, IN PVOID newAddr, OUT PVOID *ppOldAddr ) +{ + ASSERT( newAddr != NULL ); + if (newAddr == NULL) + return STATUS_INVALID_PARAMETER; + + NTSTATUS status = STATUS_SUCCESS; + PSYSTEM_SERVICE_DESCRIPTOR_TABLE pSSDT = GetSSDTBase(); + if (!pSSDT) + return STATUS_NOT_FOUND; + + if (ppOldAddr) + *ppOldAddr = (PUCHAR)pSSDT->ServiceTableBase + (((PLONG)pSSDT->ServiceTableBase)[index] >> 4); + + ULONG_PTR offset = (ULONG_PTR)newAddr - (ULONG_PTR)pSSDT->ServiceTableBase; + + // Intermediate jump is required + if (offset > 0x07FFFFFF) + { + // Allocate trampoline, if required + PVOID pTrampoline = BBFindTrampolineSpace( pSSDT->ServiceTableBase ); + if (!pTrampoline) + return STATUS_NOT_FOUND; + + // Write jmp + BBWriteTrampoline( pTrampoline, newAddr ); + offset = ((((ULONG_PTR)pTrampoline - (ULONG_PTR)pSSDT->ServiceTableBase) << 4) & 0xFFFFFFF0) | (pSSDT->ParamTableBase[index] >> 2); + } + // Direct jump + else + offset = ((offset << 4) & 0xFFFFFFF0) | (pSSDT->ParamTableBase[index] >> 2); + + // Update pointer + ULONGLONG cr0 = __readcr0(); + __writecr0( cr0 & 0xFFFEFFFF ); + InterlockedExchange( (PLONG)pSSDT->ServiceTableBase + index, (LONG)offset ); + __writecr0( cr0 ); + + return status; +} + +/// +/// Restore SSDT hook +/// +/// SSDT index to restore +/// Original function address +/// Status code +NTSTATUS BBRestoreSSDT( IN ULONG index, IN PVOID origAddr ) +{ + ASSERT( origAddr != NULL ); + if (origAddr == NULL) + return STATUS_INVALID_PARAMETER; + + PSYSTEM_SERVICE_DESCRIPTOR_TABLE pSSDT = GetSSDTBase(); + if (!pSSDT) + return STATUS_NOT_FOUND; + + ULONG_PTR offset = (((ULONG_PTR)origAddr - (ULONG_PTR)pSSDT->ServiceTableBase) << 4) | (pSSDT->ParamTableBase[index] >> 2); + ULONGLONG cr0 = __readcr0(); + __writecr0( cr0 & 0xFFFEFFFF ); + InterlockedExchange( (PLONG)pSSDT->ServiceTableBase + index, (LONG)offset ); + __writecr0( cr0 ); + + return STATUS_SUCCESS; +} + + +NTSTATUS BBHookInline( IN PVOID origAddr, IN PVOID newAddr ) +{ + UNREFERENCED_PARAMETER( origAddr ); + UNREFERENCED_PARAMETER( newAddr ); + + NOPPROCINFO info; + InitializeStopProcessors( &info ); + StopProcessors( &info ); + ULONGLONG cr0 = __readcr0(); + __writecr0( cr0 & 0xFFFEFFFF ); + + __writecr0( cr0 ); + StartProcessors( &info ); + return STATUS_SUCCESS; +} + +/// +/// Find memory allocation process entry +/// +/// Target PID +/// Found entry, NULL if not found +PMEM_PHYS_PROCESS_ENTRY BBLookupPhysProcessEntry( IN HANDLE pid ) +{ + for (PLIST_ENTRY pListEntry = g_PhysProcesses.Flink; pListEntry != &g_PhysProcesses; pListEntry = pListEntry->Flink) + { + PMEM_PHYS_PROCESS_ENTRY pEntry = CONTAINING_RECORD( pListEntry, MEM_PHYS_PROCESS_ENTRY, link ); + if (pEntry->pid == pid) + return pEntry; + } + + return NULL; +} + + +/// +/// Find allocated memory region entry +/// +/// Region list +/// Region base +/// Found entry, NULL if not found +PMEM_PHYS_ENTRY BBLookupPhysMemEntry( IN PLIST_ENTRY pList, IN PVOID pBase ) +{ + ASSERT( pList != NULL ); + if (pList == NULL) + return NULL; + + for (PLIST_ENTRY pListEntry = pList->Flink; pListEntry != pList; pListEntry = pListEntry->Flink) + { + PMEM_PHYS_ENTRY pEntry = CONTAINING_RECORD( pListEntry, MEM_PHYS_ENTRY, link ); + if (pBase >= pEntry->pMapped && pBase < (PVOID)((ULONG_PTR)pEntry->pMapped + pEntry->size)) + return pEntry; + } + + return NULL; +} + +// +// Cleanup routines +// + +void BBCleanupPhysMemEntry( IN PMEM_PHYS_ENTRY pEntry, BOOLEAN attached ) +{ + ASSERT( pEntry != NULL ); + if (pEntry == NULL) + return; + + if (attached) + MmUnmapLockedPages( pEntry->pMapped, pEntry->pMDL ); + + IoFreeMdl( pEntry->pMDL ); + ExFreePoolWithTag( pEntry->ptr, BB_POOL_TAG ); + + RemoveEntryList( &pEntry->link ); + ExFreePoolWithTag( pEntry, BB_POOL_TAG ); +} + +void BBCleanupProcessPhysEntry( IN PMEM_PHYS_PROCESS_ENTRY pEntry, BOOLEAN attached ) +{ + ASSERT( pEntry != NULL ); + if (pEntry == NULL) + return; + + while (!IsListEmpty( &pEntry->pVadList )) + BBCleanupPhysMemEntry( (PMEM_PHYS_ENTRY)pEntry->pVadList.Flink, attached ); + + RemoveEntryList( &pEntry->link ); + ExFreePoolWithTag( pEntry, BB_POOL_TAG ); +} + +void BBCleanupProcessPhysList() +{ + while (!IsListEmpty( &g_PhysProcesses )) + BBCleanupProcessPhysEntry( (PMEM_PHYS_PROCESS_ENTRY)g_PhysProcesses.Flink, FALSE ); +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/Routines.h b/third/Blackbone/src/BlackBoneDrv/Routines.h new file mode 100644 index 0000000000000000000000000000000000000000..fb85aa9b446d8554510f2205df29de7037a211f0 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/Routines.h @@ -0,0 +1,155 @@ +#pragma once + +#include "BlackBoneDef.h" +#include "Private.h" +#include "VadRoutines.h" + +/// +/// Allocated physical region entry +/// +typedef struct _MEM_PHYS_ENTRY +{ + LIST_ENTRY link; + ULONG_PTR size; // Region size + PVOID pMapped; // Mapped address + PMDL pMDL; // Related MDL + PVOID ptr; // Actual ptr in NonPagedPool +} MEM_PHYS_ENTRY, *PMEM_PHYS_ENTRY; + +/// +/// Per-process list of physical regions +/// +typedef struct _MEM_PHYS_PROCESS_ENTRY +{ + LIST_ENTRY link; + HANDLE pid; // Process ID + LIST_ENTRY pVadList; // List of mapped regions +} MEM_PHYS_PROCESS_ENTRY, *PMEM_PHYS_PROCESS_ENTRY; + +extern LIST_ENTRY g_PhysProcesses; + + +/// +/// Disable process DEP +/// Has no effect on native x64 process +/// +/// Request params +/// Status code +NTSTATUS BBDisableDEP( IN PDISABLE_DEP pData ); + +/// +/// Enable/disable process protection flag +/// +/// Request params +/// Status code +NTSTATUS BBSetProtection( IN PSET_PROC_PROTECTION pProtection ); + +/// +/// Change handle granted access +/// +/// Request params +/// Status code +NTSTATUS BBGrantAccess( IN PHANDLE_GRANT_ACCESS pAccess ); + +/// +/// Allocate/Free process memory +/// +/// Request params. +/// Allocated region info. +/// Status code +NTSTATUS BBAllocateFreeMemory( IN PALLOCATE_FREE_MEMORY pAllocFree, OUT PALLOCATE_FREE_MEMORY_RESULT pResult ); + +/// +/// Read/write process memory +/// +/// Request params +/// Status code +NTSTATUS BBCopyMemory( IN PCOPY_MEMORY pCopy ); + +/// +/// Change process memory protection +/// +/// Request params +/// Status code +NTSTATUS BBProtectMemory( IN PPROTECT_MEMORY pProtect ); + +/// +/// Hide VAD containing target address +/// +/// Address info +/// Status code +NTSTATUS BBHideVAD( IN PHIDE_VAD pData ); + +/// +/// Enumerate committed, accessible, non-guarded memory regions +/// +/// Target process ID +/// Result +/// Status code +NTSTATUS BBEnumMemRegions( IN PENUM_REGIONS pData, OUT PENUM_REGIONS_RESULT pResult ); + +/// +/// Inject dll into process +/// +/// Target PID +/// TFull-qualified dll path +/// Status code +NTSTATUS BBInjectDll( IN PINJECT_DLL pData ); + +/// +/// Change handle granted access +/// +/// Request params +/// Status code +NTSTATUS BBUnlinkHandleTable( IN PUNLINK_HTABLE pUnlink ); + +/// +/// Hook SSDT entry +/// +/// SSDT index to hook +/// Hook function +/// Original function pointer +/// Status code +NTSTATUS BBHookSSDT( IN ULONG index, IN PVOID newAddr, OUT PVOID *ppOldAddr ); + +/// +/// Restore SSDT hook +/// +/// SSDT index to restore +/// Original function address +/// Status code +NTSTATUS BBRestoreSSDT( IN ULONG index, IN PVOID origAddr ); + +NTSTATUS BBHookInline( IN PVOID origAddr, IN PVOID newAddr ); + +/// +/// Process termination handler +/// +/// Parent PID +/// PID +/// TRUE if process was created +VOID BBProcessNotify( IN HANDLE ParentId, IN HANDLE ProcessId, IN BOOLEAN Create ); + +/// +/// Find memory allocation process entry +/// +/// Target PID +/// Found entry, NULL if not found +PMEM_PHYS_PROCESS_ENTRY BBLookupPhysProcessEntry( IN HANDLE pid ); + +/// +/// Allocate kernel memory and map into User space. Or free previously allocated memory +/// +/// Target process object +/// Request params. +/// Allocated region info. +/// Status code +NTSTATUS BBAllocateFreePhysical( IN PEPROCESS pProcess, IN PALLOCATE_FREE_MEMORY pAllocFree, OUT PALLOCATE_FREE_MEMORY_RESULT pResult ); + + +// +// Memory allocation cleanup routines +// +void BBCleanupPhysMemEntry( IN PMEM_PHYS_ENTRY pEntry, BOOLEAN attached ); +void BBCleanupProcessPhysEntry( IN PMEM_PHYS_PROCESS_ENTRY pEntry, BOOLEAN attached ); +void BBCleanupProcessPhysList(); diff --git a/third/Blackbone/src/BlackBoneDrv/Utils.c b/third/Blackbone/src/BlackBoneDrv/Utils.c new file mode 100644 index 0000000000000000000000000000000000000000..750f37bb718002b1a5abfcd2945cd0b0c2b57dcc --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/Utils.c @@ -0,0 +1,495 @@ +#include "Utils.h" +#include "Private.h" +#include + +#pragma alloc_text(PAGE, BBSafeAllocateString) +#pragma alloc_text(PAGE, BBSafeInitString) +#pragma alloc_text(PAGE, BBStripPath) +#pragma alloc_text(PAGE, BBStripFilename) +#pragma alloc_text(PAGE, BBFileExists) + +/// +/// Allocate new Unicode string from Paged pool +/// +/// Resulting string +/// Buffer size in bytes to alloacate +/// Status code +NTSTATUS BBSafeAllocateString( OUT PUNICODE_STRING result, IN USHORT size ) +{ + ASSERT( result != NULL ); + if (result == NULL || size == 0) + return STATUS_INVALID_PARAMETER; + + result->Buffer = ExAllocatePoolWithTag( PagedPool, size, BB_POOL_TAG ); + result->Length = 0; + result->MaximumLength = size; + + if (result->Buffer) + RtlZeroMemory( result->Buffer, size ); + else + return STATUS_NO_MEMORY; + + return STATUS_SUCCESS; +} + +/// +/// Allocate and copy string +/// +/// Resulting string +/// Source string +/// Status code +NTSTATUS BBSafeInitString( OUT PUNICODE_STRING result, IN PUNICODE_STRING source ) +{ + ASSERT( result != NULL && source != NULL ); + if (result == NULL || source == NULL || source->Buffer == NULL) + return STATUS_INVALID_PARAMETER; + + // No data to copy + if (source->Length == 0) + { + result->Length = result->MaximumLength = 0; + result->Buffer = NULL; + return STATUS_SUCCESS; + } + + result->Buffer = ExAllocatePoolWithTag( PagedPool, source->MaximumLength, BB_POOL_TAG ); + result->Length = source->Length; + result->MaximumLength = source->MaximumLength; + + memcpy( result->Buffer, source->Buffer, source->Length ); + + return STATUS_SUCCESS; +} + +/// +/// Search for substring +/// +/// Source string +/// Target string +/// Case insensitive search +/// Found position or -1 if not found +LONG BBSafeSearchString( IN PUNICODE_STRING source, IN PUNICODE_STRING target, IN BOOLEAN CaseInSensitive ) +{ + ASSERT( source != NULL && target != NULL ); + if (source == NULL || target == NULL || source->Buffer == NULL || target->Buffer == NULL) + return STATUS_INVALID_PARAMETER; + + // Size mismatch + if (source->Length < target->Length) + return -1; + + USHORT diff = source->Length - target->Length; + for (USHORT i = 0; i <= (diff / sizeof( WCHAR )); i++) + { + if (RtlCompareUnicodeStrings( + source->Buffer + i, + target->Length / sizeof( WCHAR ), + target->Buffer, + target->Length / sizeof( WCHAR ), + CaseInSensitive + ) == 0) + { + return i; + } + } + + return -1; +} + +/// +/// Get file name from full path +/// +/// Path. +/// Resulting name +/// Status code +NTSTATUS BBStripPath( IN PUNICODE_STRING path, OUT PUNICODE_STRING name ) +{ + ASSERT( path != NULL && name ); + if (path == NULL || name == NULL) + return STATUS_INVALID_PARAMETER; + + // Empty string + if (path->Length < 2) + { + *name = *path; + return STATUS_NOT_FOUND; + } + + for (USHORT i = (path->Length / sizeof( WCHAR )) - 1; i != 0; i--) + { + if (path->Buffer[i] == L'\\' || path->Buffer[i] == L'/') + { + name->Buffer = &path->Buffer[i + 1]; + name->Length = name->MaximumLength = path->Length - (i + 1)*sizeof( WCHAR ); + return STATUS_SUCCESS; + } + } + + *name = *path; + return STATUS_NOT_FOUND; +} + +/// +/// Get directory path name from full path +/// +/// Path +/// Resulting directory path +/// Status code +NTSTATUS BBStripFilename( IN PUNICODE_STRING path, OUT PUNICODE_STRING dir ) +{ + ASSERT( path != NULL && dir ); + if (path == NULL || dir == NULL) + return STATUS_INVALID_PARAMETER; + + // Empty string + if (path->Length < 2) + { + *dir = *path; + return STATUS_NOT_FOUND; + } + + for (USHORT i = (path->Length / sizeof( WCHAR )) - 1; i != 0; i--) + { + if (path->Buffer[i] == L'\\' || path->Buffer[i] == L'/') + { + dir->Buffer = path->Buffer; + dir->Length = dir->MaximumLength = i*sizeof( WCHAR ); + return STATUS_SUCCESS; + } + } + + *dir = *path; + return STATUS_NOT_FOUND; +} + +/// +/// Check if file exists +/// +/// Fully qualifid path to a file +/// Status code +NTSTATUS BBFileExists( IN PUNICODE_STRING path ) +{ + HANDLE hFile = NULL; + IO_STATUS_BLOCK statusBlock = { 0 }; + OBJECT_ATTRIBUTES obAttr = { 0 }; + InitializeObjectAttributes( &obAttr, path, OBJ_KERNEL_HANDLE, NULL, NULL ); + + NTSTATUS status = ZwCreateFile( + &hFile, FILE_READ_DATA | SYNCHRONIZE, &obAttr, + &statusBlock, NULL, FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 + ); + + if (NT_SUCCESS( status )) + ZwClose( hFile ); + + return status; +} + +/// +/// Search for pattern +/// +/// Pattern to search for +/// Used wildcard +/// Pattern length +/// Base address for searching +/// Address range to search in +/// Found location +/// Status code +NTSTATUS BBSearchPattern( IN PCUCHAR pattern, IN UCHAR wildcard, IN ULONG_PTR len, IN const VOID* base, IN ULONG_PTR size, OUT PVOID* ppFound ) +{ + ASSERT( ppFound != NULL && pattern != NULL && base != NULL ); + if (ppFound == NULL || pattern == NULL || base == NULL) + return STATUS_INVALID_PARAMETER; + + for (ULONG_PTR i = 0; i < size - len; i++) + { + BOOLEAN found = TRUE; + for (ULONG_PTR j = 0; j < len; j++) + { + if (pattern[j] != wildcard && pattern[j] != ((PCUCHAR)base)[i + j]) + { + found = FALSE; + break; + } + } + + if (found != FALSE) + { + *ppFound = (PUCHAR)base + i; + return STATUS_SUCCESS; + } + } + + return STATUS_NOT_FOUND; +} + +/// +/// Check if process is terminating +/// +/// Process +/// If TRUE - terminating +BOOLEAN BBCheckProcessTermination( PEPROCESS pProcess ) +{ + LARGE_INTEGER zeroTime = { 0 }; + return KeWaitForSingleObject( pProcess, Executive, KernelMode, FALSE, &zeroTime ) == STATUS_WAIT_0; +} + +ULONG GenPrologue32( IN PUCHAR pBuf ) +{ + *pBuf = 0x55; + *(PUSHORT)(pBuf + 1) = 0xE589; + + return 3; +} + +ULONG GenEpilogue32( IN PUCHAR pBuf, IN INT retSize ) +{ + *(PUSHORT)pBuf = 0xEC89; + *(pBuf + 2) = 0x5D; + *(pBuf + 3) = 0xC2; + *(PUSHORT)(pBuf + 4) = (USHORT)retSize; + + return 6; +} + +ULONG GenCall32( IN PUCHAR pBuf, IN PVOID pFn, IN INT argc, ... ) +{ + va_list vl; + va_start( vl, argc ); + ULONG res = GenCall32V( pBuf, pFn, argc, vl ); + va_end( vl ); + + return res; +} + +ULONG GenCall32V( IN PUCHAR pBuf, IN PVOID pFn, IN INT argc, IN va_list vl ) +{ + ULONG ofst = 0; + + PULONG pArgBuf = ExAllocatePoolWithTag( PagedPool, argc * sizeof( ULONG ), BB_POOL_TAG ); + + // cast args + for (INT i = 0; i < argc; i++) + { + PVOID arg = va_arg( vl, PVOID ); + pArgBuf[i] = (ULONG)(ULONG_PTR)arg; + } + + // push args + for (INT i = argc - 1; i >= 0; i--) + { + *(PUSHORT)(pBuf + ofst) = 0x68; // push arg + *(PULONG)(pBuf + ofst + 1) = pArgBuf[i]; // + ofst += 5; + } + + *(PUCHAR)(pBuf + ofst) = 0xB8; // mov eax, pFn + *(PULONG)(pBuf + ofst + 1) = (ULONG)(ULONG_PTR)pFn; // + ofst += 5; + + *(PUSHORT)(pBuf + ofst) = 0xD0FF; // call eax + ofst += 2; + + ExFreePoolWithTag( pArgBuf, BB_POOL_TAG ); + + return ofst; +} + +ULONG GenSync32( IN PUCHAR pBuf, IN PNTSTATUS pStatus, IN PVOID pSetEvent, IN HANDLE hEvent ) +{ + ULONG ofst = 0; + + *(PUCHAR)(pBuf + ofst) = 0xA3; // mov [pStatus], eax + *(PVOID*)(pBuf + ofst + 1) = pStatus; // + ofst += 5; + + *(PUSHORT)(pBuf + ofst) = 0x006A; // push FALSE + ofst += 2; + + *(PUCHAR)(pBuf + ofst) = 0x68; // push hEvent + *(PULONG)(pBuf + ofst + 1) = (ULONG)(ULONG_PTR)hEvent; // + ofst += 5; + + *(PUCHAR)(pBuf + ofst) = 0xB8; // mov eax, pSetEvent + *(PULONG)(pBuf + ofst + 1) = (ULONG)(ULONG_PTR)pSetEvent;// + ofst += 5; + + *(PUSHORT)(pBuf + ofst) = 0xD0FF; // call eax + ofst += 2; + + return ofst; +} + + + +ULONG GenPrologue64( IN PUCHAR pBuf ) +{ + *(PULONG)(pBuf + 0) = 0x244C8948; // mov [rsp + 0x08], rcx + *(PUCHAR)(pBuf + 4) = 0x8; // + *(PULONG)(pBuf + 5) = 0x24548948; // mov [rsp + 0x10], rdx + *(PUCHAR)(pBuf + 9) = 0x10; // + *(PULONG)(pBuf + 10) = 0x2444894C; // mov [rsp + 0x18], r8 + *(PUCHAR)(pBuf + 14) = 0x18; // + *(PULONG)(pBuf + 15) = 0x244C894C; // mov [rsp + 0x20], r9 + *(PUCHAR)(pBuf + 19) = 0x20; // + return 20; +} + +ULONG GenEpilogue64( IN PUCHAR pBuf, IN INT retSize ) +{ + UNREFERENCED_PARAMETER( retSize ); + + *(PULONG)(pBuf + 0) = 0x244C8B48; // mov rcx, [rsp + 0x08] + *(PUCHAR)(pBuf + 4) = 0x8; // + *(PULONG)(pBuf + 5) = 0x24548B48; // mov rdx, [rsp + 0x10] + *(PUCHAR)(pBuf + 9) = 0x10; // + *(PULONG)(pBuf + 10) = 0x24448B4C; // mov r8, [rsp + 0x18] + *(PUCHAR)(pBuf + 14) = 0x18; // + *(PULONG)(pBuf + 15) = 0x244C8B4C; // mov r9, [rsp + 0x20] + *(PUCHAR)(pBuf + 19) = 0x20; // + *(PUCHAR)(pBuf + 20) = 0xC3; // ret + return 21; +} + +ULONG GenCall64( IN PUCHAR pBuf, IN PVOID pFn, INT argc, ... ) +{ + va_list vl; + va_start( vl, argc ); + ULONG res = GenCall64V( pBuf, pFn, argc, vl ); + va_end( vl ); + + return res; +} + +ULONG GenCall64V( IN PUCHAR pBuf, IN PVOID pFn, IN INT argc, IN va_list vl ) +{ + USHORT rsp_diff = 0x28; + ULONG ofst = 0; + if (argc > 4) + { + rsp_diff = (USHORT)(argc * sizeof( ULONG_PTR )); + if (rsp_diff % 0x10) + rsp_diff = ((rsp_diff / 0x10) + 1) * 0x10; + rsp_diff += 8; + } + + // sub rsp, rsp_diff + *(PULONG)(pBuf + ofst) = (0x00EC8348 | rsp_diff << 24); + ofst += 4; + + if (argc > 0) + { + PVOID arg = va_arg( vl, PVOID ); + *(PUSHORT)(pBuf + ofst) = 0xB948; // mov rcx, arg + *(PVOID*)(pBuf + ofst + 2) = arg; // + ofst += 10; + } + if (argc > 1) + { + PVOID arg = va_arg( vl, PVOID ); + *(PUSHORT)(pBuf + ofst) = 0xBA48; // mov rdx, arg + *(PVOID*)(pBuf + ofst + 2) = arg; // + ofst += 10; + } + if (argc > 2) + { + PVOID arg = va_arg( vl, PVOID ); + *(PUSHORT)(pBuf + ofst) = 0xB849; // mov r8, arg + *(PVOID*)(pBuf + ofst + 2) = arg; // + ofst += 10; + } + if (argc > 3) + { + PVOID arg = va_arg( vl, PVOID ); + *(PUSHORT)(pBuf + ofst) = 0xB949; // mov r9, arg + *(PVOID*)(pBuf + ofst + 2) = arg; // + ofst += 10; + } + + for (INT i = 4; i < argc; i++) + { + PVOID arg = va_arg( vl, PVOID ); + + *(PUSHORT)(pBuf + ofst) = 0xB848; // mov rcx, arg + *(PVOID*)(pBuf + ofst + 2) = arg; // + ofst += 10; + + // mov [rsp + i*8], rax + *(PULONG)(pBuf + ofst) = 0x24448948; + *(PUCHAR)(pBuf + ofst + 4) = (UCHAR)(0x20 + (i - 4)*sizeof( arg )); + ofst += 5; + } + + + *(PUSHORT)(pBuf + ofst) = 0xB848; // mov rax, pFn + *(PVOID*)(pBuf + ofst + 2) = pFn; // + ofst += 10; + + *(PUSHORT)(pBuf + ofst) = 0xD0FF; // call rax + ofst += 2; + + // add rsp, rsp_diff + *(PULONG)(pBuf + ofst) = (0x00C48348 | rsp_diff << 24); + ofst += 4; + + return ofst; +} + +ULONG GenSync64( IN PUCHAR pBuf, IN PNTSTATUS pStatus, IN PVOID pSetEvent, IN HANDLE hEvent ) +{ + ULONG ofst = 0; + + *(PUSHORT)(pBuf + ofst) = 0xA348; // mov [pStatus], rax + *(PVOID*)(pBuf + ofst + 2) = pStatus; // + ofst += 10; + + *(PUSHORT)(pBuf + ofst) = 0xB948; // mov rcx, hEvent + *(PHANDLE)(pBuf + ofst + 2) = hEvent; // + ofst += 10; + + *(pBuf + ofst) = 0x48; // xor rdx, rdx + *(PUSHORT)(pBuf + ofst + 1) = 0xD231; // + ofst += 3; + + *(PUSHORT)(pBuf + ofst) = 0xB848; // mov rax, pSetEvent + *(PVOID*)(pBuf + ofst + 2) = pSetEvent; // + ofst += 10; + + *(PUSHORT)(pBuf + ofst) = 0xD0FF; // call rax + ofst += 2; + + return ofst; +} + + + +ULONG GenPrologueT( IN BOOLEAN wow64, IN PUCHAR pBuf ) +{ + return wow64 ? GenPrologue32( pBuf ) : GenPrologue64( pBuf ); +} + +ULONG GenEpilogueT( IN BOOLEAN wow64, IN PUCHAR pBuf, IN INT retSize ) +{ + return wow64 ? GenEpilogue32( pBuf, retSize ) : GenEpilogue64( pBuf, retSize ); +} + +ULONG GenCallT( IN BOOLEAN wow64, IN PUCHAR pBuf, IN PVOID pFn, IN INT argc, ... ) +{ + va_list vl; + va_start( vl, argc ); + ULONG res = wow64 ? GenCall32V( pBuf, pFn, argc, vl ) : GenCall64V( pBuf, pFn, argc, vl ); + va_end( vl ); + + return res; +} + +ULONG GenCallTV( IN BOOLEAN wow64, IN PUCHAR pBuf, IN PVOID pFn, IN INT argc, IN va_list vl ) +{ + return wow64 ? GenCall32V( pBuf, pFn, argc, vl ) : GenCall64V( pBuf, pFn, argc, vl ); +} + +ULONG GenSyncT( IN BOOLEAN wow64, IN PUCHAR pBuf, IN PNTSTATUS pStatus, IN PVOID pSetEvent, IN HANDLE hEvent ) +{ + return wow64 ? GenSync32( pBuf, pStatus, pSetEvent, hEvent ) : GenSync64( pBuf, pStatus, pSetEvent, hEvent ); +} diff --git a/third/Blackbone/src/BlackBoneDrv/Utils.h b/third/Blackbone/src/BlackBoneDrv/Utils.h new file mode 100644 index 0000000000000000000000000000000000000000..cee25b3546c5012bd5fe20902d66ae44688b4d4e --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/Utils.h @@ -0,0 +1,99 @@ +#pragma once +#include + +/// +/// Allocate new Unicode string from Paged pool +/// +/// Resulting string +/// Buffer size in bytes to alloacate +/// Status code +NTSTATUS BBSafeAllocateString( OUT PUNICODE_STRING result, IN USHORT size ); + +/// +/// Allocate and copy string +/// +/// Resulting string +/// Source string +/// Status code +NTSTATUS BBSafeInitString( OUT PUNICODE_STRING result, IN PUNICODE_STRING source ); + +/// +/// Search for substring +/// +/// Source string +/// Target string +/// Case insensitive search +/// Found position or -1 if not found +LONG BBSafeSearchString( IN PUNICODE_STRING source, IN PUNICODE_STRING target, IN BOOLEAN CaseInSensitive ); + +/// +/// Get file name from full path +/// +/// Path. +/// Resulting name +/// Status code +NTSTATUS BBStripPath( IN PUNICODE_STRING path, OUT PUNICODE_STRING name ); + +/// +/// Get directory path name from full path +/// +/// Path +/// Resulting directory path +/// Status code +NTSTATUS BBStripFilename( IN PUNICODE_STRING path, OUT PUNICODE_STRING dir ); + +/// +/// Check if file exists +/// +/// Fully qualifid path to a file +/// Status code +NTSTATUS BBFileExists( IN PUNICODE_STRING path ); + +/// +/// Search for pattern +/// +/// Pattern to search for +/// Used wildcard +/// Pattern length +/// Base address for searching +/// Address range to search in +/// Found location +/// Status code +NTSTATUS BBSearchPattern( IN PCUCHAR pattern, IN UCHAR wildcard, IN ULONG_PTR len, IN const VOID* base, IN ULONG_PTR size, OUT PVOID* ppFound ); + +/// +/// Setup image security cookie +/// +/// Image base +/// Status code +NTSTATUS BBCreateCookie( IN PVOID imageBase ); + +/// +/// Check if process is terminating +/// +/// Process +/// If TRUE - terminating +BOOLEAN BBCheckProcessTermination( PEPROCESS pProcess ); + +// +// Machine code generation routines +// +ULONG GenPrologue32( IN PUCHAR pBuf ); +ULONG GenEpilogue32( IN PUCHAR pBuf, IN INT retSize ); +ULONG GenCall32( IN PUCHAR pBuf, IN PVOID pFn, IN INT argc, ... ); +ULONG GenCall32V( IN PUCHAR pBuf, IN PVOID pFn, IN INT argc, IN va_list vl ); +ULONG GenSync32( IN PUCHAR pBuf, IN PNTSTATUS pStatus, IN PVOID pSetEvent, IN HANDLE hEvent ); + + +ULONG GenPrologue64( IN PUCHAR pBuf ); +ULONG GenEpilogue64( IN PUCHAR pBuf, IN INT retSize ); +ULONG GenCall64( IN PUCHAR pBuf, IN PVOID pFn, INT argc, ... ); +ULONG GenCall64V( IN PUCHAR pBuf, IN PVOID pFn, INT argc, va_list vl ); +ULONG GenSync64( IN PUCHAR pBuf, IN PNTSTATUS pStatus, IN PVOID pSetEvent, IN HANDLE hEvent ); + + +ULONG GenPrologueT( IN BOOLEAN wow64, IN PUCHAR pBuf ); +ULONG GenEpilogueT( IN BOOLEAN wow64, IN PUCHAR pBuf, IN INT retSize ); +ULONG GenCallT( IN BOOLEAN wow64, IN PUCHAR pBuf, IN PVOID pFn, IN INT argc, ... ); +ULONG GenCallTV( IN BOOLEAN wow64, IN PUCHAR pBuf, IN PVOID pFn, IN INT argc, IN va_list vl ); +ULONG GenSyncT( IN BOOLEAN wow64, IN PUCHAR pBuf, IN PNTSTATUS pStatus, IN PVOID pSetEvent, IN HANDLE hEvent ); diff --git a/third/Blackbone/src/BlackBoneDrv/VadHelpers.c b/third/Blackbone/src/BlackBoneDrv/VadHelpers.c new file mode 100644 index 0000000000000000000000000000000000000000..81a3d9179f087fca79981984b7d3887c4aebcf5d --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/VadHelpers.c @@ -0,0 +1,916 @@ +#include "Private.h" +#include "VadHelpers.h" + +#pragma alloc_text(PAGE, MiPromoteNode) +#pragma alloc_text(PAGE, MiRebalanceNode) +#pragma alloc_text(PAGE, MiRemoveNode) +#pragma alloc_text(PAGE, MiFindNodeOrParent) + +VOID +MiPromoteNode( + IN PMMADDRESS_NODE C + ) + +/*++ + + Routine Description: + + This routine performs the fundamental adjustment required for balancing + the binary tree during insert and delete operations. Simply put, the + designated node is promoted in such a way that it rises one level in + the tree and its parent drops one level in the tree, becoming now the + child of the designated node. Generally the path length to the subtree + "opposite" the original parent. Balancing occurs as the caller chooses + which nodes to promote according to the balanced tree algorithms from + Knuth. + + This is not the same as a splay operation, typically a splay "promotes" + a designated node twice. + + Note that the pointer to the root node of the tree is assumed to be + contained in a MMADDRESS_NODE structure itself, to allow the + algorithms below to change the root of the tree without checking + for special cases. Note also that this is an internal routine, + and the caller guarantees that it never requests to promote the + root itself. + + This routine only updates the tree links; the caller must update + the balance factors as appropriate. + + Arguments: + + C - pointer to the child node to be promoted in the tree. + + Return Value: + + None. + +--*/ + +{ + PMMADDRESS_NODE P; + PMMADDRESS_NODE G; + + // + // Capture the current parent and grandparent (may be the root). + // + + P = SANITIZE_PARENT_NODE( C->u1.Parent ); + G = SANITIZE_PARENT_NODE( P->u1.Parent ); + + // + // Break down the promotion into two cases based upon whether C + // is a left or right child. + // + + if (P->LeftChild == C) { + + // + // This promotion looks like this: + // + // G G + // | | + // P C + // / \ => / \ + // C z x P + // / \ / \ + // x y y z + // + + P->LeftChild = C->RightChild; + + if (P->LeftChild != NULL) { + + P->LeftChild->u1.Parent = MI_MAKE_PARENT( P, P->LeftChild->u1.Balance ); + } + + C->RightChild = P; + + // + // Fall through to update parent and G <-> C relationship in + // common code. + // + + } + else { + + // + // This promotion looks like this: + // + // G G + // | | + // P C + // / \ => / \ + // x C P z + // / \ / \ + // y z x y + // + + P->RightChild = C->LeftChild; + + if (P->RightChild != NULL) { + P->RightChild->u1.Parent = MI_MAKE_PARENT( P, P->RightChild->u1.Balance ); + } + + C->LeftChild = P; + } + + // + // Update parent of P, for either case above. + // + + P->u1.Parent = MI_MAKE_PARENT( C, P->u1.Balance ); + + // + // Finally update G <-> C links for either case above. + // + + if (G->LeftChild == P) { + G->LeftChild = C; + } + else { + G->RightChild = C; + } + C->u1.Parent = MI_MAKE_PARENT( G, C->u1.Balance ); +} + +ULONG +MiRebalanceNode( + IN PMMADDRESS_NODE S + ) + +/*++ + + Routine Description: + + This routine performs a rebalance around the input node S, for which the + Balance factor has just effectively become +2 or -2. When called, the + Balance factor still has a value of +1 or -1, but the respective longer + side has just become one longer as the result of an insert or delete + operation. + + This routine effectively implements steps A7.iii (test for Case 1 or + Case 2) and steps A8 and A9 of Knuth's balanced insertion algorithm, + plus it handles Case 3 identified in the delete section, which can + only happen on deletes. + + The trick is, to convince yourself that while traveling from the + insertion point at the bottom of the tree up, that there are only + these two cases, and that when traveling up from the deletion point, + that there are just these three cases. Knuth says it is obvious! + + Arguments: + + S - pointer to the node which has just become unbalanced. + + Return Value: + + TRUE if Case 3 was detected (causes delete algorithm to terminate). + + Environment: + + Kernel mode. The PFN lock is held for some of the tables. + +--*/ + +{ + PMMADDRESS_NODE R, P; + SCHAR a; + + // + // Capture which side is unbalanced. + // + + a = (SCHAR)S->u1.Balance; + + if (a == +1) { + R = S->RightChild; + } + else { + R = S->LeftChild; + } + + // + // If the balance of R and S are the same (Case 1 in Knuth) then a single + // promotion of R will do the single rotation. (Step A8, A10) + // + // Here is a diagram of the Case 1 transformation, for a == +1 (a mirror + // image transformation occurs when a == -1), and where the subtree + // heights are h and h+1 as shown (++ indicates the node out of balance): + // + // | | + // S++ R + // / \ / \ + // (h) R+ ==> S (h+1) + // / \ / \ + // (h) (h+1) (h) (h) + // + // Note that on an insert we can hit this case by inserting an item in the + // right subtree of R. The original height of the subtree before the insert + // was h+2, and it is still h+2 after the rebalance, so insert rebalancing + // may terminate. + // + // On a delete we can hit this case by deleting a node from the left subtree + // of S. The height of the subtree before the delete was h+3, and after the + // rebalance it is h+2, so rebalancing must continue up the tree. + // + + if ((SCHAR)R->u1.Balance == a) { + + MiPromoteNode( R ); + R->u1.Balance = 0; + S->u1.Balance = 0; + + return FALSE; + } + + // + // Otherwise, we have to promote the appropriate child of R twice (Case 2 + // in Knuth). (Step A9, A10) + // + // Here is a diagram of the Case 2 transformation, for a == +1 (a mirror + // image transformation occurs when a == -1), and where the subtree + // heights are h and h-1 as shown. There are actually two minor subcases, + // differing only in the original balance of P (++ indicates the node out + // of balance). + // + // | | + // S++ P + // / \ / \ + // / \ / \ + // / \ / \ + // (h) R- ==> S- R + // / \ / \ / \ + // P+ (h) (h)(h-1)(h) (h) + // / \ + // (h-1) (h) + // + // + // | | + // S++ P + // / \ / \ + // / \ / \ + // / \ / \ + // (h) R- ==> S R+ + // / \ / \ / \ + // P- (h) (h) (h)(h-1)(h) + // / \ + // (h) (h-1) + // + // Note that on an insert we can hit this case by inserting an item in the + // left subtree of R. The original height of the subtree before the insert + // was h+2, and it is still h+2 after the rebalance, so insert rebalancing + // may terminate. + // + // On a delete we can hit this case by deleting a node from the left subtree + // of S. The height of the subtree before the delete was h+3, and after the + // rebalance it is h+2, so rebalancing must continue up the tree. + // + + if ((SCHAR)R->u1.Balance == -a) { + + // + // Pick up the appropriate child P for the double rotation (Link(-a,R)). + // + + if (a == 1) { + P = R->LeftChild; + } + else { + P = R->RightChild; + } + + // + // Promote him twice to implement the double rotation. + // + + MiPromoteNode( P ); + MiPromoteNode( P ); + + // + // Now adjust the balance factors. + // + + S->u1.Balance = 0; + R->u1.Balance = 0; + if ((SCHAR)P->u1.Balance == a) { + COUNT_BALANCE_MAX( (SCHAR)-a ); + S->u1.Balance = (ULONG_PTR)-a; + } + else if ((SCHAR)P->u1.Balance == -a) { + COUNT_BALANCE_MAX( (SCHAR)a ); + R->u1.Balance = (ULONG_PTR)a; + } + + P->u1.Balance = 0; + return FALSE; + } + + // + // Otherwise this is Case 3 which can only happen on Delete (identical + // to Case 1 except R->u1.Balance == 0). We do a single rotation, adjust + // the balance factors appropriately, and return TRUE. Note that the + // balance of S stays the same. + // + // Here is a diagram of the Case 3 transformation, for a == +1 (a mirror + // image transformation occurs when a == -1), and where the subtree + // heights are h and h+1 as shown (++ indicates the node out of balance): + // + // | | + // S++ R- + // / \ / \ + // (h) R ==> S+ (h+1) + // / \ / \ + // (h+1)(h+1) (h) (h+1) + // + // This case can not occur on an insert, because it is impossible for + // a single insert to balance R, yet somehow grow the right subtree of + // S at the same time. As we move up the tree adjusting balance factors + // after an insert, we terminate the algorithm if a node becomes balanced, + // because that means the subtree length did not change! + // + // On a delete we can hit this case by deleting a node from the left + // subtree of S. The height of the subtree before the delete was h+3, + // and after the rebalance it is still h+3, so rebalancing may terminate + // in the delete path. + // + + MiPromoteNode( R ); + COUNT_BALANCE_MAX( (SCHAR)-a ); + R->u1.Balance = -a; + return TRUE; +} + + +/* +VOID +MiInsertNode ( +IN PMMADDRESS_NODE NodeToInsert, +IN PMM_AVL_TABLE Table +) + +/ *++ + +Routine Description: + +This function inserts a new element in a table. + +Arguments: + +NodeToInsert - The initialized address node to insert. + +Table - Pointer to the table in which to insert the new node. + +Return Value: + +None. + +Environment: + +Kernel mode. The PFN lock is held for some of the tables. + +--* / + +{ + // + // Holds a pointer to the node in the table or what would be the + // parent of the node. + // + + PMMADDRESS_NODE NodeOrParent; + TABLE_SEARCH_RESULT SearchResult; + + SearchResult = MiFindNodeOrParent( Table, + (ULONG_PTR)((PMMVAD_SHORT)NodeToInsert)->StartingVpn, + &NodeOrParent ); + + + // + // The node wasn't in the (possibly empty) tree. + // + // We just check that the table isn't getting too big. + // + + NodeToInsert->LeftChild = NULL; + NodeToInsert->RightChild = NULL; + + Table->NumberGenericTableElements += 1; + + // + // Insert the new node in the tree. + // + + if (SearchResult == TableEmptyTree) { + + Table->BalancedRoot.RightChild = NodeToInsert; + NodeToInsert->u1.Parent = &Table->BalancedRoot; + Table->DepthOfTree = 1; + + } + else { + + PMMADDRESS_NODE R = NodeToInsert; + PMMADDRESS_NODE S = NodeOrParent; + + if (SearchResult == TableInsertAsLeft) { + NodeOrParent->LeftChild = NodeToInsert; + } + else { + NodeOrParent->RightChild = NodeToInsert; + } + + NodeToInsert->u1.Parent = NodeOrParent; + + // + // The above completes the standard binary tree insertion, which + // happens to correspond to steps A1-A5 of Knuth's "balanced tree + // search and insertion" algorithm. Now comes the time to adjust + // balance factors and possibly do a single or double rotation as + // in steps A6-A10. + // + // Set the Balance factor in the root to a convenient value + // to simplify loop control. + // + + COUNT_BALANCE_MAX( (SCHAR)-1 ); + Table->BalancedRoot.u1.Balance = (ULONG_PTR)-1; + + // + // Now loop to adjust balance factors and see if any balance operations + // must be performed, using NodeOrParent to ascend the tree. + // + + for (;;) { + + SCHAR a; + + // + // Calculate the next adjustment. + // + + a = 1; + if (MiIsLeftChild( R )) { + a = -1; + } + + // + // If this node was balanced, show that it is no longer and + // keep looping. This is essentially A6 of Knuth's algorithm, + // where he updates all of the intermediate nodes on the + // insertion path which previously had balance factors of 0. + // We are looping up the tree via Parent pointers rather than + // down the tree as in Knuth. + // + + if (S->u1.Balance == 0) { + + COUNT_BALANCE_MAX( (SCHAR)a ); + S->u1.Balance = a; + R = S; + S = SANITIZE_PARENT_NODE( S->u1.Parent ); + } + else if ((SCHAR)S->u1.Balance != a) { + + + // + // If this node has the opposite balance, then the tree got + // more balanced (or we hit the root) and we are done. + // + // Step A7.ii + // + + S->u1.Balance = 0; + + // + // If S is actually the root, then this means the depth + // of the tree just increased by 1! (This is essentially + // A7.i, but we just initialized the root balance to force + // it through here.) + // + + if (Table->BalancedRoot.u1.Balance == 0) { + Table->DepthOfTree += 1; + } + + break; + } + else { + + // + // The tree became unbalanced (path length differs + // by 2 below us) and we need to do one of the balancing + // operations, and then we are done. The RebalanceNode routine + // does steps A7.iii, A8 and A9. + // + + MiRebalanceNode( S ); + break; + } + } + } + + // + // Sanity check tree size and depth. + // + + + return; +}*/ + +VOID +MiRemoveNode( + IN PMMADDRESS_NODE NodeToDelete, + IN PMM_AVL_TABLE Table + ) + +/*++ + + Routine Description: + + This routine deletes the specified node from the balanced tree, rebalancing + as necessary. If the NodeToDelete has at least one NULL child pointers, + then it is chosen as the EasyDelete, otherwise a subtree predecessor or + successor is found as the EasyDelete. In either case the EasyDelete is + deleted and the tree is rebalanced. Finally if the NodeToDelete was + different than the EasyDelete, then the EasyDelete is linked back into the + tree in place of the NodeToDelete. + + Arguments: + + NodeToDelete - Pointer to the node which the caller wishes to delete. + + Table - The generic table in which the delete is to occur. + + Return Value: + + None. + + Environment: + + Kernel mode. The PFN lock is held for some of the tables. + +--*/ + +{ + PMMADDRESS_NODE Parent; + PMMADDRESS_NODE EasyDelete; + PMMADDRESS_NODE P; + SCHAR a; + + // + // If the NodeToDelete has at least one NULL child pointer, then we can + // delete it directly. + // + + if ((NodeToDelete->LeftChild == NULL) || + (NodeToDelete->RightChild == NULL)) { + + EasyDelete = NodeToDelete; + } + + // + // Otherwise, we may as well pick the longest side to delete from (if one is + // is longer), as that reduces the probability that we will have to + // rebalance. + // + + else if ((SCHAR)NodeToDelete->u1.Balance >= 0) { + + // + // Pick up the subtree successor. + // + + EasyDelete = NodeToDelete->RightChild; + while (EasyDelete->LeftChild != NULL) { + EasyDelete = EasyDelete->LeftChild; + } + } + else { + + // + // Pick up the subtree predecessor. + // + + EasyDelete = NodeToDelete->LeftChild; + while (EasyDelete->RightChild != NULL) { + EasyDelete = EasyDelete->RightChild; + } + } + + // + // Rebalancing must know which side of the first parent the delete occurred + // on. Assume it is the left side and otherwise correct below. + // + + a = -1; + + // + // Now we can do the simple deletion for the no left child case. + // + + if (EasyDelete->LeftChild == NULL) { + + Parent = SANITIZE_PARENT_NODE( EasyDelete->u1.Parent ); + + if (MiIsLeftChild( EasyDelete )) { + Parent->LeftChild = EasyDelete->RightChild; + } + else { + Parent->RightChild = EasyDelete->RightChild; + a = 1; + } + + if (EasyDelete->RightChild != NULL) { + EasyDelete->RightChild->u1.Parent = MI_MAKE_PARENT( Parent, EasyDelete->RightChild->u1.Balance ); + } + + // + // Now we can do the simple deletion for the no right child case, + // plus we know there is a left child. + // + + } + else { + + Parent = SANITIZE_PARENT_NODE( EasyDelete->u1.Parent ); + + if (MiIsLeftChild( EasyDelete )) { + Parent->LeftChild = EasyDelete->LeftChild; + } + else { + Parent->RightChild = EasyDelete->LeftChild; + a = 1; + } + + EasyDelete->LeftChild->u1.Parent = MI_MAKE_PARENT( Parent, + EasyDelete->LeftChild->u1.Balance ); + } + + // + // For delete rebalancing, set the balance at the root to 0 to properly + // terminate the rebalance without special tests, and to be able to detect + // if the depth of the tree actually decreased. + // + +#if defined( _WIN81_ ) || defined ( _WIN10_ ) + Table->BalancedRoot->u1.Balance = 0; +#else + Table->BalancedRoot.u1.Balance = 0; +#endif + P = SANITIZE_PARENT_NODE( EasyDelete->u1.Parent ); + + // + // Loop until the tree is balanced. + // + + for (;;) { + + // + // First handle the case where the tree became more balanced. Zero + // the balance factor, calculate a for the next loop and move on to + // the parent. + // + + if ((SCHAR)P->u1.Balance == a) { + + P->u1.Balance = 0; + + // + // If this node is curently balanced, we can show it is now unbalanced + // and terminate the scan since the subtree length has not changed. + // (This may be the root, since we set Balance to 0 above!) + // + + } + else if (P->u1.Balance == 0) + { + COUNT_BALANCE_MAX( (SCHAR)-a ); + P->u1.Balance = -a; + + // + // If we shortened the depth all the way back to the root, then + // the tree really has one less level. + // + +#if !defined( _WIN81_ ) && !defined ( _WIN10_ ) + if (Table->BalancedRoot.u1.Balance != 0) { + Table->DepthOfTree -= 1; + } +#endif + + break; + + // + // Otherwise we made the short side 2 levels less than the long side, + // and rebalancing is required. On return, some node has been promoted + // to above node P. If Case 3 from Knuth was not encountered, then we + // want to effectively resume rebalancing from P's original parent which + // is effectively its grandparent now. + // + + } + else + { + + // + // We are done if Case 3 was hit, i.e., the depth of this subtree is + // now the same as before the delete. + // + + if (MiRebalanceNode( P )) + { + break; + } + + P = SANITIZE_PARENT_NODE( P->u1.Parent ); + } + + a = -1; + if (MiIsRightChild( P )) + { + a = 1; + } + + P = SANITIZE_PARENT_NODE( P->u1.Parent ); + } + + // + // Finally, if we actually deleted a predecessor/successor of the + // NodeToDelete, we will link him back into the tree to replace + // NodeToDelete before returning. Note that NodeToDelete did have + // both child links filled in, but that may no longer be the case + // at this point. + // + + if (NodeToDelete != EasyDelete) + { + + // + // Note carefully - VADs are of differing sizes therefore it is not safe + // to just overlay the EasyDelete node with the NodeToDelete like the + // rtl avl code does. + // + // Copy just the links, preserving the rest of the original EasyDelete + // VAD. + // + + EasyDelete->u1.Parent = NodeToDelete->u1.Parent; + EasyDelete->LeftChild = NodeToDelete->LeftChild; + EasyDelete->RightChild = NodeToDelete->RightChild; + + if (MiIsLeftChild( NodeToDelete )) + { + Parent = SANITIZE_PARENT_NODE( EasyDelete->u1.Parent ); + Parent->LeftChild = EasyDelete; + } + else + { + Parent = SANITIZE_PARENT_NODE( EasyDelete->u1.Parent ); + Parent->RightChild = EasyDelete; + } + if (EasyDelete->LeftChild != NULL) + { + EasyDelete->LeftChild->u1.Parent = MI_MAKE_PARENT( EasyDelete, + EasyDelete->LeftChild->u1.Balance ); + } + if (EasyDelete->RightChild != NULL) + { + EasyDelete->RightChild->u1.Parent = MI_MAKE_PARENT( EasyDelete, + EasyDelete->RightChild->u1.Balance ); + } + } + + return; +} + +TABLE_SEARCH_RESULT +MiFindNodeOrParent( + IN PMM_AVL_TABLE Table, + IN ULONG_PTR StartingVpn, + OUT PMMADDRESS_NODE *NodeOrParent + ) + +/*++ + + Routine Description: + + This routine is used by all of the routines of the generic + table package to locate the a node in the tree. It will + find and return (via the NodeOrParent parameter) the node + with the given key, or if that node is not in the tree it + will return (via the NodeOrParent parameter) a pointer to + the parent. + + Arguments: + + Table - The generic table to search for the key. + + StartingVpn - The starting virtual page number. + + NodeOrParent - Will be set to point to the node containing the + the key or what should be the parent of the node + if it were in the tree. Note that this will *NOT* + be set if the search result is TableEmptyTree. + + Return Value: + + TABLE_SEARCH_RESULT - TableEmptyTree: The tree was empty. NodeOrParent + is *not* altered. + + TableFoundNode: A node with the key is in the tree. + NodeOrParent points to that node. + + TableInsertAsLeft: Node with key was not found. + NodeOrParent points to what would + be parent. The node would be the + left child. + + TableInsertAsRight: Node with key was not found. + NodeOrParent points to what would + be parent. The node would be + the right child. + + Environment: + + Kernel mode. The PFN lock is held for some of the tables. + +--*/ + +{ + PMMADDRESS_NODE Child; + PMMADDRESS_NODE NodeToExamine; + PMMVAD_SHORT VpnCompare; + ULONG_PTR startVpn; + ULONG_PTR endVpn; + + if (Table->NumberGenericTableElements == 0) { + return TableEmptyTree; + } + + NodeToExamine = (PMMADDRESS_NODE)GET_VAD_ROOT( Table ); + + for (;;) { + + VpnCompare = (PMMVAD_SHORT)NodeToExamine; + startVpn = VpnCompare->StartingVpn; + endVpn = VpnCompare->EndingVpn; + +#if defined( _WIN81_ ) || defined( _WIN10_ ) + startVpn |= (ULONG_PTR)VpnCompare->StartingVpnHigh << 32; + endVpn |= (ULONG_PTR)VpnCompare->EndingVpnHigh << 32; +#endif + + // + // Compare the buffer with the key in the tree element. + // + + if (StartingVpn < startVpn) { + + Child = NodeToExamine->LeftChild; + + if (Child != NULL) { + NodeToExamine = Child; + } + else { + + // + // Node is not in the tree. Set the output + // parameter to point to what would be its + // parent and return which child it would be. + // + + *NodeOrParent = NodeToExamine; + return TableInsertAsLeft; + } + } + else if (StartingVpn <= endVpn) { + + // + // This is the node. + // + + *NodeOrParent = NodeToExamine; + return TableFoundNode; + } + else { + + Child = NodeToExamine->RightChild; + + if (Child != NULL) { + NodeToExamine = Child; + } + else { + + // + // Node is not in the tree. Set the output + // parameter to point to what would be its + // parent and return which child it would be. + // + + *NodeOrParent = NodeToExamine; + return TableInsertAsRight; + } + } + + }; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/VadHelpers.h b/third/Blackbone/src/BlackBoneDrv/VadHelpers.h new file mode 100644 index 0000000000000000000000000000000000000000..866ce8dc7851504360c751077f24b9be79689870 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/VadHelpers.h @@ -0,0 +1,65 @@ +#pragma once + +#define SANITIZE_PARENT_NODE(Parent) ((PMMADDRESS_NODE)(((ULONG_PTR)(Parent)) & ~0x3)) + +// +// Various Rtl macros that reference Parent use private versions here since +// Parent is overloaded with Balance. +// + +// +// The macro function Parent takes as input a pointer to a splay link in a +// tree and returns a pointer to the splay link of the parent of the input +// node. If the input node is the root of the tree the return value is +// equal to the input value. +// +// PRTL_SPLAY_LINKS +// MiParent ( +// PRTL_SPLAY_LINKS Links +// ); +// + +#define MiParent(Links) ( \ + (PRTL_SPLAY_LINKS)(SANITIZE_PARENT_NODE((Links)->u1.Parent)) \ + ) + +// +// The macro function IsLeftChild takes as input a pointer to a splay link +// in a tree and returns TRUE if the input node is the left child of its +// parent, otherwise it returns FALSE. +// +// BOOLEAN +// MiIsLeftChild ( +// PRTL_SPLAY_LINKS Links +// ); +// + +#define MiIsLeftChild(Links) ( \ + (RtlLeftChild(MiParent(Links)) == (PRTL_SPLAY_LINKS)(Links)) \ + ) + +// +// The macro function IsRightChild takes as input a pointer to a splay link +// in a tree and returns TRUE if the input node is the right child of its +// parent, otherwise it returns FALSE. +// +// BOOLEAN +// MiIsRightChild ( +// PRTL_SPLAY_LINKS Links +// ); +// + +#define MiIsRightChild(Links) ( \ + (RtlRightChild(MiParent(Links)) == (PRTL_SPLAY_LINKS)(Links)) \ + ) + +#define MI_MAKE_PARENT(ParentNode, ExistingBalance) \ + (PMMADDRESS_NODE)((ULONG_PTR)(ParentNode) | (((ULONG_PTR)ExistingBalance) & 0x3)) + +#define COUNT_BALANCE_MAX(a) + + +TABLE_SEARCH_RESULT MiFindNodeOrParent( IN PMM_AVL_TABLE Table, IN ULONG_PTR StartingVpn, OUT PMMADDRESS_NODE *NodeOrParent ); +VOID MiPromoteNode( IN PMMADDRESS_NODE C ); +ULONG MiRebalanceNode( IN PMMADDRESS_NODE S ); +VOID MiRemoveNode( IN PMMADDRESS_NODE NodeToDelete, IN PMM_AVL_TABLE Table ); \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/VadRoutines.c b/third/Blackbone/src/BlackBoneDrv/VadRoutines.c new file mode 100644 index 0000000000000000000000000000000000000000..5655b2fc7eed8441fc565e10add8a6e34be37d14 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/VadRoutines.c @@ -0,0 +1,193 @@ +#include "VadRoutines.h" +#include "VadHelpers.h" + +#pragma alloc_text(PAGE, BBProtectVAD) +#pragma alloc_text(PAGE, BBUnlinkVAD) +#pragma alloc_text(PAGE, BBGetVadType) +#pragma alloc_text(PAGE, BBFindVAD) + +extern DYNAMIC_DATA dynData; + +ULONG MmProtectToValue[32] = +{ + PAGE_NOACCESS, + PAGE_READONLY, + PAGE_EXECUTE, + PAGE_EXECUTE_READ, + PAGE_READWRITE, + PAGE_WRITECOPY, + PAGE_EXECUTE_READWRITE, + PAGE_EXECUTE_WRITECOPY, + PAGE_NOACCESS, + PAGE_NOCACHE | PAGE_READONLY, + PAGE_NOCACHE | PAGE_EXECUTE, + PAGE_NOCACHE | PAGE_EXECUTE_READ, + PAGE_NOCACHE | PAGE_READWRITE, + PAGE_NOCACHE | PAGE_WRITECOPY, + PAGE_NOCACHE | PAGE_EXECUTE_READWRITE, + PAGE_NOCACHE | PAGE_EXECUTE_WRITECOPY, + PAGE_NOACCESS, + PAGE_GUARD | PAGE_READONLY, + PAGE_GUARD | PAGE_EXECUTE, + PAGE_GUARD | PAGE_EXECUTE_READ, + PAGE_GUARD | PAGE_READWRITE, + PAGE_GUARD | PAGE_WRITECOPY, + PAGE_GUARD | PAGE_EXECUTE_READWRITE, + PAGE_GUARD | PAGE_EXECUTE_WRITECOPY, + PAGE_NOACCESS, + PAGE_WRITECOMBINE | PAGE_READONLY, + PAGE_WRITECOMBINE | PAGE_EXECUTE, + PAGE_WRITECOMBINE | PAGE_EXECUTE_READ, + PAGE_WRITECOMBINE | PAGE_READWRITE, + PAGE_WRITECOMBINE | PAGE_WRITECOPY, + PAGE_WRITECOMBINE | PAGE_EXECUTE_READWRITE, + PAGE_WRITECOMBINE | PAGE_EXECUTE_WRITECOPY +}; + +/// +/// Change VAD protection flags +/// +/// Target process object +/// Target address +/// New protection flags +/// Status code +NTSTATUS BBProtectVAD( IN PEPROCESS pProcess, IN ULONG_PTR address, IN ULONG prot ) +{ + NTSTATUS status = STATUS_SUCCESS; + PMMVAD_SHORT pVadShort = NULL; + + status = BBFindVAD( pProcess, address, &pVadShort ); + if (NT_SUCCESS( status )) + pVadShort->u.VadFlags.Protection = prot; + + return status; +} + +#pragma warning(disable : 4055) + +/// +/// Hide memory from NtQueryVirtualMemory +/// +/// Target process object +/// Target address +/// Status code +NTSTATUS BBUnlinkVAD( IN PEPROCESS pProcess, IN ULONG_PTR address ) +{ + NTSTATUS status = STATUS_SUCCESS; + PMMVAD_SHORT pVadShort = NULL; + + status = BBFindVAD( pProcess, address, &pVadShort ); + if (!NT_SUCCESS( status )) + return status; + + // Erase image name + if (pVadShort->u.VadFlags.VadType == VadImageMap) + { + PMMVAD pVadLong = (PMMVAD)pVadShort; + if (pVadLong->Subsection && pVadLong->Subsection->ControlArea && pVadLong->Subsection->ControlArea->FilePointer.Object) + { + PFILE_OBJECT pFile = (PFILE_OBJECT)(pVadLong->Subsection->ControlArea->FilePointer.Value & ~0xF); + pFile->FileName.Buffer[0] = L'\0'; + pFile->FileName.Length = 0; + } + else + return STATUS_INVALID_ADDRESS; + } + // Make NO_ACCESS + else if (pVadShort->u.VadFlags.VadType == VadDevicePhysicalMemory) + { + pVadShort->u.VadFlags.Protection = MM_ZERO_ACCESS; + } + // Invalid VAD type + else + status = STATUS_INVALID_PARAMETER; + + return status; +} + +#pragma warning(default : 4055) + +/// +/// Get region VAD type +/// +/// Target process object +/// Target address +/// Resulting VAD type +/// Status code +NTSTATUS BBGetVadType( IN PEPROCESS pProcess, IN ULONG_PTR address, OUT PMI_VAD_TYPE pType ) +{ + NTSTATUS status = STATUS_SUCCESS; + PMMVAD_SHORT pVad = NULL; + + status = BBFindVAD( pProcess, address, &pVad ); + if (!NT_SUCCESS( status )) + return status; + + *pType = pVad->u.VadFlags.VadType; + + return status; +} + +/// +/// Find VAD that describes target address +/// +/// Target process object +/// Address to find +/// Found VAD. NULL if not found +/// Status code +NTSTATUS BBFindVAD( IN PEPROCESS pProcess, IN ULONG_PTR address, OUT PMMVAD_SHORT* pResult ) +{ + NTSTATUS status = STATUS_SUCCESS; + ULONG_PTR vpnStart = address >> PAGE_SHIFT; + + ASSERT( pProcess != NULL && pResult != NULL ); + if (pProcess == NULL || pResult == NULL) + return STATUS_INVALID_PARAMETER; + + if (dynData.VadRoot == 0) + { + DPRINT( "BlackBone: %s: Invalid VadRoot offset\n", __FUNCTION__ ); + status = STATUS_INVALID_ADDRESS; + } + + + PMM_AVL_TABLE pTable = (PMM_AVL_TABLE)((PUCHAR)pProcess + dynData.VadRoot); + PMM_AVL_NODE pNode = GET_VAD_ROOT( pTable ); + + // Search VAD + if (MiFindNodeOrParent( pTable, vpnStart, &pNode ) == TableFoundNode) + { + *pResult = (PMMVAD_SHORT)pNode; + } + else + { + DPRINT( "BlackBone: %s: VAD entry for address 0x%p not found\n", __FUNCTION__, address ); + status = STATUS_NOT_FOUND; + } + + return status; +} + +/// +/// Convert protection flags +/// +/// Protection flags. +/// If TRUE - convert to PTE protection, if FALSE - convert to Win32 protection +/// Resulting protection flags +ULONG BBConvertProtection( IN ULONG prot, IN BOOLEAN fromPTE ) +{ + if (fromPTE != FALSE) + { + // Sanity check + if (prot < ARRAYSIZE( MmProtectToValue )) + return MmProtectToValue[prot]; + } + else + { + for (int i = 0; i < ARRAYSIZE( MmProtectToValue ); i++) + if (MmProtectToValue[i] == prot) + return i; + } + + return 0; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/VadRoutines.h b/third/Blackbone/src/BlackBoneDrv/VadRoutines.h new file mode 100644 index 0000000000000000000000000000000000000000..b237a1f431bbe2dc9f772ee0e744a36e5a403d5e --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/VadRoutines.h @@ -0,0 +1,46 @@ +#pragma once + +#include "Private.h" + +/// +/// Change VAD protection flags +/// +/// Target process object +/// target address +/// New protection flags +/// Status code +NTSTATUS BBProtectVAD( IN PEPROCESS pProcess, IN ULONG_PTR address, IN ULONG prot ); + +/// +/// Hide memory from NtQueryVirtualMemory +/// +/// Target process object +/// Target address +/// Status code +NTSTATUS BBUnlinkVAD( IN PEPROCESS pProcess, IN ULONG_PTR address ); + +/// +/// Get region VAD type +/// +/// Target process object +/// Target address +/// Resulting VAD type +/// Status code +NTSTATUS BBGetVadType( IN PEPROCESS pProcess, IN ULONG_PTR address, OUT PMI_VAD_TYPE pType ); + +/// +/// Find VAD that describes target address +/// +/// Target process object +/// Address to find +/// Found VAD. NULL if not found +/// Status code +NTSTATUS BBFindVAD( IN PEPROCESS pProcess, IN ULONG_PTR address, OUT PMMVAD_SHORT* pResult ); + +/// +/// Convert protection flags +/// +/// Protection flags. +/// If TRUE - convert to PTE protection, if FALSE - convert to Win32 protection +/// Resulting protection flags +ULONG BBConvertProtection( IN ULONG prot, IN BOOLEAN fromPTE ); \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneDrv/apiset.h b/third/Blackbone/src/BlackBoneDrv/apiset.h new file mode 100644 index 0000000000000000000000000000000000000000..4bc19f1d423981e91334bf870bd8765c65ad4208 --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/apiset.h @@ -0,0 +1,247 @@ +/*++ + +Copyright (c) 2008 Microsoft Corporation + +Module Name: + + apiset.h + +Abstract: + + This module contains definitions related to the management of API namespaces. + +Author: + + Arun Kishan (arunki) 14-Sep-2008 + +--*/ + +#ifndef _API_SET2_H_ +#define _API_SET2_H_ + +// +// API schema DLL information. +// + +#define API_SET_PREFIX_NAME_A "API-" +#define API_SET_PREFIX_NAME_A_SIZE (sizeof(API_SET_PREFIX_NAME_A) - sizeof(CHAR)) +#define API_SET_PREFIX_NAME_U TEXT(API_SET_PREFIX_NAME_A) +#define API_SET_PREFIX_NAME_U_SIZE (sizeof(API_SET_PREFIX_NAME_U) - sizeof(WCHAR)) +#define API_SET_PREFIX_NAME_LENGTH (RTL_NUMBER_OF(API_SET_PREFIX_NAME_U) - 1) + +#define API_SET_EXTENSION_NAME_A "EXT-" +#define API_SET_EXTENSION_NAME_A_SIZE (sizeof(API_SET_EXTENSION_NAME_A) - sizeof(CHAR)) +#define API_SET_EXTENSION_NAME_U TEXT(API_SET_EXTENSION_NAME_A) +#define API_SET_EXTENSION_NAME_U_SIZE (sizeof(API_SET_EXTENSION_NAME_U) - sizeof(WCHAR)) +#define API_SET_EXTENSION_NAME_LENGTH (RTL_NUMBER_OF(API_SET_EXTENSION_NAME_U) - 1) + +#define API_SET_SCHEMA_NAME ApiSetSchema +#define API_SET_SECTION_NAME ".apiset" +#define API_SET_SCHEMA_SUFFIX L".sys" + +// +// All previous schema versions are listed here. Some are supported in offline +// mode because they shipped externally. Some are not supported in offline mode +// since they were only ever released internally. +// + +#define API_SET_SCHEMA_VERSION_V2 0x00000002UL +#define API_SET_SCHEMA_VERSION_V3 0x00000003UL // No offline support. +#define API_SET_SCHEMA_VERSION_V4 0x00000004UL +#define API_SET_SCHEMA_VERSION API_SET_SCHEMA_VERSION_V4 + +#define API_SET_HELPER_NAME ApiSetHelp + +#define API_SET_LOAD_SCHEMA_ORDINAL 1 +#define API_SET_LOOKUP_ORDINAL 2 +#define API_SET_RELEASE_SCHEMA_ORDINAL 3 + +#define API_SET_STRING_X(s) #s +#define API_SET_STRING(s) API_SET_STRING_X(s) +#define API_SET_STRING_U_Y(s) L ## s +#define API_SET_STRING_U_X(s) API_SET_STRING_U_Y(s) +#define API_SET_STRING_U(s) API_SET_STRING_U_X(API_SET_STRING(s)) + +// +// API set interface definitions. +// + +#define API_SET_OVERRIDE(X) X##Implementation +#define API_SET_LEGACY_OVERRIDE_DEF(X) X = API_SET_OVERRIDE(X) +#define API_SET_OVERRIDE_DEF(X) API_SET_LEGACY_OVERRIDE_DEF(X) PRIVATE + +#ifdef _API_SET_HOST + +#undef API_SET_LIBRARY + +#define API_SET_LIBRARY(X) + +#undef API_SET +#undef API_SET_PRIVATE +#undef API_SET_BY_ORDINAL +#undef API_SET_BY_ORDINAL_PRIVATE + +#define API_SET(X) X PRIVATE +#define API_SET_PRIVATE(X) X PRIVATE +#define API_SET_BY_ORDINAL(X,O,PO) X @##O NONAME PRIVATE +#define API_SET_BY_ORDINAL_PRIVATE(X,O,PO) X @##O NONAME PRIVATE + +#else + +#ifndef _API_SET_LEGACY_TARGET + +#define API_SET(X) X +#define API_SET_PRIVATE(X) X PRIVATE +#define API_SET_BY_ORDINAL(X,O,PO) X @##O NONAME +#define API_SET_BY_ORDINAL_PRIVATE(X,O,PO) X @##O NONAME PRIVATE + +#else + +#define API_SET(X) X = _API_SET_LEGACY_TARGET##.##X +#define API_SET_PRIVATE(X) X = _API_SET_LEGACY_TARGET##.##X PRIVATE +#define API_SET_BY_ORDINAL(X,O,PO) X = _API_SET_LEGACY_TARGET##.##PO @##O NONAME +#define API_SET_BY_ORDINAL_PRIVATE(X,O,PO) X = _API_SET_LEGACY_TARGET##.##PO @##O NONAME PRIVATE + +#endif // _API_SET_LEGACY_TARGET + +#define API_SET_LIBRARY(X) LIBRARY X + +#endif // _API_SET_HOST + +#ifdef _NTDEF_ + +// +// Data structures. +// + +typedef struct _API_SET_VALUE_ENTRY { + ULONG Flags; + ULONG NameOffset; + _Field_range_(0, UNICODE_STRING_MAX_BYTES) ULONG NameLength; + ULONG ValueOffset; + _Field_range_(0, UNICODE_STRING_MAX_BYTES) ULONG ValueLength; +} API_SET_VALUE_ENTRY, *PAPI_SET_VALUE_ENTRY; + +_Struct_size_bytes_(FIELD_OFFSET(API_SET_VALUE_ARRAY, Array) + (sizeof(API_SET_VALUE_ENTRY) * Count)) +typedef struct _API_SET_VALUE_ARRAY { + ULONG Flags; + ULONG Count; + _Field_size_full_(Count) API_SET_VALUE_ENTRY Array[ANYSIZE_ARRAY]; +} API_SET_VALUE_ARRAY,*PAPI_SET_VALUE_ARRAY; + +typedef struct _API_SET_NAMESPACE_ENTRY { + ULONG Flags; + ULONG NameOffset; + _Field_range_(0, UNICODE_STRING_MAX_BYTES) ULONG NameLength; + ULONG AliasOffset; + _Field_range_(0, UNICODE_STRING_MAX_BYTES) ULONG AliasLength; + ULONG DataOffset; // API_SET_VALUE_ARRAY +} API_SET_NAMESPACE_ENTRY, *PAPI_SET_NAMESPACE_ENTRY; + +_Struct_size_bytes_(Size) +typedef struct _API_SET_NAMESPACE_ARRAY { + ULONG Version; + ULONG Size; + ULONG Flags; + ULONG Count; + _Field_size_full_(Count) API_SET_NAMESPACE_ENTRY Array[ANYSIZE_ARRAY]; +} API_SET_NAMESPACE_ARRAY, *PAPI_SET_NAMESPACE_ARRAY; + +typedef const API_SET_VALUE_ENTRY *PCAPI_SET_VALUE_ENTRY; +typedef const API_SET_VALUE_ARRAY *PCAPI_SET_VALUE_ARRAY; +typedef const API_SET_NAMESPACE_ENTRY *PCAPI_SET_NAMESPACE_ENTRY; +typedef const API_SET_NAMESPACE_ARRAY *PCAPI_SET_NAMESPACE_ARRAY; + +#define API_SET_SCHEMA_FLAGS_SEALED 0x00000001UL +#define API_SET_SCHEMA_FLAGS_HOST_EXTENSION 0x00000002UL + +#define API_SET_SCHEMA_ENTRY_FLAGS_SEALED 0x00000001UL +#define API_SET_SCHEMA_ENTRY_FLAGS_EXTENSION 0x00000002UL + +// +// Support for downlevel API set schema versions. +// + +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]; +} 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; + _Field_size_full_(Count) API_SET_NAMESPACE_ENTRY_V2 Array[ANYSIZE_ARRAY]; +} API_SET_NAMESPACE_ARRAY_V2, *PAPI_SET_NAMESPACE_ARRAY_V2; + +typedef const API_SET_VALUE_ENTRY_V2 *PCAPI_SET_VALUE_ENTRY_V2; +typedef const API_SET_VALUE_ARRAY_V2 *PCAPI_SET_VALUE_ARRAY_V2; +typedef const API_SET_NAMESPACE_ENTRY *PCAPI_SET_NAMESPACE_ENTRY_V2; +typedef const API_SET_NAMESPACE_ARRAY *PCAPI_SET_NAMESPACE_ARRAY_V2; + +// +// Offline API set resolution support. +// + +typedef +_Function_class_(API_SET_LOAD_SCHEMA_RTN) +NTSTATUS +(NTAPI API_SET_LOAD_SCHEMA_RTN) ( + _In_ PCSTR SchemaPath, + _Outptr_ PCAPI_SET_NAMESPACE_ARRAY *Schema, + _Outptr_ PVOID *Context + ); + +typedef API_SET_LOAD_SCHEMA_RTN *PAPI_SET_LOAD_SCHEMA_RTN; + +typedef +_Function_class_(API_SET_LOOKUP_HELPER_RTN) +NTSTATUS +(NTAPI API_SET_LOOKUP_HELPER_RTN) ( + _In_ PCAPI_SET_NAMESPACE_ARRAY Schema, + _In_ PCSTR FileName, + _In_ PCSTR ParentName, + _Out_ PBOOLEAN Resolved, + _Out_writes_bytes_(Length) PSTR ResolvedName, + _In_ ULONG Length + ); + +typedef API_SET_LOOKUP_HELPER_RTN *PAPI_SET_LOOKUP_HELPER_RTN; + +typedef +_Function_class_(API_SET_RELEASE_SCHEMA_RTN) +NTSTATUS +(NTAPI API_SET_RELEASE_SCHEMA_RTN) ( + _In_ PVOID Context + ); + +typedef API_SET_RELEASE_SCHEMA_RTN *PAPI_SET_RELEASE_SCHEMA_RTN; + +// +// Prototypes +// + +NTSTATUS +ApiSetResolveToHost ( + _In_ PCAPI_SET_NAMESPACE_ARRAY Schema, + _In_ PCUNICODE_STRING FileNameIn, + _In_opt_ PCUNICODE_STRING ParentName, + _Out_ PBOOLEAN Resolved, + _Out_ PUNICODE_STRING HostBinary + ); + +#endif // _NTDEF_ + +#endif // _API_SET2_H_ diff --git a/third/Blackbone/src/BlackBoneDrv/ldrreloc.c b/third/Blackbone/src/BlackBoneDrv/ldrreloc.c new file mode 100644 index 0000000000000000000000000000000000000000..baac7188f12f65873233c54dae4f872444c5852c --- /dev/null +++ b/third/Blackbone/src/BlackBoneDrv/ldrreloc.c @@ -0,0 +1,463 @@ +#include "Loader.h" +#include "NativeStructs.h" + +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt). +If you do not agree to the terms, do not use the code. + + +Module Name: + + ldrreloc.c + +Abstract: + + This module contains the code to relocate an image when + the preferred base isn't available. This is called by the + boot loader, device driver loader, and system loader. + +--*/ + + +// +// Mark a HIGHADJ entry as needing an increment if reprocessing. +// +#define LDRP_RELOCATION_INCREMENT 0x1 + +// +// Mark a HIGHADJ entry as not suitable for reprocessing. +// +#define LDRP_RELOCATION_FINAL 0x2 + + +/* +#pragma alloc_text(PAGE,LdrRelocateImage) +#pragma alloc_text(PAGE,LdrRelocateImageWithBias) +#pragma alloc_text(PAGE,LdrProcessRelocationBlock) +#pragma alloc_text(PAGE,LdrProcessRelocationBlockLongLong)*/ + +typedef NTSTATUS LDR_RELOCATE_IMAGE_RETURN_TYPE; + +LDR_RELOCATE_IMAGE_RETURN_TYPE +LdrRelocateImage ( + __in PVOID NewBase, + __in LDR_RELOCATE_IMAGE_RETURN_TYPE Success, + __in LDR_RELOCATE_IMAGE_RETURN_TYPE Conflict, + __in LDR_RELOCATE_IMAGE_RETURN_TYPE Invalid + ) +/*++ + +Routine Description: + + This routine relocates an image file that was not loaded into memory + at the preferred address. + +Arguments: + + NewBase - Supplies a pointer to the image base. + + Success - Value to return if relocation successful. + + Conflict - Value to return if can't relocate. + + Invalid - Value to return if relocations are invalid. + +Return Value: + + Success if image is relocated. + Conflict if image can't be relocated. + Invalid if image contains invalid fixups. + +--*/ + +{ + // + // Just call LdrRelocateImageWithBias() with a zero bias. + // + return LdrRelocateImageWithBias( NewBase, 0, Success, Conflict, Invalid ); +} + + +LDR_RELOCATE_IMAGE_RETURN_TYPE +LdrRelocateImageWithBias ( + __in PVOID NewBase, + __in LONGLONG AdditionalBias, + __in LDR_RELOCATE_IMAGE_RETURN_TYPE Success, + __in LDR_RELOCATE_IMAGE_RETURN_TYPE Conflict, + __in LDR_RELOCATE_IMAGE_RETURN_TYPE Invalid + ) +/*++ + +Routine Description: + + This routine relocates an image file that was not loaded into memory + at the preferred address. + +Arguments: + + NewBase - Supplies a pointer to the image base. + + AdditionalBias - An additional quantity to add to all fixups. The + 32-bit X86 loader uses this when loading 64-bit images + to specify a NewBase that is actually a 64-bit value. + + Success - Value to return if relocation successful. + + Conflict - Value to return if can't relocate. + + Invalid - Value to return if relocations are invalid. + +Return Value: + + Success if image is relocated. + Conflict if image can't be relocated. + Invalid if image contains invalid fixups. + +--*/ + +{ + LONGLONG Diff; + ULONG TotalCountBytes = 0; + ULONG_PTR VA; + ULONGLONG OldBase; + ULONG SizeOfBlock; + PUSHORT NextOffset = NULL; + PIMAGE_NT_HEADERS NtHeaders; + PIMAGE_BASE_RELOCATION NextBlock; + LDR_RELOCATE_IMAGE_RETURN_TYPE Status; + + NtHeaders = RtlImageNtHeader( NewBase ); + if (NtHeaders == NULL) { + Status = Invalid; + goto Exit; + } + + switch (NtHeaders->OptionalHeader.Magic) { + + case IMAGE_NT_OPTIONAL_HDR32_MAGIC: + + OldBase = + ((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.ImageBase; + break; + + case IMAGE_NT_OPTIONAL_HDR64_MAGIC: + + OldBase = + ((PIMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.ImageBase; + break; + + default: + + Status = Invalid; + goto Exit; + } + + // + // Locate the relocation section. + // + + NextBlock = (PIMAGE_BASE_RELOCATION)RtlImageDirectoryEntryToData( + NewBase, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &TotalCountBytes); + + // + // It is possible for a file to have no relocations, but the relocations + // must not have been stripped. + // + + if (!NextBlock || !TotalCountBytes) + { + Status = (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) ? Conflict : Success; + goto Exit; + } + + // + // If the image has a relocation table, then apply the specified fixup + // information to the image. + // + Diff = (ULONG_PTR)NewBase - OldBase + AdditionalBias; + while (TotalCountBytes) + { + SizeOfBlock = NextBlock->SizeOfBlock; + + // Prevent crash + if (SizeOfBlock == 0) + { + Status = Invalid; + goto Exit; + } + + TotalCountBytes -= SizeOfBlock; + SizeOfBlock -= sizeof(IMAGE_BASE_RELOCATION); + SizeOfBlock /= sizeof(USHORT); + NextOffset = (PUSHORT)((PCHAR)NextBlock + sizeof(IMAGE_BASE_RELOCATION)); + + VA = (ULONG_PTR)NewBase + NextBlock->VirtualAddress; + NextBlock = LdrProcessRelocationBlockLongLong( VA, SizeOfBlock, NextOffset, Diff ); + + if (!NextBlock) + { + Status = Invalid; + goto Exit; + } + } + + Status = Success; +Exit: + return Status; +} + +PIMAGE_BASE_RELOCATION +LdrProcessRelocationBlock( + IN ULONG_PTR VA, + IN ULONG SizeOfBlock, + IN PUSHORT NextOffset, + IN LONG_PTR Diff + ) +{ + PIMAGE_BASE_RELOCATION baseRelocation; + + baseRelocation = LdrProcessRelocationBlockLongLong( VA, SizeOfBlock, NextOffset, (LONGLONG)Diff ); + + return baseRelocation; +} + +// begin_rebase +PIMAGE_BASE_RELOCATION +LdrProcessRelocationBlockLongLong( + IN ULONG_PTR VA, + IN ULONG SizeOfBlock, + IN PUSHORT NextOffset, + IN LONGLONG Diff + ) +{ + PUCHAR FixupVA; + USHORT Offset; + LONG Temp; + //ULONG Temp32; + ULONGLONG Value64; + //LONGLONG Temp64; + + while (SizeOfBlock--) { + + Offset = *NextOffset & (USHORT)0xfff; + FixupVA = (PUCHAR)(VA + Offset); + + // + // Apply the fixups. + // + + switch ((*NextOffset) >> 12) { + + case IMAGE_REL_BASED_HIGHLOW : + // + // HighLow - (32-bits) relocate the high and low half + // of an address. + // + *(LONG UNALIGNED *)FixupVA += (ULONG) Diff; + break; + + case IMAGE_REL_BASED_HIGH : + // + // High - (16-bits) relocate the high half of an address. + // + Temp = *(PUSHORT)FixupVA << 16; + Temp += (ULONG) Diff; + *(PUSHORT)FixupVA = (USHORT)(Temp >> 16); + break; + + case IMAGE_REL_BASED_HIGHADJ : + // + // Adjust high - (16-bits) relocate the high half of an + // address and adjust for sign extension of low half. + // + + // + // If the address has already been relocated then don't + // process it again now or information will be lost. + // + if (Offset & LDRP_RELOCATION_FINAL) { + ++NextOffset; + --SizeOfBlock; + break; + } + + Temp = *(PUSHORT)FixupVA << 16; + ++NextOffset; + --SizeOfBlock; + Temp += (LONG)(*(PSHORT)NextOffset); + Temp += (ULONG) Diff; + Temp += 0x8000; + *(PUSHORT)FixupVA = (USHORT)(Temp >> 16); + + break; + + case IMAGE_REL_BASED_LOW : + // + // Low - (16-bit) relocate the low half of an address. + // + Temp = *(PSHORT)FixupVA; + Temp += (ULONG) Diff; + *(PUSHORT)FixupVA = (USHORT)Temp; + break; + + case IMAGE_REL_BASED_IA64_IMM64: + + // + // Align it to bundle address before fixing up the + // 64-bit immediate value of the movl instruction. + // + + FixupVA = (PUCHAR)((ULONG_PTR)FixupVA & ~(15)); + Value64 = (ULONGLONG)0; + + // + // Extract the lower 32 bits of IMM64 from bundle + // + + /* + EXT_IMM64(Value64, + (PULONG)FixupVA + EMARCH_ENC_I17_IMM7B_INST_WORD_X, + EMARCH_ENC_I17_IMM7B_SIZE_X, + EMARCH_ENC_I17_IMM7B_INST_WORD_POS_X, + EMARCH_ENC_I17_IMM7B_VAL_POS_X); + EXT_IMM64(Value64, + (PULONG)FixupVA + EMARCH_ENC_I17_IMM9D_INST_WORD_X, + EMARCH_ENC_I17_IMM9D_SIZE_X, + EMARCH_ENC_I17_IMM9D_INST_WORD_POS_X, + EMARCH_ENC_I17_IMM9D_VAL_POS_X); + EXT_IMM64(Value64, + (PULONG)FixupVA + EMARCH_ENC_I17_IMM5C_INST_WORD_X, + EMARCH_ENC_I17_IMM5C_SIZE_X, + EMARCH_ENC_I17_IMM5C_INST_WORD_POS_X, + EMARCH_ENC_I17_IMM5C_VAL_POS_X); + EXT_IMM64(Value64, + (PULONG)FixupVA + EMARCH_ENC_I17_IC_INST_WORD_X, + EMARCH_ENC_I17_IC_SIZE_X, + EMARCH_ENC_I17_IC_INST_WORD_POS_X, + EMARCH_ENC_I17_IC_VAL_POS_X); + EXT_IMM64(Value64, + (PULONG)FixupVA + EMARCH_ENC_I17_IMM41a_INST_WORD_X, + EMARCH_ENC_I17_IMM41a_SIZE_X, + EMARCH_ENC_I17_IMM41a_INST_WORD_POS_X, + EMARCH_ENC_I17_IMM41a_VAL_POS_X); + + EXT_IMM64(Value64, + ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41b_INST_WORD_X), + EMARCH_ENC_I17_IMM41b_SIZE_X, + EMARCH_ENC_I17_IMM41b_INST_WORD_POS_X, + EMARCH_ENC_I17_IMM41b_VAL_POS_X); + EXT_IMM64(Value64, + ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41c_INST_WORD_X), + EMARCH_ENC_I17_IMM41c_SIZE_X, + EMARCH_ENC_I17_IMM41c_INST_WORD_POS_X, + EMARCH_ENC_I17_IMM41c_VAL_POS_X); + EXT_IMM64(Value64, + ((PULONG)FixupVA + EMARCH_ENC_I17_SIGN_INST_WORD_X), + EMARCH_ENC_I17_SIGN_SIZE_X, + EMARCH_ENC_I17_SIGN_INST_WORD_POS_X, + EMARCH_ENC_I17_SIGN_VAL_POS_X); + // + // Update 64-bit address + // + + Value64+=Diff; + + // + // Insert IMM64 into bundle + // + + INS_IMM64(Value64, + ((PULONG)FixupVA + EMARCH_ENC_I17_IMM7B_INST_WORD_X), + EMARCH_ENC_I17_IMM7B_SIZE_X, + EMARCH_ENC_I17_IMM7B_INST_WORD_POS_X, + EMARCH_ENC_I17_IMM7B_VAL_POS_X); + INS_IMM64(Value64, + ((PULONG)FixupVA + EMARCH_ENC_I17_IMM9D_INST_WORD_X), + EMARCH_ENC_I17_IMM9D_SIZE_X, + EMARCH_ENC_I17_IMM9D_INST_WORD_POS_X, + EMARCH_ENC_I17_IMM9D_VAL_POS_X); + INS_IMM64(Value64, + ((PULONG)FixupVA + EMARCH_ENC_I17_IMM5C_INST_WORD_X), + EMARCH_ENC_I17_IMM5C_SIZE_X, + EMARCH_ENC_I17_IMM5C_INST_WORD_POS_X, + EMARCH_ENC_I17_IMM5C_VAL_POS_X); + INS_IMM64(Value64, + ((PULONG)FixupVA + EMARCH_ENC_I17_IC_INST_WORD_X), + EMARCH_ENC_I17_IC_SIZE_X, + EMARCH_ENC_I17_IC_INST_WORD_POS_X, + EMARCH_ENC_I17_IC_VAL_POS_X); + INS_IMM64(Value64, + ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41a_INST_WORD_X), + EMARCH_ENC_I17_IMM41a_SIZE_X, + EMARCH_ENC_I17_IMM41a_INST_WORD_POS_X, + EMARCH_ENC_I17_IMM41a_VAL_POS_X); + INS_IMM64(Value64, + ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41b_INST_WORD_X), + EMARCH_ENC_I17_IMM41b_SIZE_X, + EMARCH_ENC_I17_IMM41b_INST_WORD_POS_X, + EMARCH_ENC_I17_IMM41b_VAL_POS_X); + INS_IMM64(Value64, + ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41c_INST_WORD_X), + EMARCH_ENC_I17_IMM41c_SIZE_X, + EMARCH_ENC_I17_IMM41c_INST_WORD_POS_X, + EMARCH_ENC_I17_IMM41c_VAL_POS_X); + INS_IMM64(Value64, + ((PULONG)FixupVA + EMARCH_ENC_I17_SIGN_INST_WORD_X), + EMARCH_ENC_I17_SIGN_SIZE_X, + EMARCH_ENC_I17_SIGN_INST_WORD_POS_X, + EMARCH_ENC_I17_SIGN_VAL_POS_X); + */ + break; + + case IMAGE_REL_BASED_DIR64: + + *(ULONGLONG UNALIGNED *)FixupVA += Diff; + + break; + + case IMAGE_REL_BASED_MIPS_JMPADDR : + // + // JumpAddress - (32-bits) relocate a MIPS jump address. + // + Temp = (*(PULONG)FixupVA & 0x3ffffff) << 2; + Temp += (ULONG) Diff; + *(PULONG)FixupVA = (*(PULONG)FixupVA & ~0x3ffffff) | + ((Temp >> 2) & 0x3ffffff); + + break; + + case IMAGE_REL_BASED_ABSOLUTE : + // + // Absolute - no fixup required. + // + break; + + case IMAGE_REL_BASED_SECTION : + // + // Section Relative reloc. Ignore for now. + // + break; + + case IMAGE_REL_BASED_REL32 : + // + // Relative intrasection. Ignore for now. + // + break; + + default : + // + // Illegal - illegal relocation type. + // + + return (PIMAGE_BASE_RELOCATION)NULL; + } + ++NextOffset; + } + return (PIMAGE_BASE_RELOCATION)NextOffset; +} + +// end_rebase + diff --git a/third/Blackbone/src/BlackBoneTest/BlackBoneTest.vcxproj b/third/Blackbone/src/BlackBoneTest/BlackBoneTest.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..9018d19874a71e90310856c1a84c646e96fd7b0f --- /dev/null +++ b/third/Blackbone/src/BlackBoneTest/BlackBoneTest.vcxproj @@ -0,0 +1,339 @@ + + + + + Debug(DLL) + Win32 + + + Debug(DLL) + x64 + + + Debug + Win32 + + + Release(DLL) + Win32 + + + Release(DLL) + x64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {15F6F215-4A5E-4B57-B0A0-90B067111285} + Win32Proj + Testing + 10.0.17763.0 + NativeUnitTestProject + BlackboneTest + + + + DynamicLibrary + true + v141 + Unicode + false + + + DynamicLibrary + true + v141 + Unicode + false + + + DynamicLibrary + false + v141 + true + Unicode + false + + + DynamicLibrary + false + v141 + true + Unicode + false + + + DynamicLibrary + true + v141 + Unicode + false + + + DynamicLibrary + true + v141 + Unicode + false + + + DynamicLibrary + false + v141 + true + Unicode + false + + + DynamicLibrary + false + v141 + true + Unicode + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + + /DCI_BUILD %(AdditionalOptions) + + + + + Level3 + Disabled + $(ProjectDir)..;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;%(PreprocessorDefinitions) + true + stdcpplatest + + + Windows + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Level3 + Disabled + $(ProjectDir)..;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;%(PreprocessorDefinitions);BLACKBONE_IMPORTS + true + stdcpplatest + + + Windows + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Level3 + Disabled + $(ProjectDir)..;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + _DEBUG;%(PreprocessorDefinitions) + true + stdcpplatest + + + Windows + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Level3 + Disabled + $(ProjectDir)..;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + _DEBUG;%(PreprocessorDefinitions);BLACKBONE_IMPORTS + true + stdcpplatest + + + Windows + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Level3 + MaxSpeed + true + true + $(ProjectDir)..;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;%(PreprocessorDefinitions) + true + stdcpplatest + MultiThreaded + + + Windows + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Level3 + MaxSpeed + true + true + $(ProjectDir)..;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;%(PreprocessorDefinitions);BLACKBONE_IMPORTS + true + stdcpplatest + MultiThreaded + + + Windows + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Level3 + MaxSpeed + true + true + $(ProjectDir)..;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + NDEBUG;%(PreprocessorDefinitions) + true + stdcpplatest + MultiThreaded + + + Windows + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Level3 + MaxSpeed + true + true + $(ProjectDir)..;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + NDEBUG;%(PreprocessorDefinitions);BLACKBONE_IMPORTS + true + stdcpplatest + MultiThreaded + + + Windows + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + + + + + + {a2c53563-46f5-4d87-903f-3f1f2fdb2deb} + + + + + + \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneTest/BlackBoneTest.vcxproj.filters b/third/Blackbone/src/BlackBoneTest/BlackBoneTest.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..62d9fcd252d83181bd208ea06caf8b2469967597 --- /dev/null +++ b/third/Blackbone/src/BlackBoneTest/BlackBoneTest.vcxproj.filters @@ -0,0 +1,49 @@ + + + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + + + + + + {b5cc080f-5ea5-4f14-b732-c1aaf61443c8} + + + \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneTest/Common.h b/third/Blackbone/src/BlackBoneTest/Common.h new file mode 100644 index 0000000000000000000000000000000000000000..5f632d983d5e89073d8b2249006c2e2bbee95970 --- /dev/null +++ b/third/Blackbone/src/BlackBoneTest/Common.h @@ -0,0 +1,101 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; +using namespace blackbone; + +constexpr wchar_t* ModuleName = L"BlackBoneTest.dll"; + +/// +/// Some extensions for Assert +/// +class AssertEx : public Assert +{ +public: + template + static void IsZero( const T& actual, const wchar_t* message = nullptr, const __LineInfo* pLineInfo = nullptr ) + { + AssertEx::AreEqual( T( 0 ), actual, message, pLineInfo ); + } + + template + static void IsNotZero( const T& actual, const wchar_t* message = nullptr, const __LineInfo* pLineInfo = nullptr ) + { + AssertEx::AreNotEqual( T( 0 ), actual, message, pLineInfo ); + } + + static void NtSuccess( NTSTATUS status, const wchar_t* message = nullptr, const __LineInfo* pLineInfo = nullptr ) + { + AssertEx::IsTrue( status >= 0, message, pLineInfo ); + } +}; + +namespace Microsoft::VisualStudio::CppUnitTestFramework { + template<> inline std::wstring ToString( const AsmVariant::eType& t ) { RETURN_WIDE_STRING( t ); } +} + +inline std::wstring GetTestHelperDir() +{ + wchar_t buf[MAX_PATH] = { }; + GetModuleFileNameW( GetModuleHandle( ModuleName ), buf, _countof( buf ) ); + std::wstring path = buf; + if (path.empty()) + return path; + + // Get project root path + for (int i = 0; i < 4; i++) + path = Utils::GetParent( path ); + + return path + L"\\Testing"; +} + +inline std::wstring GetTestHelperHost32() +{ + return GetTestHelperDir() + L"\\TestHelper32.exe"; +} + +inline std::wstring GetTestHelperHost64() +{ + return GetTestHelperDir() + L"\\TestHelper64.exe"; +} + +inline std::wstring GetTestHelperHost() +{ +#ifdef USE64 + return GetTestHelperHost64(); +#else + return GetTestHelperHost32(); +#endif +} + +inline std::wstring GetTestHelperDll32() +{ + return GetTestHelperDir() + L"\\TestDll32.dll"; +} + +inline std::wstring GetTestHelperDll64() +{ + return GetTestHelperDir() + L"\\TestDll64.dll"; +} + +inline std::wstring GetTestHelperDll() +{ +#ifdef USE64 + return GetTestHelperDll64(); +#else + return GetTestHelperDll32(); +#endif +} diff --git a/third/Blackbone/src/BlackBoneTest/TestAsmJit.cpp b/third/Blackbone/src/BlackBoneTest/TestAsmJit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..46f3f2e77f5a0c134cf2d8b3aabd948e21176c03 --- /dev/null +++ b/third/Blackbone/src/BlackBoneTest/TestAsmJit.cpp @@ -0,0 +1,92 @@ +#include "Common.h" + +namespace Microsoft::VisualStudio::CppUnitTestFramework { + template<> inline std::wstring ToString<__int64>( const __int64& t ) { RETURN_WIDE_STRING( t ); } +} + +namespace Testing +{ + TEST_CLASS( AsmJIT ) + { + public: + TEST_METHOD( Add ) + { + auto asmPtr = AsmFactory::GetAssembler(); + auto& a = *asmPtr; + + a.GenPrologue(); + a->add( a->zcx, a->zdx ); + a->mov( a->zax, a->zcx ); + a.GenEpilogue(); + + auto func = reinterpret_cast(a->make()); + + AssertEx::AreEqual( intptr_t( 15 ), func( 10, 5 ) ); + AssertEx::AreEqual( intptr_t( 5 ), func( 10, -5 ) ); + } + + TEST_METHOD( Call ) + { + auto asmPtr = AsmFactory::GetAssembler(); + auto& a = *asmPtr; + + wchar_t buf[MAX_PATH] = { }; + + a.GenPrologue(); + a.GenCall( reinterpret_cast(&GetModuleHandle), { ModuleName } ); + a.GenCall( reinterpret_cast(&GetModuleFileNameW), { a->zax, buf, _countof( buf ) } ); + a.GenEpilogue(); + + auto func = reinterpret_cast(a->make()); + func(); + + std::wstring name = Utils::ToLower( buf ); + AssertEx::AreNotEqual( name.npos, name.rfind( Utils::ToLower( ModuleName ) ) ); + } + + TEST_METHOD( MultiCall ) + { + auto asmPtr = AsmFactory::GetAssembler(); + auto& a = *asmPtr; + + a.EnableX64CallStack( false ); + auto skip = a->newLabel(); + + uint8_t writeBuf[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + auto filePath = L"DummyFile_MultiCall.dat"; + DWORD bytes = 0; + + AsmStackAllocator stack( a.assembler() ); + ALLOC_STACK_VAR( stack, handle, HANDLE ); + + a.GenPrologue(); + a->sub( a->zsp, 0x48 ); + a.GenCall( reinterpret_cast(&CreateFileW), { a->zcx, GENERIC_WRITE, 0x7, nullptr, CREATE_ALWAYS, 0, nullptr } ); + a->mov( handle, a->zax ); + a->cmp( a->zax, reinterpret_cast(INVALID_HANDLE_VALUE) ); + a->je( skip ); + a.GenCall( reinterpret_cast(&WriteFile), { handle, writeBuf, sizeof( writeBuf ), &bytes, nullptr } ); + a->test( a->zax, a->zax ); + a->jz( skip ); + a.GenCall( reinterpret_cast(&CloseHandle), { handle } ); + a->bind( skip ); + a->add( a->zsp, 0x48 ); + a.GenEpilogue(); + + auto func = reinterpret_cast(a->make()); + BOOL b = func( filePath ); + AssertEx::IsTrue( b ); + + // Check locally + FileHandle hFile = FileHandle( CreateFileW( filePath, GENERIC_READ, 0x7, nullptr, OPEN_EXISTING, FILE_DELETE_ON_CLOSE, nullptr ) ); + AssertEx::IsTrue( hFile ); + + uint8_t readBuf[sizeof( writeBuf )] = { }; + b = ReadFile( hFile, readBuf, sizeof( readBuf ), &bytes, nullptr ); + + AssertEx::IsTrue( b ); + AssertEx::AreEqual( static_cast(sizeof( readBuf )), bytes ); + AssertEx::IsZero( memcmp( writeBuf, readBuf, sizeof( readBuf ) ) ); + } + }; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneTest/TestAsmVariant.cpp b/third/Blackbone/src/BlackBoneTest/TestAsmVariant.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1e441687e3177895c40a38c43e06c8daeaf86ecc --- /dev/null +++ b/third/Blackbone/src/BlackBoneTest/TestAsmVariant.cpp @@ -0,0 +1,242 @@ +#include "Common.h" + + +namespace Testing +{ + struct IntStruct + { + int16_t ival = 10; + }; + + struct PairStruct + { + int64_t ival = 20; + float fval = 24.0f; + }; + + TEST_CLASS( AsmVariantTest ) + { + public: + TEST_CLASS_INITIALIZE( Init ) + { + Logger::WriteMessage( "" ); + } + + TEST_METHOD( IntRvalue ) + { + AsmVariant a( 1 ); + + AssertEx::AreEqual( AsmVariant::imm, a.type ); + AssertEx::AreEqual( sizeof( 1 ), a.size ); + AssertEx::AreEqual( 1ull, a.imm_val64 ); + } + + TEST_METHOD( IntLvalue ) + { + const int int_val = 2; + AsmVariant a( int_val ); + + AssertEx::AreEqual( AsmVariant::imm, a.type ); + AssertEx::AreEqual( sizeof( int_val ), a.size ); + AssertEx::AreEqual( static_cast(int_val), a.imm_val64 ); + } + + TEST_METHOD( EnumChar ) + { + enum e1 : char + { + e1_val0 = 3, + }; + + AsmVariant a( e1_val0 ); + + AssertEx::AreEqual( AsmVariant::imm, a.type ); + AssertEx::AreEqual( sizeof( e1_val0 ), a.size ); + AssertEx::AreEqual( uint64_t( e1_val0 ), a.imm_val64 ); + } + + TEST_METHOD( EnumUshort ) + { + enum class ec : unsigned short + { + ec_val0 = 4, + }; + + AsmVariant a( ec::ec_val0 ); + + AssertEx::AreEqual( AsmVariant::imm, a.type ); + AssertEx::AreEqual( sizeof( ec::ec_val0 ), a.size ); + AssertEx::AreEqual( static_cast(ec::ec_val0), a.imm_val64 ); + } + + TEST_METHOD( Float ) + { + AsmVariant a( 2.0f ); + + AssertEx::AreEqual( AsmVariant::imm_float, a.type ); + AssertEx::AreEqual( sizeof( float ), a.size ); + AssertEx::AreEqual( 2.0f, a.imm_float_val ); + } + + TEST_METHOD( Double ) + { + AsmVariant a( 3.0 ); + + AssertEx::AreEqual( AsmVariant::imm_double, a.type ); + AssertEx::AreEqual( sizeof( double ), a.size ); + AssertEx::AreEqual( 3.0, a.imm_double_val ); + } + + TEST_METHOD( StringInplace ) + { + AsmVariant a( "Text" ); + + AssertEx::AreEqual( AsmVariant::dataPtr, a.type ); + } + + TEST_METHOD( StringConstPtr ) + { + const char* cstring = "Text"; + AsmVariant a( cstring ); + + AssertEx::AreEqual( AsmVariant::dataPtr, a.type ); + AssertEx::AreEqual( reinterpret_cast(cstring), a.imm_val64 ); + } + + TEST_METHOD( StringArray ) + { + const char str_array[] = "Text"; + AsmVariant a( str_array ); + + AssertEx::AreEqual( AsmVariant::dataPtr, a.type ); + AssertEx::AreEqual( reinterpret_cast(str_array), a.imm_val64 ); + AssertEx::AreEqual( sizeof( str_array ), a.size ); + } + + TEST_METHOD( StringPtr ) + { + const char str_array[] = "Text"; + char* str_ptr = const_cast(str_array); + AsmVariant a( str_ptr ); + + AssertEx::AreEqual( AsmVariant::dataPtr, a.type ); + AssertEx::AreEqual( reinterpret_cast(str_ptr), a.imm_val64 ); + AssertEx::AreEqual( sizeof( str_array ), a.size ); + } + + TEST_METHOD( WStringInplace ) + { + AsmVariant a( L"Text" ); + + AssertEx::AreEqual( AsmVariant::dataPtr, a.type ); + } + + TEST_METHOD( WStringConstPtr ) + { + const wchar_t* cwstring = L"Text"; + AsmVariant a( cwstring ); + + AssertEx::AreEqual( AsmVariant::dataPtr, a.type ); + AssertEx::AreEqual( reinterpret_cast(cwstring), a.imm_val64 ); + } + + TEST_METHOD( WStringArray ) + { + const wchar_t wstr_array[] = L"Text"; + AsmVariant a( wstr_array ); + + AssertEx::AreEqual( a.type, AsmVariant::dataPtr ); + AssertEx::AreEqual( reinterpret_cast(wstr_array), a.imm_val64 ); + AssertEx::AreEqual( sizeof( wstr_array ), a.size ); + } + + TEST_METHOD( WStringPtr ) + { + const wchar_t wstr_array[] = L"Text"; + wchar_t* wstr_ptr = const_cast(wstr_array); + AsmVariant a( wstr_ptr ); + + AssertEx::AreEqual( AsmVariant::dataPtr, a.type ); + AssertEx::AreEqual( reinterpret_cast(wstr_ptr), a.imm_val64 ); + AssertEx::AreEqual( sizeof( wstr_array ), a.size ); + } + + TEST_METHOD( VoidPtr ) + { + const void* vptr = reinterpret_cast(0xDEAD); + AsmVariant a( vptr ); + + AssertEx::AreEqual( a.type, AsmVariant::imm ); + AssertEx::AreEqual( reinterpret_cast(vptr), a.imm_val64 ); + } + + TEST_METHOD( VoidPtrRef ) + { + const void* vptr = reinterpret_cast(0xDEAD); + const auto& vptr_ref = vptr; + + AsmVariant a( vptr_ref ); + + AssertEx::AreEqual( AsmVariant::imm, a.type ); + AssertEx::AreEqual( reinterpret_cast(vptr_ref), a.imm_val64 ); + } + + TEST_METHOD( StructPtrLittle ) + { + IntStruct little; + AsmVariant a( &little ); + + AssertEx::AreEqual( AsmVariant::dataPtr, a.type ); + AssertEx::AreEqual( sizeof( little ), a.size ); + AssertEx::AreEqual( reinterpret_cast(&little), a.imm_val64 ); + } + + TEST_METHOD( StructPtrBig ) + { + PairStruct big; + AsmVariant a( &big ); + + AssertEx::AreEqual( AsmVariant::dataPtr, a.type ); + AssertEx::AreEqual( sizeof( big ), a.size ); + AssertEx::AreEqual( reinterpret_cast(&big), a.imm_val64 ); + } + + TEST_METHOD( StructLittle ) + { + IntStruct little; + AsmVariant a( little ); + + AssertEx::AreEqual( AsmVariant::imm, a.type ); + AssertEx::AreEqual( sizeof( little ), a.size ); + AssertEx::AreEqual( 0, memcmp( &little, &a.imm_val64, sizeof( little ) ) ); + } + + TEST_METHOD( StructBig ) + { + PairStruct big; + AsmVariant a( big ); + + AssertEx::AreEqual( AsmVariant::dataStruct, a.type ); + AssertEx::AreEqual( sizeof( big ), a.size ); + AssertEx::AreEqual( 0, memcmp( &big, a.buf.data(), sizeof( big ) ) ); + } + + TEST_METHOD( FunctionPtr ) + { + AsmVariant a( &GetCurrentProcessId ); + + AssertEx::AreEqual( AsmVariant::imm, a.type ); + AssertEx::AreEqual( reinterpret_cast(&GetCurrentProcessId), a.imm_val64 ); + } + + TEST_METHOD( StructSlice ) + { + PairStruct big; + AsmVariant a( &big, 10 ); + + AssertEx::AreEqual( AsmVariant::dataPtr, a.type ); + AssertEx::AreEqual( size_t( 10 ), a.size ); + AssertEx::AreEqual( reinterpret_cast(&big), a.imm_val64 ); + } + }; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneTest/TestBasic.cpp b/third/Blackbone/src/BlackBoneTest/TestBasic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e1d92237aa6a45c92e6409a931e118d76d02942e --- /dev/null +++ b/third/Blackbone/src/BlackBoneTest/TestBasic.cpp @@ -0,0 +1,82 @@ +#include "Common.h" + +namespace Testing +{ + TEST_MODULE_INITIALIZE( ModuleInit ) + { + InitializeOnce(); + } + + TEST_CLASS( Generic ) + { + public: + TEST_METHOD_INITIALIZE( ClassInitialize ) + { + AssertEx::NtSuccess( _proc.Attach( GetCurrentProcessId() ) ); + } + + TEST_METHOD( PEB ) + { + _PEB32 peb32 = { }; + _PEB64 peb64 = { }; + + auto ppeb32 = _proc.core().peb32( &peb32 ); + auto ppeb64 = _proc.core().peb64( &peb64 ); + + AssertEx::IsNotZero( ppeb64 ); + AssertEx::IsNotZero( peb64.Ldr ); + + if (_proc.barrier().targetWow64) + { + AssertEx::IsNotZero( ppeb32 ); + AssertEx::IsNotZero( peb32.Ldr ); + } + } + + TEST_METHOD( TEB ) + { + _TEB32 teb32 = { }; + _TEB64 teb64 = { }; + + auto pteb32 = _proc.threads().getMain()->teb( &teb32 ); + auto pteb64 = _proc.threads().getMain()->teb( &teb64 ); + + AssertEx::IsNotZero( pteb64 ); + AssertEx::IsNotZero( teb64.ClientId.UniqueThread ); + + if (_proc.barrier().targetWow64) + { + AssertEx::IsNotZero( pteb32 ); + AssertEx::IsNotZero( teb32.ClientId.UniqueThread ); + AssertEx::IsNotZero( teb32.ClientId.UniqueThread ); + } + } + + static DWORD CALLBACK VoidFn( void* ) + { + return 0; + } + + TEST_METHOD( InvalidHandles ) + { + Process proc; + + HANDLE hProc = OpenProcess( PROCESS_ALL_ACCESS & ~PROCESS_CREATE_THREAD, FALSE, GetCurrentProcessId() ); + + AssertEx::NtSuccess( proc.Attach( hProc ) ); + AssertEx::AreEqual( STATUS_ACCESS_DENIED, proc.threads().CreateNew( reinterpret_cast(&VoidFn), 0 ).status ); + proc.Detach(); + + hProc = OpenProcess( PROCESS_ALL_ACCESS & ~PROCESS_VM_READ, FALSE, GetCurrentProcessId() ); + AssertEx::NtSuccess( proc.Attach( hProc ) ); + + PEB_T peb = { }; + AssertEx::IsNotZero( proc.core().peb( &peb ) ); + AssertEx::IsZero( peb.ImageBaseAddress ); + AssertEx::AreEqual( STATUS_ACCESS_DENIED, LastNtStatus() ); + } + + private: + Process _proc; + }; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneTest/TestDriver.cpp b/third/Blackbone/src/BlackBoneTest/TestDriver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d44f8be4f6e448c79a3745cc579e8b0aedb99333 --- /dev/null +++ b/third/Blackbone/src/BlackBoneTest/TestDriver.cpp @@ -0,0 +1,144 @@ +#include "Common.h" + +namespace Testing +{ + TEST_CLASS( DriverTest ) + { +#ifdef CI_BUILD +#define CHECK_AND_SKIP + BEGIN_TEST_CLASS_ATTRIBUTE() + TEST_CLASS_ATTRIBUTE( L"Ignore", L"true" ) + END_TEST_CLASS_ATTRIBUTE() +#else +#define CHECK_AND_SKIP if(_mustSkip) return +#endif + + public: + TEST_METHOD_INITIALIZE( ClassInitialize ) + { + AssertEx::NtSuccess( _explorer.Attach( L"explorer.exe" ) ); + NTSTATUS status = Driver().EnsureLoaded(); + if (!NT_SUCCESS( status )) + { + _mustSkip = status == STATUS_OBJECT_NAME_NOT_FOUND; + } + } + + TEST_METHOD( DEP ) + { + CHECK_AND_SKIP; + + // Disable DEP, x86 only; + if (_explorer.barrier().targetWow64) + { + DWORD depFlags = 0; + BOOL perm = FALSE; + + NTSTATUS status = Driver().DisableDEP( GetCurrentProcessId() ); + SAFE_CALL( GetProcessDEPPolicy, GetCurrentProcess(), &depFlags, &perm ); + + AssertEx::NtSuccess( status ); + AssertEx::IsZero( depFlags & PROCESS_DEP_ENABLE ); + } + } + + TEST_METHOD( ProtectProcess ) + { + CHECK_AND_SKIP; + + Process thisProc; + AssertEx::NtSuccess( thisProc.Attach( GetCurrentProcessId() ) ); + + // Make current process protected + AssertEx::NtSuccess( Driver().ProtectProcess( GetCurrentProcessId(), Policy_Enable ) ); + AssertEx::IsTrue( thisProc.core().isProtected() ); + + Driver().ProtectProcess( GetCurrentProcessId(), Policy_Disable ); + } + + TEST_METHOD( PromoteHandle ) + { + CHECK_AND_SKIP; + + // Grant explorer.exe handle full access + NTSTATUS status = Driver().PromoteHandle( GetCurrentProcessId(), _explorer.core().handle(), PROCESS_ALL_ACCESS ); + AssertEx::NtSuccess( status ); + + PUBLIC_OBJECT_BASIC_INFORMATION info = { }; + ULONG sz = 0; + status = SAFE_CALL( NtQueryObject, _explorer.core().handle(), ObjectBasicInformation, &info, static_cast(sizeof( info )), &sz ); + + AssertEx::NtSuccess( status ); + AssertEx::AreEqual( ACCESS_MASK( PROCESS_ALL_ACCESS ), info.GrantedAccess ); + } + + TEST_METHOD( ReadMemory ) + { + CHECK_AND_SKIP; + + uint8_t buf[0x1000] = { }; + + // Read explorer.exe PE header + auto address = _explorer.modules().GetMainModule()->baseAddress; + ptr_t size = 0x1000; + + AssertEx::NtSuccess( Driver().ReadMem( _explorer.pid(), address, size, buf ) ); + AssertEx::AreEqual( static_cast(IMAGE_DOS_SIGNATURE), *reinterpret_cast(buf) ); + } + + TEST_METHOD( AllocateMemory ) + { + CHECK_AND_SKIP; + + ptr_t size = 0x1000; + auto address = _explorer.modules().GetMainModule()->baseAddress; + + // Allocate some memory + ptr_t address2 = 0; + AssertEx::NtSuccess( Driver().AllocateMem( _explorer.pid(), address2, size, MEM_COMMIT, PAGE_READWRITE ) ); + + Driver().FreeMem( _explorer.pid(), address2, size, MEM_RELEASE ); + } + + TEST_METHOD( ProtectMemory ) + { + CHECK_AND_SKIP; + + MEMORY_BASIC_INFORMATION64 memInfo = { }; + auto address = _explorer.modules().GetMainModule()->baseAddress; + + // Make explorer.exe PE header writable + NTSTATUS status = Driver().ProtectMem( _explorer.pid(), address, 0x1000, PAGE_READWRITE ); + _explorer.memory().Query( address, &memInfo ); + + AssertEx::NtSuccess( status ); + AssertEx::IsNotZero( memInfo.Protect & (PAGE_READWRITE | PAGE_WRITECOPY) ); + + _explorer.memory().Protect( address, 0x1000, PAGE_READONLY ); + } + + TEST_METHOD( UnlinkHandleTable ) + { + CHECK_AND_SKIP; + + // Unlink handle table + //CHECK_NT_SUCCESS( status = Driver().UnlinkHandleTable( proc.pid() ) ); + } + + TEST_METHOD( EnumRegions ) + { + CHECK_AND_SKIP; + + // Enum regions + std::vector info; + + AssertEx::NtSuccess( Driver().EnumMemoryRegions( _explorer.pid(), info ) ); + AssertEx::IsNotZero( info.size() ); + } + + private: + Process _explorer; + bool _mustSkip = false; + }; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneTest/TestLocalHook.cpp b/third/Blackbone/src/BlackBoneTest/TestLocalHook.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e73bbbcef3a0cded246d20adebbf910f6e7d1f6 --- /dev/null +++ b/third/Blackbone/src/BlackBoneTest/TestLocalHook.cpp @@ -0,0 +1,160 @@ +#include "Common.h" + +namespace Testing +{ + class TestClassBase + { + public: + int Test( int a, int b, int c ) + { + return a + b + c - junk; + } + + virtual int Vfunc( int a, int b ) + { + return a + b - junk; + } + + public: + int junk = 32; + }; + + class TestClassChild : public TestClassBase + { + public: + int __declspec(noinline) Test( int a, int b, int c ) + { + return TestClassBase::Test( a, b, c ); + } + + virtual int Vfunc( int a, int b ) + { + return 2 * (a + b) - junk; + } + + public: + int junk = 64; + }; + + class MyMook + { + public: + BOOL hkCloseHandle( HANDLE& /*hObj*/ ) + { + closedHandels++; + return TRUE; + } + + int hkTest( void*& _this, int&, int&, int& ) + { + reinterpret_cast(_this)->junk = 52; + return 0; + } + + int hkVFunc( void*& _this, int&, int& ) + { + reinterpret_cast(_this)->junk = 48; + return 0; + } + + inline int handles() const { return closedHandels; } + + private: + int junk = 16; + int closedHandels = 0; + }; + + void __declspec(noinline) __fastcall TestFastcall( int& a1, float ) + { + a1 = a1 * 3; + } + + void __fastcall hkTestFastcall( int& a1, float& ) + { + a1 /= 2; + } + + int __stdcall hkTest( void*& _this, int& a1, int&, int& ) + { + reinterpret_cast(_this)->junk = 72; + a1 /= 2; + + return 5; + } + + TEST_CLASS( LocalHook ) + { +#if !defined(USE64) || defined(DEBUG) + BEGIN_TEST_CLASS_ATTRIBUTE() + TEST_CLASS_ATTRIBUTE( L"Ignore", L"true" ) + END_TEST_CLASS_ATTRIBUTE() +#endif + public: + TEST_METHOD_INITIALIZE( ClassInitialize ) + { + // Validate preconditions + AssertEx::AreEqual( 64, testClass.junk ); + AssertEx::AreEqual( 32, pTCBase->junk ); + AssertEx::AreEqual( args[0] + args[1] + args[2] - pTCBase->junk, testClass.Test( args[0], args[1], args[2] )); + AssertEx::AreEqual( 2 * (args[0] + args[1]) - testClass.junk, testClass.Vfunc( args[0], args[1] ) ); + } + + TEST_METHOD( HookHWBP ) + { + MyMook target; + Detour hook; + + AssertEx::IsTrue( hook.Hook( &CloseHandle, &MyMook::hkCloseHandle, &target, HookType::HWBP ) ); + + Process proc; + proc.Attach( GetCurrentProcessId() ); + proc.Detach(); + + AssertEx::IsTrue( target.handles() > 0 ); + } + + TEST_METHOD( HookInline ) + { + MyMook target; + Detour hook; + + AssertEx::IsTrue( hook.Hook( &TestFastcall, &hkTestFastcall, HookType::Inline ) ); + + int a = args[0]; + TestFastcall( a, 5.5f ); + + AssertEx::AreEqual( (args[0] / 2) * 3, a ); + } + + TEST_METHOD( HookInt3 ) + { + auto ptr = brutal_cast(&TestClassBase::Test); + Detour hook; + + AssertEx::IsTrue( hook.Hook( ptr, &hkTest, HookType::Int3 ) ); + + auto val = testClass.Test( args[0], args[1], args[2] ); + + AssertEx::AreEqual( 72, pTCBase->junk ); + AssertEx::AreEqual( args[0] / 2 + args[1] + args[2] - pTCBase->junk, val ); + } + + TEST_METHOD( HookVtable ) + { + MyMook target; + VTableDetour hook; + + AssertEx::IsTrue( hook.Hook( reinterpret_cast(&testClass), 0, &MyMook::hkVFunc, &target ) ); + + auto val = pTCBase->Vfunc( args[0], args[1] ); + + AssertEx::AreEqual( 48, testClass.junk ); + AssertEx::AreEqual( 2 * (args[0] + args[1]) - testClass.junk, val ); + } + + private: + TestClassChild testClass; + TestClassBase* pTCBase = &testClass; + const int args[3] = { 0x10, 0x20, 0x30 }; + }; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneTest/TestManualMap.cpp b/third/Blackbone/src/BlackBoneTest/TestManualMap.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fde245f88bde3b4436e306a2d3b52e128095c5b0 --- /dev/null +++ b/third/Blackbone/src/BlackBoneTest/TestManualMap.cpp @@ -0,0 +1,151 @@ +#include "Common.h" + +namespace Testing +{ + struct DllLoadData + { + bool initialized = false; + bool deinitialized = false; + bool static_initialized = false; + bool static_thread_initialized = false; + bool static_func_initialized = false; + bool seh_internal = false; + bool seh_external = false; + bool ceh_internal = false; + bool ceh_external = false; + bool ceh_uncaught = false; + }; + + TEST_CLASS( ManualMapping ) + { + public: + TEST_CLASS_INITIALIZE( Initialize ) + { + nativeMods.emplace( L"combase.dll" ); + nativeMods.emplace( L"user32.dll" ); + + modList.emplace( L"windows.storage.dll" ); + modList.emplace( L"shell32.dll" ); + modList.emplace( L"shlwapi.dll" ); + } + + static LoadData MapCallback( CallbackType type, void* /*context*/, Process& /*process*/, const ModuleData& modInfo ) + { + if (type == PreCallback) + { + if (nativeMods.count( modInfo.name )) + return LoadData( MT_Native, Ldr_None ); + } + else + { + if (modList.count( modInfo.name )) + return LoadData( MT_Default, Ldr_ModList ); + } + + return LoadData( MT_Default, Ldr_None ); + }; + + TEST_METHOD( FromFile32 ) + { + MapFromFile( GetTestHelperHost32(), GetTestHelperDll32() ); + } + + TEST_METHOD( FromFile64 ) + { + MapFromFile( GetTestHelperHost64(), GetTestHelperDll64() ); + } + + TEST_METHOD( FromMemory32 ) + { + MapFromMemory( GetTestHelperHost32(), GetTestHelperDll32() ); + } + + TEST_METHOD( FromMemory64 ) + { + MapFromMemory( GetTestHelperHost64(), GetTestHelperDll64() ); + } + + private: + void MapFromFile( const std::wstring& hostPath, const std::wstring& dllPath ) + { + Process proc; + NTSTATUS status = proc.CreateAndAttach( hostPath ); + AssertEx::NtSuccess( status ); + proc.EnsureInit(); + + auto image = proc.mmap().MapImage( dllPath, ManualImports, &MapCallback ); + AssertEx::IsTrue( image.success() ); + AssertEx::IsNotNull( image.result().get() ); + + auto g_loadDataPtr = proc.modules().GetExport( image.result(), "g_LoadData" ); + AssertEx::IsTrue( g_loadDataPtr.success() ); + AssertEx::IsNotZero( g_loadDataPtr->procAddress ); + + auto g_loadData = proc.memory().Read( g_loadDataPtr->procAddress ); + AssertEx::IsTrue( g_loadData.success() ); + + proc.Terminate(); + + ValidateDllLoad( g_loadData.result() ); + } + + void MapFromMemory( const std::wstring& hostPath, const std::wstring& dllPath ) + { + auto[buf, size] = GetFileData( dllPath ); + AssertEx::IsNotZero( size ); + + Process proc; + NTSTATUS status = proc.CreateAndAttach( hostPath ); + AssertEx::NtSuccess( status ); + proc.EnsureInit(); + + auto image = proc.mmap().MapImage( size, buf.get(), false, ManualImports, &MapCallback ); + AssertEx::IsTrue( image.success() ); + AssertEx::IsNotNull( image.result().get() ); + + auto g_loadDataPtr = proc.modules().GetExport( image.result(), "g_LoadData" ); + AssertEx::IsTrue( g_loadDataPtr.success() ); + AssertEx::IsNotZero( g_loadDataPtr->procAddress ); + + auto g_loadData = proc.memory().Read( g_loadDataPtr->procAddress ); + AssertEx::IsTrue( g_loadData.success() ); + + proc.Terminate(); + + ValidateDllLoad( g_loadData.result() ); + } + + void ValidateDllLoad( const DllLoadData& data ) + { + AssertEx::IsTrue( data.initialized ); + AssertEx::IsFalse( data.deinitialized ); + AssertEx::IsTrue( data.static_initialized ); + AssertEx::IsTrue( data.static_thread_initialized ); + AssertEx::IsTrue( data.static_func_initialized ); + AssertEx::IsFalse( data.seh_internal ); + AssertEx::IsTrue( data.seh_external ); + AssertEx::IsFalse( data.ceh_internal ); + AssertEx::IsTrue( data.ceh_external ); + AssertEx::IsFalse( data.ceh_uncaught ); + } + + std::pair, uint32_t> GetFileData( const std::wstring& path ) + { + auto hFile = FileHandle( CreateFileW( path.c_str(), FILE_GENERIC_READ, 0x7, nullptr, OPEN_EXISTING, 0, nullptr ) ); + if (hFile) + { + uint32_t size = GetFileSize( hFile, nullptr ); + auto buf = std::make_unique( size ); + + DWORD bytes = 0; + if (ReadFile( hFile, buf.get(), size, &bytes, nullptr )) + return std::make_pair( std::move( buf ), size ); + } + + return std::pair, uint32_t>(); + } + + private: + static inline std::set nativeMods, modList; + }; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneTest/TestMultiPtr.cpp b/third/Blackbone/src/BlackBoneTest/TestMultiPtr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bea2cf7d9281ae392aecab71a43066d1597c56d4 --- /dev/null +++ b/third/Blackbone/src/BlackBoneTest/TestMultiPtr.cpp @@ -0,0 +1,114 @@ +#include "Common.h" + +namespace Testing +{ + constexpr intptr_t off[] = { 0x10, 0x20, 0x30 }; + + struct s_end + { + int ival = 74; + float fval = 12.0f; + + virtual int fn1() { return 1; } + virtual int fn2() { return 2; } + virtual int fn3() { return ival + static_cast(fval); } + }; + + struct s1 + { + uint8_t pad[off[2]]; + s_end* pEnd = new s_end(); + }; + + struct s2 + { + uint8_t pad[off[1]]; + s1* pS1 = new s1(); + }; + + struct s3 + { + uint8_t pad[off[0]]; + s2* pS2 = new s2(); + }; + + // stupid C3865 : "'__thiscall' : can only be used on native member functions", even for a type declaration + typedef int( __fastcall* pfnClass )(s_end* _this, void* zdx); + + TEST_CLASS( MultiPtr ) + { + public: + MultiPtr() + : _object( new s3 ) + , _guard( _object ) + , _objectPtr( reinterpret_cast(&_object) ) + { + } + + TEST_METHOD_INITIALIZE( ClassInitialize ) + { + AssertEx::IsNotNull( _guard.get() ); + + auto orig = _guard->pS2->pS1->pEnd->fval; + AssertEx::AreEqual( 12.0f, orig, 0.001f ); + AssertEx::AreEqual( _guard->pS2->pS1->pEnd->ival + static_cast(_guard->pS2->pS1->pEnd->fval), _guard->pS2->pS1->pEnd->fn3() ); + } + + TEST_METHOD( LocalStruct ) + { + multi_ptr struct_ptr( _objectPtr, { off[0], off[1], off[2] } ); + s_end* pEnd = struct_ptr; + + AssertEx::AreEqual( reinterpret_cast(_guard->pS2->pS1->pEnd), reinterpret_cast(pEnd) ); + } + + TEST_METHOD( LocalFloat ) + { + multi_ptr struct_ptr( _objectPtr, { off[0], off[1], off[2] } ); + multi_ptr float_ptr( _objectPtr, { off[0], off[1], off[2], static_cast(offsetOf( &s_end::fval )) } ); + + s_end* pEnd = struct_ptr; + + const float newVal = 15.7f; + *float_ptr = 15.7f; + + AssertEx::AreEqual( pEnd->fval, newVal, 0.001f ); + } + + TEST_METHOD( LocalMethod ) + { + multi_ptr struct_ptr( _objectPtr, { off[0], off[1], off[2] } ); + multi_ptr func_ptr( _objectPtr, { off[0], off[1], off[2], 0, 2 * sizeof( pfnClass ) } ); + + s_end* pEnd = struct_ptr; + + AssertEx::AreEqual( pEnd->ival + static_cast(pEnd->fval), func_ptr( pEnd, nullptr ) ); + } + + TEST_METHOD( Remote ) + { + Process proc; + AssertEx::NtSuccess( proc.Attach( GetCurrentProcessId() ) ); + + const float newVal = 25.0f; + + multi_ptr_ex ptr_ex( &proc, _objectPtr, { off[0], off[1], off[2] } ); + auto pVal_ex = ptr_ex.get(); + AssertEx::IsNotNull( pVal_ex ); + AssertEx::IsNotZero( pVal_ex->fval ); + + pVal_ex->fval = 25.0; + AssertEx::AreEqual( STATUS_SUCCESS, ptr_ex.commit() ); + pVal_ex = ptr_ex.get(); + + AssertEx::IsNotNull( pVal_ex ); + AssertEx::AreEqual( newVal, pVal_ex->fval, 0.001f ); + } + + private: + s3 * _object; + std::unique_ptr _guard; + uintptr_t _objectPtr; + }; + +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneTest/TestPatternScan.cpp b/third/Blackbone/src/BlackBoneTest/TestPatternScan.cpp new file mode 100644 index 0000000000000000000000000000000000000000..db44b7b369890e3b73cf9e5e45c8ee965e57c869 --- /dev/null +++ b/third/Blackbone/src/BlackBoneTest/TestPatternScan.cpp @@ -0,0 +1,39 @@ +#include "Common.h" + +namespace Testing +{ + TEST_CLASS( PatternScan ) + { + public: + TEST_METHOD_INITIALIZE( ClassInitialize ) + { + AssertEx::NtSuccess( _proc.Attach( L"explorer.exe" ) ); + } + + // Scan all allocated process memory + TEST_METHOD( Simple ) + { + PatternSearch ps1( "\x48\x89\xD0" ); + + std::vector results; + ps1.SearchRemoteWhole( _proc, false, 0, results ); + AssertEx::IsTrue( results.size() > 0 ); + } + + // Scan only inside 'explorer.exe' module + TEST_METHOD( WithWildcard ) + { + PatternSearch ps2{ 0x56, 0x57, 0xCC, 0x55 }; + + auto pMainMod = _proc.modules().GetMainModule(); + AssertEx::IsNotNull( pMainMod.get() ); + + std::vector results; + ps2.SearchRemote( _proc, 0xCC, pMainMod->baseAddress, pMainMod->size, results ); + AssertEx::IsTrue( results.size() > 0 ); + } + + private: + Process _proc; + }; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneTest/TestRemoteCall.cpp b/third/Blackbone/src/BlackBoneTest/TestRemoteCall.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dd3c8980f811aabeac6039e16c97422c87295fdd --- /dev/null +++ b/third/Blackbone/src/BlackBoneTest/TestRemoteCall.cpp @@ -0,0 +1,214 @@ +#include "Common.h" + +namespace Testing +{ + constexpr char* g_string = "The quick brown fox jumps over the lazy dog"; + constexpr wchar_t* g_wstring = L"The quick brown fox jumps over the lazy dog"; + + struct Dummy + { + uint32_t ival = 0; + float fval = 0.0f; + uint64_t uval = 0ull; + }; + + int TestFn( int a1, float a2, double a3, double* a4, int64_t a5, char* a6, wchar_t* a7, Dummy* a8, Dummy a9 ) + { + *a4 = a3 + a2; + strcpy_s( a6, MAX_PATH, g_string ); + wcscpy_s( a7, MAX_PATH, g_wstring ); + *a8 = a9; + + return static_cast(a1 + a5); + } + + TEST_CLASS( RemoteCall ) + { + public: + template + void ValidateArg( const AsmVariant& arg, AsmVariant::eType type, size_t size, T value ) + { + AssertEx::AreEqual( type, arg.type ); + AssertEx::AreEqual( size, arg.size ); + + if constexpr (std::is_same_v) + { + AssertEx::AreEqual( value, arg.imm_float_val ); + } + else if constexpr(std::is_same_v) + { + AssertEx::AreEqual( value, arg.imm_double_val ); + } + else if constexpr (std::is_pointer_v>) + { + AssertEx::AreEqual( reinterpret_cast(value), arg.imm_val64 ); + } + else if (value != 0) + { + AssertEx::AreEqual( uint64_t( value ), arg.imm_val64 ); + } + } + + TEST_METHOD( ConstructDirect ) + { + Process process; + RemoteFunction pFN( process, ptr_t( 0 ) ); + + float f = 2.0; + double d = 3.0; + double& ref = d; + + decltype(pFN)::CallArguments args( 1, f, ref, &d, 5ll, _cbuf, _wbuf, &_output, _input ); + + AssertEx::AreEqual( size_t( 9 ), args.arguments.size() ); + + ValidateArg( args.arguments[0], AsmVariant::imm, sizeof( int ), 1 ); + ValidateArg( args.arguments[1], AsmVariant::imm_float, sizeof( float ), 2.0f ); + ValidateArg( args.arguments[2], AsmVariant::imm_double, sizeof( double ), 3.0 ); + ValidateArg( args.arguments[3], AsmVariant::dataPtr, sizeof( double ), &d ); + ValidateArg( args.arguments[4], AsmVariant::imm, sizeof( int64_t ), 5 ); + ValidateArg( args.arguments[5], AsmVariant::dataPtr, sizeof( '\0' ), _cbuf ); + ValidateArg( args.arguments[6], AsmVariant::dataPtr, sizeof( L'\0' ), _wbuf ); + ValidateArg( args.arguments[7], AsmVariant::dataPtr, sizeof( _output ), &_output ); + ValidateArg( args.arguments[8], AsmVariant::dataStruct, sizeof( _input ), 0 ); + } + + TEST_METHOD( ConstructFromList ) + { + Process process; + RemoteFunction pFN( process, ptr_t( 0 ) ); + + float f = 2.0; + double d = 3.0; + double& ref = d; + + decltype(pFN)::CallArguments args{ 1, f, ref, &d, 5ll, _cbuf, _wbuf, &_output, _input }; + + AssertEx::AreEqual( size_t( 9 ), args.arguments.size() ); + + ValidateArg( args.arguments[0], AsmVariant::imm, sizeof( int ), 1 ); + ValidateArg( args.arguments[1], AsmVariant::imm_float, sizeof( float ), 2.0f ); + ValidateArg( args.arguments[2], AsmVariant::imm_double, sizeof( double ), 3.0 ); + ValidateArg( args.arguments[3], AsmVariant::dataPtr, sizeof( double ), &d ); + ValidateArg( args.arguments[4], AsmVariant::imm, sizeof( int64_t ), 5 ); + ValidateArg( args.arguments[5], AsmVariant::dataPtr, sizeof( _cbuf ), _cbuf ); + ValidateArg( args.arguments[6], AsmVariant::dataPtr, sizeof( _wbuf ), _wbuf ); + ValidateArg( args.arguments[7], AsmVariant::dataPtr, sizeof( _output ), &_output ); + ValidateArg( args.arguments[8], AsmVariant::dataStruct, sizeof( _input ), 0 ); + } + + TEST_METHOD( LocalCall ) + { + Process process; + AssertEx::NtSuccess( process.Attach( GetCurrentProcessId() ) ); + auto pFN = MakeRemoteFunction( process, &TestFn ); + double d = 0.0; + + _input.ival = 0xDEAD; + _input.fval = 1337.0f; + _input.uval = 0xDEADC0DEA4DBEEFull; + + auto[status, result] = pFN.Call( { 1, 2.0f, 3.0, &d, 5ll, _cbuf, _wbuf, &_output, _input } ); + AssertEx::NtSuccess( status ); + AssertEx::IsTrue( result.has_value() ); + + AssertEx::AreEqual( 1 + 5, result.value() ); + AssertEx::AreEqual( 3.0 + 2.0f, d, 0.001 ); + AssertEx::AreEqual( _cbuf, g_string ); + AssertEx::AreEqual( _wbuf, g_wstring ); + AssertEx::IsZero( memcmp( &_input, &_output, sizeof( _input ) ) ); + } + + TEST_METHOD( NtQueryVirtualMemory ) + { + auto path = GetTestHelperHost(); + AssertEx::IsTrue( Utils::FileExists( path ) ); + + // Give process some time to initialize + Process process; + AssertEx::NtSuccess( process.CreateAndAttach( path ) ); + Sleep( 100 ); + + auto hMainMod = process.modules().GetMainModule(); + AssertEx::IsNotNull( hMainMod.get() ); + + auto pFN = MakeRemoteFunction( process, L"ntdll.dll", "NtQueryVirtualMemory" ); + AssertEx::IsTrue( pFN.valid() ); + + uint8_t buf[0x200] = { }; + auto result = pFN.Call( { + INVALID_HANDLE_VALUE, + static_cast(hMainMod->baseAddress), + MemorySectionName, + buf, + sizeof( buf ), + nullptr + } ); + + process.Terminate(); + + AssertEx::NtSuccess( result.status ); + AssertEx::NtSuccess( result.result() ); + + std::wstring name( reinterpret_cast(buf + sizeof( UNICODE_STRING )) ); + AssertEx::AreNotEqual( name.npos, name.rfind( Utils::StripPath( path ) ) ); + } + + TEST_METHOD( FileOP ) + { + auto path = GetTestHelperHost(); + AssertEx::IsTrue( Utils::FileExists( path ) ); + + // Give process some time to initialize + Process process; + AssertEx::NtSuccess( process.CreateAndAttach( path ) ); + Sleep( 100 ); + + auto CreateFileWPtr = process.modules().GetExport( L"kernel32.dll", "CreateFileW" ); + auto WriteFilePtr = process.modules().GetExport( L"kernel32.dll", "WriteFile" ); + auto CloseHandlePtr = process.modules().GetExport( L"kernel32.dll", "CloseHandle" ); + + AssertEx::IsTrue( CreateFileWPtr.success() ); + AssertEx::IsTrue( WriteFilePtr.success() ); + AssertEx::IsTrue( CloseHandlePtr.success() ); + + uint8_t writeBuf[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + + RemoteFunction pCreateFile( process, CreateFileWPtr->procAddress ); + RemoteFunction pWriteFile( process, WriteFilePtr->procAddress ); + RemoteFunction pCloseHandle( process, CloseHandlePtr->procAddress ); + + auto filePath = L"DummyFile_FileOP.dat"; + auto handle = pCreateFile.Call( filePath, GENERIC_WRITE, 0x7, nullptr, CREATE_ALWAYS, 0, nullptr ); + + AssertEx::NtSuccess( handle.status ); + AssertEx::IsNotNull( handle.result() ); + + DWORD bytes = 0; + auto success = pWriteFile.Call( { handle.result(), writeBuf, sizeof( writeBuf ), &bytes, nullptr } ); + pCloseHandle.Call( handle.result(), nullptr ); + + process.Terminate(); + + AssertEx::NtSuccess( success.status ); + AssertEx::IsTrue( success.result() ); + AssertEx::AreEqual( static_cast(sizeof( writeBuf )), bytes ); + + // Check locally + FileHandle hFile = FileHandle( CreateFileW( filePath, GENERIC_READ, 0x7, nullptr, OPEN_EXISTING, FILE_DELETE_ON_CLOSE, nullptr ) ); + AssertEx::IsTrue( hFile ); + + uint8_t readBuf[sizeof( writeBuf )] = { }; + BOOL b = ReadFile( hFile, readBuf, sizeof( readBuf ), &bytes, nullptr ); + + AssertEx::IsTrue( b ); + AssertEx::AreEqual( static_cast(sizeof( readBuf )), bytes ); + AssertEx::IsZero( memcmp( writeBuf, readBuf, sizeof( readBuf ) ) ); + } + + private: + char _cbuf[MAX_PATH] = { }; + wchar_t _wbuf[MAX_PATH] = { }; + Dummy _input, _output; + }; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneTest/TestRemoteHook.cpp b/third/Blackbone/src/BlackBoneTest/TestRemoteHook.cpp new file mode 100644 index 0000000000000000000000000000000000000000..19494d7202950ecf6994d2a76a71d0fbfa179461 --- /dev/null +++ b/third/Blackbone/src/BlackBoneTest/TestRemoteHook.cpp @@ -0,0 +1,109 @@ +#include "Common.h" + +namespace Testing +{ + struct HookClass + { + void HookNtOpenProcess( RemoteContext& context ) + { + // + // Get process ID + // + _CLIENT_ID_T cid = { }; + auto pcid = context.getArg( 3 ); + process.memory().Read( pcid, sizeof( cid ), &cid ); + DWORD pid = static_cast(cid.UniqueProcess); + + if (pid == GetCurrentProcessId()) + { + // Remove PROCESS_TERMINATE access right + auto mask = context.getArg( 1 ); + if (mask & PROCESS_TERMINATE) + { + context.setArg( 1, mask & ~PROCESS_TERMINATE ); + calls++; + } + } + } + + void HookNtAllocateVirtualMemory( RemoteContext& context ) + { + AssertEx::AreEqual( reinterpret_cast(context.getArg( 0 )), GetCurrentProcess() ); + AssertEx::AreNotEqual( context.getArg( 1 ), DWORD64( 0 ) ); + AssertEx::AreEqual( context.getArg( 2 ), DWORD64( 0 ) ); + AssertEx::AreNotEqual( context.getArg( 3 ), DWORD64( 0 ) ); + AssertEx::AreEqual( context.getArg( 4 ), DWORD64( MEM_RESERVE | MEM_COMMIT ) ); + AssertEx::AreEqual( context.getArg( 5 ), DWORD64( PAGE_EXECUTE_READWRITE ) ); + + calls++; + } + + Process process; + int calls = 0; + }; + + TEST_CLASS( RemoteHooking ) + { + public: + TEST_METHOD( NtOpenProcess ) + { + HookClass hooker; + + auto path = GetTestHelperHost(); + AssertEx::IsFalse( path.empty() ); + + + // Give process some time to initialize + AssertEx::NtSuccess( hooker.process.CreateAndAttach( path ) ); + Sleep( 100 ); + + // Remote helper function + auto terminatePtr = hooker.process.modules().GetExport( hooker.process.modules().GetMainModule(), "TerminateProc" ); + AssertEx::IsTrue( terminatePtr.success() ); + + // Get function + auto pHookFn = hooker.process.modules().GetNtdllExport( "NtOpenProcess" ); + AssertEx::IsTrue( pHookFn.success() ); + + // Hook and try to terminate from remote process + AssertEx::NtSuccess( hooker.process.hooks().Apply( RemoteHook::hwbp, pHookFn->procAddress, &HookClass::HookNtOpenProcess, hooker ) ); + + auto terminate = MakeRemoteFunction( hooker.process, terminatePtr->procAddress ); + auto result = terminate( GetCurrentProcessId() ); + + hooker.process.Terminate(); + + AssertEx::IsTrue( result.success() ); + AssertEx::AreEqual( ERROR_ACCESS_DENIED, result.result() ); + AssertEx::AreEqual( 1, hooker.calls ); + } + + TEST_METHOD( NtAllocateVirtualMemory ) + { + HookClass hooker; + + auto path = GetTestHelperHost(); + AssertEx::IsFalse( path.empty() ); + + // Give process some time to initialize + AssertEx::NtSuccess( hooker.process.CreateAndAttach( path ) ); + Sleep( 100 ); + + // Get function + auto pHookFn = hooker.process.modules().GetNtdllExport( "NtAllocateVirtualMemory" ); + AssertEx::IsTrue( pHookFn.success() ); + + PVOID base = nullptr; + SIZE_T size = 0xDEAD; + auto NtAllocateVirtualMemory = MakeRemoteFunction( hooker.process, pHookFn->procAddress ); + + // Hook and try to call + AssertEx::NtSuccess( hooker.process.hooks().Apply( RemoteHook::hwbp, pHookFn->procAddress, &HookClass::HookNtAllocateVirtualMemory, hooker ) ); + auto result = NtAllocateVirtualMemory.Call( { GetCurrentProcess(), &base, 0, &size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE } ); + + hooker.process.Terminate(); + + AssertEx::AreEqual( 1, hooker.calls ); + } + }; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneTest/TestRemoteMemory.cpp b/third/Blackbone/src/BlackBoneTest/TestRemoteMemory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8baf6b7cd2eb3c28b1f791c896bde8b07e4bf7b5 --- /dev/null +++ b/third/Blackbone/src/BlackBoneTest/TestRemoteMemory.cpp @@ -0,0 +1,38 @@ +#include "Common.h" + +namespace Testing +{ + TEST_CLASS( RemoteMem ) + { +#ifdef CI_BUILD + BEGIN_TEST_CLASS_ATTRIBUTE() + TEST_CLASS_ATTRIBUTE( L"Ignore", L"true" ) + END_TEST_CLASS_ATTRIBUTE() +#endif + public: + TEST_METHOD( Everything ) + { + Process proc; + + NTSTATUS status = Driver().EnsureLoaded(); + if (!NT_SUCCESS( status )) + { + AssertEx::AreEqual( STATUS_OBJECT_NAME_NOT_FOUND, status ); + return; + } + + AssertEx::NtSuccess( proc.Attach( L"explorer.exe" ) ); + AssertEx::NtSuccess( proc.memory().Map( false ) ); + + // Translate main module base address + auto addr = proc.modules().GetMainModule()->baseAddress; + auto translated = proc.memory().TranslateAddress( addr ); + AssertEx::IsNotZero( translated ); + + AssertEx::NtSuccess( proc.memory().SetupHook( RemoteMemory::MemVirtualAlloc ) ); + AssertEx::NtSuccess( proc.memory().SetupHook( RemoteMemory::MemVirtualFree ) ); + AssertEx::NtSuccess( proc.memory().SetupHook( RemoteMemory::MemMapSection ) ); + AssertEx::NtSuccess( proc.memory().SetupHook( RemoteMemory::MemUnmapSection ) ); + } + }; +} \ No newline at end of file diff --git a/third/Blackbone/src/BlackBoneTest/TestSyscall.cpp b/third/Blackbone/src/BlackBoneTest/TestSyscall.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6389e77b65c8185215a732944b4b9a17bc338752 --- /dev/null +++ b/third/Blackbone/src/BlackBoneTest/TestSyscall.cpp @@ -0,0 +1,72 @@ +#include "Common.h" +#include <3rd_party/VersionApi.h> + +namespace Microsoft::VisualStudio::CppUnitTestFramework { + template<> inline std::wstring ToString( HWND__* t ) { RETURN_WIDE_STRING( t ); } +} + +namespace Testing +{ + TEST_CLASS( Syscall ) + { + public: + TEST_METHOD( NtAllocateVirtualMemory ) + { + constexpr SIZE_T requested = 0x3000; + PVOID ptr = nullptr; + SIZE_T size = requested; + + auto status = syscall::nt_syscall( + syscall::get_index( "NtAllocateVirtualMemory" ), + GetCurrentProcess(), + &ptr, + 0, + &size, + MEM_COMMIT, + PAGE_EXECUTE_READWRITE + ); + +#ifdef USE32 + // Not ready yet + AssertEx::AreEqual( STATUS_NOT_SUPPORTED, status ); +#else + AssertEx::NtSuccess( status ); + + AssertEx::IsNotNull( ptr ); + AssertEx::AreEqual( requested, size ); + + VirtualFree( ptr, 0, MEM_RELEASE ); +#endif + } + + TEST_METHOD( NtUserFindWindowEx ) + { + UNICODE_STRING empty = { }; + UNICODE_STRING wndName = { }; + + constexpr wchar_t name[] = L"Program Manager"; + SAFE_CALL( RtlInitUnicodeString, &wndName, name ); + + auto hwnd = syscall::syscall( + syscall::get_index( IsWindows10OrGreater() ? L"win32u.dll" : L"user32.dll", "NtUserFindWindowEx" ), + HWND_DESKTOP, + nullptr, + &empty, + &wndName, + 0 + ); + +#ifdef USE32 + // Not ready yet + AssertEx::AreEqual( HWND{}, hwnd ); +#else + AssertEx::AreNotEqual( HWND_DESKTOP, hwnd ); + + wchar_t title[MAX_PATH] = { }; + GetWindowTextW( hwnd, title, _countof( title ) ); + + AssertEx::AreEqual( name, title ); +#endif + } + }; +} \ No newline at end of file diff --git a/third/Blackbone/src/CMakeLists.txt b/third/Blackbone/src/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..8230182f73e691949a04cde73c19465be547f914 --- /dev/null +++ b/third/Blackbone/src/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required (VERSION 3.13) +project (BlackBone) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + +add_subdirectory(BlackBone) +add_subdirectory(Samples) \ No newline at end of file diff --git a/third/Blackbone/src/Samples/CMakeLists.txt b/third/Blackbone/src/Samples/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..cbc4d2a1b1bfe3941a70de04741215699f30a325 --- /dev/null +++ b/third/Blackbone/src/Samples/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required (VERSION 3.13) +project (Samples) + +include_directories(..) + +cmake_policy(SET CMP0015 NEW) + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + link_directories(../3rd_party/DIA/lib/amd64) +elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) + link_directories(../3rd_party/DIA/lib) +endif() + +add_executable(Samples Main.cpp ManualMap.cpp) + +target_link_libraries(Samples BlackBone diaguids.lib) \ No newline at end of file diff --git a/third/Blackbone/src/Samples/Main.cpp b/third/Blackbone/src/Samples/Main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb36b67d4d0aec79dfba27e91dc536d593dae174 --- /dev/null +++ b/third/Blackbone/src/Samples/Main.cpp @@ -0,0 +1,275 @@ +#include +#include +#include +#include +#include + +using namespace blackbone; + +void MapCalcFromFile(); +void MapCmdFromMem(); + +int main( int /*argc*/, char* /*argv[]*/ ) +{ + // List all process PIDs matching name + auto pids = Process::EnumByName( L"explorer.exe" ); + + // List all process PIDs matching either by PID only + auto procInfo = Process::EnumByNameOrPID( 0x1234, L"" ); + + // List all processes + auto all = Process::EnumByNameOrPID( 0, L"" ); + + // Attach to a process + if (Process explorer; !pids.empty() && NT_SUCCESS( explorer.Attach( pids.front() ) )) + { + auto& core = explorer.core(); + + // Get bitness info about this and target processes + [[maybe_unused]] auto barrier = explorer.barrier(); + + // Get process PID and handle + [[maybe_unused]] auto pid = core.pid(); + [[maybe_unused]] auto handle = core.handle(); + + // Get PEB + PEB_T peb = { }; + [[maybe_unused]] auto peb_ptr = core.peb( &peb ); + + // Get all process handles + if (auto handles = explorer.EnumHandles(); handles) + { + // do stuff with handles... + } + } + + // Start new suspended process and attach immediately + Process notepad; + notepad.CreateAndAttach( L"C:\\windows\\system32\\notepad.exe", true ); + { + // do stuff... + notepad.Resume(); + } + + // Process modules manipulation + { + auto& modules = notepad.modules(); + + // List all modules (both x86 and x64 for WOW64 processes) + auto mods = modules.GetAllModules(); + + // Get main module (.exe) + auto mainMod = modules.GetMainModule(); + + // Get module base address + [[maybe_unused]] auto base = mainMod->baseAddress; + + // Get export symbol from module found by name + auto LoadLibraryWPtr = modules.GetExport( L"kernel32.dll", "LoadLibraryW" ); + if (LoadLibraryWPtr) + { + } + + // Unlink module from loader structures + if (modules.Unlink( mainMod )) + { + } + } + + // Process memory manipulation + { + auto& memory = notepad.memory(); + auto mainMod = notepad.modules().GetMainModule(); + + // + // Read memory + // + IMAGE_DOS_HEADER dosHeader = { }; + + // Method 1 + memory.Read( mainMod->baseAddress, dosHeader ); + + // Method 2 + memory.Read( mainMod->baseAddress, sizeof( dosHeader ), &dosHeader ); + + // Method 3 + auto[status, dosHeader2] = memory.Read( mainMod->baseAddress ); + + // Change memory protection + if (NT_SUCCESS( memory.Protect( mainMod->baseAddress, sizeof( dosHeader ), PAGE_READWRITE ) )) + { + // + // Write memory + // + + // Method 1 + memory.Write( mainMod->baseAddress, dosHeader ); + + // Method 2 + memory.Write( mainMod->baseAddress, sizeof( dosHeader ), &dosHeader ); + } + + // Allocate memory + if (auto[status2, block] = memory.Allocate( 0x1000, PAGE_EXECUTE_READWRITE ); NT_SUCCESS( status2 )) + { + // Write into memory block + block->Write( 0x10, 12.0 ); + + // Read from memory block + [[maybe_unused]] auto dval = block->Read( 0x10, 0.0 ); + } + + // Enumerate regions + auto regions = memory.EnumRegions(); + } + + // Threads manipulation + { + // Get all thread + auto threads = notepad.threads().getAll(); + + // Get main thread + auto mainThread = notepad.threads().getMain(); + + // Get thread by TID + auto thread = notepad.threads().get( mainThread->id() ); + + // Get context + CONTEXT_T ctx = { }; + if (thread->GetContext( ctx, CONTEXT_FLOATING_POINT )) + { + // Set context + thread->SetContext( ctx ); + } + + // Wait for thread exit + thread->Join( 100 ); + } + + // JIT Assembler + if (auto asmPtr = AsmFactory::GetAssembler()) + { + auto& a = *asmPtr; + + a.GenPrologue(); + a->add( a->zcx, a->zdx ); + a->mov( a->zax, a->zcx ); + a.GenEpilogue(); + + auto func = reinterpret_cast(a->make()); + [[maybe_unused]] uintptr_t r = func( 10, 5 ); + } + + // Remote code execution + { + auto& remote = notepad.remote(); + remote.CreateRPCEnvironment( Worker_None, true ); + + auto GetModuleHandleWPtr = notepad.modules().GetExport( L"kernel32.dll", "GetModuleHandleW" ); + if (GetModuleHandleWPtr) + { + // Direct execution in the new thread without stub + [[maybe_unused]] DWORD mod = remote.ExecDirect( GetModuleHandleWPtr->procAddress, 0 ); + } + + // Execute in the new thread using stub + if (auto asmPtr = AsmFactory::GetAssembler(); asmPtr && GetModuleHandleWPtr) + { + auto& a = *asmPtr; + + a.GenPrologue(); + a.GenCall( static_cast(GetModuleHandleWPtr->procAddress), { nullptr }, cc_stdcall ); + a.GenEpilogue(); + + uint64_t result = 0; + remote.ExecInNewThread( a->make(), a->getCodeSize(), result ); + } + + // Execute in main thread + auto mainThread = notepad.threads().getMain(); + if (auto asmPtr = AsmFactory::GetAssembler(); asmPtr && mainThread && GetModuleHandleWPtr) + { + auto& a = *asmPtr; + + a.GenPrologue(); + a.GenCall( static_cast(GetModuleHandleWPtr->procAddress), { nullptr }, cc_stdcall ); + a.GenEpilogue(); + + uint64_t result = 0; + remote.ExecInAnyThread( a->make(), a->getCodeSize(), result, mainThread ); + } + } + + // Pattern scanning + if (Process process; NT_SUCCESS( process.Attach( GetCurrentProcessId() ) )) + { + PatternSearch ps{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + + std::vector results; + ps.SearchRemoteWhole( process, false, 0, results ); + } + + // Remote function calls + { + // Simple direct invocation + if (auto pMessageBoxW = MakeRemoteFunction( notepad, L"user32.dll", "MessageBoxW" )) + { + auto result = pMessageBoxW( HWND_DESKTOP, L"Hello world!", L"Title", MB_OKCANCEL ); + if (*result == IDCANCEL) + { + } + } + + // Call in specific thread + auto mainThread = notepad.threads().getMain(); + if (auto pIsGUIThread = MakeRemoteFunction( notepad, L"user32.dll", "IsGUIThread" ); pIsGUIThread && mainThread) + { + auto result = pIsGUIThread.Call( { FALSE }, mainThread ); + if (*result) + { + } + } + + // Complex args + if (auto pMultiByteToWideChar = MakeRemoteFunction( notepad, L"kernel32.dll", "MultiByteToWideChar" )) + { + auto args = pMultiByteToWideChar.MakeArguments( { CP_ACP, 0, "Sample text", -1, nullptr, 0 } ); + std::wstring converted( 32, L'\0' ); + + // Set buffer pointer and size manually + args.set( 4, AsmVariant( converted.data(), converted.size() * sizeof( wchar_t ) ) ); + args.set( 5, converted.size() ); + + auto length = pMultiByteToWideChar.Call( args ); + if (length) + converted.resize( *length - 1 ); + } + } + + // Direct syscalls, currently works for x64 only + { + uint8_t buf[32] = { }; + uintptr_t bytes = 0; + + NTSTATUS status = syscall::nt_syscall( + syscall::get_index( "NtReadVirtualMemory" ), + GetCurrentProcess(), + GetModuleHandle( nullptr ), + buf, + sizeof(buf), + &bytes + ); + + if (NT_SUCCESS( status )) + { + } + } + + notepad.Terminate(); + + // Manual mapping. See following functions for more info + MapCalcFromFile(); + MapCmdFromMem(); + + return 0; +} \ No newline at end of file diff --git a/third/Blackbone/src/Samples/ManualMap.cpp b/third/Blackbone/src/Samples/ManualMap.cpp new file mode 100644 index 0000000000000000000000000000000000000000..206f074434439e81a70c535dfbd48266ae7f0d2c --- /dev/null +++ b/third/Blackbone/src/Samples/ManualMap.cpp @@ -0,0 +1,102 @@ +#include +#include <3rd_party/VersionApi.h> + +#include +#include +using namespace blackbone; + +std::set nativeMods, modList; + +/* + Try to map calc.exe into current process +*/ +void MapCalcFromFile() +{ + Process thisProc; + thisProc.Attach( GetCurrentProcessId() ); + + nativeMods.clear(); + modList.clear(); + + nativeMods.emplace( L"combase.dll" ); + nativeMods.emplace( L"user32.dll" ); + if (WinVer().ver == Win7) + { + nativeMods.emplace( L"gdi32.dll" ); + nativeMods.emplace( L"msvcr120.dll" ); + nativeMods.emplace( L"msvcp120.dll" ); + } + + modList.emplace( L"windows.storage.dll" ); + modList.emplace( L"shell32.dll" ); + modList.emplace( L"shlwapi.dll" ); + + auto callback = []( CallbackType type, void* /*context*/, Process& /*process*/, const ModuleData& modInfo ) + { + if(type == PreCallback) + { + if(nativeMods.count(modInfo.name)) + return LoadData( MT_Native, Ldr_None ); + } + else + { + if (modList.count( modInfo.name )) + return LoadData( MT_Default, Ldr_ModList ); + } + + return LoadData( MT_Default, Ldr_None ); + }; + + std::wcout << L"Manual image mapping test" << std::endl; + std::wcout << L"Trying to map C:\\windows\\system32\\calc.exe into current process" << std::endl; + + auto image = thisProc.mmap().MapImage( L"C:\\windows\\system32\\calc.exe", ManualImports | RebaseProcess, callback ); + if (!image) + { + std::wcout << L"Mapping failed with error 0x" << std::hex << image.status + << L". " << Utils::GetErrorDescription( image.status ) << std::endl << std::endl; + } + else + std::wcout << L"Successfully mapped, unmapping\n"; + + thisProc.mmap().UnmapAllModules(); +} + +/* + Try to map cmd.exe into current process from buffer +*/ +void MapCmdFromMem() +{ + Process thisProc; + thisProc.Attach( GetCurrentProcessId() ); + + void* buf = nullptr; + auto size = 0; + + std::wcout << L"Manual image mapping from buffer test" << std::endl; + std::wcout << L"Trying to map C:\\windows\\system32\\cmd.exe into current process" << std::endl; + + // Get image context + HANDLE hFile = CreateFileW( L"C:\\windows\\system32\\cmd.exe", FILE_GENERIC_READ, 0x7, 0, OPEN_EXISTING, 0, 0 ); + if (hFile != INVALID_HANDLE_VALUE) + { + DWORD bytes = 0; + size = GetFileSize( hFile, NULL ); + buf = VirtualAlloc( NULL, size, MEM_COMMIT, PAGE_READWRITE ); + ReadFile( hFile, buf, size, &bytes, NULL ); + CloseHandle( hFile ); + } + + auto image = thisProc.mmap().MapImage( size, buf, false, CreateLdrRef | RebaseProcess | NoDelayLoad ); + if (!image) + { + std::wcout << L"Mapping failed with error 0x" << std::hex << image.status + << L". " << Utils::GetErrorDescription( image.status ) << std::endl << std::endl; + } + else + std::wcout << L"Successfully mapped, unmapping\n"; + + VirtualFree( buf, 0, MEM_RELEASE ); + + thisProc.mmap().UnmapAllModules(); +} diff --git a/third/Blackbone/src/Samples/Samples.vcxproj b/third/Blackbone/src/Samples/Samples.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..2c5288f4d67bd030a730cae135da448315b54f85 --- /dev/null +++ b/third/Blackbone/src/Samples/Samples.vcxproj @@ -0,0 +1,606 @@ + + + + + Debug(DLL) + Win32 + + + Debug(DLL) + x64 + + + Debug(XP) + Win32 + + + Debug(XP) + x64 + + + Debug + Win32 + + + Debug + x64 + + + Release(DLL) + Win32 + + + Release(DLL) + x64 + + + Release(XP) + Win32 + + + Release(XP) + x64 + + + Release + Win32 + + + Release + x64 + + + + {D31B07B5-C75F-4382-B07F-D95922764BD7} + Win32Proj + TestApp + 10.0.17763.0 + Samples + + + + Application + true + v141 + Unicode + + + Application + true + v141_xp + Unicode + false + + + Application + true + v141 + Unicode + + + Application + true + v141 + Unicode + + + Application + true + v141_xp + Unicode + false + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + false + v141_xp + true + Unicode + false + + + Application + false + v141 + true + Unicode + + + Application + false + v141 + true + Unicode + + + Application + false + v141_xp + true + Unicode + false + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + true + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + $(ProjectName)64 + true + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + $(ProjectName)64 + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + $(ProjectName)64 + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + $(ProjectName)64 + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + $(ProjectName)64 + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\$(ProjectName)\ + $(ProjectName)64 + + + + + + Level4 + Disabled + WIN32;_DEBUG;_CONSOLE;CONSOLE_TRACE;%(PreprocessorDefinitions) + true + false + ProgramDatabase + stdcpplatest + true + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + DebugFastLink + mscoree.lib;dbghelp.lib;%(AdditionalDependencies) + + + false + true + RequireAdministrator + + + copy /Y "$(ProjectDir)..\3rd_party\BeaEngine\Win32\Dll\BeaEngineCheetah.dll" "$(TargetDir)BeaEngineCheetah.dll" + + + + + + + Level4 + Disabled + WIN32;_DEBUG;_CONSOLE;CONSOLE_TRACE;%(PreprocessorDefinitions) + true + false + ProgramDatabase + stdcpplatest + true + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + DebugFastLink + mscoree.lib;dbghelp.lib;%(AdditionalDependencies) + + + false + true + + + copy /Y "$(ProjectDir)..\3rd_party\BeaEngine\Win32\Dll\BeaEngineCheetah.dll" "$(TargetDir)BeaEngineCheetah.dll" + + + + + + + Level4 + Disabled + WIN32;_DEBUG;_CONSOLE;CONSOLE_TRACE;BLACKBONE_IMPORTS;%(PreprocessorDefinitions) + true + false + ProgramDatabase + stdcpplatest + true + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + DebugFastLink + mscoree.lib;dbghelp.lib;%(AdditionalDependencies) + + + false + true + + + copy /Y "$(ProjectDir)..\3rd_party\BeaEngine\Win32\Dll\BeaEngineCheetah.dll" "$(TargetDir)BeaEngineCheetah.dll" + + + + + + + Level4 + Disabled + WIN32;_DEBUG;_CONSOLE;CONSOLE_TRACE;%(PreprocessorDefinitions) + true + Async + ProgramDatabase + stdcpplatest + true + false + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + DebugFastLink + mscoree.lib;dbghelp.lib;%(AdditionalDependencies) + false + true + RequireAdministrator + + + copy /Y "$(ProjectDir)..\3rd_party\BeaEngine\Win64\Dll\BeaEngineCheetah64.dll" "$(TargetDir)BeaEngineCheetah64.dll" + + + + + + + Level4 + Disabled + WIN32;_DEBUG;_CONSOLE;CONSOLE_TRACE;BLACKBONE_STATIC;%(PreprocessorDefinitions) + true + Async + stdcpplatest + true + false + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + DebugFastLink + mscoree.lib;dbghelp.lib;%(AdditionalDependencies) + false + false + + + copy /Y "$(ProjectDir)..\3rd_party\BeaEngine\Win64\Dll\BeaEngineCheetah64.dll" "$(TargetDir)BeaEngineCheetah64.dll" + + + + + + + Level4 + Disabled + WIN32;_DEBUG;_CONSOLE;CONSOLE_TRACE;BLACKBONE_IMPORTS;%(PreprocessorDefinitions) + true + Async + stdcpplatest + true + false + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + DebugFastLink + mscoree.lib;dbghelp.lib;%(AdditionalDependencies) + false + false + + + copy /Y "$(ProjectDir)..\3rd_party\BeaEngine\Win64\Dll\BeaEngineCheetah64.dll" "$(TargetDir)BeaEngineCheetah64.dll" + + + + + Level3 + + + Full + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + false + MultiThreaded + false + AnySuitable + stdcpplatest + true + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + DebugFastLink + true + true + mscoree.lib;dbghelp.lib;%(AdditionalDependencies) + false + + + copy /Y "$(ProjectDir)..\3rd_party\BeaEngine\Win32\Dll\BeaEngineCheetah.dll" "$(TargetDir)BeaEngineCheetah.dll" + + + + + Level3 + + + Full + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + false + MultiThreaded + false + stdcpplatest + true + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + DebugFastLink + true + true + mscoree.lib;dbghelp.lib;%(AdditionalDependencies) + false + + + copy /Y "$(ProjectDir)..\3rd_party\BeaEngine\Win32\Dll\BeaEngineCheetah.dll" "$(TargetDir)BeaEngineCheetah.dll" + + + + + Level3 + + + Full + true + true + WIN32;NDEBUG;_CONSOLE;BLACKBONE_IMPORTS;%(PreprocessorDefinitions) + + + false + MultiThreadedDLL + false + stdcpplatest + true + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + DebugFastLink + true + true + mscoree.lib;dbghelp.lib;%(AdditionalDependencies) + false + + + copy /Y "$(ProjectDir)..\3rd_party\BeaEngine\Win32\Dll\BeaEngineCheetah.dll" "$(TargetDir)BeaEngineCheetah.dll" + + + + + Level3 + + + Full + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + stdcpplatest + true + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + DebugFastLink + true + true + mscoree.lib;dbghelp.lib;%(AdditionalDependencies) + false + + + copy /Y "$(ProjectDir)..\3rd_party\BeaEngine\Win64\Dll\BeaEngineCheetah64.dll" "$(TargetDir)BeaEngineCheetah64.dll" + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;BLACKBONE_STATIC;%(PreprocessorDefinitions) + true + MultiThreaded + stdcpplatest + true + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + DebugFastLink + true + true + mscoree.lib;dbghelp.lib;%(AdditionalDependencies) + false + + + copy /Y "$(ProjectDir)..\3rd_party\BeaEngine\Win64\Dll\BeaEngineCheetah64.dll" "$(TargetDir)BeaEngineCheetah64.dll" + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;BLACKBONE_IMPORTS;%(PreprocessorDefinitions) + true + MultiThreadedDLL + stdcpplatest + true + $(ProjectDir)..;%(AdditionalIncludeDirectories) + + + Console + DebugFastLink + true + true + mscoree.lib;dbghelp.lib;%(AdditionalDependencies) + false + + + copy /Y "$(ProjectDir)..\3rd_party\BeaEngine\Win64\Dll\BeaEngineCheetah64.dll" "$(TargetDir)BeaEngineCheetah64.dll" + + + + + + + + + + + + + + + + {a2c53563-46f5-4d87-903f-3f1f2fdb2deb} + false + false + false + true + false + + + + + + \ No newline at end of file diff --git a/third/Blackbone/src/Samples/Samples.vcxproj.filters b/third/Blackbone/src/Samples/Samples.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..4b44f1fe7146e8329b733f69a1f9e594d73691ef --- /dev/null +++ b/third/Blackbone/src/Samples/Samples.vcxproj.filters @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file