├── README.md ├── RazorSharp.sln ├── RazorSharp ├── Analysis │ ├── Inspect.cs │ ├── InspectOptions.cs │ ├── ObjectGuide.cs │ └── ObjectInfo.cs ├── Core │ ├── Clr.cs │ ├── Global.cs │ └── Initializer.cs ├── CoreClr │ ├── Constants.cs │ ├── GCHeap.cs │ ├── Meta │ │ ├── Base │ │ │ ├── AnonymousClrStructure.cs │ │ │ ├── ClrStructure.cs │ │ │ ├── ClrStructureSettings.cs │ │ │ └── EmbeddedClrStructure.cs │ │ ├── MetaField.cs │ │ ├── MetaIL.cs │ │ ├── MetaLayout.cs │ │ ├── MetaMethod.cs │ │ └── MetaType.cs │ ├── Metadata │ │ ├── Enums │ │ │ ├── CorEnums.cs │ │ │ ├── EEClassEnums.cs │ │ │ ├── FieldDescEnums.cs │ │ │ ├── MethodDescEnums.cs │ │ │ └── MethodTableEnums.cs │ │ ├── ExecutionEngine │ │ │ ├── EEClass.cs │ │ │ ├── EEClassLayoutInfo.cs │ │ │ └── LayoutEEClass.cs │ │ ├── FieldDesc.cs │ │ ├── JitIL │ │ │ ├── FatILMethod.cs │ │ │ ├── ILMethod.cs │ │ │ ├── InspectIL.cs │ │ │ ├── Instruction.cs │ │ │ └── TinyILMethod.cs │ │ ├── MethodDesc.cs │ │ ├── MethodTable.cs │ │ ├── ObjHeader.cs │ │ ├── PackedDWORDFields.cs │ │ └── TypeHandle.cs │ ├── Offsets.cs │ ├── Runtime.Info.cs │ ├── Runtime.cs │ └── Tokens.cs ├── Import │ ├── Attributes │ │ ├── ImportAttribute.cs │ │ ├── ImportCallAttribute.cs │ │ ├── ImportFieldAttribute.cs │ │ ├── ImportForwardCallAttribute.cs │ │ ├── ImportMapDesignationAttribute.cs │ │ └── ImportNamespaceAttribute.cs │ ├── Enums │ │ ├── IdentifierOptions.cs │ │ ├── ImportCallOptions.cs │ │ └── ImportFieldOptions.cs │ ├── IImportProvider.cs │ ├── ImportManager.cs │ ├── ImportMap.cs │ ├── ModuleImport.cs │ └── SymbolManager.cs ├── Interop │ ├── Enums │ │ ├── DataSectionFlags.cs │ │ ├── MemState.cs │ │ ├── MemType.cs │ │ ├── MemoryProtection.cs │ │ ├── ProcessAccess.cs │ │ ├── SymbolFlag.cs │ │ ├── SymbolOptions.cs │ │ └── SymbolTag.cs │ ├── FunctionFactory.Delegates.cs │ ├── FunctionFactory.Managed.cs │ ├── FunctionFactory.cs │ ├── Functions.Fluid.cs │ ├── Functions.Module.cs │ ├── Functions.Native.cs │ ├── Functions.Reflection.cs │ ├── Functions.cs │ ├── Native.DebugHelp.cs │ ├── Native.Kernel32.cs │ ├── Native.cs │ ├── Structures │ │ ├── ImageDOSHeader.cs │ │ ├── ImageDataDirectory.cs │ │ ├── ImageFileHeader.cs │ │ ├── ImageOptionalHeader32.cs │ │ ├── ImageOptionalHeader64.cs │ │ ├── ImageSectionHeader.cs │ │ ├── ImageSectionInfo.cs │ │ ├── MemoryBasicInformation.cs │ │ ├── Symbol.cs │ │ └── SymbolInfo.cs │ └── Utilities │ │ ├── NativeAttribute.cs │ │ └── PEHeaderReader.cs ├── Memory │ ├── Allocation │ │ ├── AllocationManager.cs │ │ ├── Allocators.cs │ │ └── IAllocator.cs │ ├── Components │ │ ├── ComponentField.cs │ │ ├── IStructure.cs │ │ ├── MemoryField.cs │ │ └── PaddingField.cs │ ├── Converter.cs │ ├── Enums │ │ ├── OffsetOptions.cs │ │ └── SizeOfOptions.cs │ ├── Mem.Kernel.cs │ ├── Mem.cs │ ├── Pointers │ │ ├── Handle.cs │ │ └── Pointer.cs │ ├── Segment.cs │ ├── SigScanner.cs │ └── Unsafe.cs ├── Model │ ├── Closable.cs │ └── Releasable.cs ├── Properties │ └── AssemblyInfo.cs ├── RazorSharp.csproj ├── Utilities │ ├── Bits.cs │ ├── EnumFlags.cs │ ├── Fixed │ │ ├── ObjectPinner.cs │ │ └── PinHelper.cs │ ├── Members.cs │ ├── Modules.cs │ └── Security │ │ ├── Exceptions │ │ ├── AmbiguousStateException.cs │ │ ├── ClrException.cs │ │ ├── CorILException.cs │ │ ├── CoreException.cs │ │ ├── ImageException.cs │ │ ├── ImportException.cs │ │ └── SentryException.cs │ │ ├── FailMessageTemplateAttribute.cs │ │ └── Guard.cs └── packages.config ├── Test ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── Test.csproj ├── icon512.png └── icon64.png /README.md: -------------------------------------------------------------------------------- 1 | # RazorSharp 2 | 3 | [![nuget](https://img.shields.io/nuget/v/RazorSharp.svg?logo=NuGet)](https://www.nuget.org/packages/RazorSharp/) 4 | [![nuget dl](https://img.shields.io/nuget/dt/RazorSharp.svg?logo=NuGet)](https://www.nuget.org/packages/RazorSharp/) 5 | 6 | ![Icon](https://github.com/Decimation/RazorSharp/raw/master/icon64.png) 7 | 8 | Low-level utilities and tools for working with the CLR, CLR internal structures, and memory. 9 | 10 | # Notice 11 | 12 | **For a new and improved .NET 5 implementation, see [Novus](https://github.com/Decimation/Novus).** 13 | 14 | # Goals 15 | 16 | `RazorSharp` aims to provide functionality similar to that of `ClrMD`, `WinDbg SOS`, and `Reflection` but in a more detailed fashion while also exposing more underlying metadata and CLR functionality. 17 | 18 | `RazorSharp` also allows for manipulation of the CLR and low-level operations with managed objects. Additionally, `RazorSharp` doesn't require attachment of a debugger to the process to acquire metadata. All metadata is acquired through memory or low-level functions. 19 | 20 | # Usage 21 | 22 | Some structures of `RazorSharp` must be set up to use certain features. Their respective type initializers and constructors should do this automatically, but this is still being tested as static initialization can be tricky. 23 | 24 | # Features 25 | 26 | * Calculating heap size of managed objects 27 | * Taking the address of managed objects 28 | * Pointer to managed types 29 | * Pinning unblittable objects 30 | * And much more 31 | 32 | # Compatibility 33 | * 64-bit (only partial 32-bit support) 34 | * Windows 35 | * .NET CLR 36 | * .NET Framework 4.7.2 37 | * Workstation GC 38 | 39 | # License 40 | 41 | Icons made by Freepik 42 | -------------------------------------------------------------------------------- /RazorSharp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2016 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RazorSharp", "RazorSharp\RazorSharp.csproj", "{D350BF0A-5CA4-43C3-8F01-32F561FE0727}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{B2CA536C-C670-4643-A5C7-C57070E95223}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {D350BF0A-5CA4-43C3-8F01-32F561FE0727}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {D350BF0A-5CA4-43C3-8F01-32F561FE0727}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {D350BF0A-5CA4-43C3-8F01-32F561FE0727}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {D350BF0A-5CA4-43C3-8F01-32F561FE0727}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {B2CA536C-C670-4643-A5C7-C57070E95223}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {B2CA536C-C670-4643-A5C7-C57070E95223}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {B2CA536C-C670-4643-A5C7-C57070E95223}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {B2CA536C-C670-4643-A5C7-C57070E95223}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {22D521BA-2C52-4408-A385-DA2E6A9DE6E2} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /RazorSharp/Analysis/Inspect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RazorSharp.Utilities; 3 | 4 | namespace RazorSharp.Analysis 5 | { 6 | public static class Inspect 7 | { 8 | public static ObjectInfo Scan(ref T value, InspectOptions options) 9 | { 10 | var info = Scan(value.GetType(), options); 11 | 12 | info.Update(ref value); 13 | 14 | return info; 15 | } 16 | 17 | public static ObjectInfo Scan(Type t, InspectOptions options) 18 | { 19 | var info = new ObjectInfo(t, options); 20 | 21 | info.Update(); 22 | 23 | return info; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /RazorSharp/Analysis/InspectOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RazorSharp.Analysis 4 | { 5 | [Flags] 6 | public enum InspectOptions 7 | { 8 | None = 0, 9 | 10 | Fields = 1 << 0, 11 | 12 | Values = 1 << 1, 13 | 14 | MemoryFields = (1 << 2) | Fields, 15 | 16 | Addresses = 1 << 3, 17 | 18 | Padding = 1 << 4, 19 | } 20 | } -------------------------------------------------------------------------------- /RazorSharp/Analysis/ObjectGuide.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using RazorSharp.Memory; 4 | using RazorSharp.Memory.Components; 5 | using RazorSharp.Memory.Pointers; 6 | using RazorSharp.Utilities; 7 | using RazorSharp.Utilities.Security; 8 | using SimpleSharp.Diagnostics; 9 | 10 | namespace RazorSharp.Analysis 11 | { 12 | internal class ObjectGuide 13 | { 14 | private IStructure Struct { get; } 15 | 16 | private InspectOptions Options { get; } 17 | 18 | private Pointer Address { get; set; } 19 | 20 | private object Value { get; set; } 21 | 22 | internal ObjectGuide(IStructure structure, InspectOptions options) 23 | { 24 | Struct = structure; 25 | Address = Mem.Nullptr; 26 | Value = null; 27 | Options = options; 28 | } 29 | 30 | internal void Update(ref T t) 31 | { 32 | Value = Struct.GetValue(t); 33 | Address = Struct.GetAddress(ref t); 34 | 35 | Conditions.AssertDebug(Value == Address.ReadAny(Value.GetType())); 36 | } 37 | 38 | public override string ToString() 39 | { 40 | var sb = new StringBuilder(); 41 | sb.AppendFormat("Name: {0} | ", Struct.Name) 42 | .AppendFormat("Offset: {0} | ", Struct.Offset) 43 | .AppendFormat("Size: {0}", Struct.Size); 44 | 45 | if (Options.HasFlagFast(InspectOptions.Values)) { 46 | if (Value == null) { 47 | throw Guard.InvalidOperationFail("Value is required"); 48 | } 49 | 50 | sb.AppendFormat(" | Value: {0}", Value); 51 | } 52 | 53 | if (Options.HasFlagFast(InspectOptions.Addresses)) { 54 | if (Address.IsNull) { 55 | throw Guard.InvalidOperationFail("Address is null"); 56 | } 57 | sb.AppendFormat(" | Address: {0}", Address); 58 | } 59 | 60 | return sb.ToString(); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /RazorSharp/Analysis/ObjectInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using RazorSharp.CoreClr; 7 | using RazorSharp.CoreClr.Meta; 8 | using RazorSharp.CoreClr.Metadata.Enums; 9 | using RazorSharp.Memory; 10 | using RazorSharp.Memory.Components; 11 | using RazorSharp.Memory.Pointers; 12 | using RazorSharp.Utilities; 13 | using RazorSharp.Utilities.Security; 14 | using SimpleSharp.Diagnostics; 15 | 16 | // ReSharper disable ReturnTypeCanBeEnumerable.Local 17 | 18 | namespace RazorSharp.Analysis 19 | { 20 | public class ObjectInfo 21 | { 22 | private object m_value; 23 | 24 | public IStructure[] Structures { get; private set; } 25 | 26 | public MetaType Type { get; } 27 | 28 | private object Value { 29 | get => m_value; 30 | set { 31 | if (value.GetType() != Type || value == null) { 32 | throw Guard.InvalidOperationFail(nameof(value)); 33 | } 34 | 35 | m_value = value; 36 | } 37 | } 38 | 39 | private Pointer Address { get; set; } 40 | 41 | private InspectOptions Options { get; } 42 | 43 | private InspectOptions Completed { get; set; } 44 | 45 | private bool HasValue => Value != null; 46 | 47 | private ObjectGuide[] m_guides; 48 | 49 | 50 | internal ObjectInfo(MetaType t, InspectOptions options) 51 | { 52 | if (options.HasFlagFast(InspectOptions.None)) { 53 | throw new ArgumentException(); 54 | } 55 | 56 | Type = t; 57 | Options = options; 58 | } 59 | 60 | private void HandleOption(InspectOptions options, Action fn) 61 | { 62 | if (Options.HasFlagFast(options) && !Completed.HasFlagFast(options)) { 63 | fn(); 64 | Completed |= options; 65 | } 66 | } 67 | 68 | internal ObjectInfo Update(ref T t) 69 | { 70 | Update(); 71 | 72 | Value = t; 73 | Address = Unsafe.AddressOf(ref t).Cast(); 74 | 75 | foreach (var objectGuide in m_guides) { 76 | objectGuide.Update(ref t); 77 | } 78 | 79 | return this; 80 | } 81 | 82 | internal ObjectInfo Update() 83 | { 84 | if (HasValue) { 85 | HandleOption(InspectOptions.MemoryFields, AddMemoryFields); 86 | } 87 | 88 | HandleOption(InspectOptions.Fields, AddFields); 89 | 90 | HandleOption(InspectOptions.Padding, AddPaddingFields); 91 | 92 | m_guides = BuildGuides(); 93 | 94 | return this; 95 | } 96 | 97 | private void AddFields() 98 | { 99 | var fields = Type.Fields.Where(f => !f.IsStatic).ToArray(); 100 | 101 | var structures = new List(fields.Length); 102 | structures.AddRange(fields); 103 | Structures = structures.ToArray(); 104 | } 105 | 106 | private void AddMemoryFields() 107 | { 108 | var structures = new List(); 109 | 110 | if (Type.IsStringOrArray) { 111 | Array array = null; 112 | 113 | if (Type.IsString) { 114 | string s = m_value as string; 115 | 116 | // ReSharper disable once AssignNullToNotNullAttribute 117 | array = s.ToArray(); 118 | } 119 | 120 | if (Type.IsArray) { 121 | array = m_value as Array; 122 | 123 | structures.Add(new MemoryField("(Array length)", 0, sizeof(int))); 124 | 125 | if (Mem.Is64Bit) { 126 | structures.Add(new PaddingField(sizeof(int))); 127 | } 128 | } 129 | 130 | // ReSharper disable once PossibleNullReferenceException 131 | for (int i = 0; i < array.Length; i++) { 132 | structures.Add(new ComponentField(Type, i)); 133 | } 134 | } 135 | 136 | 137 | // We assume that fields are already added 138 | var buf = Structures.ToList(); 139 | buf.AddRange(structures); 140 | Structures = buf.ToArray(); 141 | } 142 | 143 | private void AddPaddingFields() 144 | { 145 | var padding = new List(); 146 | var nextOffsetOrSize = Type.InstanceFieldsSize; 147 | var memFields = Type.Fields.Where(f => !f.IsStatic).ToArray(); 148 | 149 | for (int i = 0; i < memFields.Length; i++) { 150 | // start padding 151 | 152 | if (i != memFields.Length - 1) { 153 | nextOffsetOrSize = Type.Fields[i + 1].Offset; 154 | } 155 | 156 | int nextSectOfsCandidate = Type.Fields[i].Offset + Type.Fields[i].Size; 157 | 158 | if (nextSectOfsCandidate < nextOffsetOrSize) { 159 | int padSize = nextOffsetOrSize - nextSectOfsCandidate; 160 | 161 | padding.Add(new PaddingField(nextSectOfsCandidate, padSize)); 162 | } 163 | 164 | // end padding 165 | } 166 | 167 | 168 | // We assume that fields are already added 169 | var buf = Structures.ToList(); 170 | buf.AddRange(padding); 171 | Structures = buf.OrderBy(f => f.Offset).ToArray(); 172 | } 173 | 174 | 175 | private ObjectGuide[] BuildGuides() 176 | { 177 | var dumps = new ObjectGuide[Structures.Length]; 178 | for (int i = 0; i < dumps.Length; i++) { 179 | dumps[i] = new ObjectGuide(Structures[i], Options); 180 | } 181 | 182 | return dumps; 183 | } 184 | 185 | public void Dump() 186 | { 187 | foreach (var structure in m_guides) { 188 | Console.WriteLine(structure); 189 | } 190 | } 191 | 192 | public override string ToString() 193 | { 194 | return base.ToString(); 195 | } 196 | } 197 | } -------------------------------------------------------------------------------- /RazorSharp/Core/Clr.cs: -------------------------------------------------------------------------------- 1 | #region 2 | 3 | using System; 4 | using System.Configuration; 5 | using System.Diagnostics; 6 | using System.IO; 7 | using System.Runtime; 8 | using System.Runtime.InteropServices; 9 | using RazorSharp.Import; 10 | using RazorSharp.Model; 11 | using RazorSharp.Utilities; 12 | using SimpleSharp.Diagnostics; 13 | 14 | #endregion 15 | 16 | namespace RazorSharp.Core 17 | { 18 | /// 19 | /// Contains resources for working with the CLR. 20 | /// 21 | internal sealed class Clr : Releasable 22 | { 23 | protected override string Id => nameof(Clr); 24 | 25 | /// 26 | /// CLR DLL file 27 | /// 28 | internal FileInfo LibraryFile { get; } 29 | 30 | /// 31 | /// CLR symbol file 32 | /// A PDB file will be searched for in 33 | /// 34 | internal FileInfo SymbolsFile { get; } 35 | 36 | /// 37 | /// The of the CLR 38 | /// 39 | internal ProcessModule Module { get; } 40 | 41 | /// 42 | /// The of the CLR 43 | /// 44 | internal Version Version { get; } 45 | 46 | /// 47 | /// CLR symbol access. 48 | /// 49 | internal IImportProvider Imports { get; } 50 | 51 | 52 | private static FileInfo GetRuntimeFile(string fileName) 53 | { 54 | string path = RuntimeEnvironment.GetRuntimeDirectory() + fileName; 55 | var file = new FileInfo(path); 56 | 57 | Conditions.Require(file.Exists); 58 | 59 | return file; 60 | } 61 | 62 | public override void Close() 63 | { 64 | // Delete instance 65 | Value = null; 66 | 67 | base.Close(); 68 | } 69 | 70 | 71 | #region Constants 72 | 73 | /// 74 | /// CLR module file: clr.dll 75 | /// 76 | private const string CLR_DLL_SHORT = "clr.dll"; 77 | 78 | /// 79 | /// CLR symbol file name: clr.pdb 80 | /// 81 | private const string CLR_PDB_SHORT = "clr.pdb"; 82 | 83 | #endregion 84 | 85 | #region Singleton 86 | 87 | /// 88 | /// Gets an instance of 89 | /// 90 | internal static Clr Value { get; private set; } = new Clr(); 91 | 92 | private Clr() 93 | { 94 | // Version: 4.0.30319.42000 95 | // symchk "C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll" /s SRV*C:\Users\Deci\Desktop\clr.pdb*http://msdl.microsoft.com/download/symbols 96 | // symchk "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll" /s SRV*C:\Users\Deci\Desktop\clr.pdb*http://msdl.microsoft.com/download/symbols 97 | 98 | LibraryFile = GetRuntimeFile(CLR_DLL_SHORT); 99 | SymbolsFile = GetRuntimeFile(CLR_PDB_SHORT); 100 | Module = Modules.FindModule(CLR_DLL_SHORT); 101 | Version = new Version(4, 0, 30319, 42000); 102 | Imports = new ModuleImport(SymbolsFile, Module); 103 | 104 | Setup(); 105 | } 106 | 107 | #endregion 108 | } 109 | } -------------------------------------------------------------------------------- /RazorSharp/Core/Initializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RazorSharp.CoreClr; 3 | using RazorSharp.CoreClr.Metadata; 4 | using RazorSharp.Import; 5 | using RazorSharp.Interop; 6 | using RazorSharp.Interop.Utilities; 7 | using RazorSharp.Memory; 8 | using RazorSharp.Model; 9 | using SimpleSharp.Diagnostics; 10 | 11 | namespace RazorSharp.Core 12 | { 13 | internal static class Initializer 14 | { 15 | private const string CONTEXT = "Init"; 16 | 17 | private static bool IsSetup { get; set; } 18 | 19 | /// 20 | /// Core CLR types 21 | /// 22 | private static readonly Type[] CoreClrTypes = 23 | { 24 | typeof(FunctionFactory), 25 | typeof(MethodDesc), 26 | typeof(FieldDesc), 27 | typeof(MethodTable), 28 | typeof(GCHeap), 29 | typeof(TypeHandle) 30 | }; 31 | 32 | /// 33 | /// Core objects 34 | /// 35 | private static readonly Closable[] CoreObjects = 36 | { 37 | Clr.Value, // Calls Setup in ctor 38 | SymbolManager.Value, // Calls Setup in ctor 39 | ImportManager.Value, // Calls Setup in ctor 40 | Global.Value, // Calls Setup in ctor 41 | Mem.Allocator 42 | }; 43 | 44 | internal static void Setup() 45 | { 46 | // Original order: Clr, SymbolManager, Global 47 | 48 | /*foreach (var core in CoreObjects) { 49 | if (core is Releasable releasable && !releasable.IsSetup) { 50 | releasable.Setup(); 51 | } 52 | } 53 | 54 | ImportManager.Value.LoadAll(CoreClrTypes, Clr.Value.Imports);*/ 55 | 56 | // Register for domain unload 57 | 58 | var appDomain = AppDomain.CurrentDomain; 59 | appDomain.ProcessExit += (sender, eventArgs) => { Close(); }; 60 | 61 | IsSetup = true; 62 | } 63 | 64 | 65 | internal static void Close() 66 | { 67 | Conditions.Require(IsSetup); 68 | 69 | // SHUT IT DOWN 70 | 71 | // Original order: Clr, Global, SymbolManager, Mem.Allocator 72 | 73 | foreach (var core in CoreObjects) { 74 | core?.Close(); 75 | } 76 | 77 | IsSetup = false; 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace RazorSharp.CoreClr 2 | { 3 | internal static unsafe class Constants 4 | { 5 | /// 6 | /// Common value representing an invalid value or a failure 7 | /// 8 | internal const int INVALID_VALUE = -1; 9 | 10 | /// 11 | /// Bits per or 12 | /// 13 | internal const int BITS_PER_DWORD = sizeof(int) * 8; 14 | } 15 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/GCHeap.cs: -------------------------------------------------------------------------------- 1 | using RazorSharp.Core; 2 | using RazorSharp.CoreClr.Meta; 3 | using RazorSharp.CoreClr.Metadata; 4 | using RazorSharp.Import; 5 | using RazorSharp.Import.Attributes; 6 | using RazorSharp.Import.Enums; 7 | using RazorSharp.Interop; 8 | using RazorSharp.Memory; 9 | using RazorSharp.Memory.Pointers; 10 | 11 | // ReSharper disable InconsistentNaming 12 | 13 | namespace RazorSharp.CoreClr 14 | { 15 | [ImportNamespace(WKS_NAMESPACE)] 16 | public static unsafe class GCHeap 17 | { 18 | private const string WKS_NAMESPACE = "WKS"; 19 | 20 | static GCHeap() 21 | { 22 | ImportManager.Value.Load(typeof(GCHeap), Clr.Value.Imports); 23 | } 24 | 25 | [ImportField(IdentifierOptions.FullyQualified, ImportFieldOptions.Fast)] 26 | private static readonly Pointer g_pGCHeap; 27 | 28 | [ImportMapDesignation] 29 | private static readonly ImportMap Imports = new ImportMap(); 30 | 31 | public static int GCCount { 32 | [ImportCall("GetGcCount", ImportCallOptions.Map)] 33 | get => Functions.Native.Call((void*) Imports[nameof(GCCount)], g_pGCHeap.ToPointer()); 34 | } 35 | 36 | public static object AllocateObject(MetaType mt, bool fHandleCom = false) 37 | { 38 | void* ptr = AllocateObject(mt.Value.ToPointer(), fHandleCom); 39 | return Unsafe.Read(&ptr); 40 | } 41 | 42 | public static T AllocateObject(bool fHandleCom = false) 43 | { 44 | return (T) AllocateObject(typeof(T), fHandleCom); 45 | } 46 | 47 | 48 | [ImportCall(IdentifierOptions.FullyQualified, ImportCallOptions.Map)] 49 | public static void* AllocateObject(Pointer mt, bool fHandleCom = false) 50 | { 51 | return Functions.Native.CallReturnPointer((void*) Imports[nameof(AllocateObject)], 52 | mt.ToPointer(), fHandleCom); 53 | } 54 | 55 | [ImportCall(ImportCallOptions.Map)] 56 | public static bool IsHeapPointer(Pointer p, bool smallHeapOnly = false) 57 | { 58 | return Functions.Native.Call((void*) Imports[nameof(IsHeapPointer)], 59 | g_pGCHeap.ToPointer(), p.ToPointer(), smallHeapOnly); 60 | } 61 | 62 | public static bool IsHeapPointer(T value, bool smallHeapOnly = false) 63 | { 64 | return Unsafe.TryGetAddressOfHeap(value, out Pointer ptr) && 65 | IsHeapPointer(ptr.ToPointer(), smallHeapOnly); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Meta/Base/AnonymousClrStructure.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using RazorSharp.Memory.Pointers; 3 | 4 | namespace RazorSharp.CoreClr.Meta.Base 5 | { 6 | /// 7 | /// Describes a that doesn't have an accompanying 8 | /// or 9 | /// 10 | /// CLR structure type 11 | public abstract class AnonymousClrStructure : ClrStructure where TClr : unmanaged 12 | { 13 | #region Constructors 14 | 15 | internal AnonymousClrStructure(Pointer ptr) : base(ptr) { } 16 | 17 | #endregion 18 | 19 | /// 20 | /// Returns null 21 | /// 22 | public override MemberInfo Info => null; 23 | 24 | /// 25 | /// Returns 26 | /// 27 | public override int Token => Constants.INVALID_VALUE; 28 | } 29 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Meta/Base/ClrStructure.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Reflection; 4 | using RazorSharp.Memory.Pointers; 5 | using RazorSharp.Utilities.Security; 6 | using SimpleSharp; 7 | using SimpleSharp.Strings.Formatting; 8 | 9 | namespace RazorSharp.CoreClr.Meta.Base 10 | { 11 | /// 12 | /// Describes a CLR structure that has metadata information. 13 | /// 14 | /// CLR structure type 15 | public abstract unsafe class ClrStructure : IFormattable where TClr : unmanaged 16 | { 17 | #region Fields 18 | 19 | /// 20 | /// Points to the internal CLR structure representing this instance 21 | /// 22 | public Pointer Value { get; } 23 | 24 | /// 25 | /// The native, built-in form of 26 | /// 27 | protected internal TClr* NativePointer => Value.ToPointer(); 28 | 29 | public abstract MemberInfo Info { get; } 30 | 31 | public string Name => Info.Name; 32 | 33 | protected virtual ConsoleTable InfoTable => IdTable; 34 | 35 | private ConsoleTable IdTable { 36 | get { 37 | var table = new ConsoleTable("Property", "Value"); 38 | 39 | table.AddRow("Handle", Value); 40 | table.AddRow(nameof(Token), Hex.ToHex(Token)); 41 | 42 | return table; 43 | } 44 | } 45 | 46 | public abstract int Token { get; } 47 | 48 | #endregion 49 | 50 | #region Constructors 51 | 52 | // Root constructor 53 | protected ClrStructure(Pointer ptr) 54 | { 55 | Value = ptr; 56 | } 57 | 58 | internal ClrStructure(MemberInfo member) : this(Runtime.ResolveHandle(member)) { } 59 | 60 | #endregion 61 | 62 | 63 | #region ToString 64 | 65 | public string ToString(string format) => ToString(format, CultureInfo.CurrentCulture); 66 | 67 | public override string ToString() => ToString(ClrStructureSettings.DefaultFormat); 68 | 69 | public string ToString(string format, IFormatProvider formatProvider) 70 | { 71 | return format switch 72 | { 73 | ClrStructureSettings.FORMAT_ALL => InfoTable.ToString(), 74 | ClrStructureSettings.FORMAT_MIN => IdTable.ToString(), 75 | _ => IdTable.ToString(), 76 | }; 77 | } 78 | 79 | #endregion 80 | 81 | #region Equality 82 | 83 | public override bool Equals(object obj) 84 | { 85 | if (ReferenceEquals(null, obj)) 86 | return false; 87 | 88 | if (ReferenceEquals(this, obj)) 89 | return true; 90 | 91 | if (obj.GetType() != this.GetType()) 92 | return false; 93 | 94 | return Equals((ClrStructure) obj); 95 | } 96 | 97 | public bool Equals(ClrStructure other) 98 | { 99 | return this.Value == other.Value; 100 | } 101 | 102 | public override int GetHashCode() 103 | { 104 | throw Guard.NotImplementedFail(nameof(GetHashCode)); 105 | } 106 | 107 | public static bool operator ==(ClrStructure left, ClrStructure right) => Equals(left, right); 108 | 109 | public static bool operator !=(ClrStructure left, ClrStructure right) => !Equals(left, right); 110 | 111 | #endregion 112 | } 113 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Meta/Base/ClrStructureSettings.cs: -------------------------------------------------------------------------------- 1 | using RazorSharp.CoreClr.Meta.Base; 2 | 3 | namespace RazorSharp.CoreClr.Meta.Base 4 | { 5 | internal static class ClrStructureSettings 6 | { 7 | /// 8 | /// Prints 9 | /// 10 | internal const string FORMAT_ALL = "A"; 11 | 12 | /// 13 | /// Prints 14 | /// 15 | internal const string FORMAT_MIN = "M"; 16 | 17 | internal static string DefaultFormat { get; set; } = FORMAT_MIN; 18 | } 19 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Meta/Base/EmbeddedClrStructure.cs: -------------------------------------------------------------------------------- 1 | using RazorSharp.CoreClr.Metadata; 2 | using RazorSharp.Memory.Pointers; 3 | 4 | // ReSharper disable InconsistentNaming 5 | 6 | namespace RazorSharp.CoreClr.Meta.Base 7 | { 8 | /// 9 | /// Describes a that is enclosed by an accompanying 10 | /// 11 | /// CLR structure type 12 | public abstract unsafe class EmbeddedClrStructure : ClrStructure where TClr : unmanaged 13 | { 14 | #region Constructors 15 | 16 | protected EmbeddedClrStructure(Pointer ptr) : base(ptr) { } 17 | 18 | #endregion 19 | 20 | #region MethodTable 21 | 22 | public abstract MetaType EnclosingType { get; } 23 | 24 | public MetaType EnclosingRuntimeType => EnclosingType.RuntimeType; 25 | 26 | #endregion 27 | } 28 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Meta/MetaField.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using RazorSharp.Analysis; 4 | using RazorSharp.CoreClr.Meta.Base; 5 | using RazorSharp.CoreClr.Metadata; 6 | using RazorSharp.CoreClr.Metadata.Enums; 7 | using RazorSharp.Memory; 8 | using RazorSharp.Memory.Components; 9 | using RazorSharp.Memory.Pointers; 10 | using SimpleSharp; 11 | using SimpleSharp.Diagnostics; 12 | 13 | // ReSharper disable SuggestBaseTypeForParameter 14 | 15 | // ReSharper disable InconsistentNaming 16 | 17 | namespace RazorSharp.CoreClr.Meta 18 | { 19 | /// 20 | /// 21 | /// CLR structure: 22 | /// Reflection structure: 23 | /// 24 | /// 25 | public unsafe class MetaField : EmbeddedClrStructure, IStructure 26 | { 27 | private const int FIELD_OFFSET_MAX = (1 << 27) - 1; 28 | 29 | private const int FIELD_OFFSET_NEW_ENC = FIELD_OFFSET_MAX - 4; 30 | 31 | private const int DW2_OFFSET_BITS = 27; 32 | 33 | #region Constructors 34 | 35 | internal MetaField(Pointer ptr) : base(ptr) { } 36 | 37 | public MetaField(FieldInfo info) : this(Runtime.ResolveHandle(info)) { } 38 | 39 | #endregion 40 | 41 | #region Accessors 42 | 43 | public FieldInfo FieldInfo => (FieldInfo) Info; 44 | 45 | public CorElementType CorType => Value.Reference.CorType; 46 | 47 | public ProtectionLevel Protection => Value.Reference.ProtectionLevel; 48 | 49 | public int Offset => Value.Reference.Offset; 50 | 51 | public override MemberInfo Info => EnclosingType.RuntimeType.Module.ResolveField(Token); 52 | 53 | public MetaType FieldType => FieldInfo.FieldType; 54 | 55 | public override MetaType EnclosingType { 56 | get { return (Pointer) Value.Reference.GetApproxEnclosingMethodTable(); } 57 | } 58 | 59 | public override int Token => Value.Reference.Token; 60 | 61 | public FieldAttributes Attributes => FieldInfo.Attributes; 62 | 63 | // public bool IsPrivate { 64 | // get => (((CorFieldAttr)Value.Reference.Dword1) & CorFieldAttr.fdFieldAccessMask) == CorFieldAttr.fdPrivate; 65 | // } 66 | 67 | #region bool 68 | 69 | public bool IsPointer => Value.Reference.IsPointer; 70 | 71 | public bool IsStatic => Value.Reference.IsStatic; 72 | 73 | public bool IsThreadLocal => Value.Reference.IsThreadLocal; 74 | 75 | public bool IsRVA => Value.Reference.IsRVA; 76 | 77 | public bool IsLiteral => FieldInfo.IsLiteral; 78 | 79 | #endregion 80 | 81 | #region Delegates 82 | 83 | public int Size => Value.Reference.LoadSize(); 84 | 85 | public Pointer GetStaticAddress() => Value.Reference.GetCurrentStaticAddress(); 86 | 87 | #endregion 88 | 89 | #endregion 90 | 91 | 92 | public Pointer GetValueAddress(ref T value) 93 | { 94 | return IsStatic ? GetStaticAddress() : GetAddress(ref value); 95 | } 96 | 97 | public Pointer GetAddress(ref T value) 98 | { 99 | Conditions.Require(!IsStatic, nameof(IsStatic)); 100 | Conditions.Require(Offset != FIELD_OFFSET_NEW_ENC); 101 | 102 | var data = Unsafe.AddressOfFields(ref value) + Offset; 103 | 104 | return data; 105 | } 106 | 107 | public object GetValue(object value) 108 | { 109 | return FieldInfo.GetValue(value); 110 | } 111 | 112 | public T GetValue(T value) 113 | { 114 | return GetAddress(ref value).Cast().Read(); 115 | } 116 | 117 | 118 | #region Operators 119 | 120 | public static implicit operator MetaField(Pointer ptr) 121 | { 122 | return new MetaField(ptr); 123 | } 124 | 125 | public static implicit operator MetaField(FieldInfo t) 126 | { 127 | return new MetaField(t); 128 | } 129 | 130 | #region Equality 131 | 132 | 133 | 134 | // public static bool operator ==(MetaField left, MetaField right) => Equals(left, right); 135 | 136 | // public static bool operator !=(MetaField left, MetaField right) => !Equals(left, right); 137 | 138 | #endregion 139 | 140 | #endregion 141 | 142 | #region Overrides 143 | 144 | protected override ConsoleTable InfoTable { 145 | get { 146 | var table = base.InfoTable; 147 | 148 | table.AddRow(nameof(Offset), Offset); 149 | table.AddRow(nameof(Size), Size); 150 | table.AddRow(nameof(Type), FieldType.Name); 151 | 152 | if (IsStatic) { 153 | table.AddRow(nameof(GetStaticAddress), GetStaticAddress()); 154 | } 155 | 156 | return table; 157 | } 158 | } 159 | 160 | #endregion 161 | } 162 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Meta/MetaIL.cs: -------------------------------------------------------------------------------- 1 | #region 2 | 3 | using System; 4 | using System.Reflection; 5 | using RazorSharp.CoreClr.Meta.Base; 6 | using RazorSharp.CoreClr.Metadata.JitIL; 7 | using RazorSharp.Interop; 8 | using RazorSharp.Interop.Enums; 9 | using RazorSharp.Memory.Pointers; 10 | using SimpleSharp; 11 | using SimpleSharp.Diagnostics; 12 | 13 | // ReSharper disable ReturnTypeCanBeEnumerable.Global 14 | 15 | #endregion 16 | 17 | // ReSharper disable InconsistentNaming 18 | 19 | namespace RazorSharp.CoreClr.Meta 20 | { 21 | /// 22 | /// 23 | /// CLR structure: 24 | /// Reflection structure: 25 | /// 26 | /// 27 | [Obsolete] 28 | public class MetaIL : AnonymousClrStructure 29 | { 30 | #region Constructor 31 | 32 | internal MetaIL(Pointer ptr) : base(ptr) { } 33 | 34 | #endregion 35 | 36 | #region Accessors 37 | 38 | /// 39 | /// Whether this type is 40 | /// 41 | public bool IsTiny => Value.Reference.IsTiny; 42 | 43 | /// 44 | /// Whether this type is 45 | /// 46 | public bool IsFat => Value.Reference.IsFat; 47 | 48 | /// 49 | /// Points to the JIT IL code 50 | /// 51 | public Pointer Code => Value.Reference.Code; 52 | 53 | /// 54 | /// Length/size of the IL code () 55 | /// 56 | public int CodeSize => Value.Reference.CodeSize; 57 | 58 | /// 59 | /// 60 | /// Equals 61 | /// 62 | /// 63 | public int MaxStackSize => Value.Reference.MaxStackSize; 64 | 65 | /// 66 | /// 67 | /// Equals 68 | /// 69 | /// 70 | public override int Token => Value.Reference.Token; 71 | 72 | /// 73 | /// 74 | /// must be true 75 | /// 76 | /// 77 | public CorILMethodFlags Flags => Value.Reference.Flags; 78 | 79 | /// 80 | /// 81 | /// Equals 82 | /// 83 | /// 84 | /// 85 | public byte[] RawIL => Value.Reference.RawIL; 86 | 87 | public Instruction[] Instructions => InspectIL.GetInstructions(RawIL); 88 | 89 | #endregion 90 | 91 | internal void SetCode(byte[] code) //todo: WIP 92 | { 93 | Conditions.Require(code.Length <= CodeSize, nameof(code)); 94 | 95 | int ul = code.Length; 96 | var ptr = Code.Address; 97 | 98 | Native.Kernel32.VirtualProtect(ptr, ul, MemoryProtection.ExecuteReadWrite, out var oldProtect); 99 | 100 | Code.WriteAll(code); 101 | 102 | Native.Kernel32.VirtualProtect(ptr, ul, oldProtect, out oldProtect); 103 | } 104 | 105 | protected override ConsoleTable InfoTable { 106 | get { 107 | var table = base.InfoTable; 108 | 109 | table.AddRow(nameof(Code), Code); 110 | table.AddRow(nameof(CodeSize), CodeSize); 111 | table.AddRow(nameof(MaxStackSize), MaxStackSize); 112 | 113 | if (IsFat) { 114 | table.AddRow(nameof(Flags), Flags); 115 | } 116 | 117 | table.AddRow(nameof(IsTiny), IsTiny); 118 | table.AddRow(nameof(IsFat), IsFat); 119 | 120 | return table; 121 | } 122 | } 123 | } 124 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Meta/MetaLayout.cs: -------------------------------------------------------------------------------- 1 | using RazorSharp.CoreClr.Meta.Base; 2 | using RazorSharp.CoreClr.Metadata.Enums; 3 | using RazorSharp.CoreClr.Metadata.ExecutionEngine; 4 | using RazorSharp.Memory.Pointers; 5 | 6 | // ReSharper disable InconsistentNaming 7 | 8 | namespace RazorSharp.CoreClr.Meta 9 | { 10 | /// 11 | /// 12 | /// CLR structure: 13 | /// Reflection structure: N/A 14 | /// 15 | /// 16 | public unsafe class MetaLayout : AnonymousClrStructure 17 | { 18 | #region Constructors 19 | 20 | internal MetaLayout(Pointer ptr) : base(ptr) { } 21 | 22 | #endregion 23 | 24 | #region Accessors 25 | 26 | public int NativeSize => Value.Reference.NativeSize; 27 | 28 | public int ManagedSize => Value.Reference.ManagedSize; 29 | 30 | public LayoutFlags Flags => Value.Reference.Flags; 31 | 32 | public int PackingSize => Value.Reference.PackingSize; 33 | 34 | public int NumCTMFields => Value.Reference.NumCTMFields; 35 | 36 | public Pointer FieldMarshalers => Value.Reference.FieldMarshalers; 37 | 38 | #endregion 39 | } 40 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Meta/MetaMethod.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using RazorSharp.CoreClr.Meta.Base; 5 | using RazorSharp.CoreClr.Metadata; 6 | using RazorSharp.CoreClr.Metadata.Enums; 7 | using RazorSharp.Memory.Pointers; 8 | using RazorSharp.Utilities; 9 | using SimpleSharp; 10 | 11 | // ReSharper disable SuggestBaseTypeForParameter 12 | 13 | 14 | // ReSharper disable InconsistentNaming 15 | 16 | namespace RazorSharp.CoreClr.Meta 17 | { 18 | /// 19 | /// 20 | /// CLR structure: 21 | /// Reflection structure: 22 | /// 23 | /// 24 | public unsafe class MetaMethod : EmbeddedClrStructure 25 | { 26 | #region Constructors 27 | 28 | internal MetaMethod(Pointer ptr) : base(ptr) { } 29 | 30 | public MetaMethod(MethodInfo member) : this(Runtime.ResolveHandle(member)) { } 31 | 32 | #endregion 33 | 34 | #region Accessors 35 | 36 | public int ChunkIndex => Value.Reference.ChunkIndex; 37 | 38 | public int SlotNumber => Value.Reference.SlotNumber; 39 | 40 | #region bool 41 | 42 | public bool IsRuntimeSupplied => 43 | Classification == MethodClassification.FCall || 44 | Classification == MethodClassification.Array; 45 | 46 | public bool IsNoMetadata => Classification == MethodClassification.Dynamic; 47 | 48 | public bool HasILHeader => IsIL && !IsUnboxingStub && RVA > default(long); 49 | 50 | private bool IsUnboxingStub => Flags2.HasFlagFast(MethodDescFlags2.IsUnboxingStub); 51 | 52 | public bool IsIL => MethodClassification.IL == Classification || 53 | MethodClassification.Instantiated == Classification; 54 | 55 | public bool IsPreImplemented => !PreImplementedCode.IsNull; 56 | 57 | #endregion 58 | 59 | #region Flags 60 | 61 | public MethodClassification Classification => Value.Reference.Classification; 62 | public MethodDescClassification Flags => Value.Reference.Flags; 63 | public MethodDescFlags2 Flags2 => Value.Reference.Flags2; 64 | public MethodDescFlags3 Flags3 => Value.Reference.Flags3AndTokenRemainder; 65 | public MethodAttributes Attributes => MethodInfo.Attributes; 66 | 67 | #endregion 68 | 69 | public MethodInfo MethodInfo => (MethodInfo) Info; 70 | 71 | public override MemberInfo Info => EnclosingRuntimeType.RuntimeType.Module.ResolveMethod(Token); 72 | 73 | public void Prepare() 74 | { 75 | RuntimeHelpers.PrepareMethod(MethodInfo.MethodHandle); 76 | } 77 | 78 | protected override ConsoleTable InfoTable { 79 | get { 80 | var table = base.InfoTable; 81 | table.AddRow(nameof(Classification), Classification); 82 | return table; 83 | } 84 | } 85 | 86 | #endregion 87 | 88 | #region Delegates 89 | 90 | public long RVA => Value.Reference.RVA; 91 | 92 | [Obsolete] 93 | private MetaIL GetILHeaderInternal(bool fAllowOverrides = default) 94 | { 95 | return new MetaIL(Value.Reference.GetILHeader(Convert.ToInt32(fAllowOverrides))); 96 | } 97 | 98 | [Obsolete] 99 | public MetaIL ILHeader => GetILHeaderInternal(); 100 | 101 | public override MetaType EnclosingType => (Pointer) Value.Reference.MethodTable; 102 | 103 | public override int Token => Value.Reference.Token; 104 | 105 | public Pointer NativeCode { 106 | get => Value.Reference.NativeCode; 107 | set => Value.Reference.SetNativeCodeInterlocked(value.ToInt64()); 108 | } 109 | 110 | public Pointer Function { 111 | get => MethodInfo.MethodHandle.GetFunctionPointer(); 112 | set => NativeCode = value; 113 | } 114 | 115 | public void Reset() => Value.Reference.Reset(); 116 | 117 | public bool IsPointingToNativeCode => Value.Reference.IsPointingToNativeCode(); 118 | 119 | public Pointer PreImplementedCode => Value.Reference.PreImplementedCode; 120 | 121 | #endregion 122 | 123 | #region Operators 124 | 125 | public static implicit operator MetaMethod(Pointer ptr) => new MetaMethod(ptr); 126 | 127 | public static implicit operator MetaMethod(MethodInfo t) => new MetaMethod(t); 128 | 129 | #endregion 130 | } 131 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Metadata/Enums/CorEnums.cs: -------------------------------------------------------------------------------- 1 | namespace RazorSharp.CoreClr.Metadata.Enums 2 | { 3 | 4 | // [Flags] 5 | public enum CorInterfaceAttr 6 | { 7 | Dual = 0, // Interface derives from IDispatch. 8 | Vtable = 1, // Interface derives from IUnknown. 9 | Dispatch = 2, // Interface is a dispinterface. 10 | Inspectable = 3, // Interface derives from IInspectable. 11 | Last = 4, // The last member of the enum. 12 | } 13 | 14 | public enum CorElementType : byte 15 | { 16 | End = 0x00, 17 | Void = 0x01, 18 | 19 | /// 20 | /// bool 21 | /// 22 | Boolean = 0x02, 23 | 24 | /// 25 | /// char 26 | /// 27 | Char = 0x03, 28 | 29 | /// 30 | /// sbyte 31 | /// 32 | I1 = 0x04, 33 | 34 | /// 35 | /// byte 36 | /// 37 | U1 = 0x05, 38 | 39 | /// 40 | /// short 41 | /// 42 | I2 = 0x06, 43 | 44 | /// 45 | /// ushort 46 | /// 47 | U2 = 0x07, 48 | 49 | /// 50 | /// int 51 | /// 52 | I4 = 0x08, 53 | 54 | /// 55 | /// uint 56 | /// 57 | U4 = 0x09, 58 | 59 | /// 60 | /// long 61 | /// 62 | I8 = 0x0A, 63 | 64 | /// 65 | /// ulong 66 | /// 67 | U8 = 0x0B, 68 | 69 | /// 70 | /// float 71 | /// 72 | R4 = 0x0C, 73 | 74 | /// 75 | /// double 76 | /// 77 | R8 = 0x0D, 78 | 79 | /// 80 | /// Note: strings don't actually map to this. They map to 81 | /// 82 | String = 0x0E, 83 | 84 | Ptr = 0x0F, 85 | ByRef = 0x10, 86 | 87 | /// 88 | /// Struct type 89 | /// 90 | ValueType = 0x11, 91 | 92 | /// 93 | /// Reference type (i.e. string, object) 94 | /// 95 | Class = 0x12, 96 | 97 | Var = 0x13, 98 | Array = 0x14, 99 | GenericInst = 0x15, 100 | TypedByRef = 0x16, 101 | I = 0x18, 102 | U = 0x19, 103 | FnPtr = 0x1B, 104 | Object = 0x1C, 105 | SzArray = 0x1D, 106 | MVar = 0x1E, 107 | CModReqd = 0x1F, 108 | CModOpt = 0x20, 109 | Internal = 0x21, 110 | Max = 0x22, 111 | Modifier = 0x40, 112 | Sentinel = 0x41, 113 | Pinned = 0x45 114 | } 115 | 116 | public enum CorTokenType : uint 117 | { 118 | Module = 0x00000000, 119 | TypeRef = 0x01000000, 120 | TypeDef = 0x02000000, 121 | FieldDef = 0x04000000, 122 | MethodDef = 0x06000000, 123 | ParamDef = 0x08000000, 124 | InterfaceImpl = 0x09000000, 125 | MemberRef = 0x0a000000, 126 | CustomAttribute = 0x0c000000, 127 | Permission = 0x0e000000, 128 | Signature = 0x11000000, 129 | Event = 0x14000000, 130 | Property = 0x17000000, 131 | MethodImpl = 0x19000000, 132 | ModuleRef = 0x1a000000, 133 | TypeSpec = 0x1b000000, 134 | Assembly = 0x20000000, 135 | AssemblyRef = 0x23000000, 136 | File = 0x26000000, 137 | ExportedType = 0x27000000, 138 | ManifestResource = 0x28000000, 139 | GenericParam = 0x2a000000, 140 | MethodSpec = 0x2b000000, 141 | GenericParamConstraint = 0x2c000000, 142 | String = 0x70000000, 143 | Name = 0x71000000, 144 | 145 | BaseType = 0x72000000 // Leave this on the high end value. This does not correspond to metadata table 146 | } 147 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Metadata/Enums/EEClassEnums.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable InconsistentNaming 2 | 3 | using System; 4 | 5 | namespace RazorSharp.CoreClr.Metadata.Enums 6 | { 7 | public enum EEClassFieldId : uint 8 | { 9 | NumInstanceFields = 0, 10 | NumMethods, 11 | NumStaticFields, 12 | NumHandleStatics, 13 | NumBoxedStatics, 14 | NonGCStaticFieldBytes, 15 | NumThreadStaticFields, 16 | NumHandleThreadStatics, 17 | NumBoxedThreadStatics, 18 | NonGCThreadStaticFieldBytes, 19 | NumNonVirtualSlots, 20 | COUNT 21 | } 22 | 23 | [Flags] 24 | public enum LayoutFlags : byte 25 | { 26 | /// 27 | /// TRUE if the GC layout of the class is bit-for-bit identical 28 | /// to its unmanaged counterpart (i.e. no internal reference fields, 29 | /// no ansi-unicode char conversions required, etc.) Used to 30 | /// optimize marshaling. 31 | /// 32 | Blittable = 0x01, 33 | 34 | /// 35 | /// Is this type also sequential in managed memory? 36 | /// 37 | ManagedSequential = 0x02, 38 | 39 | /// 40 | /// When a sequential/explicit type has no fields, it is conceptually 41 | /// zero-sized, but actually is 1 byte in length. This holds onto this 42 | /// fact and allows us to revert the 1 byte of padding when another 43 | /// explicit type inherits from this type. 44 | /// 45 | ZeroSized = 0x04, 46 | 47 | /// 48 | /// The size of the struct is explicitly specified in the meta-data. 49 | /// 50 | HasExplicitSize = 0x08, 51 | 52 | /// 53 | /// Whether a native struct is passed in registers. 54 | /// 55 | NativePassInRegisters = 0x10, 56 | 57 | R4HFA = 0x10, 58 | R8HFA = 0x20 59 | } 60 | 61 | [Flags] 62 | public enum VMFlags : uint 63 | { 64 | LayoutDependsOnOtherModules = 0x00000001, 65 | Delegate = 0x00000002, 66 | 67 | /// 68 | /// Value type Statics in this class will be pinned 69 | /// 70 | FixedAddressVtStatics = 0x00000020, 71 | HasLayout = 0x00000040, 72 | IsNested = 0x00000080, 73 | IsEquivalentType = 0x00000200, 74 | 75 | // OVERLAYED is used to detect whether Equals can safely optimize to a bit-compare across the structure. 76 | HasOverlayedFields = 0x00000400, 77 | 78 | // Set this if this class or its parent have instance fields which 79 | // must be explicitly inited in a constructor (e.g. pointers of any 80 | // kind, gc or native). 81 | // 82 | // Currently this is used by the verifier when verifying value classes 83 | // - it's ok to use uninitialised value classes if there are no 84 | // pointer fields in them. 85 | HasFieldsWhichMustBeInited = 0x00000800, 86 | 87 | UnsafeValueType = 0x00001000, 88 | 89 | /// 90 | /// and are valid only if this is set 91 | /// 92 | BestFitMappingInited = 0x00002000, 93 | BestFitMapping = 0x00004000, // BestFitMappingAttribute.Value 94 | ThrowOnUnmappableChar = 0x00008000, // BestFitMappingAttribute.ThrowOnUnmappableChar 95 | 96 | // unused = 0x00010000, 97 | NoGuid = 0x00020000, 98 | HasNonPublicFields = 0x00040000, 99 | 100 | // unused = 0x00080000, 101 | ContainsStackPtr = 0x00100000, 102 | 103 | /// 104 | /// Would like to have 8-byte alignment 105 | /// 106 | PreferAlign8 = 0x00200000, 107 | // unused = 0x00400000, 108 | 109 | SparseForCominterop = 0x00800000, 110 | 111 | // interfaces may have a coclass attribute 112 | HasCoClassAttrib = 0x01000000, 113 | ComEventItfMask = 0x02000000, // class is a special COM event interface 114 | ProjectedFromWinRT = 0x04000000, 115 | ExportedToWinRT = 0x08000000, 116 | 117 | // This one indicates that the fields of the valuetype are 118 | // not tightly packed and is used to check whether we can 119 | // do bit-equality on value types to implement ValueType::Equals. 120 | // It is not valid for classes, and only matters if ContainsPointer 121 | // is false. 122 | NotTightlyPacked = 0x10000000, 123 | 124 | // True if methoddesc on this class have any real (non-interface) methodimpls 125 | ContainsMethodImpls = 0x20000000, 126 | MarshalingTypeMask = 0xc0000000, 127 | MarshalingTypeInhibit = 0x40000000, 128 | MarshalingTypeFreeThreaded = 0x80000000, 129 | MarshalingTypeStandard = 0xc0000000 130 | } 131 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Metadata/Enums/FieldDescEnums.cs: -------------------------------------------------------------------------------- 1 | namespace RazorSharp.CoreClr.Metadata.Enums 2 | { 3 | public enum ProtectionLevel 4 | { 5 | Private = 4, 6 | PrivateProtected = 8, 7 | Internal = 12, 8 | Protected = 16, 9 | ProtectedInternal = 20, 10 | Public = 24 11 | } 12 | 13 | internal enum MbMask 14 | { 15 | PackedMbLayoutMbMask = 0x01FFFF, 16 | PackedMbLayoutNameHashMask = 0xFE0000 17 | } 18 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Metadata/ExecutionEngine/EEClass.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | using RazorSharp.CoreClr.Metadata.Enums; 4 | using RazorSharp.Memory.Pointers; 5 | 6 | // ReSharper disable ArrangeAccessorOwnerBody 7 | 8 | // ReSharper disable UnassignedGetOnlyAutoProperty 9 | // ReSharper disable InconsistentNaming 10 | 11 | namespace RazorSharp.CoreClr.Metadata.ExecutionEngine 12 | { 13 | [StructLayout(LayoutKind.Sequential)] 14 | public unsafe struct EEClass 15 | { 16 | #region Fields 17 | 18 | internal void* GuidInfo { get; } 19 | 20 | internal void* OptionalFields { get; } 21 | 22 | internal MethodTable* MethodTable { get; } 23 | 24 | private FieldDesc* FieldDescListRaw { get; } 25 | 26 | internal void* Chunks { get; } 27 | 28 | 29 | #region Union 1 30 | 31 | /// 32 | /// Union 1 33 | /// void* 34 | /// uint 35 | /// int 36 | /// 37 | private void* m_union1; 38 | 39 | internal void* OhDelegate => m_union1; 40 | 41 | internal uint NativeSize { 42 | get { 43 | fixed (EEClass* value = &this) { 44 | Pointer ptr = &value->m_union1; 45 | return ptr.Reference; 46 | } 47 | } 48 | } 49 | 50 | internal CorInterfaceAttr ComInterfaceType { 51 | get { 52 | fixed (EEClass* value = &this) { 53 | Pointer ptr = &value->m_union1; 54 | return (CorInterfaceAttr) ptr.Reference; 55 | } 56 | } 57 | } 58 | 59 | #endregion 60 | 61 | 62 | internal void* CCWTemplate { get; } 63 | 64 | internal TypeAttributes Attributes { get; } 65 | 66 | internal VMFlags VMFlags { get; } 67 | 68 | internal CorElementType NormType { get; } 69 | 70 | internal bool FieldsArePacked { get; } 71 | 72 | internal byte FixedEEClassFields { get; } 73 | 74 | internal byte BaseSizePadding { get; } 75 | 76 | #endregion 77 | 78 | #region Accessors 79 | 80 | internal FieldDesc* FieldDescList { 81 | get { 82 | //PTR_HOST_MEMBER_TADDR(EEClass, this, m_pFieldDescList) 83 | return (FieldDesc*) Runtime.HostMemberOffset(ref this, FD_LIST_FIELD_OFFSET, FieldDescListRaw); 84 | } 85 | } 86 | 87 | 88 | internal Pointer LayoutInfo { 89 | get { 90 | fixed (EEClass* value = &this) { 91 | var thisptr = ((Pointer) value) 92 | .Add(sizeof(EEClass)) 93 | .Address; 94 | 95 | return &((LayoutEEClass*) thisptr)->m_LayoutInfo; 96 | } 97 | } 98 | } 99 | 100 | /// 101 | /// Abstracted to 102 | /// 103 | internal int FieldDescListLength { 104 | get { 105 | Pointer pClass = MethodTable->EEClass; 106 | int fieldCount = pClass.Reference.NumInstanceFields + pClass.Reference.NumStaticFields; 107 | Pointer pParentMT = MethodTable->Parent; 108 | 109 | if (!pParentMT.IsNull) 110 | fieldCount -= pParentMT.Reference.EEClass.Reference.NumInstanceFields; 111 | 112 | return fieldCount; 113 | } 114 | } 115 | 116 | // todo: fd list 117 | 118 | #endregion 119 | 120 | #region Packed fields 121 | 122 | internal int NumInstanceFields => GetPackableField(EEClassFieldId.NumInstanceFields); 123 | internal int NumStaticFields => GetPackableField(EEClassFieldId.NumStaticFields); 124 | internal int NumMethods => GetPackableField(EEClassFieldId.NumMethods); 125 | internal int NumNonVirtualSlots => GetPackableField(EEClassFieldId.NumNonVirtualSlots); 126 | 127 | private int GetPackableField(EEClassFieldId eField) 128 | { 129 | uint u = (uint) eField; 130 | return (int) (FieldsArePacked ? PackedFields->GetPackedField(u) : PackedFields->GetUnpackedField(u)); 131 | } 132 | 133 | private PackedDWORDFields* PackedFields { 134 | get { 135 | fixed (EEClass* value = &this) { 136 | var bp = (Pointer) value; 137 | return (PackedDWORDFields*) bp.Add(FixedEEClassFields); 138 | } 139 | } 140 | } 141 | 142 | #endregion 143 | 144 | #region EEClass offsets 145 | 146 | /// 147 | /// Offset for the field 148 | /// 149 | /// Relative to address of a 150 | /// 151 | /// 152 | private const int FD_LIST_FIELD_OFFSET = 24; 153 | 154 | #endregion 155 | } 156 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Metadata/ExecutionEngine/EEClassLayoutInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using RazorSharp.CoreClr.Metadata.Enums; 3 | 4 | // ReSharper disable UnassignedGetOnlyAutoProperty 5 | // ReSharper disable InconsistentNaming 6 | 7 | namespace RazorSharp.CoreClr.Metadata.ExecutionEngine 8 | { 9 | [StructLayout(LayoutKind.Sequential)] 10 | public unsafe struct EEClassLayoutInfo 11 | { 12 | #region Fields 13 | 14 | // why is there an m_cbNativeSize in EEClassLayoutInfo and EEClass? 15 | internal int NativeSize { get; } 16 | 17 | internal int ManagedSize { get; } 18 | 19 | // 1,2,4 or 8: this is equal to the largest of the alignment requirements 20 | // of each of the EEClass's members. If the NStruct extends another NStruct, 21 | // the base NStruct is treated as the first member for the purpose of 22 | // this calculation. 23 | internal byte LargestAlignmentRequirementOfAllMembers { get; } 24 | 25 | // Post V1.0 addition: This is the equivalent of m_LargestAlignmentRequirementOfAllMember 26 | // for the managed layout. 27 | internal byte ManagedLargestAlignmentRequirementOfAllMembers { get; } 28 | 29 | internal LayoutFlags Flags { get; } 30 | 31 | internal byte PackingSize { get; } 32 | 33 | /// 34 | /// # of fields that are of the calltime-marshal variety. 35 | /// 36 | internal int NumCTMFields { get; } 37 | 38 | internal void* FieldMarshalers { get; } 39 | 40 | #endregion 41 | } 42 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Metadata/ExecutionEngine/LayoutEEClass.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | // ReSharper disable InconsistentNaming 4 | 5 | namespace RazorSharp.CoreClr.Metadata.ExecutionEngine 6 | { 7 | [StructLayout(LayoutKind.Explicit)] 8 | internal struct LayoutEEClass 9 | { 10 | // Note: This offset should be 72 or sizeof(EEClass) 11 | // but I'm keeping it at 0 to minimize size usage, 12 | // so I'll just offset the pointer by 72 bytes 13 | [FieldOffset(0)] 14 | internal EEClassLayoutInfo m_LayoutInfo; 15 | } 16 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Metadata/FieldDesc.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.InteropServices; 3 | using RazorSharp.Core; 4 | using RazorSharp.CoreClr.Metadata.Enums; 5 | using RazorSharp.Import; 6 | using RazorSharp.Import.Attributes; 7 | using RazorSharp.Import.Enums; 8 | using RazorSharp.Interop; 9 | using RazorSharp.Memory; 10 | using RazorSharp.Memory.Pointers; 11 | using RazorSharp.Utilities; 12 | 13 | // ReSharper disable UnassignedGetOnlyAutoProperty 14 | // ReSharper disable InconsistentNaming 15 | 16 | namespace RazorSharp.CoreClr.Metadata 17 | { 18 | [ImportNamespace] 19 | [StructLayout(LayoutKind.Sequential)] 20 | public unsafe struct FieldDesc 21 | { 22 | static FieldDesc() 23 | { 24 | ImportManager.Value.Load(typeof(FieldDesc), Clr.Value.Imports); 25 | } 26 | 27 | [ImportMapDesignation] 28 | private static readonly ImportMap Imports = new ImportMap(); 29 | 30 | #region Fields 31 | 32 | private MethodTable* EnclosingMethodTableStub { get; } 33 | 34 | /// 35 | /// DWORD #1 36 | /// unsigned m_mb : 24; 37 | /// unsigned m_isStatic : 1; 38 | /// unsigned m_isThreadLocal : 1; 39 | /// unsigned m_isRVA : 1; 40 | /// unsigned m_prot : 3; 41 | /// unsigned m_requiresFullMbValue : 1; 42 | /// 43 | private uint UInt1 { get; } 44 | 45 | /// 46 | /// DWORD #2 47 | /// unsigned m_dwOffset : 27; 48 | /// unsigned m_type : 5; 49 | /// 50 | private uint UInt2 { get; } 51 | 52 | #endregion 53 | 54 | #region Calculated values 55 | 56 | private bool RequiresFullMBValue => Bits.ReadBit(UInt1, 31); 57 | 58 | internal int Token { 59 | get { 60 | var rawToken = (int) (UInt1 & 0xFFFFFF); 61 | // Check if this FieldDesc is using the packed mb layout 62 | if (!RequiresFullMBValue) 63 | return Tokens.TokenFromRid(rawToken & (int) MbMask.PackedMbLayoutMbMask, 64 | CorTokenType.FieldDef); 65 | 66 | return Tokens.TokenFromRid(rawToken, CorTokenType.FieldDef); 67 | } 68 | } 69 | 70 | internal int Offset => (int) (UInt2 & 0x7FFFFFF); 71 | 72 | internal CorElementType CorType => (CorElementType) (int) ((UInt2 >> 27) & 0x7FFFFFF); 73 | 74 | internal ProtectionLevel ProtectionLevel => (ProtectionLevel) (int) ((UInt1 >> 26) & 0x3FFFFFF); 75 | 76 | internal bool IsPointer => CorType == CorElementType.Ptr; 77 | 78 | 79 | internal bool IsStatic => Bits.ReadBit(UInt1, 24); 80 | 81 | 82 | internal bool IsThreadLocal => Bits.ReadBit(UInt1, 25); 83 | 84 | 85 | internal bool IsRVA => Bits.ReadBit(UInt1, 26); 86 | 87 | #endregion 88 | 89 | #region Imports 90 | 91 | [ImportCall(CallOptions = ImportCallOptions.Map)] 92 | internal int LoadSize() 93 | { 94 | fixed (FieldDesc* value = &this) { 95 | return Functions.Native.Call((void*) Imports[nameof(LoadSize)], value); 96 | } 97 | } 98 | 99 | [ImportCall(CallOptions = ImportCallOptions.Map)] 100 | internal void* GetCurrentStaticAddress() 101 | { 102 | fixed (FieldDesc* value = &this) { 103 | return Functions.Native.CallReturnPointer((void*) Imports[nameof(GetCurrentStaticAddress)], value); 104 | } 105 | } 106 | 107 | 108 | 109 | [ImportCall(CallOptions = ImportCallOptions.Map)] 110 | internal void* GetApproxEnclosingMethodTable() 111 | { 112 | fixed (FieldDesc* value = &this) { 113 | return Functions.Native.CallReturnPointer((void*) Imports[nameof(GetApproxEnclosingMethodTable)], 114 | value); 115 | } 116 | } 117 | 118 | #endregion 119 | } 120 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Metadata/JitIL/FatILMethod.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using RazorSharp.CoreClr.Meta; 3 | using RazorSharp.Memory; 4 | using RazorSharp.Memory.Pointers; 5 | 6 | // ReSharper disable FieldCanBeMadeReadOnly.Local 7 | 8 | // ReSharper disable InconsistentNaming 9 | 10 | namespace RazorSharp.CoreClr.Metadata.JitIL 11 | { 12 | /// 13 | /// 14 | /// CLR . Functionality is implemented in this struct and exposed via 15 | /// 16 | /// 17 | /// Internal name: COR_ILMETHOD_FAT 18 | /// This structure is the 'fat' layout, where no compression is attempted. 19 | /// Note that this structure can be added on at the end, thus making it extensible 20 | /// typedef struct tagCOR_ILMETHOD_FAT : IMAGE_COR_ILMETHOD_FAT 21 | /// Corresponding files: 22 | /// 23 | /// 24 | /// /src/inc/corhlpr.h 25 | /// 26 | /// 27 | /// Lines of interest: 28 | /// 29 | /// 30 | /// /src/inc/corhlpr.h: 510 31 | /// 32 | /// 33 | /// 34 | [StructLayout(LayoutKind.Explicit)] 35 | internal unsafe struct FatILMethod /* : IMAGE_COR_ILMETHOD_FAT */ 36 | { 37 | #region Structs 38 | 39 | /// 40 | /// Internal name: IMAGE_COR_ILMETHOD_FAT 41 | /// This structure is the 'fat' layout, where no compression is attempted. 42 | /// Note that this structure can be added on at the end, thus making it extensible 43 | /// Corresponding files: 44 | /// 45 | /// 46 | /// /src/inc/corhdr.h 47 | /// 48 | /// 49 | /// Lines of interest: 50 | /// 51 | /// 52 | /// /src/inc/corhdr.h: 1238 53 | /// 54 | /// 55 | /// 56 | [StructLayout(LayoutKind.Sequential)] 57 | private struct IMAGE_COR_ILMETHOD_FAT 58 | { 59 | /// 60 | /// Flags 61 | /// unsigned Flags : 12; 62 | /// Size in dwords of this structure (currently 3) 63 | /// unsigned Size : 4; 64 | /// Maximum number of items (I4, I, I8, obj ...), on the operand stack 65 | /// unsigned MaxStack : 16; 66 | /// 67 | internal uint m_dword1; 68 | 69 | internal uint m_codeSize; 70 | 71 | internal uint m_sigTok; 72 | } 73 | 74 | #endregion 75 | 76 | /// 77 | /// This value is inherited from 78 | /// 79 | [FieldOffset(0)] 80 | private readonly IMAGE_COR_ILMETHOD_FAT m_value; 81 | 82 | // public uint Flags => m_inlineValue.m_dword1 & 0xFFF; 83 | // public uint Size => (m_inlineValue.m_dword1 >> 4) & 0xFFF; 84 | // public uint MaxStack => (m_inlineValue.m_dword1 >> 16) & 0xFFF; 85 | 86 | internal uint CodeSize => m_value.m_codeSize; 87 | internal uint Token => m_value.m_sigTok; 88 | 89 | 90 | /// 91 | /// Max stack size 92 | /// 93 | /// return VAL16(*(USHORT*)((BYTE*)this+2)); 94 | /// 95 | /// 96 | internal uint MaxStackSize => *(ushort*) ((byte*) Unsafe.AddressOf(ref this) + 2); 97 | 98 | /// 99 | /// 100 | /// /* return Flags; */ 101 | /// BYTE* p = (BYTE*)this; 102 | /// return ((unsigned)*(p+0)) | (( ((unsigned)*(p+1)) & 0x0F) << 8); 103 | /// 104 | /// 105 | internal CorILMethodFlags Flags { 106 | get { 107 | var p = (byte*) Unsafe.AddressOf(ref this); 108 | return (CorILMethodFlags) (((uint) *p + 0) | ((((uint) *p + 1) & 0x0F) << 8)); 109 | } 110 | } 111 | 112 | 113 | /// 114 | /// 115 | /// return (*(BYTE*)this & CorILMethod_FormatMask) == CorILMethod_FatFormat; 116 | /// 117 | /// 118 | internal bool IsFat { 119 | get { 120 | return (CorILMethodFlags) (*(byte*) Unsafe.AddressOf(ref this) & 121 | (byte) CorILMethodFlags.FormatMask) == CorILMethodFlags.FatFormat; 122 | } 123 | } 124 | 125 | /// 126 | /// 127 | /// /* return Size; */ 128 | /// BYTE* p = (BYTE*)this; 129 | /// return *(p+1) >> 4; 130 | /// 131 | /// 132 | private int Size { 133 | get { 134 | var p = (byte*) Unsafe.AddressOf(ref this); 135 | return *(p + 1) >> 4; 136 | } 137 | } 138 | 139 | /// 140 | /// 141 | /// return(((BYTE*) this) + 4*GetSize()); 142 | /// 143 | /// 144 | internal Pointer Code { 145 | get { 146 | var ptr = (byte*) Unsafe.AddressOf(ref this) + sizeof(int) * Size; 147 | return ptr; 148 | } 149 | } 150 | } 151 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Metadata/JitIL/ILMethod.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using RazorSharp.Memory; 4 | using RazorSharp.Memory.Pointers; 5 | using RazorSharp.Utilities.Security; 6 | 7 | // ReSharper disable InconsistentNaming 8 | 9 | namespace RazorSharp.CoreClr.Metadata.JitIL 10 | { 11 | [Flags] 12 | public enum CorILMethodFlags : byte 13 | { 14 | /// 15 | /// Call default constructor on all local vars 16 | /// 17 | InitLocals = 0x0010, 18 | 19 | /// 20 | /// There is another attribute after this one 21 | /// 22 | MoreSects = 0x0008, 23 | 24 | /// 25 | /// Not used. 26 | /// 27 | CompressedIL = 0x0040, 28 | 29 | /// 30 | /// Indicates the format for the header 31 | /// 32 | FormatShift = 3, 33 | FormatMask = (1 << FormatShift) - 1, 34 | 35 | /// 36 | /// Use this code if the code size is even 37 | /// 38 | TinyFormat = 0x0002, 39 | SmallFormat = 0x0000, 40 | FatFormat = 0x0003, 41 | 42 | /// 43 | /// use this code if the code size is odd 44 | /// 45 | TinyFormat1 = 0x0006 46 | } 47 | 48 | /// 49 | /// Aggregates both and 50 | /// Internal name: COR_ILMETHOD 51 | /// Corresponding files: 52 | /// 53 | /// 54 | /// /src/inc/corhlpr.h 55 | /// 56 | /// 57 | /// Lines of interest: 58 | /// 59 | /// 60 | /// /src/inc/corhlpr.h: 595 61 | /// 62 | /// 63 | /// 64 | [StructLayout(LayoutKind.Explicit)] 65 | public struct ILMethod 66 | { 67 | /** 68 | * union 69 | * { 70 | * COR_ILMETHOD_TINY Tiny; 71 | * COR_ILMETHOD_FAT Fat; 72 | * }; 73 | * // Code follows the Header, then immediately after the code comes 74 | * // any sections (COR_ILMETHOD_SECT). 75 | */ 76 | 77 | [FieldOffset(default)] 78 | private TinyILMethod m_tiny; 79 | 80 | [FieldOffset(default)] 81 | private FatILMethod m_fat; 82 | 83 | private Pointer Tiny => Unsafe.AddressOf(ref m_tiny); 84 | private Pointer Fat => Unsafe.AddressOf(ref m_fat); 85 | 86 | internal bool IsTiny => Tiny.Reference.IsTiny; 87 | 88 | internal bool IsFat => Fat.Reference.IsFat; 89 | 90 | internal byte[] RawIL => Code.Copy(CodeSize); 91 | 92 | internal CorILMethodFlags Flags { 93 | get { 94 | // todo: I don't know if the type has to be Fat or not, but just to be safe... 95 | if (!IsFat) 96 | throw Guard.CorILFail("IL method type must be Fat"); 97 | 98 | return Fat.Reference.Flags; 99 | } 100 | } 101 | 102 | 103 | internal Pointer Code { 104 | get { 105 | Pointer code = IsTiny ? Tiny.Reference.Code : Fat.Reference.Code; 106 | return code; 107 | } 108 | } 109 | 110 | internal int CodeSize => (int) (IsTiny ? Tiny.Reference.CodeSize : Fat.Reference.CodeSize); 111 | 112 | internal int MaxStackSize => (int) (IsTiny ? TinyILMethod.MaxStackSize : Fat.Reference.MaxStackSize); 113 | 114 | /// 115 | /// LocalSignatureMetadataToken 116 | /// 117 | internal int Token => (int) (IsTiny ? TinyILMethod.Token : Fat.Reference.Token); 118 | } 119 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Metadata/JitIL/Instruction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Reflection.Emit; 4 | using SimpleSharp.Strings.Formatting; 5 | 6 | namespace RazorSharp.CoreClr.Metadata.JitIL 7 | { 8 | /// 9 | /// Represents an IL instruction. 10 | /// 11 | public struct Instruction 12 | { 13 | public int Offset { get; internal set; } 14 | 15 | public OpCode OpCode { get; internal set; } 16 | 17 | public object Operand { get; internal set; } 18 | 19 | public bool IsMethodCall => Operand is MethodInfo; 20 | 21 | public bool IsConstructorCall => Operand is MethodInfo m && m.IsConstructor; 22 | 23 | public override string ToString() 24 | { 25 | string dataString; 26 | 27 | if (Operand != null) { 28 | if (!Hex.TryCreateHex(Operand, out dataString)) { 29 | dataString = Operand.ToString(); 30 | } 31 | } 32 | else { 33 | dataString = String.Empty; 34 | } 35 | 36 | return String.Format("IL_{0:X}: {1} (opcode: {2:X}) {3}", Offset, OpCode, OpCode.Value, dataString); 37 | 38 | // return String.Format("IL_{0:X}: {1} ({2:X}, {3}) {4}", Offset, OpCode, OpCode.Value,OpCode.OperandType , dataString); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Metadata/JitIL/TinyILMethod.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using RazorSharp.CoreClr.Meta; 3 | using RazorSharp.Memory.Pointers; 4 | 5 | // ReSharper disable FieldCanBeMadeReadOnly.Local 6 | 7 | // ReSharper disable InconsistentNaming 8 | 9 | namespace RazorSharp.CoreClr.Metadata.JitIL 10 | { 11 | /// 12 | /// 13 | /// CLR . Functionality is implemented in this struct and exposed via 14 | /// 15 | /// 16 | /// Internal name: COR_ILMETHOD_TINY 17 | /// Used when the method is tiny (less than 64 bytes), and there are no local vars 18 | /// typedef struct tagCOR_ILMETHOD_TINY : IMAGE_COR_ILMETHOD_TINY 19 | /// Corresponding files: 20 | /// 21 | /// 22 | /// /src/inc/corhlpr.h 23 | /// 24 | /// 25 | /// Lines of interest: 26 | /// 27 | /// 28 | /// /src/inc/corhlpr.h: 473 29 | /// 30 | /// 31 | /// 32 | [StructLayout(LayoutKind.Explicit)] 33 | internal unsafe struct TinyILMethod /* : IMAGE_COR_ILMETHOD_TINY */ 34 | { 35 | #region Structs 36 | 37 | /// 38 | /// Internal name: IMAGE_COR_ILMETHOD_TINY 39 | /// Used when the method is tiny (less than 64 bytes), and there are no local vars 40 | /// Corresponding files: 41 | /// 42 | /// 43 | /// /src/inc/corhdr.h 44 | /// 45 | /// 46 | /// Lines of interest: 47 | /// 48 | /// 49 | /// /src/inc/corhdr.h: 1230 50 | /// 51 | /// 52 | /// 53 | [StructLayout(LayoutKind.Explicit)] 54 | private struct IMAGE_COR_ILMETHOD_TINY 55 | { 56 | [FieldOffset(default)] 57 | internal byte m_flagsAndCodeSize; 58 | } 59 | 60 | #endregion 61 | 62 | /// 63 | /// This value is inherited from 64 | /// 65 | [FieldOffset(default)] 66 | private IMAGE_COR_ILMETHOD_TINY m_value; 67 | 68 | /// 69 | /// Contains both and 70 | /// 71 | private byte FlagsAndCodeSize => m_value.m_flagsAndCodeSize; 72 | 73 | internal bool IsTiny { 74 | get { 75 | bool v = (FlagsAndCodeSize & ((uint) CorILMethodFlags.FormatMask >> 1)) == 76 | (uint) CorILMethodFlags.TinyFormat; 77 | return v; 78 | } 79 | } 80 | 81 | /// 82 | /// 83 | /// return(((BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_TINY)); 84 | /// 85 | /// 86 | internal Pointer Code { 87 | get { 88 | fixed (TinyILMethod* thisPtr = &this) { 89 | var value = (byte*) thisPtr; 90 | 91 | return value + sizeof(IMAGE_COR_ILMETHOD_TINY); 92 | } 93 | } 94 | } 95 | 96 | internal uint CodeSize => (uint) FlagsAndCodeSize >> (int) (CorILMethodFlags.FormatShift - 1); 97 | 98 | internal const uint MaxStackSize = 8; 99 | internal const uint Token = 0; 100 | } 101 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Metadata/MethodDesc.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using RazorSharp.Core; 5 | using RazorSharp.CoreClr.Metadata.Enums; 6 | using RazorSharp.Import; 7 | using RazorSharp.Import.Attributes; 8 | using RazorSharp.Import.Enums; 9 | using RazorSharp.Interop; 10 | using RazorSharp.Memory.Pointers; 11 | 12 | // ReSharper disable ArrangeAccessorOwnerBody 13 | // ReSharper disable InconsistentNaming 14 | // ReSharper disable UnassignedGetOnlyAutoProperty 15 | 16 | namespace RazorSharp.CoreClr.Metadata 17 | { 18 | [ImportNamespace] 19 | [StructLayout(LayoutKind.Sequential)] 20 | public unsafe struct MethodDesc 21 | { 22 | static MethodDesc() 23 | { 24 | ImportManager.Value.Load(typeof(MethodDesc), Clr.Value.Imports); 25 | } 26 | 27 | [ImportMapDesignation] 28 | private static readonly ImportMap Imports = new ImportMap(); 29 | 30 | #region Fields 31 | 32 | internal MethodDescFlags3 Flags3AndTokenRemainder { get; } 33 | 34 | internal byte ChunkIndex { get; } 35 | 36 | internal MethodDescFlags2 Flags2 { get; } 37 | 38 | internal ushort SlotNumber { get; } 39 | 40 | internal MethodDescClassification Flags { get; } 41 | 42 | /// 43 | /// Valid only if the function is non-virtual, 44 | /// non-abstract, non-generic (size of this MethodDesc == 16) 45 | /// 46 | internal void* Function { get; } 47 | 48 | #endregion 49 | 50 | #region Accessors 51 | 52 | #region Flags 53 | 54 | internal MethodClassification Classification { 55 | get { return (MethodClassification) ((ushort) Flags & (ushort) MethodDescClassification.Classification); } 56 | } 57 | 58 | #endregion 59 | 60 | #endregion 61 | 62 | #region Import 63 | 64 | [ImportCall(ImportCallOptions.Map)] 65 | internal void Reset() 66 | { 67 | fixed (MethodDesc* value = &this) { 68 | Functions.Native.CallVoid((void*) Imports[nameof(Reset)], value); 69 | } 70 | } 71 | 72 | [ImportCall(ImportCallOptions.Map)] 73 | internal bool IsPointingToNativeCode() 74 | { 75 | fixed (MethodDesc* value = &this) { 76 | return Functions.Native.Call((void*) Imports[nameof(IsPointingToNativeCode)], value); 77 | } 78 | } 79 | 80 | 81 | internal void* PreImplementedCode { 82 | [ImportCall(IdentifierOptions.UseAccessorName, ImportCallOptions.Map)] 83 | get { 84 | fixed (MethodDesc* value = &this) { 85 | return Functions.Native.CallReturnPointer((void*) Imports[nameof(PreImplementedCode)], value); 86 | } 87 | } 88 | } 89 | 90 | 91 | internal void* NativeCode { 92 | [ImportCall(IdentifierOptions.UseAccessorName, ImportCallOptions.Map)] 93 | get { 94 | fixed (MethodDesc* value = &this) { 95 | return Functions.Native.CallReturnPointer((void*) Imports[nameof(NativeCode)], value); 96 | } 97 | } 98 | } 99 | 100 | [ImportCall(ImportCallOptions.Map)] 101 | internal bool SetNativeCodeInterlocked(long p) 102 | { 103 | fixed (MethodDesc* value = &this) { 104 | return Functions.Native.Call((void*) Imports[nameof(SetNativeCodeInterlocked)], 105 | value, (void*) p); 106 | } 107 | } 108 | 109 | internal int Token { 110 | [ImportCall("GetMemberDef", ImportCallOptions.Map)] 111 | get { 112 | fixed (MethodDesc* value = &this) { 113 | return Functions.Native.Call((void*) Imports[nameof(Token)], value); 114 | } 115 | } 116 | } 117 | 118 | 119 | [Obsolete] 120 | [ImportCall(ImportCallOptions.Map)] 121 | internal void* GetILHeader(int fAllowOverrides) 122 | { 123 | fixed (MethodDesc* value = &this) { 124 | return Functions.Native.CallReturnPointer((void*) Imports[nameof(GetILHeader)], value, fAllowOverrides); 125 | } 126 | } 127 | 128 | 129 | internal long RVA { 130 | [ImportCall(IdentifierOptions.UseAccessorName, ImportCallOptions.Map)] 131 | get { 132 | fixed (MethodDesc* value = &this) { 133 | return Functions.Native.Call((void*) Imports[nameof(RVA)], value); 134 | } 135 | } 136 | } 137 | 138 | 139 | internal MethodTable* MethodTable { 140 | [ImportCall(IdentifierOptions.UseAccessorName, ImportCallOptions.Map)] 141 | get { 142 | fixed (MethodDesc* value = &this) { 143 | return (MethodTable*) Functions.Native.CallReturnPointer((void*) Imports[nameof(MethodTable)], value); 144 | } 145 | } 146 | } 147 | 148 | #endregion 149 | } 150 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Metadata/MethodTable.cs: -------------------------------------------------------------------------------- 1 | #region 2 | 3 | using System; 4 | using System.Runtime.InteropServices; 5 | using RazorSharp.Core; 6 | using RazorSharp.CoreClr.Metadata.Enums; 7 | using RazorSharp.CoreClr.Metadata.ExecutionEngine; 8 | using RazorSharp.Import; 9 | using RazorSharp.Import.Attributes; 10 | using RazorSharp.Memory.Pointers; 11 | 12 | #endregion 13 | 14 | // ReSharper disable UnassignedGetOnlyAutoProperty 15 | // ReSharper disable InconsistentNaming 16 | 17 | namespace RazorSharp.CoreClr.Metadata 18 | { 19 | /// 20 | /// The value of lowest two bits describe what the union contains 21 | /// 22 | /// Use with 23 | /// 24 | /// 25 | [Flags] 26 | public enum UnionType 27 | { 28 | /// 29 | /// 0 - pointer to 30 | /// This is the canonical method table. 31 | /// 32 | EEClass = 0, 33 | 34 | /// 35 | /// 1 - not used 36 | /// 37 | Invalid = 1, 38 | 39 | /// 40 | /// 2 - pointer to canonical . 41 | /// 42 | MethodTable = 2, 43 | 44 | /// 45 | /// 3 - pointer to indirection cell that points to canonical . 46 | /// (used only if FEATURE_PREJIT is defined) 47 | /// 48 | Indirection = 3 49 | } 50 | 51 | [ImportNamespace] 52 | [StructLayout(LayoutKind.Sequential)] 53 | public unsafe struct MethodTable 54 | { 55 | static MethodTable() 56 | { 57 | ImportManager.Value.Load(typeof(MethodTable), Clr.Value.Imports); 58 | } 59 | 60 | internal short ComponentSize { get; } 61 | internal MethodTableFlagsLow FlagsLow { get; } 62 | internal int BaseSize { get; } 63 | internal MethodTableFlags2 Flags2 { get; } 64 | internal short RawToken { get; } 65 | internal short NumVirtuals { get; } 66 | internal short NumInterfaces { get; } 67 | internal void* Parent { get; } 68 | internal void* Module { get; } 69 | internal void* WriteableData { get; } 70 | 71 | internal MethodTableFlags Flags { 72 | get { 73 | fixed (MethodTable* ptr = &this) { 74 | return (MethodTableFlags) (*(int*) ptr); 75 | } 76 | } 77 | } 78 | 79 | #region Union 1 80 | 81 | /// 82 | /// Union 1 83 | /// EEClass* 84 | /// MethodTable* 85 | /// 86 | private void* Union1 { get; } 87 | 88 | internal Pointer EEClass => (EEClass*) Union1; 89 | internal Pointer Canon => (MethodTable*) Union1; 90 | 91 | #endregion 92 | 93 | #region Union 2 94 | 95 | /// 96 | /// Union 2 97 | /// void* 98 | /// void* 99 | /// void* 100 | /// 101 | private void* Union2 { get; } 102 | 103 | internal Pointer PerInstInfo => Union2; 104 | 105 | internal Pointer ElementTypeHandle => Union2; 106 | 107 | internal Pointer MultipurposeSlot1 => Union2; 108 | 109 | #endregion 110 | 111 | #region Union 3 112 | 113 | /// 114 | /// Union 3 115 | /// void* 116 | /// void* 117 | /// 118 | private void* Union3 { get; } 119 | 120 | internal Pointer InterfaceMap => Union3; 121 | 122 | internal Pointer MultipurposeSlot2 => Union3; 123 | 124 | #endregion 125 | 126 | /// 127 | /// Bit mask for 128 | /// 129 | private const long UNION_MASK = 3; 130 | 131 | /// 132 | /// Describes what the union at offset 40 () 133 | /// contains. 134 | /// 135 | internal UnionType UnionType { 136 | get { 137 | long l = (long) Union1; 138 | return (UnionType) (l & UNION_MASK); 139 | } 140 | } 141 | } 142 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Metadata/ObjHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using RazorSharp.Memory; 4 | 5 | namespace RazorSharp.CoreClr.Metadata 6 | { 7 | [Flags] 8 | public enum SyncBlockFlags : uint 9 | { 10 | StringHasNoHighChars = 0x80000000, 11 | AgileInProgress = 0x80000000, 12 | StringHighCharsKnown = 0x40000000, 13 | StringHasSpecialSort = 0xC0000000, 14 | StringHighCharMask = 0xC0000000, 15 | FinalizerRun = 0x40000000, 16 | GcReserve = 0x20000000, 17 | SpinLock = 0x10000000, 18 | IsHashOrSyncblkindex = 0x08000000, 19 | IsHashcode = 0x04000000 20 | } 21 | 22 | [StructLayout(LayoutKind.Explicit)] 23 | public struct ObjHeader 24 | { 25 | #region Fields 26 | 27 | /// 28 | /// This is the sync block on x86. This is padding on x64. 29 | /// 30 | [FieldOffset(default)] 31 | private readonly int m_dword1; 32 | 33 | /// 34 | /// This is the sync block on x64. 35 | /// 36 | [FieldOffset(sizeof(int))] 37 | private readonly int m_dword2; 38 | 39 | #endregion 40 | 41 | private int SyncBlockValue => !Mem.Is64Bit ? m_dword1 : m_dword2; 42 | 43 | public SyncBlockFlags Flags => (SyncBlockFlags) SyncBlockValue; 44 | 45 | 46 | public override string ToString() 47 | { 48 | return String.Format("Sync block: {0}", Flags); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Metadata/PackedDWORDFields.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using RazorSharp.CoreClr.Metadata.Enums; 4 | 5 | // ReSharper disable BuiltInTypeReferenceStyle 6 | // ReSharper disable InconsistentNaming 7 | 8 | namespace RazorSharp.CoreClr.Metadata 9 | { 10 | using DWORD = UInt32; 11 | 12 | [StructLayout(LayoutKind.Explicit)] 13 | internal unsafe struct PackedDWORDFields 14 | { 15 | /// 16 | /// == == 11 17 | /// 18 | private const int EECLASS_LENGTH = (int) EEClassFieldId.COUNT; 19 | 20 | private const int MAX_LENGTH_BITS = 5; 21 | 22 | [FieldOffset(0)] 23 | private fixed DWORD m_rgUnpackedFields[EECLASS_LENGTH]; 24 | 25 | [FieldOffset(0)] 26 | private fixed DWORD m_rgPackedFields[1]; 27 | 28 | /// 29 | /// Get the value of the given field when the structure is in its unpacked state. 30 | /// 31 | internal DWORD GetUnpackedField(DWORD dwFieldIndex) 32 | { 33 | fixed (PackedDWORDFields* p = &this) { 34 | return p->m_rgUnpackedFields[dwFieldIndex]; 35 | } 36 | } 37 | 38 | internal DWORD GetPackedField(DWORD dwFieldIndex) 39 | { 40 | DWORD dwOffset = 0; 41 | 42 | for (DWORD i = 0; i < dwFieldIndex; i++) { 43 | // +1 since size is [1,32] not [0,31] 44 | dwOffset += MAX_LENGTH_BITS + BitVectorGet(dwOffset, MAX_LENGTH_BITS) + 1; 45 | } 46 | 47 | 48 | // The next kMaxLengthBits bits contain the length in bits of the field we want (-1 due to the way we 49 | // encode the length). 50 | DWORD dwFieldLength = BitVectorGet(dwOffset, MAX_LENGTH_BITS) + 1; 51 | dwOffset += MAX_LENGTH_BITS; 52 | 53 | // Grab the field value. 54 | DWORD dwReturn = BitVectorGet(dwOffset, dwFieldLength); 55 | 56 | return dwReturn; 57 | } 58 | 59 | private DWORD BitVectorGet(DWORD dwOffset, DWORD dwLength) 60 | { 61 | // Calculate the start and end naturally aligned DWORDs from which the value will come. 62 | DWORD dwStartBlock = dwOffset / Constants.BITS_PER_DWORD; 63 | DWORD dwEndBlock = (dwOffset + dwLength - 1) / Constants.BITS_PER_DWORD; 64 | 65 | if (dwStartBlock == dwEndBlock) { 66 | // Easy case: the new value fits entirely within one aligned DWORD. Compute the number of bits 67 | // we'll need to shift the extracted value (to the right) and a mask of the bits that will be 68 | // extracted in the destination DWORD. 69 | DWORD dwValueShift = dwOffset % Constants.BITS_PER_DWORD; 70 | DWORD dwValueMask = ((1U << (int) dwLength) - 1) << (int) dwValueShift; 71 | 72 | // Mask out the bits we want and shift them down into the bottom of the result DWORD. 73 | 74 | fixed (PackedDWORDFields* p = &this) { 75 | return (p->m_rgPackedFields[dwStartBlock] & dwValueMask) >> (int) dwValueShift; 76 | } 77 | } 78 | 79 | // Hard case: the return value is split across two DWORDs (two DWORDs is the max as the new value 80 | // can be at most DWORD-sized itself). For simplicity we'll simply break this into two separate 81 | // non-spanning gets and stitch the result together from that. We can revisit this in the future 82 | // if the perf is a problem. 83 | DWORD dwInitialBits = Constants.BITS_PER_DWORD - dwOffset % Constants.BITS_PER_DWORD; // Number of bits to get in the first DWORD 84 | DWORD dwReturn; 85 | 86 | // Get the initial (low-order) bits from the first DWORD. 87 | dwReturn = BitVectorGet(dwOffset, dwInitialBits); 88 | 89 | // Get the remaining bits from the second DWORD. These bits will need to be shifted to the left 90 | // (past the bits we've already read) before being OR'd into the result. 91 | dwReturn |= BitVectorGet(dwOffset + dwInitialBits, dwLength - dwInitialBits) << (int) dwInitialBits; 92 | 93 | return dwReturn; 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Metadata/TypeHandle.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Runtime.InteropServices; 3 | using RazorSharp.Core; 4 | using RazorSharp.Import; 5 | using RazorSharp.Import.Attributes; 6 | using RazorSharp.Import.Enums; 7 | using RazorSharp.Interop; 8 | using RazorSharp.Memory.Pointers; 9 | 10 | // ReSharper disable FieldCanBeMadeReadOnly.Local 11 | // ReSharper disable MemberCanBeMadeStatic.Global 12 | 13 | namespace RazorSharp.CoreClr.Metadata 14 | { 15 | [ImportNamespace] 16 | [StructLayout(LayoutKind.Explicit)] 17 | internal unsafe struct TypeHandle 18 | { 19 | static TypeHandle() 20 | { 21 | ImportManager.Value.Load(typeof(TypeHandle), Clr.Value.Imports); 22 | } 23 | 24 | #region Fields 25 | 26 | // [FieldOffset(default)] 27 | // private TAddr m_asTAddr; 28 | 29 | [FieldOffset(default)] 30 | private void* m_asPtr; 31 | 32 | [FieldOffset(default)] 33 | private MethodTable* m_asMT; 34 | 35 | #endregion 36 | 37 | [ImportMapDesignation] 38 | private static readonly ImportMap Imports = new ImportMap(); 39 | 40 | internal Pointer MethodTable { 41 | [ImportCall(IdentifierOptions.UseAccessorName, ImportCallOptions.Map)] 42 | get { 43 | fixed (TypeHandle* value = &this) { 44 | return Functions.Native.CallReturnPointer((void*) Imports[nameof(MethodTable)], value); 45 | } 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Offsets.cs: -------------------------------------------------------------------------------- 1 | #region 2 | 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | using RazorSharp.CoreClr.Metadata; 6 | // ReSharper disable ConvertToConstant.Global 7 | 8 | #endregion 9 | 10 | namespace RazorSharp.CoreClr 11 | { 12 | /// 13 | /// Common runtime offsets. 14 | /// 15 | public static class Offsets 16 | { 17 | /// 18 | /// The offset, in bytes, of an array's actual pointer, relative to the 19 | /// address pointed to by an array type's . 20 | /// 21 | /// An array's pointer is located 1 indirection of 22 | /// + bytes. 23 | /// 24 | /// 25 | /// Relative to (1 indirection) 26 | /// 27 | /// 28 | internal const int ARRAY_MT_PTR_OFFSET = 6; 29 | 30 | /// 31 | /// Size of the length field and first character 32 | /// 33 | /// 34 | /// + 2: First character 35 | /// 36 | /// 37 | /// + 4: String length 38 | /// 39 | /// 40 | /// 41 | public static readonly int StringOverhead = sizeof(char) + sizeof(int); 42 | 43 | /// 44 | /// Size of the length field and padding (x64) 45 | /// 46 | public static readonly int ArrayOverhead = IntPtr.Size; 47 | 48 | /// 49 | /// Size of and 50 | /// 51 | /// 52 | /// + : 53 | /// 54 | /// 55 | /// + : pointer 56 | /// 57 | /// 58 | /// 59 | public static readonly int ObjectOverhead = IntPtr.Size * 2; 60 | 61 | /// 62 | /// Heap offset to the first field. 63 | /// 64 | /// 65 | /// + for 66 | /// 67 | /// 68 | /// 69 | public static readonly int OffsetToData = IntPtr.Size; 70 | 71 | /// 72 | /// Heap offset to the first array element. 73 | /// 74 | /// 75 | /// + for 76 | /// 77 | /// 78 | /// + 4 for length () 79 | /// 80 | /// 81 | /// + 4 for padding () (x64 only) 82 | /// 83 | /// 84 | /// 85 | public static readonly int OffsetToArrayData = OffsetToData + ArrayOverhead; 86 | 87 | /// 88 | /// Heap offset to the first string character. 89 | /// On 64 bit platforms, this should be 12 (8 + 4) and on 32 bit 8 (4 + 4). 90 | /// ( + ) 91 | /// 92 | public static readonly int OffsetToStringData = RuntimeHelpers.OffsetToStringData; 93 | 94 | /// 95 | /// Minimum GC object heap size 96 | /// Sources: 97 | /// 98 | /// 99 | /// /src/vm/object.h: 119 100 | /// 101 | /// 102 | /// 103 | public static readonly int MinObjectSize = ObjectOverhead + IntPtr.Size; 104 | } 105 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Runtime.Info.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using InlineIL; 3 | using JetBrains.Annotations; 4 | using RazorSharp.CoreClr.Meta; 5 | using RazorSharp.Interop.Utilities; 6 | using RazorSharp.Memory; 7 | using RazorSharp.Utilities.Security; 8 | 9 | namespace RazorSharp.CoreClr 10 | { 11 | 12 | /// 13 | /// Provides auxiliary runtime information and convenience functions 14 | /// 15 | public static unsafe partial class Runtime 16 | { 17 | public static class Info 18 | { 19 | #region Is 20 | 21 | #region Other 22 | 23 | public static bool IsBoxed(T value) 24 | { 25 | return (typeof(T).IsInterface || typeof(T) == typeof(object)) && value != null && IsStruct(value); 26 | } 27 | 28 | public static bool IsPinnable(T value) where T : class 29 | { 30 | // https://github.com/dotnet/coreclr/blob/adecd858f558489d8f52c9187fca395ec669a715/src/vm/marshalnative.cpp#L257 31 | 32 | if (value == null) { 33 | return true; 34 | } 35 | 36 | var mt = Runtime.ReadMetaType(value); 37 | 38 | if (mt.IsString) { 39 | return true; 40 | } 41 | 42 | if (mt.IsArray) { 43 | // todo 44 | throw Guard.NotImplementedFail(nameof(mt.IsArray)); 45 | } 46 | 47 | 48 | return mt.IsBlittable; 49 | } 50 | 51 | /// 52 | /// Determines whether is the same size as . 53 | /// If they are equal, can act as a surrogate pointer. This means 54 | /// it can be substituted for a pointer. 55 | /// 56 | /// Type to test 57 | /// true if equals ; 58 | /// false otherwise. 59 | public static bool IsPointerSubstitute() where TPointer : struct 60 | { 61 | return IntPtr.Size == Unsafe.SizeOf(); 62 | } 63 | 64 | #endregion 65 | 66 | #region Nil 67 | 68 | /// 69 | /// Whether the value of is default or null bytes, 70 | /// or is null 71 | /// 72 | /// "Nil" is null or default. 73 | /// 74 | public static bool IsNil([CanBeNull, Native] T value) 75 | { 76 | // Fastest method for calculating whether a value is nil. 77 | IL.Emit.Ldarg(nameof(value)); 78 | IL.Emit.Ldnull(); 79 | IL.Emit.Ceq(); 80 | IL.Emit.Ret(); 81 | return IL.Return(); 82 | } 83 | 84 | /*public static bool IsNullOrDefault([CanBeNull] T value) 85 | { 86 | return EqualityComparer.Default.Equals(value, default); 87 | }*/ 88 | 89 | #endregion 90 | 91 | #region String 92 | 93 | internal static bool IsString() => typeof(T) == typeof(string); 94 | 95 | internal static bool IsString(T value) => value is string; 96 | 97 | #endregion 98 | 99 | #region Array 100 | 101 | internal static bool IsArray() => typeof(T).IsArray || typeof(T) == typeof(Array); 102 | 103 | internal static bool IsArray(T value) => value is Array; 104 | 105 | #endregion 106 | 107 | #region Struct 108 | 109 | internal static bool IsStruct() => ((MetaType) typeof(T)).IsStruct; 110 | 111 | internal static bool IsStruct(T value) => ((MetaType) value.GetType()).IsStruct; 112 | 113 | #endregion 114 | 115 | #endregion 116 | } 117 | } 118 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Runtime.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using RazorSharp.CoreClr.Meta; 4 | using RazorSharp.CoreClr.Metadata; 5 | using RazorSharp.Interop; 6 | using RazorSharp.Memory; 7 | using RazorSharp.Memory.Enums; 8 | using RazorSharp.Memory.Pointers; 9 | using RazorSharp.Utilities; 10 | using RazorSharp.Utilities.Security; 11 | using SimpleSharp.Diagnostics; 12 | 13 | namespace RazorSharp.CoreClr 14 | { 15 | public static unsafe partial class Runtime 16 | { 17 | static Runtime() 18 | { 19 | const string FN_NAME = "GetTypeFromHandleUnsafe"; 20 | var method = typeof(Type).GetAnyMethod(FN_NAME); 21 | 22 | GetTypeFromHandle = (GetTypeFromHandleFunction) method.CreateDelegate(typeof(GetTypeFromHandleFunction)); 23 | } 24 | 25 | public static MetaType GetMetaType(this Type t) => t; 26 | 27 | /// 28 | /// Allocates an object of type in the GC heap. 29 | /// 30 | /// Constructor arguments 31 | /// Type to allocate 32 | /// An initialized object 33 | public static T AllocObject(params object[] args) 34 | { 35 | var value = GCHeap.AllocateObject(); 36 | Functions.Reflection.CallConstructor(value, args); 37 | return value; 38 | } 39 | 40 | /// 41 | /// PTR_HOST_MEMBER_TADDR 42 | /// 43 | internal static Pointer HostMemberOffset(ref T value, long ofs, Pointer fieldValue) 44 | where T : struct 45 | { 46 | return Unsafe.AddressOf(ref value).Add((long) fieldValue).Add(ofs).Cast(); 47 | } 48 | 49 | internal static TypeHandle ReadTypeHandle(T value) 50 | { 51 | // Value types do not have a MethodTable ptr, but they do have a TypeHandle. 52 | if (Runtime.Info.IsStruct(value)) 53 | return ReadTypeHandle(value.GetType()); 54 | 55 | Unsafe.TryGetAddressOfHeap(value, out Pointer ptr); 56 | Conditions.Ensure(!ptr.IsNull); 57 | return *(TypeHandle*) ptr; 58 | } 59 | 60 | internal static TypeHandle ReadTypeHandle(Type t) 61 | { 62 | var handle = t.TypeHandle.Value; 63 | var typeHandleValue = *(TypeHandle*) &handle; 64 | return typeHandleValue; 65 | } 66 | 67 | internal static MetaType ReadMetaType(T value) 68 | { 69 | return new MetaType(ReadTypeHandle(value).MethodTable); 70 | } 71 | 72 | 73 | /// 74 | /// Returns a pointer to the internal CLR metadata structure of 75 | /// 76 | /// Reflection type 77 | /// A pointer to the corresponding structure 78 | /// The type of doesn't have a handle 79 | internal static Pointer ResolveHandle(MemberInfo member) 80 | { 81 | if (member == null) { 82 | throw new ArgumentNullException(nameof(member)); 83 | } 84 | 85 | return member switch 86 | { 87 | Type t => ReadTypeHandle(t).MethodTable.Cast(), 88 | FieldInfo field => field.FieldHandle.Value, 89 | MethodInfo method => method.MethodHandle.Value, 90 | _ => throw Guard.NotSupportedMemberFail(member) 91 | }; 92 | } 93 | 94 | 95 | #region Type from handle 96 | 97 | /// 98 | /// Returns the corresponding Reflection of the handle specified by 99 | /// 100 | /// 101 | /// 102 | public static Type ResolveType(Pointer handle) 103 | { 104 | return GetTypeFromHandle(handle.Address); 105 | } 106 | 107 | private delegate Type GetTypeFromHandleFunction(IntPtr handle); 108 | 109 | private static readonly GetTypeFromHandleFunction GetTypeFromHandle; 110 | 111 | #endregion 112 | 113 | 114 | internal static ObjHeader ReadObjHeader(T value) where T : class 115 | { 116 | Pointer ptr = Unsafe.AddressOfHeap(value, OffsetOptions.Header).Cast(); 117 | return ptr.Value; 118 | } 119 | } 120 | } -------------------------------------------------------------------------------- /RazorSharp/CoreClr/Tokens.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RazorSharp.CoreClr.Metadata.Enums; 3 | using RazorSharp.Utilities.Security; 4 | 5 | namespace RazorSharp.CoreClr 6 | { 7 | internal static class Tokens 8 | { 9 | private const int RID_FROM_TOKEN = 0x00FFFFFF; 10 | 11 | private const uint TYPE_FROM_TOKEN = 0xFF000000; 12 | 13 | internal static int TokenFromRid(int rid, CorTokenType tktype) => rid | (int) tktype; 14 | 15 | internal static int RidFromToken(int tk) => tk & RID_FROM_TOKEN; 16 | 17 | internal static long TypeFromToken(int tk) => tk & TYPE_FROM_TOKEN; 18 | 19 | /// 20 | /// Sources: 21 | /// 22 | /// 23 | /// src/vm/siginfo.cpp: 63 24 | /// 25 | /// 26 | /// If size is unknown 27 | /// 28 | internal static int SizeOfCorElementType(CorElementType t) 29 | { 30 | switch (t) { 31 | case CorElementType.Void: 32 | return default; 33 | 34 | case CorElementType.Boolean: 35 | return sizeof(bool); 36 | 37 | case CorElementType.Char: 38 | return sizeof(char); 39 | 40 | case CorElementType.I1: 41 | return sizeof(sbyte); 42 | case CorElementType.U1: 43 | return sizeof(byte); 44 | 45 | case CorElementType.I2: 46 | return sizeof(short); 47 | case CorElementType.U2: 48 | return sizeof(ushort); 49 | 50 | case CorElementType.I4: 51 | return sizeof(int); 52 | case CorElementType.U4: 53 | return sizeof(uint); 54 | 55 | case CorElementType.I8: 56 | return sizeof(long); 57 | case CorElementType.U8: 58 | return sizeof(ulong); 59 | 60 | case CorElementType.R4: 61 | return sizeof(float); 62 | case CorElementType.R8: 63 | return sizeof(double); 64 | 65 | case CorElementType.String: 66 | case CorElementType.Ptr: 67 | case CorElementType.ByRef: 68 | case CorElementType.Class: 69 | case CorElementType.Array: 70 | case CorElementType.I: 71 | case CorElementType.U: 72 | case CorElementType.FnPtr: 73 | case CorElementType.Object: 74 | case CorElementType.SzArray: 75 | case CorElementType.End: 76 | return IntPtr.Size; 77 | 78 | 79 | case CorElementType.ValueType: 80 | case CorElementType.Var: 81 | case CorElementType.GenericInst: 82 | case CorElementType.CModReqd: 83 | case CorElementType.CModOpt: 84 | case CorElementType.Internal: 85 | case CorElementType.MVar: 86 | return Constants.INVALID_VALUE; 87 | 88 | case CorElementType.TypedByRef: 89 | return IntPtr.Size * 2; 90 | 91 | case CorElementType.Max: 92 | case CorElementType.Modifier: 93 | case CorElementType.Sentinel: 94 | case CorElementType.Pinned: 95 | break; 96 | default: 97 | throw new ArgumentOutOfRangeException(nameof(t), t, null); 98 | } 99 | 100 | throw Guard.ClrFail($"Size for CorElementType {t} is unknown"); 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /RazorSharp/Import/Attributes/ImportAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using JetBrains.Annotations; 3 | using RazorSharp.Import.Enums; 4 | 5 | namespace RazorSharp.Import.Attributes 6 | { 7 | [MeansImplicitUse] 8 | [AttributeUsage(ImportFieldAttribute.FIELD_TARGETS | ImportCallAttribute.METHOD_TARGETS)] 9 | public abstract class ImportAttribute : Attribute 10 | { 11 | public string Identifier { get; protected set; } 12 | 13 | public IdentifierOptions Options { get; protected set; } 14 | 15 | public ImportAttribute() : this(IdentifierOptions.None) { } 16 | 17 | public ImportAttribute(IdentifierOptions options) : this(null, options) { } 18 | 19 | public ImportAttribute(string id, IdentifierOptions options = IdentifierOptions.None) 20 | { 21 | Identifier = id; 22 | Options = options; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /RazorSharp/Import/Attributes/ImportCallAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using JetBrains.Annotations; 3 | using RazorSharp.CoreClr.Metadata.Enums; 4 | using RazorSharp.Import.Enums; 5 | using RazorSharp.Utilities; 6 | 7 | namespace RazorSharp.Import.Attributes 8 | { 9 | [MeansImplicitUse] 10 | [AttributeUsage(METHOD_TARGETS)] 11 | public class ImportCallAttribute : ImportAttribute 12 | { 13 | internal const AttributeTargets METHOD_TARGETS = AttributeTargets.Method | AttributeTargets.Property; 14 | 15 | public ImportCallOptions CallOptions { get; set; } = ImportCallOptions.Bind; 16 | 17 | public ImportCallAttribute() { } 18 | 19 | public ImportCallAttribute(ImportCallOptions callOptions) 20 | { 21 | CallOptions = callOptions; 22 | 23 | // Convenience 24 | if (callOptions.HasFlagFast(ImportCallOptions.Constructor)) { 25 | Options = IdentifierOptions.FullyQualified; 26 | } 27 | } 28 | 29 | public ImportCallAttribute(IdentifierOptions options,ImportCallOptions callOptions) : this(callOptions) 30 | { 31 | base.Options = options; 32 | } 33 | 34 | public ImportCallAttribute(IdentifierOptions options) : base(options) { } 35 | 36 | public ImportCallAttribute(string id, ImportCallOptions options) : this(options) 37 | { 38 | Identifier = id; 39 | } 40 | 41 | public ImportCallAttribute(string id, IdentifierOptions options = IdentifierOptions.None) 42 | : base(id, options) { } 43 | } 44 | } -------------------------------------------------------------------------------- /RazorSharp/Import/Attributes/ImportFieldAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using JetBrains.Annotations; 3 | using RazorSharp.CoreClr; 4 | using RazorSharp.Import.Enums; 5 | using RazorSharp.Memory; 6 | 7 | namespace RazorSharp.Import.Attributes 8 | { 9 | [MeansImplicitUse] 10 | [AttributeUsage(FIELD_TARGETS)] 11 | public sealed class ImportFieldAttribute : ImportAttribute 12 | { 13 | internal const AttributeTargets FIELD_TARGETS = AttributeTargets.Field; 14 | 15 | /// 16 | /// The to load this field as. If left unset, the field will be interpreted as 17 | /// the target field's type. 18 | /// To use this, must be . 19 | /// 20 | public Type LoadAs { get; set; } 21 | 22 | /// 23 | /// Specifies the size of memory to be copied into the field. If this is not specified, the base size of 24 | /// the field type will be used. () 25 | /// 26 | /// To use this, must be . 27 | /// 28 | /// 29 | public int SizeConst { get; set; } = Constants.INVALID_VALUE; 30 | 31 | /// 32 | /// Specifies how the target field will be loaded. 33 | /// 34 | public ImportFieldOptions FieldOptions { get; set; } = ImportFieldOptions.Proxy; 35 | 36 | public ImportFieldAttribute() { } 37 | 38 | public ImportFieldAttribute(IdentifierOptions options, ImportFieldOptions loadOptions) : this(options) 39 | { 40 | FieldOptions = loadOptions; 41 | } 42 | 43 | public ImportFieldAttribute(IdentifierOptions options) : base(options) { } 44 | 45 | public ImportFieldAttribute(string id, IdentifierOptions options = IdentifierOptions.None) 46 | : base(id, options) { } 47 | } 48 | } -------------------------------------------------------------------------------- /RazorSharp/Import/Attributes/ImportForwardCallAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using JetBrains.Annotations; 3 | using RazorSharp.Import.Enums; 4 | 5 | namespace RazorSharp.Import.Attributes 6 | { 7 | /// 8 | /// Used when the function is not resolved from its declaring type -- that is, its identifier is resolved 9 | /// from another type. 10 | /// 11 | [MeansImplicitUse] 12 | [AttributeUsage(METHOD_TARGETS)] 13 | public sealed class ImportForwardCallAttribute : ImportCallAttribute 14 | { 15 | public ImportForwardCallAttribute(string nameSpace, string id, ImportCallOptions options) 16 | { 17 | Identifier = ImportManager.Combine(nameSpace, id); 18 | Options = IdentifierOptions.FullyQualified; 19 | CallOptions = options; 20 | } 21 | 22 | public ImportForwardCallAttribute(Type type, string id, ImportCallOptions options) 23 | : this(type.Name, id, options) { } 24 | } 25 | } -------------------------------------------------------------------------------- /RazorSharp/Import/Attributes/ImportMapDesignationAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using JetBrains.Annotations; 4 | using RazorSharp.Import.Enums; 5 | 6 | namespace RazorSharp.Import.Attributes 7 | { 8 | /// 9 | /// Designates the to use for members specified with 10 | /// 11 | /// 12 | [MeansImplicitUse] 13 | [AttributeUsage(AttributeTargets.Field)] 14 | public sealed class ImportMapDesignationAttribute : Attribute 15 | { 16 | 17 | } 18 | } -------------------------------------------------------------------------------- /RazorSharp/Import/Attributes/ImportNamespaceAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using JetBrains.Annotations; 3 | using RazorSharp.Import.Enums; 4 | 5 | namespace RazorSharp.Import.Attributes 6 | { 7 | [MeansImplicitUse] 8 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] 9 | public sealed class ImportNamespaceAttribute : Attribute 10 | { 11 | public ImportNamespaceAttribute(string nameSpace) 12 | { 13 | Namespace = nameSpace; 14 | } 15 | 16 | public ImportNamespaceAttribute() : this(null) { } 17 | 18 | /// 19 | /// All members with in the 20 | /// annotated class or struct will be prefixed with if the attribute has not 21 | /// set 22 | /// 23 | public string Namespace { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /RazorSharp/Import/Enums/IdentifierOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RazorSharp.Import.Attributes; 3 | 4 | namespace RazorSharp.Import.Enums 5 | { 6 | /// 7 | /// Specifies how the identifier will be resolved. 8 | /// 9 | [Flags] 10 | public enum IdentifierOptions 11 | { 12 | None = 0, 13 | 14 | /// 15 | /// Don't use in the identifier name resolution. 16 | /// 17 | IgnoreNamespace = 1, 18 | 19 | /// 20 | /// Don't use the enclosing type's name in the identifier name resolution. 21 | /// 22 | IgnoreEnclosingNamespace = 1 << 1, 23 | 24 | /// 25 | /// If the method is a get accessor, replace the get_ in the name with Get 26 | /// 27 | UseAccessorName = 1 << 2, 28 | 29 | /// 30 | /// Use only the identifier name. 31 | /// 32 | /// This is a combination of , . 33 | /// This can also be used for global variables. 34 | /// 35 | /// 36 | /// 37 | FullyQualified = IgnoreNamespace | IgnoreEnclosingNamespace, 38 | } 39 | } -------------------------------------------------------------------------------- /RazorSharp/Import/Enums/ImportCallOptions.cs: -------------------------------------------------------------------------------- 1 | #region 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using RazorSharp.Interop; 6 | using RazorSharp.Memory.Pointers; 7 | 8 | #endregion 9 | 10 | namespace RazorSharp.Import.Enums 11 | { 12 | /// 13 | /// Designates how the annotated function is imported. 14 | /// 15 | [Flags] 16 | public enum ImportCallOptions 17 | { 18 | None = 0, 19 | 20 | /// 21 | /// Treat the method as a constructor. must be used. 22 | /// 23 | Constructor = 1, 24 | 25 | /// 26 | /// Sets the method entry point to the resolved address. This only works on 64 bit. 27 | /// 28 | Bind = 1 << 1, 29 | 30 | /// 31 | /// 32 | /// Adds the resolved address to an in the enclosing type 33 | /// 34 | /// 35 | /// The key of the import map is the name of the annotated member. The name is obtained using the 36 | /// nameof operator. The value is the resolved address. 37 | /// 38 | /// Best used in conjunction with the functions in 39 | /// 40 | Map = 1 << 2 41 | } 42 | } -------------------------------------------------------------------------------- /RazorSharp/Import/Enums/ImportFieldOptions.cs: -------------------------------------------------------------------------------- 1 | using RazorSharp.Import.Attributes; 2 | 3 | namespace RazorSharp.Import.Enums 4 | { 5 | /// 6 | /// Specifies how the field will be loaded. 7 | /// 8 | public enum ImportFieldOptions 9 | { 10 | /// 11 | /// Copy the value directly into the field from a byte array. Use to 12 | /// specify the size of the value. If the value isn't set, the size of the target field will be used. 13 | /// 14 | /// 15 | /// If the target field is a reference type, the memory is copied into the data (fields) of the object, not the 16 | /// pointer itself. 17 | /// 18 | /// 19 | CopyIn, 20 | 21 | /// 22 | /// Loads the value as the type specified by 23 | /// (or the field type if the type isn't specified) 24 | /// 25 | Proxy, 26 | 27 | Fast 28 | } 29 | } -------------------------------------------------------------------------------- /RazorSharp/Import/IImportProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RazorSharp.Memory.Pointers; 3 | 4 | namespace RazorSharp.Import 5 | { 6 | /// 7 | /// Describes a type that provides methods for use in . 8 | /// 9 | public interface IImportProvider 10 | { 11 | /// 12 | /// Retrieves the address of the specified member specified by . 13 | /// 14 | /// Any identifier for the imported member 15 | /// Address of the imported member 16 | Pointer GetAddress(string id); 17 | 18 | /// 19 | /// Creates a from the imported member 20 | /// specified by . 21 | /// 22 | /// Any identifier for the imported function 23 | /// of type 24 | TDelegate GetFunction(string id) where TDelegate : Delegate; 25 | } 26 | } -------------------------------------------------------------------------------- /RazorSharp/Import/ImportMap.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using RazorSharp.Memory.Pointers; 3 | 4 | namespace RazorSharp.Import 5 | { 6 | public sealed class ImportMap 7 | { 8 | private readonly Dictionary> m_imports; 9 | 10 | public ImportMap() 11 | { 12 | m_imports = new Dictionary>(); 13 | } 14 | 15 | public Pointer this[string key] => m_imports[key]; 16 | 17 | internal void Add(string key, Pointer value) => m_imports.Add(key, value); 18 | 19 | internal void Clear() => m_imports.Clear(); 20 | 21 | public const string FIELD_NAME = "Imports"; 22 | } 23 | } -------------------------------------------------------------------------------- /RazorSharp/Import/ModuleImport.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using RazorSharp.Interop; 5 | using RazorSharp.Interop.Structures; 6 | using RazorSharp.Interop.Utilities; 7 | using RazorSharp.Memory.Pointers; 8 | using SimpleSharp.Diagnostics; 9 | 10 | namespace RazorSharp.Import 11 | { 12 | /// 13 | /// Combines a process module with a PDB file, allowing access to the module's symbols. 14 | /// 15 | internal class ModuleImport : IImportProvider 16 | { 17 | private readonly FileInfo m_pdb; 18 | private readonly Pointer m_baseAddress; 19 | 20 | internal ModuleImport(FileInfo pdb, ProcessModule module) : this(pdb, module.BaseAddress) { } 21 | 22 | private ModuleImport(FileInfo pdb, Pointer baseAddr) 23 | { 24 | Conditions.NotNull(baseAddr.Address, nameof(baseAddr)); 25 | 26 | m_baseAddress = baseAddr; 27 | m_pdb = pdb; 28 | } 29 | 30 | private Symbol GetSymbol(string name) 31 | { 32 | SymbolManager.Value.CurrentImage = m_pdb; 33 | return SymbolManager.Value.GetSymbol(name); 34 | } 35 | 36 | public Pointer GetAddress(string id) 37 | { 38 | long ofs = GetSymbol(id).Offset; 39 | return m_baseAddress + ofs; 40 | } 41 | 42 | public Pointer[] GetAddresses(string[] names) 43 | { 44 | SymbolManager.Value.CurrentImage = m_pdb; 45 | var offsets = SymbolManager.Value.GetSymOffsets(names); 46 | 47 | var rg = new Pointer[offsets.Length]; 48 | 49 | for (int i = 0; i < rg.Length; i++) { 50 | rg[i] = m_baseAddress + offsets[i]; 51 | } 52 | 53 | return rg; 54 | } 55 | 56 | public TDelegate GetFunctionSafe(string name) where TDelegate : Delegate 57 | { 58 | return FunctionFactory.Delegates.CreateSafe(GetAddress(name)); 59 | } 60 | 61 | public TDelegate GetFunction(string id) where TDelegate : Delegate 62 | { 63 | return FunctionFactory.Delegates.Create(GetAddress(id)); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Enums/MemState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RazorSharp.Interop.Enums 4 | { 5 | /// 6 | /// 7 | /// Doc 8 | /// 9 | /// 10 | [Flags] 11 | public enum MemState 12 | { 13 | /// 14 | /// Indicates committed pages for which physical storage has been allocated, either in memory or in the paging file on 15 | /// disk. 16 | /// 17 | Commit = 0x1000, 18 | 19 | /// 20 | /// Indicates reserved pages where a range of the process's virtual address space is reserved without any physical 21 | /// storage being allocated. For reserved pages, the information in the Protect member is undefined. 22 | /// 23 | Reserve = 0x2000, 24 | 25 | /// 26 | /// Indicates free pages not accessible to the calling process and available to be allocated. For free pages, the 27 | /// information in the AllocationBase, AllocationProtect, Protect, and Type members is undefined. 28 | /// 29 | Free = 0x10000 30 | } 31 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Enums/MemType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RazorSharp.Interop.Enums 4 | { 5 | /// 6 | /// 7 | /// Doc 8 | /// 9 | /// 10 | [Flags] 11 | public enum MemType 12 | { 13 | /// 14 | /// Indicates that the memory pages within the region are mapped into the view of an image section. 15 | /// 16 | Image = 0x1000000, 17 | 18 | /// 19 | /// Indicates that the memory pages within the region are mapped into the view of a section. 20 | /// 21 | Mapped = 0x40000, 22 | 23 | /// 24 | /// Indicates that the memory pages within the region are private (that is, not shared by other processes). 25 | /// 26 | Private = 0x20000 27 | } 28 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Enums/MemoryProtection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RazorSharp.Interop.Enums 4 | { 5 | /// 6 | /// Doc 7 | /// 8 | [Flags] 9 | public enum MemoryProtection : uint 10 | { 11 | /// 12 | /// Enables execute access to the committed region of pages. An attempt to write to the committed region results in an 13 | /// access violation. 14 | /// 15 | Execute = 0x10, 16 | 17 | /// 18 | /// Enables execute or read-only access to the committed region of pages. An attempt to write to the committed region 19 | /// results in an access violation. 20 | /// 21 | ExecuteRead = 0x20, 22 | 23 | /// 24 | /// Enables execute, read-only, or read/write access to the committed region of pages. 25 | /// 26 | ExecuteReadWrite = 0x40, 27 | 28 | /// 29 | /// Enables execute, read-only, or copy-on-write access to a mapped view of a file mapping object. 30 | /// An attempt to write to a committed copy-on-write page results in a private copy of the page being made for the 31 | /// process. 32 | /// The private page is marked as , and the change is written to the new page. 33 | /// This flag is not supported by the VirtualAlloc or VirtualAllocEx functions. 34 | /// 35 | ExecuteWriteCopy = 0x80, 36 | 37 | /// 38 | /// Disables all access to the committed region of pages. An attempt to read from, write to, or execute the committed 39 | /// region results in an access violation. 40 | /// 41 | NoAccess = 0x01, 42 | 43 | /// 44 | /// Enables read-only access to the committed region of pages. An attempt to write to the committed region results in 45 | /// an access violation. If Data Execution Prevention is enabled, an attempt to execute code in the committed region 46 | /// results in an access violation. 47 | /// 48 | ReadOnly = 0x02, 49 | 50 | /// 51 | /// Enables read-only or read/write access to the committed region of pages. If Data Execution Prevention is enabled, 52 | /// attempting to execute code in the committed region results in an access violation. 53 | /// 54 | ReadWrite = 0x04, 55 | 56 | /// 57 | /// Enables read-only or copy-on-write access to a mapped view of a file mapping object. An attempt to write to a 58 | /// committed copy-on-write page results in a private copy of the page being made for the process. The private page is 59 | /// marked as , and the change is written to the new page. 60 | /// If Data Execution Prevention is enabled, attempting to execute code in the committed region results in an access 61 | /// violation. 62 | /// This flag is not supported by the VirtualAlloc or VirtualAllocEx functions. 63 | /// 64 | WriteCopy = 0x08, 65 | 66 | /// 67 | /// Pages in the region become guard pages. Any attempt to access a guard page causes the system to raise a 68 | /// STATUS_GUARD_PAGE_VIOLATION exception and turn off the guard page status. Guard pages thus act as a one-time access 69 | /// alarm. When an access attempt leads the system to turn off guard page status, the underlying page protection takes 70 | /// over. 71 | /// If a guard page exception occurs during a system service, the service typically returns a failure status indicator. 72 | /// This value cannot be used with . 73 | /// 74 | Guard = 0x100, 75 | 76 | /// 77 | /// Sets all pages to be non-cachable. Applications should not use this attribute except when explicitly required for a 78 | /// device. Using the interlocked functions with memory that is mapped with SEC_NOCACHE can result in an 79 | /// EXCEPTION_ILLEGAL_INSTRUCTION exception. The flag cannot be used with the 80 | /// , , or flags. 81 | /// The flag can be used only when allocating private memory with the VirtualAlloc, 82 | /// VirtualAllocEx, or VirtualAllocExNuma functions. 83 | /// 84 | NoCache = 0x200, 85 | 86 | /// 87 | /// Sets all pages to be write-combined. 88 | /// Applications should not use this attribute except when explicitly required for a device. Using the 89 | /// interlocked functions with memory that is mapped as write-combined can result in an EXCEPTION_ILLEGAL_INSTRUCTION 90 | /// exception. 91 | /// The flag cannot be specified with the , , 92 | /// and flags. 93 | /// The flag can be used only when allocating private memory with the VirtualAlloc, 94 | /// VirtualAllocEx, or VirtualAllocExNuma functions. 95 | /// 96 | WriteCombine = 0x400 97 | 98 | 99 | // PAGE_TARGETS_INVALID 0x40000000 100 | 101 | // PAGE_TARGETS_NO_UPDATE 0x40000000 102 | } 103 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Enums/ProcessAccess.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RazorSharp.Interop.Enums 4 | { 5 | [Flags] 6 | public enum ProcessAccess : uint 7 | { 8 | All = 0x1F0FFF, 9 | Terminate = 0x000001, 10 | CreateThread = 0x000002, 11 | VmOperation = 0x00000008, 12 | VmRead = 0x000010, 13 | VmWrite = 0x000020, 14 | DupHandle = 0x00000040, 15 | CreateProcess = 0x000080, 16 | SetInformation = 0x00000200, 17 | QueryInformation = 0x000400, 18 | QueryLimitedInformation = 0x001000, 19 | Synchronize = 0x00100000 20 | } 21 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Enums/SymbolFlag.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RazorSharp.Interop.Enums 4 | { 5 | [Flags] 6 | public enum SymbolFlag 7 | { 8 | /// 9 | /// The symbol is a CLR token. 10 | /// 11 | CLR_TOKEN = 0x00040000, 12 | 13 | 14 | /// 15 | /// The symbol is a constant. 16 | /// 17 | CONSTANT = 0x00000100, 18 | 19 | 20 | /// 21 | /// The symbol is from the export table. 22 | /// 23 | EXPORT = 0x00000200, 24 | 25 | 26 | /// 27 | /// The symbol is a forwarder. 28 | /// 29 | FORWARDER = 0x00000400, 30 | 31 | 32 | /// 33 | /// Offsets are frame relative. 34 | /// 35 | FRAMEREL = 0x00000020, 36 | 37 | 38 | /// 39 | /// The symbol is a known function. 40 | /// 41 | FUNCTION = 0x00000800, 42 | 43 | 44 | /// 45 | /// The symbol address is an offset relative to the beginning of the intermediate language block. This applies to managed code only. 46 | /// 47 | ILREL = 0x00010000, 48 | 49 | 50 | /// 51 | /// The symbol is a local variable. 52 | /// 53 | LOCAL = 0x00000080, 54 | 55 | 56 | /// 57 | /// The symbol is managed metadata. 58 | /// 59 | METADATA = 0x00020000, 60 | 61 | 62 | /// 63 | /// The symbol is a parameter. 64 | /// 65 | PARAMETER = 0x00000040, 66 | 67 | 68 | /// 69 | /// The symbol is a register. The Register member is used. 70 | /// 71 | REGISTER = 0x00000008, 72 | 73 | /// 74 | /// Offsets are register relative. 75 | /// 76 | REGREL = 0x00000010, 77 | 78 | /// 79 | /// The symbol is a managed code slot. 80 | /// 81 | SLOT = 0x00008000, 82 | 83 | /// 84 | /// The symbol is a thunk. 85 | /// 86 | THUNK = 0x00002000, 87 | 88 | /// 89 | /// The symbol is an offset into the TLS data area. 90 | /// 91 | TLSREL = 0x00004000, 92 | 93 | /// 94 | /// The Value member is used. 95 | /// 96 | VALUEPRESENT = 0x00000001, 97 | 98 | /// 99 | /// The symbol is a virtual symbol created by the SymAddSymbol function. 100 | /// 101 | VIRTUAL = 0x00001000, 102 | } 103 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Enums/SymbolOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RazorSharp.Interop.Enums 4 | { 5 | [Flags] 6 | public enum SymbolOptions : uint 7 | { 8 | ALLOW_ABSOLUTE_SYMBOLS = 0x00000800, 9 | 10 | ALLOW_ZERO_ADDRESS = 0x01000000, 11 | 12 | AUTO_PUBLICS = 0x00010000, 13 | 14 | CASE_INSENSITIVE = 0x00000001, 15 | 16 | DEBUG = 0x80000000, 17 | 18 | DEFERRED_LOADS = 0x00000004, 19 | 20 | DISABLE_SYMSRV_AUTODETECT = 0x02000000, 21 | 22 | EXACT_SYMBOLS = 0x00000400, 23 | 24 | FAIL_CRITICAL_ERRORS = 0x00000200, 25 | 26 | FAVOR_COMPRESSED = 0x00800000, 27 | 28 | FLAT_DIRECTORY = 0x00400000, 29 | 30 | IGNORE_CVREC = 0x00000080, 31 | 32 | IGNORE_IMAGEDIR = 0x00200000, 33 | 34 | IGNORE_NT_SYMPATH = 0x00001000, 35 | 36 | INCLUDE_32BIT_MODULES = 0x00002000, 37 | 38 | LOAD_ANYTHING = 0x00000040, 39 | 40 | LOAD_LINES = 0x00000010, 41 | 42 | NO_CPP = 0x00000008, 43 | 44 | NO_IMAGE_SEARCH = 0x00020000, 45 | 46 | NO_PROMPTS = 0x00080000, 47 | 48 | NO_PUBLICS = 0x00008000, 49 | 50 | NO_UNQUALIFIED_LOADS = 0x00000100, 51 | 52 | OVERWRITE = 0x00100000, 53 | 54 | PUBLICS_ONLY = 0x00004000, 55 | 56 | SECURE = 0x00040000, 57 | 58 | UNDNAME = 0x00000002, 59 | } 60 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Enums/SymbolTag.cs: -------------------------------------------------------------------------------- 1 | namespace RazorSharp.Interop.Enums 2 | { 3 | public enum SymbolTag 4 | { 5 | Null, 6 | Exe, 7 | Compiland, 8 | CompilandDetails, 9 | CompilandEnv, 10 | Function, 11 | Block, 12 | Data, 13 | Annotation, 14 | Label, 15 | PublicSymbol, 16 | UDT, 17 | Enum, 18 | FunctionType, 19 | PointerType, 20 | ArrayType, 21 | BaseType, 22 | Typedef, 23 | BaseClass, 24 | Friend, 25 | FunctionArgType, 26 | FuncDebugStart, 27 | FuncDebugEnd, 28 | UsingNamespace, 29 | VTableShape, 30 | VTable, 31 | Custom, 32 | Thunk, 33 | CustomType, 34 | ManagedType, 35 | Dimension, 36 | CallSite, 37 | InlineSite, 38 | BaseInterface, 39 | VectorType, 40 | MatrixType, 41 | HLSLType, 42 | Caller, 43 | Callee, 44 | Export, 45 | HeapAllocationSite, 46 | CoffGroup, 47 | Max 48 | } 49 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/FunctionFactory.Delegates.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using RazorSharp.CoreClr.Meta; 4 | using RazorSharp.Import.Attributes; 5 | using RazorSharp.Import.Enums; 6 | using RazorSharp.Memory; 7 | using RazorSharp.Memory.Pointers; 8 | 9 | namespace RazorSharp.Interop 10 | { 11 | 12 | public static unsafe partial class FunctionFactory 13 | { 14 | /// 15 | /// Provides utilities for creating delegates from function pointers. 16 | /// 17 | public static class Delegates 18 | { 19 | [ImportForwardCall("COMDelegate", nameof(ConvertToDelegate), ImportCallOptions.Map)] 20 | private static void* ConvertToDelegate(void* fn, void* mt) 21 | { 22 | return Functions.Native.CallReturnPointer((void*) Imports[nameof(ConvertToDelegate)], 23 | fn, mt); 24 | } 25 | 26 | public static Delegate CreateSafe(Pointer ptr, Type t) 27 | { 28 | return Marshal.GetDelegateForFunctionPointer(ptr.Address, t); 29 | } 30 | 31 | public static TDelegate CreateSafe(Pointer ptr) 32 | { 33 | return Marshal.GetDelegateForFunctionPointer(ptr.Address); 34 | } 35 | 36 | /// 37 | /// Creates a from a function pointer. 38 | /// 39 | /// Similar to 40 | /// 41 | /// 42 | /// Function pointer 43 | /// type 44 | /// A from 45 | public static Delegate Create(Pointer ptr, Type t) 46 | { 47 | MetaType mt = t; 48 | return Converter.ToObject(ConvertToDelegate(ptr.ToPointer(), mt.NativePointer)); 49 | } 50 | 51 | /// 52 | /// Creates a from a function pointer. 53 | /// 54 | /// Similar to 55 | /// 56 | /// 57 | /// Function pointer 58 | /// type 59 | /// A from 60 | public static TDelegate Create(Pointer ptr) where TDelegate : Delegate 61 | { 62 | return (TDelegate) Create(ptr, typeof(TDelegate)); 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/FunctionFactory.Managed.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using RazorSharp.Core; 4 | using RazorSharp.CoreClr; 5 | using RazorSharp.CoreClr.Metadata; 6 | using RazorSharp.Import; 7 | using RazorSharp.Import.Attributes; 8 | using RazorSharp.Import.Enums; 9 | using RazorSharp.Memory; 10 | using RazorSharp.Memory.Pointers; 11 | using RazorSharp.Utilities.Security; 12 | 13 | namespace RazorSharp.Interop 14 | { 15 | 16 | public static unsafe partial class FunctionFactory 17 | { 18 | /// 19 | /// Provides functions for resetting and setting the entry point for managed methods. 20 | /// 21 | internal static class Managed 22 | { 23 | /// 24 | /// Resets the method represented by to its original, blank state. 25 | /// 26 | /// Method 27 | [ImportForwardCall(typeof(MethodDesc), nameof(MethodDesc.Reset), ImportCallOptions.Map)] 28 | internal static void Restore(MethodInfo mi) 29 | { 30 | Functions.Native.CallVoid((void*) Imports[nameof(Restore)], Runtime.ResolveHandle(mi).ToPointer()); 31 | } 32 | 33 | /// 34 | /// Sets the entry point for the method represented by to 35 | /// 36 | /// Method 37 | /// Function pointer 38 | /// true if the operation succeeded; false otherwise 39 | /// The process is not 64-bit 40 | [ImportForwardCall(typeof(MethodDesc), nameof(MethodDesc.SetNativeCodeInterlocked), ImportCallOptions.Map)] 41 | internal static bool SetEntryPoint(MethodInfo mi, Pointer ptr) 42 | { 43 | if (!Mem.Is64Bit) { 44 | throw Guard.Require64BitFail(nameof(SetEntryPoint)); 45 | } 46 | 47 | Restore(mi); 48 | 49 | return Functions.Native.Call((void*) Imports[nameof(SetEntryPoint)], 50 | mi.MethodHandle.Value.ToPointer(), ptr.ToPointer()); 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/FunctionFactory.cs: -------------------------------------------------------------------------------- 1 | using RazorSharp.Core; 2 | using RazorSharp.Import; 3 | using RazorSharp.Import.Attributes; 4 | 5 | namespace RazorSharp.Interop 6 | { 7 | /// 8 | /// Provides methods for creating and modifying functions. 9 | /// 10 | [ImportNamespace] 11 | public static unsafe partial class FunctionFactory 12 | { 13 | static FunctionFactory() 14 | { 15 | ImportManager.Value.Load(typeof(FunctionFactory), Clr.Value.Imports); 16 | } 17 | 18 | [ImportMapDesignation] 19 | private static readonly ImportMap Imports = new ImportMap(); 20 | } 21 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Functions.Fluid.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using RazorSharp.Interop.Utilities; 6 | using RazorSharp.Memory.Pointers; 7 | 8 | namespace RazorSharp.Interop 9 | { 10 | public static partial class Functions 11 | { 12 | /// 13 | /// Provides methods for dynamic function invocation. 14 | /// 15 | public static class Fluid 16 | { 17 | #region FluidCall 18 | 19 | /// 20 | /// Dynamically creates a . 21 | /// 22 | /// Function pointer 23 | /// Return type of the 24 | /// Delegate arguments 25 | /// A matching 26 | private static Delegate CreateFluidCallDelegate(Pointer ptr, Type returnType, object[] args) 27 | { 28 | var argTypes = new List(); 29 | argTypes.AddRange(args.Select(o => o.GetType())); 30 | argTypes.Add(returnType); 31 | 32 | var type = Expression.GetDelegateType(argTypes.ToArray()); 33 | return FunctionFactory.Delegates.Create(ptr, type); 34 | } 35 | 36 | /// 37 | /// Calls the void function located at the address specified by with the 38 | /// arguments specified by . No return value. 39 | /// 40 | /// Function pointer 41 | /// Function arguments 42 | public static void CallVoid(Pointer ptr, params object[] args) 43 | { 44 | var d = CreateFluidCallDelegate(ptr, typeof(void), args); 45 | d.DynamicInvoke(args); 46 | } 47 | 48 | /// 49 | /// Calls the function located at the address specified by with the 50 | /// arguments specified by 51 | /// 52 | /// Function pointer 53 | /// Function arguments 54 | /// The value returned by the function as an 55 | public static object Call(Pointer ptr, params object[] args) => Call(ptr, args); 56 | 57 | /// 58 | /// Calls the function located at the address specified by with the 59 | /// arguments specified by 60 | /// 61 | /// Function pointer 62 | /// Function arguments 63 | /// Function return type 64 | /// The value returned by the function 65 | public static T Call(Pointer ptr, params object[] args) 66 | { 67 | var d = CreateFluidCallDelegate(ptr, typeof(T), args); 68 | return (T) d.DynamicInvoke(args); 69 | } 70 | 71 | #endregion 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Functions.Module.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RazorSharp.Interop.Utilities; 3 | 4 | namespace RazorSharp.Interop 5 | { 6 | public static partial class Functions 7 | { 8 | /// 9 | /// Provides methods for accessing DLL-exported functions. 10 | /// 11 | public static class Module 12 | { 13 | /// 14 | /// Gets an exported function 15 | /// 16 | public static TDelegate FindExportedFunction(string dllName, string fn) where TDelegate : Delegate 17 | { 18 | var hModule = Interop.Native.Kernel32.GetModuleHandle(dllName); 19 | var hFn = Interop.Native.Kernel32.GetProcAddress(hModule, fn); 20 | return FunctionFactory.Delegates.Create(hFn); 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Functions.Reflection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | 5 | namespace RazorSharp.Interop 6 | { 7 | public static partial class Functions 8 | { 9 | /// 10 | /// Provides methods for invoking managed methods via Reflection. 11 | /// 12 | public static class Reflection 13 | { 14 | #region Generic 15 | 16 | /// 17 | /// Executes a generic method 18 | /// 19 | /// Method to execute 20 | /// Generic type parameters 21 | /// Instance of type; null if the method is static 22 | /// Method arguments 23 | /// Return value of the method specified by 24 | public static object CallGeneric(MethodInfo method, 25 | Type[] typeArgs, 26 | object value, 27 | params object[] args) 28 | { 29 | return method.MakeGenericMethod(typeArgs).Invoke(value, args); 30 | } 31 | 32 | public static object CallGeneric(MethodInfo method, 33 | Type typeArg, 34 | object value, 35 | params object[] args) 36 | { 37 | return method.MakeGenericMethod(typeArg).Invoke(value, args); 38 | } 39 | 40 | #endregion 41 | 42 | /// 43 | /// Runs a constructor whose parameters match 44 | /// 45 | /// Instance 46 | /// Constructor arguments 47 | /// 48 | /// true if a matching constructor was found and executed; 49 | /// false if a constructor couldn't be found 50 | /// 51 | public static bool CallConstructor(T value, params object[] args) 52 | { 53 | ConstructorInfo[] ctors = value.GetType().GetConstructors(); 54 | Type[] argTypes = args.Select(x => x.GetType()).ToArray(); 55 | 56 | foreach (var ctor in ctors) { 57 | ParameterInfo[] paramz = ctor.GetParameters(); 58 | 59 | if (paramz.Length == args.Length) { 60 | if (paramz.Select(x => x.ParameterType).SequenceEqual(argTypes)) { 61 | ctor.Invoke(value, args); 62 | return true; 63 | } 64 | } 65 | } 66 | 67 | return false; 68 | } 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Functions.cs: -------------------------------------------------------------------------------- 1 | #region 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Linq.Expressions; 7 | using System.Reflection; 8 | using RazorSharp.Import.Attributes; 9 | using RazorSharp.Memory.Pointers; 10 | 11 | // ReSharper disable SuggestBaseTypeForParameter 12 | 13 | #endregion 14 | 15 | // ReSharper disable ParameterTypeCanBeEnumerable.Local 16 | 17 | namespace RazorSharp.Interop 18 | { 19 | /// 20 | /// Provides methods of invoking various function types. 21 | /// 22 | public static partial class Functions { } 23 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Native.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace RazorSharp.Interop 4 | { 5 | internal static unsafe partial class Native 6 | { 7 | private const uint INVALID_FILE_SIZE = 0xFFFFFFFF; 8 | } 9 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Structures/ImageDOSHeader.cs: -------------------------------------------------------------------------------- 1 | using RazorSharp.Interop.Utilities; 2 | 3 | // ReSharper disable InconsistentNaming 4 | 5 | namespace RazorSharp.Interop.Structures 6 | { 7 | [Native] 8 | public struct ImageDOSHeader 9 | { 10 | // DOS .EXE header 11 | 12 | /// 13 | /// Magic number 14 | /// 15 | public ushort EMagic { get; } 16 | 17 | /// 18 | /// Bytes on last page of file 19 | /// 20 | public ushort ECblp { get; } 21 | 22 | /// 23 | /// Pages in file 24 | /// 25 | public ushort ECp { get; } 26 | 27 | /// 28 | /// Relocations 29 | /// 30 | public ushort ECrlc { get; } 31 | 32 | /// 33 | /// Size of header in paragraphs 34 | /// 35 | public ushort ECparhdr { get; } 36 | 37 | 38 | /// 39 | /// Minimum extra paragraphs needed 40 | /// 41 | public ushort EMinalloc { get; } 42 | 43 | /// 44 | /// Maximum extra paragraphs needed 45 | /// 46 | public ushort EMaxalloc { get; } 47 | 48 | /// 49 | /// Initial (relative) SS value 50 | /// 51 | public ushort ESs { get; } 52 | 53 | /// 54 | /// Initial SP value 55 | /// 56 | public ushort ESp { get; } 57 | 58 | /// 59 | /// Checksum 60 | /// 61 | public ushort ECsum { get; } 62 | 63 | /// 64 | /// Initial IP value 65 | /// 66 | public ushort EIp { get; } 67 | 68 | /// 69 | /// Initial (relative) CS value 70 | /// 71 | public ushort ECs { get; } 72 | 73 | /// 74 | /// File address of relocation table 75 | /// 76 | public ushort ELfarlc { get; } 77 | 78 | /// 79 | /// Overlay number 80 | /// 81 | public ushort EOvno { get; } 82 | 83 | /// 84 | /// Reserved 85 | /// 86 | public ushort ERes0 { get; } 87 | 88 | /// 89 | /// Reserved 90 | /// 91 | public ushort ERes1 { get; } 92 | 93 | /// 94 | /// Reserved 95 | /// 96 | public ushort ERes2 { get; } 97 | 98 | /// 99 | /// Reserved 100 | /// 101 | public ushort ERes3 { get; } 102 | 103 | /// 104 | /// OEM identifier (for ) 105 | /// 106 | public ushort EOemid { get; } 107 | 108 | /// 109 | /// OEM information; specific 110 | /// 111 | public ushort EOeminfo { get; } 112 | 113 | /// 114 | /// Reserved 115 | /// 116 | public ushort ERes20 { get; } 117 | 118 | /// 119 | /// Reserved 120 | /// 121 | public ushort ERes21 { get; } 122 | 123 | /// 124 | /// Reserved 125 | /// 126 | public ushort ERes22 { get; } 127 | 128 | /// 129 | /// Reserved 130 | /// 131 | public ushort ERes23 { get; } 132 | 133 | /// 134 | /// Reserved 135 | /// 136 | public ushort ERes24 { get; } 137 | 138 | /// 139 | /// Reserved 140 | /// 141 | public ushort ERes25 { get; } 142 | 143 | /// 144 | /// Reserved 145 | /// 146 | public ushort ERes26 { get; } 147 | 148 | /// 149 | /// Reserved 150 | /// 151 | public ushort ERes27 { get; } 152 | 153 | /// 154 | /// Reserved 155 | /// 156 | public ushort ERes28 { get; } 157 | 158 | /// 159 | /// Reserved 160 | /// 161 | public ushort ERes29 { get; } 162 | 163 | /// 164 | /// File address of new exe header 165 | /// 166 | public uint ELfanew { get; } 167 | } 168 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Structures/ImageDataDirectory.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using RazorSharp.Interop.Utilities; 3 | 4 | namespace RazorSharp.Interop.Structures 5 | { 6 | [Native] 7 | [StructLayout(LayoutKind.Sequential)] 8 | public struct ImageDataDirectory 9 | { 10 | public uint VirtualAddress { get; } 11 | public uint Size { get; } 12 | } 13 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Structures/ImageFileHeader.cs: -------------------------------------------------------------------------------- 1 | #region 2 | 3 | using System.Runtime.InteropServices; 4 | using RazorSharp.Interop.Utilities; 5 | 6 | #endregion 7 | 8 | namespace RazorSharp.Interop.Structures 9 | { 10 | [Native] 11 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 12 | public struct ImageFileHeader 13 | { 14 | public ushort Machine { get; } 15 | 16 | public ushort NumberOfSections { get; } 17 | 18 | public uint TimeDateStamp { get; } 19 | 20 | public uint PointerToSymbolTable { get; } 21 | 22 | public uint NumberOfSymbols { get; } 23 | 24 | public ushort SizeOfOptionalHeader { get; } 25 | 26 | public ushort Characteristics { get; } 27 | } 28 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Structures/ImageOptionalHeader32.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using RazorSharp.Interop.Utilities; 3 | 4 | namespace RazorSharp.Interop.Structures 5 | { 6 | [Native] 7 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 8 | public struct ImageOptionalHeader32 9 | { 10 | public ushort Magic; 11 | 12 | public byte MajorLinkerVersion; 13 | 14 | public byte MinorLinkerVersion; 15 | 16 | public uint SizeOfCode; 17 | 18 | public uint SizeOfInitializedData; 19 | 20 | public uint SizeOfUninitializedData; 21 | 22 | public uint AddressOfEntryPoint; 23 | 24 | public uint BaseOfCode; 25 | 26 | public uint BaseOfData; 27 | 28 | public uint ImageBase; 29 | 30 | public uint SectionAlignment; 31 | 32 | public uint FileAlignment; 33 | 34 | public ushort MajorOperatingSystemVersion; 35 | 36 | public ushort MinorOperatingSystemVersion; 37 | 38 | public ushort MajorImageVersion; 39 | 40 | public ushort MinorImageVersion; 41 | 42 | public ushort MajorSubsystemVersion; 43 | 44 | public ushort MinorSubsystemVersion; 45 | 46 | public uint Win32VersionValue; 47 | 48 | public uint SizeOfImage; 49 | 50 | public uint SizeOfHeaders; 51 | 52 | public uint CheckSum; 53 | 54 | public ushort Subsystem; 55 | 56 | public ushort DllCharacteristics; 57 | 58 | public uint SizeOfStackReserve; 59 | 60 | public uint SizeOfStackCommit; 61 | 62 | public uint SizeOfHeapReserve; 63 | 64 | public uint SizeOfHeapCommit; 65 | 66 | public uint LoaderFlags; 67 | 68 | public uint NumberOfRvaAndSizes; 69 | 70 | public ImageDataDirectory ExportTable; 71 | 72 | public ImageDataDirectory ImportTable; 73 | 74 | public ImageDataDirectory ResourceTable; 75 | 76 | public ImageDataDirectory ExceptionTable; 77 | 78 | public ImageDataDirectory CertificateTable; 79 | 80 | public ImageDataDirectory BaseRelocationTable; 81 | 82 | public ImageDataDirectory Debug; 83 | 84 | public ImageDataDirectory Architecture; 85 | 86 | public ImageDataDirectory GlobalPtr; 87 | 88 | public ImageDataDirectory TLSTable; 89 | 90 | public ImageDataDirectory LoadConfigTable; 91 | 92 | public ImageDataDirectory BoundImport; 93 | 94 | public ImageDataDirectory IAT; 95 | 96 | public ImageDataDirectory DelayImportDescriptor; 97 | 98 | public ImageDataDirectory CLRRuntimeHeader; 99 | 100 | public ImageDataDirectory Reserved; 101 | } 102 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Structures/ImageOptionalHeader64.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using RazorSharp.Interop.Utilities; 3 | 4 | namespace RazorSharp.Interop.Structures 5 | { 6 | [Native] 7 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 8 | public struct ImageOptionalHeader64 9 | { 10 | public ushort Magic; 11 | 12 | 13 | public byte MajorLinkerVersion; 14 | 15 | 16 | public byte MinorLinkerVersion; 17 | 18 | 19 | public uint SizeOfCode; 20 | 21 | 22 | public uint SizeOfInitializedData; 23 | 24 | 25 | public uint SizeOfUninitializedData; 26 | 27 | 28 | public uint AddressOfEntryPoint; 29 | 30 | 31 | public uint BaseOfCode; 32 | 33 | 34 | public ulong ImageBase; 35 | 36 | 37 | public uint SectionAlignment; 38 | 39 | 40 | public uint FileAlignment; 41 | 42 | 43 | public ushort MajorOperatingSystemVersion; 44 | 45 | 46 | public ushort MinorOperatingSystemVersion; 47 | 48 | 49 | public ushort MajorImageVersion; 50 | 51 | 52 | public ushort MinorImageVersion; 53 | 54 | 55 | public ushort MajorSubsystemVersion; 56 | 57 | 58 | public ushort MinorSubsystemVersion; 59 | 60 | 61 | public uint Win32VersionValue; 62 | 63 | 64 | public uint SizeOfImage; 65 | 66 | 67 | public uint SizeOfHeaders; 68 | 69 | 70 | public uint CheckSum; 71 | 72 | 73 | public ushort Subsystem; 74 | 75 | 76 | public ushort DllCharacteristics; 77 | 78 | 79 | public ulong SizeOfStackReserve; 80 | 81 | 82 | public ulong SizeOfStackCommit; 83 | 84 | 85 | public ulong SizeOfHeapReserve; 86 | 87 | 88 | public ulong SizeOfHeapCommit; 89 | 90 | 91 | public uint LoaderFlags; 92 | 93 | 94 | public uint NumberOfRvaAndSizes; 95 | 96 | 97 | public ImageDataDirectory ExportTable; 98 | 99 | 100 | public ImageDataDirectory ImportTable; 101 | 102 | 103 | public ImageDataDirectory ResourceTable; 104 | 105 | 106 | public ImageDataDirectory ExceptionTable; 107 | 108 | 109 | public ImageDataDirectory CertificateTable; 110 | 111 | 112 | public ImageDataDirectory BaseRelocationTable; 113 | 114 | 115 | public ImageDataDirectory Debug; 116 | 117 | 118 | public ImageDataDirectory Architecture; 119 | 120 | 121 | public ImageDataDirectory GlobalPtr; 122 | 123 | 124 | public ImageDataDirectory TLSTable; 125 | 126 | 127 | public ImageDataDirectory LoadConfigTable; 128 | 129 | 130 | public ImageDataDirectory BoundImport; 131 | 132 | 133 | public ImageDataDirectory IAT; 134 | 135 | 136 | public ImageDataDirectory DelayImportDescriptor; 137 | 138 | 139 | public ImageDataDirectory CLRRuntimeHeader; 140 | 141 | 142 | public ImageDataDirectory Reserved; 143 | } 144 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Structures/ImageSectionHeader.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using RazorSharp.Interop.Enums; 3 | using RazorSharp.Interop.Utilities; 4 | 5 | namespace RazorSharp.Interop.Structures 6 | { 7 | [Native] 8 | [StructLayout(LayoutKind.Explicit)] 9 | public struct ImageSectionHeader 10 | { 11 | // Grabbed the following 2 definitions from http://www.pinvoke.net/default.aspx/Structures/IMAGE_SECTION_HEADER.html 12 | 13 | 14 | [FieldOffset(0)] 15 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] 16 | public char[] Name; 17 | 18 | 19 | [FieldOffset(8)] 20 | public uint VirtualSize; 21 | 22 | 23 | [FieldOffset(12)] 24 | public uint VirtualAddress; 25 | 26 | 27 | [FieldOffset(16)] 28 | public uint SizeOfRawData; 29 | 30 | 31 | [FieldOffset(20)] 32 | public uint PointerToRawData; 33 | 34 | 35 | [FieldOffset(24)] 36 | public uint PointerToRelocations; 37 | 38 | 39 | [FieldOffset(28)] 40 | public uint PointerToLinenumbers; 41 | 42 | 43 | [FieldOffset(32)] 44 | public ushort NumberOfRelocations; 45 | 46 | 47 | [FieldOffset(34)] 48 | public ushort NumberOfLinenumbers; 49 | 50 | 51 | [FieldOffset(36)] 52 | public DataSectionFlags Characteristics; 53 | 54 | public string Section => new string(Name); 55 | } 56 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Structures/ImageSectionInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RazorSharp.Interop.Enums; 3 | 4 | namespace RazorSharp.Interop.Structures 5 | { 6 | /// 7 | /// Wraps an 8 | /// 9 | public sealed class ImageSectionInfo 10 | { 11 | public string Name { get; } 12 | 13 | public int Number { get; } 14 | 15 | public IntPtr Address { get; } 16 | 17 | public int Size { get; } 18 | 19 | public DataSectionFlags Characteristics { get; } 20 | 21 | internal ImageSectionInfo(ImageSectionHeader struc, int number, IntPtr address) 22 | { 23 | Number = number; 24 | Name = struc.Section; 25 | Address = address; 26 | Size = (int) struc.VirtualSize; 27 | Characteristics = struc.Characteristics; 28 | } 29 | 30 | public override string ToString() 31 | { 32 | return String.Format("Number: {0} | Name: {1} | Address: {2:X} | Size: {3} | Characteristics: {4}", Number, 33 | Name, 34 | Address.ToInt64(), Size, Characteristics); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Structures/MemoryBasicInformation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using RazorSharp.Interop.Enums; 4 | using RazorSharp.Interop.Utilities; 5 | 6 | namespace RazorSharp.Interop.Structures 7 | { 8 | [Native] 9 | [StructLayout(LayoutKind.Sequential)] 10 | internal struct MemoryBasicInformation 11 | { 12 | internal IntPtr BaseAddress; 13 | internal IntPtr AllocationBase; 14 | internal MemoryProtection AllocationProtect; 15 | internal IntPtr RegionSize; 16 | internal MemState State; 17 | internal MemoryProtection Protect; 18 | internal MemType Type; 19 | } 20 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Structures/Symbol.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using RazorSharp.Interop.Enums; 4 | using RazorSharp.Interop.Utilities; 5 | using RazorSharp.Memory; 6 | 7 | namespace RazorSharp.Interop.Structures 8 | { 9 | /// 10 | /// Wraps a 11 | /// 12 | public unsafe class Symbol 13 | { 14 | internal Symbol(SymbolInfo* pSymInfo, string name) 15 | { 16 | Name = name; 17 | 18 | SizeOfStruct = pSymInfo->SizeOfStruct; 19 | TypeIndex = pSymInfo->TypeIndex; 20 | Index = pSymInfo->Index; 21 | Size = pSymInfo->Size; 22 | ModBase = pSymInfo->ModBase; 23 | Flags = (SymbolFlag) pSymInfo->Flags; 24 | Value = pSymInfo->Value; 25 | Address = pSymInfo->Address; 26 | Register = pSymInfo->Register; 27 | Scope = pSymInfo->Scope; 28 | Tag = (SymbolTag) pSymInfo->Tag; 29 | } 30 | 31 | internal Symbol(IntPtr pSym) : this((SymbolInfo*) pSym, Native.DebugHelp.GetSymbolName(pSym)) { } 32 | 33 | 34 | public string Name { get; } 35 | 36 | public uint SizeOfStruct { get; } 37 | 38 | public uint TypeIndex { get; } 39 | 40 | public uint Index { get; } 41 | 42 | public uint Size { get; } 43 | 44 | public ulong ModBase { get; } 45 | 46 | public ulong Value { get; } 47 | 48 | public ulong Address { get; } 49 | 50 | public uint Register { get; } 51 | 52 | public uint Scope { get; } 53 | 54 | public SymbolTag Tag { get; } 55 | 56 | public SymbolFlag Flags { get; } 57 | 58 | public long Offset => (long) (Address - ModBase); 59 | 60 | 61 | private static int GetSymbolInfoSize(SymbolInfo* pSym) 62 | { 63 | // SizeOfStruct + (MaxNameLen - 1) * sizeof(TCHAR) 64 | return (int) (pSym->SizeOfStruct + (pSym->MaxNameLen - 1) * sizeof(byte)); 65 | } 66 | 67 | public override string ToString() 68 | { 69 | return String.Format("Name: {0} | Offset: {1:X} | Address: {2:X} | Tag: {3} | Flags: {4}", Name, Offset, 70 | Address, Tag, Flags); 71 | } 72 | 73 | internal const uint MAX_SYM_NAME = 2000; 74 | 75 | internal static readonly int StructureSize = Marshal.SizeOf(); 76 | } 77 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Structures/SymbolInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using RazorSharp.Interop.Utilities; 4 | 5 | namespace RazorSharp.Interop.Structures 6 | { 7 | #region 8 | 9 | using ULONG = UInt32; 10 | using ULONG64 = UInt64; 11 | using CHAR = SByte; 12 | 13 | #endregion 14 | 15 | [Native] 16 | [StructLayout(LayoutKind.Sequential)] 17 | internal struct SymbolInfo 18 | { 19 | internal uint SizeOfStruct; 20 | internal uint TypeIndex; 21 | internal ulong Reserved_1; 22 | internal ulong Reserved_2; 23 | internal uint Index; 24 | internal uint Size; 25 | internal ulong ModBase; 26 | internal uint Flags; 27 | internal ulong Value; 28 | internal ulong Address; 29 | internal uint Register; 30 | internal uint Scope; 31 | internal uint Tag; 32 | internal uint NameLen; 33 | internal uint MaxNameLen; 34 | internal sbyte Name; 35 | } 36 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Utilities/NativeAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using JetBrains.Annotations; 3 | 4 | namespace RazorSharp.Interop.Utilities 5 | { 6 | 7 | [MeansImplicitUse(ImplicitUseTargetFlags.WithMembers)] 8 | public class NativeAttribute : Attribute { } 9 | } -------------------------------------------------------------------------------- /RazorSharp/Interop/Utilities/PEHeaderReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | using System.Runtime.InteropServices; 5 | using RazorSharp.Interop.Structures; 6 | using RazorSharp.Memory; 7 | 8 | // ReSharper disable InconsistentNaming 9 | 10 | namespace RazorSharp.Interop.Utilities 11 | { 12 | // Credits: John Stewien 13 | // From: http://code.cheesydesign.com/?p=572 14 | 15 | // How it works is that it first reads in the old DOS header, 16 | // at the end of this header is a file offset to the new NT File Header structure. 17 | // I seek to that position, and read in the NT File Header. From that header I can get the linker time stamp. 18 | // As this is a general purpose library I also check whether the header is 32 or 64 bit, and read in either 19 | // the Optional 32 bit Header, or the Optional 64 bit Header, which can then be used however you like. 20 | // This is how you would get the 32 bit header: 21 | 22 | /// 23 | /// Reads in the header information of the Portable Executable format. 24 | /// Provides information such as the date the assembly was compiled. 25 | /// 26 | public class PEHeaderReader 27 | { 28 | #region Public Methods 29 | 30 | public PEHeaderReader(string filePath) 31 | { 32 | // Read in the DLL or EXE and get the timestamp 33 | using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read); 34 | var reader = new BinaryReader(stream); 35 | 36 | DOSHeader = Mem.ReadFromBinaryReader(reader); 37 | 38 | // Add 4 bytes to the offset 39 | stream.Seek(DOSHeader.ELfanew, SeekOrigin.Begin); 40 | 41 | uint ntHeadersSignature = reader.ReadUInt32(); 42 | FileHeader = Mem.ReadFromBinaryReader(reader); 43 | 44 | if (Is32BitHeader) { 45 | OptionalHeader32 = Mem.ReadFromBinaryReader(reader); 46 | } 47 | else { 48 | OptionalHeader64 = Mem.ReadFromBinaryReader(reader); 49 | } 50 | 51 | ImageSectionHeaders = new ImageSectionHeader[FileHeader.NumberOfSections]; 52 | for (int headerNo = 0; headerNo < ImageSectionHeaders.Length; ++headerNo) { 53 | ImageSectionHeaders[headerNo] = Mem.ReadFromBinaryReader(reader); 54 | } 55 | } 56 | 57 | /// 58 | /// Gets the header of the .NET assembly that called this function 59 | /// 60 | /// 61 | public static PEHeaderReader GetCallingAssemblyHeader() 62 | { 63 | // Get the path to the calling assembly, which is the path to the 64 | // DLL or EXE that we want the time of 65 | string filePath = Assembly.GetCallingAssembly().Location; 66 | 67 | // Get and return the timestamp 68 | return new PEHeaderReader(filePath); 69 | } 70 | 71 | /// 72 | /// Gets the header of the .NET assembly that called this function 73 | /// 74 | /// 75 | public static PEHeaderReader GetAssemblyHeader() 76 | { 77 | // Get the path to the calling assembly, which is the path to the 78 | // DLL or EXE that we want the time of 79 | string filePath = Assembly.GetAssembly(typeof(PEHeaderReader)).Location; 80 | 81 | // Get and return the timestamp 82 | return new PEHeaderReader(filePath); 83 | } 84 | 85 | #endregion Public Methods 86 | 87 | #region Properties 88 | 89 | /// 90 | /// Gets if the file header is 32 bit or not 91 | /// 92 | public bool Is32BitHeader { 93 | get { 94 | const ushort IMAGE_FILE_32BIT_MACHINE = 0x0100; 95 | return (IMAGE_FILE_32BIT_MACHINE & FileHeader.Characteristics) == IMAGE_FILE_32BIT_MACHINE; 96 | } 97 | } 98 | 99 | public ImageDOSHeader DOSHeader { get; } 100 | 101 | /// 102 | /// Gets the file header 103 | /// 104 | public ImageFileHeader FileHeader { get; } 105 | 106 | /// 107 | /// Gets the optional header 108 | /// 109 | public ImageOptionalHeader32 OptionalHeader32 { get; } 110 | 111 | /// 112 | /// Gets the optional header 113 | /// 114 | public ImageOptionalHeader64 OptionalHeader64 { get; } 115 | 116 | /// 117 | /// Image Section headers. Number of sections is in the file header. 118 | /// 119 | public ImageSectionHeader[] ImageSectionHeaders { get; } 120 | 121 | /// 122 | /// Gets the timestamp from the file header 123 | /// 124 | public DateTime TimeStamp { 125 | get { 126 | // Timestamp is a date offset from 1970 127 | var date = new DateTime(1970, 1, 1, 0, 0, 0); 128 | 129 | // Add in the number of seconds since 1970/1/1 130 | date = date.AddSeconds(FileHeader.TimeDateStamp); 131 | 132 | // Adjust to local timezone 133 | date += TimeZone.CurrentTimeZone.GetUtcOffset(date); 134 | 135 | return date; 136 | } 137 | } 138 | 139 | #endregion Properties 140 | } 141 | } -------------------------------------------------------------------------------- /RazorSharp/Memory/Allocation/AllocationManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using RazorSharp.Memory.Pointers; 4 | using RazorSharp.Model; 5 | using SimpleSharp.Diagnostics; 6 | 7 | namespace RazorSharp.Memory.Allocation 8 | { 9 | /// 10 | /// Allocates and manages memory/resources. 11 | /// 12 | public class AllocationManager : Closable 13 | { 14 | /// 15 | /// Counts the number of allocations (allocated pointers) 16 | /// 17 | public int AllocCount => m_pointers.Count; 18 | 19 | public bool IsMemoryInUse => AllocCount > default(int); 20 | 21 | private readonly List> m_pointers; 22 | 23 | private readonly IAllocator m_allocator; 24 | 25 | protected override string Id => nameof(AllocationManager); 26 | 27 | public AllocationManager(IAllocator allocator) 28 | { 29 | m_allocator = allocator; 30 | m_pointers = new List>(); 31 | } 32 | 33 | /// 34 | /// 35 | /// Allocates elements of type in zeroed memory 36 | /// using the specified allocate function. 37 | /// 38 | /// 39 | /// 40 | /// Once you are done using the memory, dispose using 41 | /// 42 | /// 43 | /// Element type to allocate 44 | /// A pointer to the allocated memory 45 | public Pointer Alloc(int elemCnt = 1) 46 | { 47 | Conditions.Require(elemCnt > default(int), nameof(elemCnt)); 48 | int size = Mem.FullSize(elemCnt); 49 | var alloc = m_allocator.Alloc(size); 50 | 51 | alloc.Clear(); 52 | 53 | m_pointers.Add(alloc); 54 | 55 | return alloc; 56 | } 57 | 58 | public Pointer ReAlloc(Pointer p, int elemCnt = 1) 59 | { 60 | int size = Mem.FullSize(elemCnt); 61 | var reAlloc = m_allocator.ReAlloc(p.Address, size); 62 | 63 | var i = m_pointers.IndexOf(p.Cast()); 64 | m_pointers[i] = reAlloc; 65 | 66 | return reAlloc; 67 | } 68 | 69 | public void Free(Pointer p) 70 | { 71 | m_allocator.Free(p.Cast()); 72 | m_pointers.Remove(p.Cast()); 73 | } 74 | 75 | 76 | public override string ToString() 77 | { 78 | return String.Format("Number of allocations: {0}", AllocCount); 79 | } 80 | 81 | public override void Close() 82 | { 83 | foreach (Pointer pointer in m_pointers) { 84 | Free(pointer); 85 | } 86 | 87 | base.Close(); 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /RazorSharp/Memory/Allocation/Allocators.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using RazorSharp.Memory.Pointers; 4 | 5 | namespace RazorSharp.Memory.Allocation 6 | { 7 | /// 8 | /// Contains common memory allocators. 9 | /// 10 | public static class Allocators 11 | { 12 | /// 13 | /// Exposes LocalAlloc functions from Kernel32.dll 14 | /// (AllocHGlobal functions from ) 15 | /// 16 | private sealed class LocalAllocator : IAllocator 17 | { 18 | /// 19 | /// 20 | /// 21 | public Pointer Alloc(int size) => 22 | Marshal.AllocHGlobal(size); 23 | 24 | /// 25 | /// 26 | /// 27 | public Pointer ReAlloc(Pointer p, int size) => 28 | Marshal.ReAllocHGlobal(p.Address, (IntPtr) size); 29 | 30 | /// 31 | /// 32 | /// 33 | public void Free(Pointer p) => 34 | Marshal.FreeHGlobal(p.Address); 35 | } 36 | 37 | 38 | public static IAllocator Local { get; } = new LocalAllocator(); 39 | } 40 | } -------------------------------------------------------------------------------- /RazorSharp/Memory/Allocation/IAllocator.cs: -------------------------------------------------------------------------------- 1 | using RazorSharp.Memory.Pointers; 2 | 3 | namespace RazorSharp.Memory.Allocation 4 | { 5 | /// 6 | /// Describes a type that contains memory allocation functions. 7 | /// 8 | public interface IAllocator 9 | { 10 | Pointer Alloc(int size); 11 | 12 | Pointer ReAlloc(Pointer p, int size); 13 | 14 | void Free(Pointer p); 15 | } 16 | } -------------------------------------------------------------------------------- /RazorSharp/Memory/Components/ComponentField.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RazorSharp.CoreClr; 3 | using RazorSharp.CoreClr.Meta; 4 | 5 | namespace RazorSharp.Memory.Components 6 | { 7 | /// 8 | /// Describes the component the represents 9 | /// 10 | public enum ComponentType 11 | { 12 | /// 13 | /// The represents a in a 14 | /// 15 | StringChar, 16 | 17 | /// 18 | /// The represents an element in an array 19 | /// 20 | ArrayElement, 21 | } 22 | 23 | /// 24 | /// Represents a component in a dynamically-sized object - an array or string. 25 | /// 26 | public class ComponentField : MemoryField 27 | { 28 | /// 29 | /// Index in the array/string 30 | /// 31 | public int Index { get; } 32 | 33 | /// 34 | /// Type of this 35 | /// 36 | public ComponentType Type { get; } 37 | 38 | public int BaseOffset { get; } 39 | 40 | public override int Offset => BaseOffset + (Index * Size); 41 | 42 | public override string Name { 43 | get { 44 | string s; 45 | switch (Type) { 46 | case ComponentType.StringChar: 47 | s = "Char"; 48 | break; 49 | case ComponentType.ArrayElement: 50 | s = "Element"; 51 | break; 52 | default: 53 | throw new ArgumentOutOfRangeException(); 54 | } 55 | 56 | return String.Format("({0} #{1})", s, Index); 57 | } 58 | } 59 | 60 | internal ComponentField(MetaType type, int index) : base(type.ComponentSize) 61 | { 62 | Index = index; 63 | Type = type.IsString ? ComponentType.StringChar : ComponentType.ArrayElement; 64 | BaseOffset = type.IsString ? Offsets.StringOverhead : Offsets.ArrayOverhead; 65 | 66 | // int ofs = baseOfs + (i * elemSize); 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /RazorSharp/Memory/Components/IStructure.cs: -------------------------------------------------------------------------------- 1 | using RazorSharp.Memory.Pointers; 2 | 3 | namespace RazorSharp.Memory.Components 4 | { 5 | 6 | public interface IStructure 7 | { 8 | string Name { get; } 9 | 10 | int Offset { get; } 11 | 12 | int Size { get; } 13 | 14 | Pointer GetAddress(ref T value); 15 | 16 | object GetValue(object value); 17 | } 18 | } -------------------------------------------------------------------------------- /RazorSharp/Memory/Components/MemoryField.cs: -------------------------------------------------------------------------------- 1 | using RazorSharp.CoreClr.Meta; 2 | using RazorSharp.Memory.Pointers; 3 | 4 | namespace RazorSharp.Memory.Components 5 | { 6 | public class MemoryField : IStructure 7 | { 8 | public virtual string Name { get; } 9 | 10 | public virtual int Offset { get; } 11 | 12 | public virtual int Size { get; } 13 | 14 | internal MemoryField(string name, int offset, int size) : this(size) 15 | { 16 | Name = name; 17 | Offset = offset; 18 | } 19 | 20 | protected MemoryField(int size) 21 | { 22 | Size = size; 23 | } 24 | 25 | public Pointer GetAddress(ref T value) 26 | { 27 | return Unsafe.AddressOfFields(ref value).Cast() + Offset; 28 | } 29 | 30 | public virtual object GetValue(object value) 31 | { 32 | MetaType t = value.GetType(); 33 | // GetElementType doesn't work for some reason 34 | 35 | if (t.IsArray) { 36 | t = t.ElementTypeHandle; 37 | } 38 | 39 | var ptr = GetAddress(ref value); 40 | 41 | 42 | return ptr.ReadAny(t.RuntimeType); 43 | } 44 | 45 | 46 | public override string ToString() 47 | { 48 | return base.ToString(); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /RazorSharp/Memory/Components/PaddingField.cs: -------------------------------------------------------------------------------- 1 | namespace RazorSharp.Memory.Components 2 | { 3 | /// 4 | /// Represents padding in memory. 5 | /// 6 | internal class PaddingField : MemoryField 7 | { 8 | internal PaddingField(int offset, int size = sizeof(int)) : base("(Padding)", offset, size) { } 9 | 10 | public override object GetValue(object value) 11 | { 12 | // Padding is always null 13 | return default(int); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /RazorSharp/Memory/Converter.cs: -------------------------------------------------------------------------------- 1 | #region 2 | 3 | using System; 4 | using RazorSharp.CoreClr; 5 | using RazorSharp.CoreClr.Metadata; 6 | using RazorSharp.Interop; 7 | using RazorSharp.Memory.Enums; 8 | using RazorSharp.Memory.Pointers; 9 | 10 | #endregion 11 | 12 | namespace RazorSharp.Memory 13 | { 14 | #region 15 | 16 | /// 17 | /// Specifies how a value will be converted 18 | /// 19 | public enum ConversionType 20 | { 21 | /// 22 | /// Reinterprets a value as a value of the specified conversion type 23 | /// 24 | Reinterpret, 25 | 26 | /// 27 | /// 28 | /// 29 | Normal, 30 | 31 | /// 32 | /// 33 | /// 34 | Proxy 35 | } 36 | 37 | #endregion 38 | 39 | /// 40 | /// 41 | /// 42 | /// 43 | public static unsafe class Converter 44 | { 45 | public static T ToObject(Pointer ptr) 46 | { 47 | void* cpy = ptr.ToPointer(); 48 | return Unsafe.Read(&cpy); 49 | } 50 | 51 | public static TTo[] ConvertArray(byte[] mem) 52 | { 53 | fixed (byte* ptr = mem) { 54 | Pointer memPtr = ptr; 55 | return memPtr.Copy(mem.Length / memPtr.ElementSize); 56 | } 57 | } 58 | 59 | public static TTo Convert(TFrom t, ConversionType c = ConversionType.Reinterpret) 60 | { 61 | switch (c) { 62 | case ConversionType.Reinterpret: 63 | return Unsafe.AddressOf(ref t).Cast().Read(); 64 | case ConversionType.Normal: 65 | return (TTo) System.Convert.ChangeType(t, typeof(TTo)); 66 | case ConversionType.Proxy: 67 | return Unsafe.As(ref t); 68 | default: 69 | return default; 70 | } 71 | } 72 | 73 | public static TTo Convert(byte[] mem) /*where TTo : struct*/ 74 | { 75 | fixed (byte* bptr = mem) { 76 | Pointer ptr = bptr; 77 | return ptr.Read(); 78 | } 79 | } 80 | 81 | /// 82 | /// Creates an instance of from . 83 | /// If is a reference type, should not contain 84 | /// object internals like its pointer or its ; it should 85 | /// only contain its fields. This memory does not need to be freed, as it is GC allocated. 86 | /// 87 | /// Memory to load from 88 | /// Type to load 89 | /// An instance created from 90 | public static T AllocRaw(byte[] mem) 91 | { 92 | T value = default; 93 | 94 | Pointer addr; 95 | 96 | if (Runtime.Info.IsStruct()) { 97 | addr = Unsafe.AddressOf(ref value).Cast(); 98 | } 99 | else { 100 | value = Runtime.AllocObject(); 101 | addr = Unsafe.AddressOfFields(ref value).Cast(); 102 | } 103 | 104 | addr.WriteAll(mem); 105 | 106 | return value; 107 | } 108 | 109 | public static object AllocRaw(byte[] mem, Type type) 110 | { 111 | return Functions.Reflection.CallGeneric(typeof(Converter).GetMethod(nameof(AllocRaw)), 112 | type, null, mem); 113 | } 114 | } 115 | } -------------------------------------------------------------------------------- /RazorSharp/Memory/Enums/OffsetOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using RazorSharp.CoreClr; 4 | using RazorSharp.CoreClr.Metadata; 5 | 6 | namespace RazorSharp.Memory.Enums 7 | { 8 | /// 9 | /// Offset options for 10 | /// 11 | public enum OffsetOptions 12 | { 13 | /// 14 | /// Return the pointer offset by -, 15 | /// so it points to the object's . 16 | /// 17 | Header, 18 | 19 | /// 20 | /// If the type is a , return the 21 | /// pointer offset by so it 22 | /// points to the string's characters. 23 | /// 24 | /// Note: Equal to and fixed. 25 | /// 26 | /// 27 | StringData, 28 | 29 | /// 30 | /// If the type is an array, return 31 | /// the pointer offset by so it points 32 | /// to the array's elements. 33 | /// 34 | /// Note: Equal to and fixed 35 | /// 36 | /// 37 | ArrayData, 38 | 39 | /// 40 | /// If the type is a reference type, return 41 | /// the pointer offset by so it points 42 | /// to the object's fields. 43 | /// 44 | Fields, 45 | 46 | /// 47 | /// Don't offset the heap pointer at all, so it 48 | /// points to the 49 | /// 50 | None 51 | } 52 | } -------------------------------------------------------------------------------- /RazorSharp/Memory/Mem.Kernel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Runtime.InteropServices; 6 | using RazorSharp.Interop; 7 | using RazorSharp.Memory.Pointers; 8 | 9 | namespace RazorSharp.Memory 10 | { 11 | public static partial class Mem 12 | { 13 | public static unsafe class Kernel 14 | { 15 | #region Read / Write 16 | 17 | public static T ReadCurrentProcessMemory(Pointer lpBaseAddress) => 18 | ReadProcessMemory(Process.GetCurrentProcess(), lpBaseAddress); 19 | 20 | public static T ReadProcessMemory(Process proc, Pointer lpBaseAddress) 21 | { 22 | T t = default; 23 | int size = Unsafe.SizeOf(); 24 | var ptr = Unsafe.AddressOf(ref t); 25 | 26 | ReadProcessMemory(proc, lpBaseAddress.Address, ptr.Address, size); 27 | 28 | return t; 29 | } 30 | 31 | public static void WriteCurrentProcessMemory(Pointer lpBaseAddress, T value) => 32 | WriteProcessMemory(Process.GetCurrentProcess(), lpBaseAddress, value); 33 | 34 | public static void WriteProcessMemory(Process proc, Pointer lpBaseAddress, T value) 35 | { 36 | int dwSize = Unsafe.SizeOf(); 37 | var ptr = Unsafe.AddressOf(ref value); 38 | 39 | WriteProcessMemory(proc, lpBaseAddress.Address, ptr.Address, dwSize); 40 | } 41 | 42 | #endregion 43 | 44 | #region Read / write raw bytes 45 | 46 | #region Read raw bytes 47 | 48 | public static void ReadProcessMemory(Process proc, Pointer lpBaseAddress, 49 | Pointer lpBuffer, int cb) 50 | { 51 | var hProc = Native.Kernel32.OpenProcess(proc); 52 | 53 | 54 | // Read the memory 55 | bool ok = (Native.Kernel32.ReadProcessMemoryInternal(hProc, lpBaseAddress.Address, 56 | lpBuffer.Address, cb, 57 | out int numberOfBytesRead)); 58 | 59 | if (numberOfBytesRead != cb || !ok) { 60 | throw new Win32Exception(); 61 | } 62 | 63 | // Close the handle 64 | Native.Kernel32.CloseHandle(hProc); 65 | } 66 | 67 | public static byte[] ReadProcessMemory(Process proc, Pointer lpBaseAddress, int cb) 68 | { 69 | var mem = new byte[cb]; 70 | 71 | fixed (byte* p = mem) { 72 | ReadProcessMemory(proc, lpBaseAddress, (IntPtr) p, cb); 73 | } 74 | 75 | return mem; 76 | } 77 | 78 | 79 | #region Current process 80 | 81 | public static byte[] ReadCurrentProcessMemory(Pointer lpBaseAddress, int cb) 82 | { 83 | return ReadProcessMemory(Process.GetCurrentProcess(), lpBaseAddress, cb); 84 | } 85 | 86 | public static void ReadCurrentProcessMemory(Pointer lpBaseAddress, Pointer lpBuffer, int cb) 87 | { 88 | ReadProcessMemory(Process.GetCurrentProcess(), lpBaseAddress, lpBuffer, cb); 89 | } 90 | 91 | #endregion 92 | 93 | #endregion 94 | 95 | #region Write raw bytes 96 | 97 | #region Current process 98 | 99 | public static void WriteCurrentProcessMemory(Pointer lpBaseAddress, byte[] value) 100 | { 101 | WriteProcessMemory(Process.GetCurrentProcess(), lpBaseAddress, value); 102 | } 103 | 104 | public static void WriteCurrentProcessMemory(Pointer lpBaseAddress, Pointer lpBuffer, 105 | int dwSize) 106 | { 107 | WriteProcessMemory(Process.GetCurrentProcess(), lpBaseAddress, lpBuffer, dwSize); 108 | } 109 | 110 | #endregion 111 | 112 | public static void WriteProcessMemory(Process proc, Pointer lpBaseAddress, Pointer lpBuffer, 113 | int dwSize) 114 | { 115 | var hProc = Native.Kernel32.OpenProcess(proc); 116 | 117 | // Write the memory 118 | bool ok = (Native.Kernel32.WriteProcessMemoryInternal(hProc, lpBaseAddress.Address, lpBuffer.Address, 119 | dwSize, out int numberOfBytesWritten)); 120 | 121 | 122 | if (numberOfBytesWritten != dwSize || !ok) { 123 | throw new Win32Exception(); 124 | } 125 | 126 | 127 | // Close the handle 128 | Native.Kernel32.CloseHandle(hProc); 129 | } 130 | 131 | public static void WriteProcessMemory(Process proc, Pointer lpBaseAddress, byte[] value) 132 | { 133 | int dwSize = value.Length; 134 | 135 | // Write the memory 136 | fixed (byte* rg = value) { 137 | WriteProcessMemory(proc, lpBaseAddress, (IntPtr) rg, dwSize); 138 | } 139 | } 140 | 141 | #endregion 142 | 143 | #endregion 144 | } 145 | } 146 | } -------------------------------------------------------------------------------- /RazorSharp/Memory/Mem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Runtime.InteropServices; 5 | using RazorSharp.CoreClr; 6 | using RazorSharp.Memory.Allocation; 7 | using RazorSharp.Memory.Enums; 8 | using RazorSharp.Memory.Pointers; 9 | using RazorSharp.Model; 10 | 11 | // ReSharper disable UnusedParameter.Global 12 | 13 | namespace RazorSharp.Memory 14 | { 15 | /// 16 | /// Provides functions for interacting with memory. 17 | /// 18 | /// 19 | /// 20 | /// 21 | public static unsafe partial class Mem 22 | { 23 | public static bool Is64Bit => IntPtr.Size == sizeof(long) && Environment.Is64BitProcess; 24 | 25 | /// 26 | /// Represents a null pointer. 27 | /// 28 | /// 29 | public static readonly Pointer Nullptr = null; 30 | 31 | #region Calculation 32 | 33 | public static int FullSize(int elemCnt) => Unsafe.SizeOf() * elemCnt; 34 | 35 | #endregion 36 | 37 | 38 | #region Alloc / free 39 | 40 | public static AllocationManager Allocator { get; } = new AllocationManager(Allocators.Local); 41 | 42 | public static void Destroy(ref T value) 43 | { 44 | if (!Runtime.Info.IsStruct(value)) { 45 | int size = Unsafe.SizeOf(value, SizeOfOptions.Data); 46 | Pointer ptr = Unsafe.AddressOfFields(ref value); 47 | ptr.ClearBytes(size); 48 | } 49 | else { 50 | value = default; 51 | } 52 | } 53 | 54 | /// 55 | /// Zeros the memory of 56 | /// 57 | /// Value to zero 58 | /// Type of 59 | public static void Clear(ref T value) 60 | { 61 | var ptr = Unsafe.AddressOf(ref value); 62 | ptr.Clear(); 63 | } 64 | 65 | #endregion 66 | 67 | #region Read / write 68 | 69 | /// 70 | /// Reads in a block from a file and converts it to the struct 71 | /// type specified by the template parameter 72 | /// 73 | public static T ReadFromBinaryReader(BinaryReader reader) 74 | { 75 | // Read in a byte array 76 | byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T))); 77 | 78 | // Pin the managed memory while, copy it out the data, then unpin it 79 | var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); 80 | var value = (T) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); 81 | handle.Free(); 82 | 83 | return value; 84 | } 85 | 86 | public static string ReadString(sbyte* first, int len) 87 | { 88 | if (first == null || len <= 0) { 89 | return null; 90 | } 91 | 92 | // return Marshal.PtrToStringAuto(new IntPtr(first), len) 93 | // .Erase(StringConstants.NULL_TERMINATOR); 94 | 95 | /*byte[] rg = new byte[len]; 96 | Marshal.Copy(new IntPtr(first), rg, 0, rg.Length); 97 | return Encoding.ASCII.GetString(rg);*/ 98 | 99 | return new string(first, 0, len); 100 | } 101 | 102 | #endregion 103 | } 104 | } -------------------------------------------------------------------------------- /RazorSharp/Memory/Segment.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using RazorSharp.Interop.Structures; 3 | using RazorSharp.Memory.Pointers; 4 | 5 | namespace RazorSharp.Memory 6 | { 7 | /// 8 | /// Represents a region in memory. 9 | /// 10 | public class Segment 11 | { 12 | public Pointer BaseAddress { get; } 13 | 14 | public int Size { get; } 15 | 16 | public Segment(Pointer p, int s) 17 | { 18 | BaseAddress = p; 19 | Size = s; 20 | } 21 | 22 | public Segment(ImageSectionInfo p) : this(p.Address, p.Size) { } 23 | 24 | public Segment(ProcessModule p) : this(p.BaseAddress, p.ModuleMemorySize) { } 25 | } 26 | } -------------------------------------------------------------------------------- /RazorSharp/Memory/SigScanner.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using RazorSharp.Memory.Pointers; 4 | using SimpleSharp.Strings; 5 | 6 | namespace RazorSharp.Memory 7 | { 8 | /// 9 | /// A basic sig scanner. 10 | /// 11 | public class SigScanner 12 | { 13 | private byte[] m_buffer; 14 | private Pointer m_lo; 15 | 16 | public SigScanner(Segment r) 17 | { 18 | SelectRegion(r); 19 | } 20 | 21 | public SigScanner() : this(null) { } 22 | 23 | private void EnsureSetup() 24 | { 25 | if (m_lo.IsNull || m_buffer == null) { 26 | throw new Exception("A memory region must be specified."); 27 | } 28 | } 29 | 30 | public void SelectRegion(Segment r) 31 | { 32 | m_buffer = r.BaseAddress.CopyBytes(r.Size); 33 | m_lo = r.BaseAddress; 34 | } 35 | 36 | private bool PatternCheck(int nOffset, IReadOnlyList arrPattern) 37 | { 38 | // ReSharper disable once LoopCanBeConvertedToQuery 39 | for (int i = 0; i < arrPattern.Count; i++) { 40 | if (arrPattern[i] == 0x0) 41 | continue; 42 | 43 | if (arrPattern[i] != m_buffer[nOffset + i]) 44 | return false; 45 | } 46 | 47 | return true; 48 | } 49 | 50 | public Pointer FindPattern(string pattern) 51 | { 52 | return FindPattern(Strings.ParseByteArray(pattern)); 53 | } 54 | 55 | public Pointer FindPattern(byte[] pattern) 56 | { 57 | EnsureSetup(); 58 | 59 | for (int i = 0; i < m_buffer.Length; i++) { 60 | if (m_buffer[i] != pattern[0]) 61 | continue; 62 | 63 | 64 | if (PatternCheck(i, pattern)) { 65 | Pointer p = m_lo + i; 66 | return p; 67 | } 68 | } 69 | 70 | return Mem.Nullptr; 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /RazorSharp/Model/Closable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using RazorSharp.Core; 4 | 5 | namespace RazorSharp.Model 6 | { 7 | /// 8 | /// Describes a type that must be closed after usage. Implements . 9 | /// 10 | public abstract class Closable : IDisposable 11 | { 12 | protected abstract string Id { get; } 13 | 14 | public virtual void Close() { } 15 | 16 | public void Dispose() => Close(); 17 | } 18 | } -------------------------------------------------------------------------------- /RazorSharp/Model/Releasable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using RazorSharp.Core; 4 | using RazorSharp.Import; 5 | using SimpleSharp.Diagnostics; 6 | 7 | namespace RazorSharp.Model 8 | { 9 | /// 10 | /// 11 | /// Inheriting types: 12 | /// 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | /// (implicit) 25 | /// 26 | /// 27 | /// 28 | /// 29 | /// 30 | /// 31 | /// 32 | /// 33 | /// 34 | /// 35 | /// 36 | /// 37 | /// 38 | /// 39 | public abstract class Releasable : Closable 40 | { 41 | public bool IsSetup { get; protected set; } 42 | 43 | public Releasable() { } 44 | 45 | public virtual void Setup() 46 | { 47 | if (!IsSetup) { 48 | IsSetup = true; 49 | 50 | } 51 | } 52 | 53 | public override void Close() 54 | { 55 | if (IsSetup) { 56 | IsSetup = false; 57 | base.Close(); 58 | } 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /RazorSharp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | #region 2 | 3 | using System.Reflection; 4 | using System.Runtime.CompilerServices; 5 | using System.Runtime.InteropServices; 6 | 7 | #endregion 8 | 9 | // General Information about an assembly is controlled through the following 10 | // set of attributes. Change these attribute values to modify the information 11 | // associated with an assembly. 12 | [assembly: AssemblyTitle("RazorSharp")] 13 | [assembly: AssemblyDescription("")] 14 | [assembly: AssemblyConfiguration("")] 15 | [assembly: AssemblyCompany("")] 16 | [assembly: AssemblyProduct("RazorSharp")] 17 | [assembly: AssemblyCopyright("Copyright © 2019")] 18 | [assembly: AssemblyTrademark("")] 19 | [assembly: AssemblyCulture("")] 20 | 21 | // Setting ComVisible to false makes the types in this assembly not visible 22 | // to COM components. If you need to access a type in this assembly from 23 | // COM, set the ComVisible attribute to true on that type. 24 | [assembly: ComVisible(false)] 25 | 26 | // The following GUID is for the ID of the typelib if this project is exposed to COM 27 | [assembly: Guid("D350BF0A-5CA4-43C3-8F01-32F561FE0727")] 28 | 29 | // Version information for an assembly consists of the following four values: 30 | // 31 | // Major Version 32 | // Minor Version 33 | // Build Number 34 | // Revision 35 | // 36 | // You can specify all the values or you can default the Build and Revision Numbers 37 | // by using the '*' as shown below: 38 | // [assembly: AssemblyVersion("1.0.*")] 39 | [assembly: AssemblyVersion("1.2.7")] 40 | [assembly: AssemblyFileVersion("1.2.7")] 41 | 42 | 43 | // Test project 44 | [assembly: InternalsVisibleTo("Test")] 45 | 46 | // Benchmarking/testing solution 47 | [assembly: InternalsVisibleTo("Sandbox")] 48 | 49 | // Nuget testing 50 | [assembly: InternalsVisibleTo("NSandbox")] 51 | 52 | // nuget pack 53 | // nuget pack -Prop Configuration=Release -------------------------------------------------------------------------------- /RazorSharp/Utilities/Bits.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | namespace RazorSharp.Utilities 4 | { 5 | internal static class Bits 6 | { 7 | /// 8 | /// Reads from at offset 9 | /// 10 | /// value to read from 11 | /// Beginning offset 12 | /// Number of bits to read 13 | internal static int ReadBits(int value, int bitOfs, int bitCount) 14 | { 15 | return ((1 << bitCount) - 1) & (value >> bitOfs); 16 | } 17 | 18 | internal static int ReadBits(uint value, int bitOfs, int bitCount) 19 | { 20 | return ReadBits((int) value, bitOfs, bitCount); 21 | } 22 | 23 | /** 24 | * #define GETMASK(index, size) (((1 << (size)) - 1) << (index)) 25 | * #define READFROM(data, index, size) (((data) & GETMASK((index), (size))) >> (index)) 26 | * #define WRITETO(data, index, size, value) ((data) = ((data) & (~GETMASK((index), (size)))) | ((value) << (index))) 27 | */ 28 | 29 | private static int GetMask(int index, int size) => ((1 << size) - 1) << index; 30 | 31 | internal static int ReadFrom(int data, int index, int size) => (data & GetMask(index, size)) >> index; 32 | 33 | internal static int WriteTo(int data, int index, int size, int value) 34 | { 35 | return (data & ~GetMask(index, size)) | (value << index); 36 | } 37 | 38 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 39 | internal static bool ReadBit(int value, int bitOfs) => (value & (1 << bitOfs)) != 0; 40 | 41 | internal static bool ReadBit(uint value, int bitOfs) => ReadBit((int) value, bitOfs); 42 | } 43 | } -------------------------------------------------------------------------------- /RazorSharp/Utilities/EnumFlags.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RazorSharp.Analysis; 3 | using RazorSharp.CoreClr.Metadata.Enums; 4 | using RazorSharp.Import.Enums; 5 | 6 | namespace RazorSharp.Utilities 7 | { 8 | /// 9 | /// Contains optimized versions of the function. 10 | /// 11 | public static class EnumFlags 12 | { 13 | // ((uThis & uFlag) == uFlag) 14 | 15 | public static bool HasFlagFast(this InspectOptions value, InspectOptions flag) 16 | { 17 | return (value & flag) == flag; 18 | } 19 | 20 | public static bool HasFlagFast(this MethodDescFlags2 value, MethodDescFlags2 flag) 21 | { 22 | return (value & flag) == flag; 23 | } 24 | 25 | public static bool HasFlagFast(this MethodTableFlags value, MethodTableFlags flag) 26 | { 27 | return (value & flag) == flag; 28 | } 29 | 30 | public static bool HasFlagFast(this LayoutFlags value, LayoutFlags flag) 31 | { 32 | return (value & flag) == flag; 33 | } 34 | 35 | public static bool HasFlagFast(this VMFlags value, VMFlags flag) 36 | { 37 | return (value & flag) == flag; 38 | } 39 | 40 | public static bool HasFlagFast(this IdentifierOptions value, IdentifierOptions flag) 41 | { 42 | return (value & flag) == flag; 43 | } 44 | 45 | public static bool HasFlagFast(this ImportCallOptions value, ImportCallOptions flag) 46 | { 47 | return (value & flag) == flag; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /RazorSharp/Utilities/Fixed/ObjectPinner.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection.Emit; 3 | 4 | namespace RazorSharp.Utilities.Fixed 5 | { 6 | /// 7 | /// Pins an object in memory even if the type is unblittable. 8 | /// 9 | /// Source: https://www.reddit.com/r/csharp/comments/917tyq/pinning_unblittable_objects/ 10 | /// 11 | /// 12 | public static class ObjectPinner 13 | { 14 | private static readonly Action> PinImpl = CreatePinImpl(); 15 | 16 | private static Action> CreatePinImpl() 17 | { 18 | var method = new DynamicMethod("InvokeWhilePinnedImpl", typeof(void), 19 | new[] {typeof(object), typeof(Action)}, typeof(ObjectPinner).Module); 20 | var il = method.GetILGenerator(); 21 | 22 | // create a pinned local variable of type object 23 | // this wouldn't be valid in C#, but the runtime doesn't complain about the IL 24 | var local = il.DeclareLocal(typeof(object), true); 25 | 26 | 27 | // store first argument obj in the pinned local variable 28 | il.Emit(OpCodes.Ldarg_0); 29 | il.Emit(OpCodes.Stloc_0); 30 | 31 | // invoke the delegate 32 | il.Emit(OpCodes.Ldarg_1); 33 | il.Emit(OpCodes.Ldarg_0); 34 | il.EmitCall(OpCodes.Callvirt, typeof(Action).GetMethod("Invoke"), null); 35 | 36 | il.Emit(OpCodes.Ret); 37 | 38 | return (Action>) method.CreateDelegate(typeof(Action>)); 39 | } 40 | 41 | /// 42 | /// Pins an object in memory, preventing the GC from moving it. 43 | /// 44 | /// Object to pin 45 | /// The action during which the object will be pinned 46 | public static void InvokeWhilePinned(object obj, Action action) 47 | { 48 | PinImpl(obj, action); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /RazorSharp/Utilities/Fixed/PinHelper.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | using RazorSharp.Memory; 3 | using RazorSharp.Memory.Enums; 4 | 5 | // ReSharper disable ClassCannotBeInstantiated 6 | 7 | namespace RazorSharp.Utilities.Fixed 8 | { 9 | /// 10 | /// Allows for pinning of unblittable objects, similar to but 11 | /// with the fixed statement. 12 | /// 13 | public static class PinHelper 14 | { 15 | /// 16 | /// Used for unsafe pinning of arbitrary objects. 17 | /// 18 | public static PinningHelper GetPinningHelper(object value) 19 | { 20 | return Unsafe.As(value); 21 | } 22 | 23 | 24 | /// 25 | /// Helper class to assist with unsafe pinning of arbitrary objects. The typical usage pattern is: 26 | /// 27 | /// fixed (byte* pData = &PinHelper.GetPinningHelper(value).Data) 28 | /// { 29 | /// } 30 | /// 31 | /// 32 | /// pData is what Object::GetData() returns in VM. 33 | /// pData is also equal to offsetting the pointer by . 34 | /// From . 35 | /// 36 | /// 37 | [UsedImplicitly] 38 | public sealed class PinningHelper 39 | { 40 | /// 41 | /// Represents the first field in an object, such as . 42 | /// 43 | public byte Data; 44 | 45 | private PinningHelper() { } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /RazorSharp/Utilities/Members.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | 5 | // ReSharper disable ReturnTypeCanBeEnumerable.Global 6 | 7 | namespace RazorSharp.Utilities 8 | { 9 | /// 10 | /// Provides utilities for accessing members of a type. 11 | /// 12 | internal static class Members 13 | { 14 | #region Flags 15 | 16 | /// 17 | /// and 18 | /// 19 | public const BindingFlags ALL_FLAGS = ALL_INSTANCE_FLAGS | BindingFlags.Static; 20 | 21 | /// 22 | /// , , 23 | /// and 24 | /// 25 | public const BindingFlags ALL_INSTANCE_FLAGS = 26 | BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic; 27 | 28 | #endregion 29 | 30 | #region Member 31 | 32 | internal static MemberInfo[] GetAllMembers(this Type t) => t.GetMembers(ALL_FLAGS); 33 | 34 | internal static MemberInfo[] GetAnyMember(this Type t, string name) => 35 | t.GetMember(name, ALL_FLAGS); 36 | 37 | #endregion 38 | 39 | #region Field 40 | 41 | internal static FieldInfo GetAnyField(this Type t, string name) => 42 | t.GetField(name, ALL_FLAGS); 43 | 44 | internal static FieldInfo[] GetAllFields(this Type t) => t.GetFields(ALL_FLAGS); 45 | 46 | #endregion 47 | 48 | #region Methods 49 | 50 | internal static MethodInfo[] GetAllMethods(this Type t) => t.GetMethods(ALL_FLAGS); 51 | 52 | internal static MethodInfo GetAnyMethod(this Type t, string name) => 53 | t.GetMethod(name, (BindingFlags) ALL_FLAGS); 54 | 55 | #endregion 56 | 57 | #region Attributes 58 | 59 | internal static (MemberInfo, TAttribute) GetFirstAnnotated(this Type t) 60 | where TAttribute : Attribute 61 | { 62 | (MemberInfo[] memberInfos, TAttribute[] attributes) = t.GetAnnotated(); 63 | 64 | if (memberInfos.Length == default || attributes.Length == default) { 65 | return (null, null); 66 | } 67 | 68 | return (memberInfos[0], attributes[0]); 69 | } 70 | 71 | internal static (MemberInfo[], TAttribute[]) GetAnnotated(this Type t) 72 | where TAttribute : Attribute 73 | { 74 | var members = new List(); 75 | var attributes = new List(); 76 | 77 | foreach (var member in t.GetAllMembers()) { 78 | if (Attribute.IsDefined(member, typeof(TAttribute))) { 79 | members.Add(member); 80 | attributes.Add(member.GetCustomAttribute()); 81 | } 82 | } 83 | 84 | return (members.ToArray(), attributes.ToArray()); 85 | } 86 | 87 | #endregion 88 | } 89 | } -------------------------------------------------------------------------------- /RazorSharp/Utilities/Modules.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace RazorSharp.Utilities 4 | { 5 | public static class Modules 6 | { 7 | /// 8 | /// The of the current 9 | /// 10 | public static ProcessModuleCollection CurrentModules => Process.GetCurrentProcess().Modules; 11 | 12 | /// 13 | /// Returns any with the 14 | /// of . 15 | /// 16 | /// to search for 17 | public static ProcessModule FindModule(string name) 18 | { 19 | foreach (ProcessModule m in CurrentModules) { 20 | if (m.ModuleName == name) 21 | return m; 22 | } 23 | 24 | return null; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /RazorSharp/Utilities/Security/Exceptions/AmbiguousStateException.cs: -------------------------------------------------------------------------------- 1 | namespace RazorSharp.Utilities.Security.Exceptions 2 | { 3 | /// 4 | /// Describes an exception in which the current program state is ambiguous. 5 | /// 6 | internal sealed class AmbiguousStateException : CoreException 7 | { 8 | [FailMessageTemplate] 9 | private const string ERR_MSG = "Ambiguous state exception"; 10 | 11 | public AmbiguousStateException() : base() { } 12 | 13 | public AmbiguousStateException(string message) : base(message) { } 14 | } 15 | } -------------------------------------------------------------------------------- /RazorSharp/Utilities/Security/Exceptions/ClrException.cs: -------------------------------------------------------------------------------- 1 | namespace RazorSharp.Utilities.Security.Exceptions 2 | { 3 | /// 4 | /// Describes an exception within the CLR. 5 | /// 6 | internal sealed class ClrException : CoreException 7 | { 8 | [FailMessageTemplate] 9 | private const string ERR_MSG = "CLR exception"; 10 | 11 | public ClrException() : base() { } 12 | 13 | public ClrException(string message) : base(message) { } 14 | } 15 | } -------------------------------------------------------------------------------- /RazorSharp/Utilities/Security/Exceptions/CorILException.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | // ReSharper disable InconsistentNaming 4 | 5 | namespace RazorSharp.Utilities.Security.Exceptions 6 | { 7 | /// 8 | /// Describes an IL exception. 9 | /// 10 | internal sealed class CorILException : CoreException 11 | { 12 | [FailMessageTemplate] 13 | private const string ERR_MSG = "IL exception"; 14 | 15 | public CorILException() : base() { } 16 | 17 | public CorILException(string message) : base(message) { } 18 | } 19 | } -------------------------------------------------------------------------------- /RazorSharp/Utilities/Security/Exceptions/CoreException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RazorSharp.Utilities.Security.Exceptions 4 | { 5 | 6 | internal abstract class CoreException : Exception 7 | { 8 | protected CoreException() : base() { } 9 | 10 | protected CoreException(string message) : base(message) { } 11 | } 12 | } -------------------------------------------------------------------------------- /RazorSharp/Utilities/Security/Exceptions/ImageException.cs: -------------------------------------------------------------------------------- 1 | namespace RazorSharp.Utilities.Security.Exceptions 2 | { 3 | /// 4 | /// Describes an exception with symbol/image handling. 5 | /// 6 | internal sealed class ImageException : CoreException 7 | { 8 | [FailMessageTemplate] 9 | private const string ERR_MSG = "Error loading image"; 10 | 11 | public ImageException() : base() { } 12 | 13 | public ImageException(string msg) : base(msg) { } 14 | } 15 | } -------------------------------------------------------------------------------- /RazorSharp/Utilities/Security/Exceptions/ImportException.cs: -------------------------------------------------------------------------------- 1 | using RazorSharp.Import; 2 | 3 | namespace RazorSharp.Utilities.Security.Exceptions 4 | { 5 | /// 6 | /// Describes an exception with 7 | /// 8 | internal sealed class ImportException : CoreException 9 | { 10 | [FailMessageTemplate] 11 | private const string ERR_MSG = "Import exception"; 12 | 13 | public ImportException() : base() { } 14 | 15 | public ImportException(string message) : base(message) { } 16 | } 17 | } -------------------------------------------------------------------------------- /RazorSharp/Utilities/Security/Exceptions/SentryException.cs: -------------------------------------------------------------------------------- 1 | namespace RazorSharp.Utilities.Security.Exceptions 2 | { 3 | /// 4 | /// Thrown by 5 | /// 6 | internal class SentryException : CoreException 7 | { 8 | [FailMessageTemplate] 9 | private const string ERR_MSG = "Sentry exception"; 10 | 11 | public SentryException() : base() { } 12 | 13 | public SentryException(string message) : base(message) { } 14 | } 15 | } -------------------------------------------------------------------------------- /RazorSharp/Utilities/Security/FailMessageTemplateAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using JetBrains.Annotations; 3 | using RazorSharp.Utilities.Security.Exceptions; 4 | 5 | namespace RazorSharp.Utilities.Security 6 | { 7 | /// 8 | /// Describes the failure message template used by inheriting types in 9 | /// 10 | /// 11 | [MeansImplicitUse] 12 | [AttributeUsage(AttributeTargets.Field)] 13 | internal class FailMessageTemplateAttribute : Attribute 14 | { 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /RazorSharp/Utilities/Security/Guard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Text; 4 | using JetBrains.Annotations; 5 | using RazorSharp.Utilities.Security.Exceptions; 6 | 7 | // ReSharper disable InconsistentNaming 8 | 9 | namespace RazorSharp.Utilities.Security 10 | { 11 | // todo: rewrite 12 | 13 | internal static class Guard 14 | { 15 | /// 16 | /// Raised when there is an error with retrieving the fail message template. 17 | /// 18 | /// 19 | [Pure] 20 | private static SentryException DeepFail() 21 | { 22 | const string FAILMSG_ERR = "Fail message was not found, not const/static, or not a string"; 23 | return Fail(FAILMSG_ERR); 24 | } 25 | 26 | private static string GetFailMessage() where TException : CoreException, new() 27 | { 28 | var (memberInfo, failMessageAttribute) = 29 | typeof(TException).GetFirstAnnotated(); 30 | 31 | // This should never happen 32 | 33 | if (memberInfo == null || failMessageAttribute == null) { 34 | throw DeepFail(); 35 | } 36 | 37 | var field = (FieldInfo) memberInfo; 38 | 39 | // const string REQ_NAME = "ERR_MSG"; 40 | 41 | if (!field.IsStatic || !field.IsLiteral || field.FieldType != typeof(string)) { 42 | throw DeepFail(); 43 | } 44 | 45 | var value = field.GetValue(null); 46 | 47 | if (value is string failMsg) { 48 | return failMsg; 49 | } 50 | 51 | throw DeepFail(); 52 | } 53 | 54 | private static TException Fail(string msg = null, string extra = null) 55 | where TException : CoreException, new() 56 | { 57 | var template = GetFailMessage(); 58 | return CreateFailStub(template, msg, extra); 59 | } 60 | 61 | private static TException CreateFailStub(string template, string msg = null, string extra = null) 62 | where TException : CoreException, new() 63 | { 64 | var sb = new StringBuilder(); 65 | sb.Append(template); 66 | 67 | if (msg != null) { 68 | const string APPEND = ": {0}"; 69 | 70 | sb.AppendFormat(APPEND, msg); 71 | 72 | if (extra != null) { 73 | sb.AppendFormat(APPEND, extra); 74 | } 75 | } 76 | 77 | return (TException) Activator.CreateInstance(typeof(TException), sb.ToString()); 78 | } 79 | 80 | 81 | #region CoreException 82 | 83 | /// 84 | /// Shortcut to with 85 | /// 86 | [Pure] 87 | internal static ImportException ImportFail(string msg = null, string extra = null) 88 | { 89 | return Fail(msg, extra); 90 | } 91 | 92 | /// 93 | /// Shortcut to with 94 | /// 95 | [Pure] 96 | internal static ImageException ImageFail(string msg = null, string extra = null) 97 | { 98 | return Fail(msg, extra); 99 | } 100 | 101 | /// 102 | /// Shortcut to with 103 | /// 104 | [Pure] 105 | internal static CorILException CorILFail(string msg = null, string extra = null) 106 | { 107 | return Fail(msg, extra); 108 | } 109 | 110 | /// 111 | /// Shortcut to with 112 | /// 113 | [Pure] 114 | internal static ClrException ClrFail(string msg = null, string extra = null) 115 | { 116 | return Fail(msg, extra); 117 | } 118 | 119 | /// 120 | /// Shortcut to with 121 | /// 122 | [Pure] 123 | internal static AmbiguousStateException AmbiguousFail(string msg = null, string extra = null) 124 | { 125 | return Fail(msg, extra); 126 | } 127 | 128 | #endregion 129 | 130 | [Pure] 131 | internal static InvalidOperationException InvalidOperationFail(string func) 132 | { 133 | return new InvalidOperationException($"Invalid operation attempted in {func}"); 134 | } 135 | 136 | [Pure] 137 | internal static NotImplementedException NotImplementedFail(string func) 138 | { 139 | return new NotImplementedException($"{func} is not implemented."); 140 | } 141 | 142 | [Pure] 143 | internal static NotSupportedException NotSupportedMemberFail(MemberInfo member) 144 | { 145 | return new NotSupportedException($"Member type {member.MemberType} not supported."); 146 | } 147 | 148 | [Pure] 149 | internal static InvalidOperationException Require64BitFail(string func) 150 | { 151 | return new InvalidOperationException($"64 bit is required for the requested operation: {func} "); 152 | } 153 | 154 | 155 | } 156 | } -------------------------------------------------------------------------------- /RazorSharp/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Test/Program.cs: -------------------------------------------------------------------------------- 1 | #region 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Configuration; 6 | using System.Diagnostics; 7 | using System.Runtime.ExceptionServices; 8 | using System.Runtime.InteropServices; 9 | using RazorSharp; 10 | using RazorSharp.Analysis; 11 | using RazorSharp.CoreClr; 12 | using RazorSharp.CoreClr.Meta; 13 | using RazorSharp.Interop; 14 | using RazorSharp.Memory; 15 | using RazorSharp.Memory.Pointers; 16 | using RazorSharp.Utilities; 17 | using System.Linq; 18 | using RazorSharp.Core; 19 | using RazorSharp.Interop.Utilities; 20 | 21 | #endregion 22 | 23 | 24 | namespace Test 25 | { 26 | #region 27 | 28 | using DWORD = UInt32; 29 | 30 | #endregion 31 | 32 | 33 | public static unsafe class Program 34 | { 35 | // Common library: SimpleSharp 36 | // Testing library: Sandbox 37 | 38 | [HandleProcessCorruptedStateExceptions] 39 | public static void Main(string[] args) 40 | { 41 | var f = (MetaField) typeof(string).GetAnyField("m_firstChar"); 42 | Console.WriteLine("{0:A}",f); 43 | 44 | var l = Runtime.AllocObject>(); 45 | l.Add(1); 46 | Console.WriteLine(l.Count); 47 | Console.WriteLine(GCHeap.GCCount); 48 | GC.Collect(); 49 | Console.WriteLine(GCHeap.GCCount); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | #region 2 | 3 | using System.Reflection; 4 | using System.Runtime.InteropServices; 5 | 6 | #endregion 7 | 8 | // General Information about an assembly is controlled through the following 9 | // set of attributes. Change these attribute values to modify the information 10 | // associated with an assembly. 11 | [assembly: AssemblyTitle("Test")] 12 | [assembly: AssemblyDescription("")] 13 | [assembly: AssemblyConfiguration("")] 14 | [assembly: AssemblyCompany("")] 15 | [assembly: AssemblyProduct("Test")] 16 | [assembly: AssemblyCopyright("Copyright © 2018")] 17 | [assembly: AssemblyTrademark("")] 18 | [assembly: AssemblyCulture("")] 19 | 20 | // Setting ComVisible to false makes the types in this assembly not visible 21 | // to COM components. If you need to access a type in this assembly from 22 | // COM, set the ComVisible attribute to true on that type. 23 | [assembly: ComVisible(false)] 24 | 25 | // The following GUID is for the ID of the typelib if this project is exposed to COM 26 | [assembly: Guid("B2CA536C-C670-4643-A5C7-C57070E95223")] 27 | 28 | // Version information for an assembly consists of the following four values: 29 | // 30 | // Major Version 31 | // Minor Version 32 | // Build Number 33 | // Revision 34 | // 35 | // You can specify all the values or you can default the Build and Revision Numbers 36 | // by using the '*' as shown below: 37 | // [assembly: AssemblyVersion("1.0.*")] 38 | [assembly: AssemblyVersion("1.0.0.0")] 39 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /Test/Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 5 | 8 | 10 | 11 | 12 | Debug 13 | AnyCPU 14 | {B2CA536C-C670-4643-A5C7-C57070E95223} 15 | Exe 16 | Properties 17 | Test 18 | Test 19 | 512 20 | v4.7.2 21 | 8 22 | true 23 | 24 | 25 | app.manifest 26 | 27 | 28 | bin\Debug\ 29 | true 30 | full 31 | false 32 | DEBUG;TRACE;JETBRAINS_ANNOTATIONS 33 | prompt 34 | 4 35 | v4.7.2 36 | 8 37 | true 38 | AnyCPU 39 | 40 | 41 | bin\Release\ 42 | pdbonly 43 | true 44 | TRACE;JETBRAINS_ANNOTATIONS 45 | prompt 46 | 4 47 | v4.7.2 48 | 8 49 | true 50 | AnyCPU 51 | 52 | 53 | 54 | 55 | ..\packages\NativeSharp.1.0.3\lib\net472\NativeSharp.dll 56 | 57 | 58 | ..\packages\SimpleSharp.1.1.9\lib\net472\SimpleSharp.dll 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | {d350bf0a-5ca4-43c3-8f01-32f561fe0727} 78 | RazorSharp 79 | 80 | 81 | 82 | 88 | 95 | -------------------------------------------------------------------------------- /icon512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Decimation/RazorSharp/c61fbf99c90d7d11753250851339e560bd146d55/icon512.png -------------------------------------------------------------------------------- /icon64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Decimation/RazorSharp/c61fbf99c90d7d11753250851339e560bd146d55/icon64.png --------------------------------------------------------------------------------