msdn-whiteknight / ciltools Goto Github PK
View Code? Open in Web Editor NEWA set of tools to work with CIL in .NET applications
License: BSD 3-Clause "New" or "Revised" License
A set of tools to work with CIL in .NET applications
License: BSD 3-Clause "New" or "Revised" License
CilTools.Metadata: support reading managed modules without assembly manifest, such as System.EnterpriseServices.Wrapper in .NET Framework.
From ECMA 335 II.5 General syntax:
ID is a contiguous string of characters which starts with either an alphabetic character (A–Z, a–z) or
one of “_”, “$”, “@”, “`” (grave accent), or “?”, and is followed by any number of alphanumeric
characters (A–Z, a–z, 0–9) or the characters “_”, “$”, “@”, “`” (grave accent), and “?”....
Identifiers are used to name entities. Simple identifiers are equivalent to an ID. However, the ILAsm
syntax allows the use of any identifier that can be formed using the Unicode character set (see
Partition I). To achieve this, an identifier shall be placed within single quotation marks.
Example C++/CLI program:
using namespace System;
public class A {
int _x;
public: A(int x) { this->_x = x; }
};
int main(array<System::String ^> ^args)
{
A a(1);
Console::ReadKey();
return 0;
}
Expected disassembler output:
.method assembly static valuetype A* modopt([mscorlib]System.Runtime.CompilerServices.CallConvThiscall)
'A.{ctor}'(valuetype A* modopt([mscorlib]System.Runtime.CompilerServices.IsConst) modopt([mscorlib]System.Runtime.CompilerServices.IsConst) A_0,
int32 x) cil managed
Current output:
.method assembly static valuetype [CliTest]A* modopt([mscorlib]System.Runtime.CompilerServices.CallConvThiscall) A.{ctor}(
valuetype [CliTest]A* modopt([mscorlib]System.Runtime.CompilerServices.IsConst) modopt([mscorlib]System.Runtime.CompilerServices.IsConst) par0,
int32 x
) cil managed
In public CilBrowserPage(MethodBase m, int start, int end, RoutedEventHandler navigation)
constructor, CilGraph.ToSyntaxTree is called twice: in CilVisualization.VisualizeGraph and when generating plaintext view.
ECMA 335 II.10.2 - Body of a type definition
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TestStruct
{
public int dummy;
}
Expected disassembly:
.class public sequential ansi sealed beforefieldinit CilTools.Tests.Common.TestStruct
extends [mscorlib]System.ValueType
{
.pack 1
.size 0
//...
}
using System;
using System.Collections.Generic;
using System.Text;
using CilTools.BytecodeAnalysis;
namespace CilToolsTest
{
class Program
{
public static T Sum<T>(T x,T y) where T:struct
{
if (typeof(T) == typeof(int))
{
int res = (Convert.ToInt32(x) + Convert.ToInt32(y));
return (T)Convert.ChangeType(res, typeof(int));
}
else if (typeof(T) == typeof(float))
{
float res = (Convert.ToSingle(x) + Convert.ToSingle(y));
return (T)Convert.ChangeType(res, typeof(int));
}
else throw new NotSupportedException();
}
static void Main(string[] args)
{
Console.WriteLine(CilAnalysis.MethodToText(typeof(Program).GetMethod("Sum")));
Console.ReadKey();
}
}
}
Current output:
.method public hidebysig static !!T Sum<T>(
!!T x,
!!T y
) cil managed
// ...
Expected output:
.method public hidebysig static !!T Sum<valuetype .ctor ([mscorlib]System.ValueType) T>(
!!T x,
!!T y
) cil managed
// ...
C++/CLI assemblies contain VTable fixups declared like this:
.vtfixup [1] int32 retainappdomain at D_0000E000 // 06000001
.vtfixup [1] int32 retainappdomain at D_0000E00C // 06000029
.vtfixup [1] int32 retainappdomain at D_0000E010 // 06000004
.vtfixup [1] int32 retainappdomain at D_0000E014 // 06000005
.vtfixup [1] int32 retainappdomain at D_0000E018 // 06000006
ECMA-335 II.15.5.1 - Method transition thunks
Related to #69
MethodRef.LoadImpl goes into infinite recursion when signatures being compared involve generic parameters
mscorlib.dll!System.Text.StringBuilder.StringBuilder(string value, int startIndex, int length, int capacity)
mscorlib.dll!System.Text.StringBuilder.StringBuilder(int capacity)
> CilTools.Metadata.dll!CilTools.Metadata.TypeRef.FullName.get()Строка 97 C#
CilTools.Metadata.dll!CilTools.Metadata.AssemblyReader.LoadType(System.Type t)Строка 256 C#
CilTools.Metadata.dll!CilTools.Metadata.MethodRef.LoadImpl()Строка 102 C#
CilTools.Metadata.dll!CilTools.Metadata.MethodRef.IsGenericMethod.get()Строка 434 C#
CilTools.BytecodeAnalysis.dll!CilTools.Reflection.GenericContext.TryGetGenericArguments(System.Reflection.MemberInfo member)Строка 102 C#
CilTools.BytecodeAnalysis.dll!CilTools.Reflection.GenericParamType.TryLoadName()Строка 47 C#
CilTools.BytecodeAnalysis.dll!CilTools.Reflection.GenericParamType.Name.get()Строка 319 C#
CilTools.BytecodeAnalysis.dll!CilTools.Reflection.ComplexType.Name.get()Строка 377 C#
CilTools.BytecodeAnalysis.dll!CilTools.BytecodeAnalysis.TypeSpec.Name.get()Строка 517 C#
CilTools.Metadata.dll!CilTools.Metadata.MethodRef.LoadImpl()Строка 160 C#
netstandard.dll
.class extern forwarder Microsoft.Win32.SafeHandles.SafeFileHandle
{
.assembly extern System.Runtime
}
Test_CilGraph_DynamicMethod crashes on .NET Core 3.1+ Linux
Error:
System.MissingMethodException: GetTypeFromHandleUnsafe is not found
at CilTools.Reflection.ModuleWrapperDynamic.ResolveMember(Int32 metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) in /home/runner/work/CilTools/CilTools/CilTools.BytecodeAnalysis/Reflection/ModuleWrapperDynamic.cs:line 278
at CilTools.BytecodeAnalysis.CilInstruction.ResolveMemberToken(Int32 token) in /home/runner/work/CilTools/CilTools/CilTools.BytecodeAnalysis/CilInstruction.cs:line 248
at CilTools.BytecodeAnalysis.CilTokenInstruction.get_ReferencedMember() in /home/runner/work/CilTools/CilTools/CilTools.BytecodeAnalysis/CilTokenInstruction.cs:line 39
Followup to 13f1256
Navigation in CIL View could be improved to use Frame and standard WPF navigation mechanisms (https://docs.microsoft.com/en-us/dotnet/desktop/wpf/app-development/navigation-overview?view=netframeworkdesktop-4.8#the-frame-class)
ECMA-335 II.10.3.2
using System;
using System.Reflection;
using CilTools.BytecodeAnalysis;
class Program
{
static void Main(string[] args)
{
CilGraph graph = CilGraph.Create(typeof(Derived).GetMethod(
"IBase.PrintName",
BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance
));
Console.WriteLine(graph.ToText());
Console.ReadKey();
}
}
public interface IBase
{
void PrintName();
}
public class Derived:IBase
{
void IBase.PrintName()
{
Console.WriteLine("Derived");
}
}
Current output:
.method private hidebysig newslot virtual final instance void IBase.PrintName() cil managed
{
.maxstack 8
nop
ldstr "Derived"
call void [mscorlib]System.Console::WriteLine(string)
nop
ret
}
Expected output:
.method private hidebysig newslot virtual final
instance void IBase.PrintName() cil managed
{
.override IBase::PrintName
.maxstack 8
nop
ldstr "Derived"
call void [mscorlib]System.Console::WriteLine(string)
nop
ret
}
System.NullReferenceException: Ссылка на объект не указывает на экземпляр объекта.
в System.Reflection.Metadata.Parameter.GetCustomAttributes()
в CilTools.Metadata.ParameterSpec.GetCustomAttributes(Boolean inherit)
в CilTools.Syntax.SyntaxNode.GetDefaultsSyntax(MethodBase m, Int32 startIndent)
в CilTools.BytecodeAnalysis.CilGraph.ToSyntaxTreeImpl(DisassemblerParams pars, Int32 startIndent)
в CilTools.BytecodeAnalysis.CilGraph.ToSyntaxTree(DisassemblerParams pars)
в CilView.UI.Controls.CilBrowserPage..ctor(MethodBase m, Int32 start, Int32 end, RoutedEventHandler navigation) в D:\VADIM\repos\CilTools\CilView\UI.Controls\CilBrowserPage.xaml.cs:строка 31
в CilView.UI.Controls.CilBrowser.NavigateToMethod(MethodBase mb, Int32 start, Int32 end) в D:\VADIM\repos\CilTools\CilView\UI.Controls\CilBrowser.xaml.cs:строка 124
в CilView.UI.Controls.CilBrowser.Navigated(Object sender, RoutedEventArgs e) в D:\VADIM\repos\CilTools\CilView\UI.Controls\CilBrowser.xaml.cs:строка 109
Module: System.Reflection.Metadata
Method: System.Reflection.Metadata.CustomAttributeHandleCollection GetCustomAttributes()
(Introduced after v2.4)
For example: newarr uint8[]
instead of newarr [mscorlib]System.Byte[]
https://gitflic.ru/project/smallsoft/ciltools/commit/ad90b7cf3608f387fe7e2bba3f0ed74b2a3157eb
https://gitflic.ru/project/smallsoft/ciltools/commit/67a67a773bd71fd3e1c4cdfa30fc5dd175c5ed17
CLI specification defines a set of keywords that must be escaped (enclosed into single or double quotes) when used as identifiers; for example: field
, assembly
. Methods that convert instructions/method signatures to text should be updated to escape them.
Example code:
using System;
using System.Reflection;
using CilBytecodeParser;
class Program
{
public static void field()
{
Console.WriteLine("In the method 'field'...");
}
public static void Main(string[] args)
{
Console.WriteLine(CilAnalysis.MethodToText(typeof(Program).GetMethod("field")));
Console.ReadKey();
}
}
Current output:
.method public hidebysig static void field() cil managed {
.maxstack 8
nop
ldstr "In the method 'field'..."
call void [mscorlib]System.Console::WriteLine(string)
nop
ret
}
Expected output:
.method public hidebysig static void 'field'() cil managed {
.maxstack 8
nop
ldstr "In the method 'field'..."
call void [mscorlib]System.Console::WriteLine(string)
nop
ret
}
Ths list of keywords is defined in ECMA-335 Specification, section VI.C.1.
using System;
using System.Collections.Generic;
using System.Text;
using CilTools.BytecodeAnalysis;
using CilTools.BytecodeAnalysis.Extensions;
using CilTools.Syntax;
namespace NetCoreTest
{
class Program
{
public static void Foo(int x, int y)
{
if (x > y) Console.WriteLine("x>y");
else if (x == y) Console.WriteLine("x=y");
else Console.WriteLine("x<y");
}
public static void Main(string[] args)
{
CilGraph graph = typeof(Program).GetMethod("Foo").GetCilGraph();
MethodDefSyntax syntax = graph.ToSyntaxTree();
Console.WriteLine(syntax.ToString());
Console.ReadKey();
}
}
}
Current output:
ldstr "x\076y"
Expected:
ldstr "x>y"
extends [mscorlib]System.Object
instead of extends class [mscorlib]System.Object
ECMA-335 II.10.1 Type header (ClassHeader)
When outputting signature of entry point method as CIL assembler code, it should be marked with .entrypoint
directive.
Example code:
using System;
using System.Reflection;
using CilBytecodeParser;
class Program
{
public static void Main(string[] args)
{
Console.WriteLine(CilAnalysis.MethodToText(MethodBase.GetCurrentMethod()));
Console.ReadKey();
}
}
Current output:
.method public hidebysig static void Main(
string[] args
) cil managed {
.maxstack 8
nop
call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetCurrentMethod()
call string [CilBytecodeParser]CilBytecodeParser.CilAnalysis::MethodToText(class [mscorlib]System.Reflection.MethodBase)
call void [mscorlib]System.Console::WriteLine(string)
nop
call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
pop
ret
}
Expected output:
.method public hidebysig static void Main(
string[] args
) cil managed {
.entrypoint
.maxstack 8
nop
call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetCurrentMethod()
call string [CilBytecodeParser]CilBytecodeParser.CilAnalysis::MethodToText(class [mscorlib]System.Reflection.MethodBase)
call void [mscorlib]System.Console::WriteLine(string)
nop
call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
pop
ret
}
The Assembly.EntryPoint property can be used to determine what method is an entry point in the given assembly.
Relevant ECMA-335 Specification section: II.15.4.1.2 The .entrypoint directive.
MyNamespace.MyType
should be "IdentifierSyntax - PunctuationSyntax - IdentifierSyntax" instead of single identifier.
ECMA-335 II.16.3.1 - Data declaration
Current:
.field static assembly initonly int64 '8F1A52EA427069AA8B6FC1D0A7BC426B2160A963E2DBFA59CE3E254462981A0B'
Expected:
.field static assembly initonly int64 '8F1A52EA427069AA8B6FC1D0A7BC426B2160A963E2DBFA59CE3E254462981A0B' at I_0000DC30
// ...
.data cil I_0000DC30 = bytearray (
20 00 09 00 0D 00 0A 00)
mscorlib / System.Threading.Interlocked / CompareExchange
Expected:
.method public hidebysig static !!T CompareExchange<class T>(!!T& location1,
!!T 'value',
!!T comparand) cil managed
Actual
.method public hidebysig static !!0 CompareExchange<T>(
!0 location1,
!!0 'value',
!!0 comparand
) cil managed
Not specified as keyword in ECMA-335 spec, but used as a keyword (on type definitions) in current CLR implementation.
[TestMethod]
[TypeTestData(typeof(SequentialStructSample), BytecodeProviders.Metadata)]
public void Test_StructLayoutAttribute_Sequential(Type t)
{
Assert.IsTrue(t.IsValueType); //fails
}
SyntaxGenerator.GetPropertyMethod runs into TypeLoadException when property is on a type derived from external assembly which cannot be resolved.
> CilTools.Metadata.dll!CilTools.Metadata.AssemblyReader.LoadType(System.Type t)Строка 277 C#
CilTools.Metadata.dll!CilTools.Metadata.TypeRef.LoadImpl()Строка 42 C#
CilTools.Metadata.dll!CilTools.Metadata.TypeRef.GetMembers(System.Reflection.BindingFlags bindingAttr)Строка 193 C#
CilTools.Metadata.dll!CilTools.Metadata.TypeDef.GetMembers(System.Reflection.BindingFlags bindingAttr)Строка 482 C#
CilTools.Metadata.dll!CilTools.Metadata.TypeDef.GetMember(string name, System.Reflection.BindingFlags bindingAttr)Строка 406 C#
CilTools.BytecodeAnalysis.dll!CilTools.Syntax.Generation.SyntaxGenerator.GetPropertyMethod(System.Reflection.PropertyInfo p, string accName)Строка 458 C#
CilTools.BytecodeAnalysis.dll!CilTools.Syntax.Generation.SyntaxGenerator.GetTypeDefSyntaxImpl(System.Type t, bool full, CilTools.Syntax.DisassemblerParams disassemblerParams, int startIndent)Строка 1061 C#
System.Linq.dll!System.Collections.Generic.LargeArrayBuilder<CilTools.Syntax.SyntaxNode>.AddRange(System.Collections.Generic.IEnumerable<CilTools.Syntax.SyntaxNode> items) Нет данных
System.Linq.dll!System.Collections.Generic.EnumerableHelpers.ToArray<CilTools.Syntax.SyntaxNode>(System.Collections.Generic.IEnumerable<CilTools.Syntax.SyntaxNode> source) Нет данных
System.Linq.dll!System.Linq.Enumerable.ToArray<CilTools.Syntax.SyntaxNode>(System.Collections.Generic.IEnumerable<CilTools.Syntax.SyntaxNode> source) Нет данных
CilBrowser.Core.dll!CilBrowser.Core.HtmlGenerator.VisualizeType(System.Type t, System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<System.Type>> typeMap)Строка 382 C#
CilBrowser.Core.dll!CilBrowser.Core.WebsiteGenerator.GenerateFromAssembly(System.Reflection.Assembly ass, string nsFilter, string outputPath, string customFooter)Строка 105 C#
CilBrowser.dll!CilBrowser.Program.GenerateDemo()Строка 33 C#
CilBrowser.dll!CilBrowser.Program.Main(string[] args)Строка 98 C#
Test method CilTools.Metadata.Tests.MethodDefTests.Test_GetBaseDefinition_FromObject threw exception:
System.NotImplementedException: The method or operation is not implemented.
TypeRef.GetMethodImpl(String name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) строка 188
Type.GetMethod(String name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
MdMethodInfoBase.GetBaseDefinition() строка 107
MethodDefTests.Test_GetBaseDefinition_FromObject() строка 284
using System;
using System.Collections.Generic;
using System.Text;
using CilTools.BytecodeAnalysis;
namespace CilToolsTest
{
class MyParamAttribute : Attribute { public MyParamAttribute(int n) { } }
class MyReturnAttribute : Attribute { }
class Program
{
[return: MyReturn]
public static int Sum([MyParam(1)]int x, [MyParam(2)] int y)
{
return x + y;
}
static void Main(string[] args)
{
Console.WriteLine(CilAnalysis.MethodToText(typeof(Program).GetMethod("Sum")));
Console.ReadKey();
}
}
}
Current output:
.method public hidebysig static int32 Sum(
int32 x,
int32 y
) cil managed
{
//...
}
Expected output:
.method public hidebysig static int32 Sum(int32 x,
int32 y) cil managed
{
.param [0]
.custom instance void CilToolsTest.MyReturnAttribute::.ctor() = ( 01 00 00 00 )
.param [1]
.custom instance void CilToolsTest.MyParamAttribute::.ctor(int32) = ( 01 00 01 00 00 00 00 00 )
.param [2]
.custom instance void CilToolsTest.MyParamAttribute::.ctor(int32) = ( 01 00 02 00 00 00 00 00 )
//...
}
Make ITypeInfo interface public to enable inspecting function pointer types with CilTools.Metadata. This is currently not supported both in standard reflection and MetadataLoadContext (dotnet/runtime#43791, dotnet/runtime#11354).
System.TypeLoadException: Failed to resolve type System.Runtime.ConstrainedExecution.CriticalFinalizerObject, System.Runtime, Version=4.2.2.0, PublicKeyToken=b03f5f7f11d50a3a
в CilTools.Metadata.AssemblyReader.LoadType(Type t)
в CilTools.Metadata.TypeRef.LoadImpl()
в CilTools.Metadata.TypeRef.get_BaseType()
в System.Type.IsSubclassOf(Type c)
в System.Type.IsValueTypeImpl()
в System.Type.get_IsValueType()
в CilTools.BytecodeAnalysis.CilAnalysis.<GetTypeSyntax>d__4.MoveNext()
в CilTools.BytecodeAnalysis.CilAnalysis.GetMethodRefSyntax(MethodBase m, Boolean inlineTok)
в CilTools.Syntax.SyntaxNode.<GetTypeDefSyntaxImpl>d__24.MoveNext()
в CilView.Core.Syntax.SyntaxWriter.<WriteSyntaxAsync>d__1.MoveNext()
--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---
в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
в System.Runtime.CompilerServices.TaskAwaiter.GetResult()
в CilView.Core.Syntax.SyntaxWriter.<DisassembleAsync>d__5.MoveNext()
--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---
в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
в System.Runtime.CompilerServices.TaskAwaiter.GetResult()
в CilView.MainWindow.<miExportAssembly_Click>d__23.MoveNext() в D:\VADIM\repos\CilTools\CilView\MainWindow.xaml.cs:строка 595
Module: CilTools.Metadata
Method: System.Type LoadType(System.Type)
static void M(delegate *<out int, void> pfn)
)ReadMemoryIgnoreErrors can be speeded up by scanning valid memory regions via VirtualQueryEx and reading them as whole, instead of by pages. Example:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
namespace ConsoleApp1
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
[Flags]
enum LoadLibraryFlags : uint
{
None = 0,
DONT_RESOLVE_DLL_REFERENCES = 0x00000001,
LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010,
LOAD_LIBRARY_AS_DATAFILE = 0x00000002,
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040,
LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020,
LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200,
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000,
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100,
LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800,
LOAD_LIBRARY_SEARCH_USER_DIRS = 0x00000400,
LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags);
[StructLayout(LayoutKind.Sequential)]
public struct MODULEINFO
{
public IntPtr lpBaseOfDll;
public uint SizeOfImage;
public IntPtr EntryPoint;
}
[DllImport("psapi.dll", SetLastError = true)]
static extern bool GetModuleInformation(IntPtr hProcess, IntPtr hModule, out MODULEINFO lpmodinfo, uint cb);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
[Out] byte[] lpBuffer,
int dwSize,
out IntPtr lpNumberOfBytesRead);
[DllImport("kernel32.dll", SetLastError = true, EntryPoint = "ReadProcessMemory")]
static extern bool ReadProcessMemory_Byte(
IntPtr hProcess, IntPtr lpBaseAddress, out byte lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead
);
[StructLayout(LayoutKind.Sequential)]
public struct MEMORY_BASIC_INFORMATION
{
public IntPtr BaseAddress;
public IntPtr AllocationBase;
public uint AllocationProtect;
public IntPtr RegionSize;
public uint State;
public uint Protect;
public uint Type;
}
public enum AllocationProtect : uint
{
PAGE_EXECUTE = 0x00000010,
PAGE_EXECUTE_READ = 0x00000020,
PAGE_EXECUTE_READWRITE = 0x00000040,
PAGE_EXECUTE_WRITECOPY = 0x00000080,
PAGE_NOACCESS = 0x00000001,
PAGE_READONLY = 0x00000002,
PAGE_READWRITE = 0x00000004,
PAGE_WRITECOPY = 0x00000008,
PAGE_GUARD = 0x00000100,
PAGE_NOCACHE = 0x00000200,
PAGE_WRITECOMBINE = 0x00000400
}
const uint MEM_COMMIT = 0x1000;
const uint MEM_FREE = 0x10000;
const uint MEM_RESERVE = 0x2000;
[DllImport("kernel32.dll")]
static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength);
public struct MemoryRegion
{
public long Address { get; set; }
public long Size { get; set; }
public bool IsReadable { get; set; }
}
static bool IsReadAccess(uint protectionFlags)
{
AllocationProtect ap = (AllocationProtect)protectionFlags;
return ap == AllocationProtect.PAGE_EXECUTE_READ ||
ap == AllocationProtect.PAGE_EXECUTE_READWRITE ||
ap == AllocationProtect.PAGE_EXECUTE_WRITECOPY ||
ap == AllocationProtect.PAGE_READONLY ||
ap == AllocationProtect.PAGE_READWRITE ||
ap == AllocationProtect.PAGE_WRITECOPY;
}
public static MemoryRegion[] GetMemoryRegions(IntPtr hProcess, IntPtr address, int size)
{
List<MemoryRegion> ret = new List<MemoryRegion>(50);
long MaxAddress = (long)address + size;
while(true)
{
MEMORY_BASIC_INFORMATION m=new MEMORY_BASIC_INFORMATION();
int result = VirtualQueryEx(
hProcess, address, out m, (uint)Marshal.SizeOf(m)
);
if (result==0||m.RegionSize == IntPtr.Zero) break;
MemoryRegion reg = new MemoryRegion();
reg.Address = (long)m.BaseAddress;
reg.Size = (long)m.RegionSize;
if (m.State == MEM_COMMIT && IsReadAccess(m.AllocationProtect))
{
reg.IsReadable = true;
}
ret.Add(reg);
address = (IntPtr)((long)m.BaseAddress + (long)m.RegionSize);
if ((long)address > MaxAddress) break;
}
return ret.ToArray();
}
static void EnumMemoryRegions(IntPtr hProcess,IntPtr address, int size)
{
MemoryRegion[] regions = GetMemoryRegions(hProcess, address, size);
for (int i = 0; i < regions.Length; i++)
{
Console.WriteLine("0x{0} : {1} bytes, Readable: {2}",
regions[i].Address.ToString("X"), regions[i].Size, regions[i].IsReadable
);
}
}
static void Main(string[] args)
{
string path = "C:\\Test\\Lib.dll";
//string path = typeof(object).Assembly.Location;
IntPtr hModule = LoadLibraryEx(path, IntPtr.Zero, LoadLibraryFlags.None);
if (hModule == IntPtr.Zero) throw new Win32Exception(Marshal.GetLastWin32Error());
IntPtr hProcess = Process.GetCurrentProcess().Handle;
MODULEINFO mi = new MODULEINFO();
bool res = GetModuleInformation(hProcess, hModule, out mi, (uint)Marshal.SizeOf(mi));
if (res == false) throw new Win32Exception(Marshal.GetLastWin32Error());
EnumMemoryRegions(hProcess, mi.lpBaseOfDll, (int)mi.SizeOfImage);
Console.ReadKey();
}
}
}
System.Console.dll (.NET Core 2.1) / System.IO.ConsoleStream
Expected:
.class private abstract auto ansi beforefieldinit System.IO.ConsoleStream
extends [System.Runtime]System.IO.Stream
Actual:
.class private abstract auto ansi beforefieldinit System.IO.ConsoleStream
extends UnknownType
aggressiveinlining
, uint8
, uint16
, uint32
, type
(Fixed on GitFlic: ea8e39)winapi
instead of platformapi
CilTools.Tests.Common.il(4103) : error : syntax error at token 'platformapi' in: .method public hidebysig static pinvok
eimpl("user32.dll" lasterr platformapi ) bool ShowWindow(***** FAILURE *****
CilTools.Tests.Common.il(8814) : error : syntax error at token 'type' in: class [mscorlib]System.Type type,
***** FAILURE *****
Related to: dotnet/runtime#58344 , dotnet/runtime#58319
inherit
parameterThere's a constrined. prefix which is emitted by compilers on virtual method calls when the type comes from generic argument which can be a struct. CilInstruction
class should be updated to properly parse its operand. Example:
using System;
using System.Reflection;
using CilBytecodeParser;
class Program
{
public static void Test<T>(T x)
{
Console.WriteLine(x.ToString());
}
public static void Main(string[] args)
{
Console.WriteLine(CilAnalysis.MethodToText(typeof(Program).GetMethod("Test")));
Console.ReadKey();
}
}
Current output:
.method public hidebysig static void Test<T>(
!!T x
) cil managed {
.maxstack 8
nop
ldarga.s x
constrained. 452984833
callvirt instance string [mscorlib]System.Object::ToString()
call void [mscorlib]System.Console::WriteLine(string)
nop
ret
}
Expected output:
.method public hidebysig static void Test<T>(
!!T x
) cil managed {
.maxstack 8
nop
ldarga.s x
constrained. !!T
callvirt instance string [mscorlib]System.Object::ToString()
call void [mscorlib]System.Console::WriteLine(string)
nop
ret
}
string[] GetProcessModules(int id)
{
List<string> res = new List<string>();
string query = "references of {win32_process.Handle="+id.ToString()+
"} WHERE ResultClass = CIM_ProcessExecutable";
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
using (ManagementObjectCollection results = searcher.Get())
{
foreach (ManagementObject x in results)
{
var antecedent = new ManagementObject((string)x["Antecedent"]);
if (antecedent["Name"] == null) continue;
string name = antecedent["Name"].ToString();
res.Add(name);
}
}
return res.ToArray();
}
In .NET 3.5, every managed module has corresponding .ni.dll native module loaded via LoadLibrary. In .NET 4.0 and newer, some modules might be memory-mapped rather then loaded from native image file.
Version 1.1.142101+
StringBuilder sb = new StringBuilder(1000);
using (DataTarget dt = DataTarget.AttachToProcess(8036, false))
{
ClrInfo ci = dt.ClrVersions[0];
ClrRuntime clr = ci.CreateRuntime();
foreach (ClrModule module in clr.EnumerateModules())
{
if (module.IsPEFile) sb.AppendLine(module.Name);
}
}
Example C++/CLI program:
using namespace System;
public class A {
int _x;
public: A(int x) { this->_x = x; }
};
int main(array<System::String ^> ^args)
{
A a(1);
Console::ReadKey();
return 0;
}
Expected disassembler output:
.method assembly static valuetype A* modopt([mscorlib]System.Runtime.CompilerServices.CallConvThiscall)
'A.{ctor}'(valuetype A* modopt([mscorlib]System.Runtime.CompilerServices.IsConst) modopt([mscorlib]System.Runtime.CompilerServices.IsConst) A_0,
int32 x) cil managed
{
.vtentry 1 : 1
//...
}
The VTable data is stored in the location pointed int the CLI Header (ECMA 335 II.25.3.3). Code to get vtable data:
PEReader pr;
//...
int vt_rva = pr.PEHeaders.CorHeader.VtableFixupsDirectory.RelativeVirtualAddress;
var vt_data=pr.GetSectionData(vt_rva).GetContent();
When generating CIL assembler code, current string literal escaping uses rules similar to those of C#.
The actual escaping rules in CIL assembler are different. From ECMA-335 II.5.2 - Basic syntax categories:
QSTRING is a string surrounded by double quote (″) marks. Within the quoted string the character
“\”
can be used as an escape character, with“\t”
representing a tab character,“\n”
representing a newline
character, and“\”
followed by three octal digits representing a byte with that value
[Example: The following result in strings that are equivalent to "Hello World from CIL!":
ldstr "Hello " + "World " +
"from CIL!"
and
ldstr "Hello World\
\040from CIL!"
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.