Skip to content

Commit

Permalink
Introducing ILSpy.ReadyToRun
Browse files Browse the repository at this point in the history
  • Loading branch information
cshung committed Dec 21, 2019
1 parent f831e47 commit 8add5ea
Show file tree
Hide file tree
Showing 4 changed files with 238 additions and 0 deletions.
65 changes: 65 additions & 0 deletions ILSpy.ReadyToRun/ILSpy.ReadyToRun.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.props" />

<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AssemblyName>ILSpy.ReadyToRun.Plugin</AssemblyName>
<LangVersion>7.2</LangVersion>

<GenerateAssemblyInfo>False</GenerateAssemblyInfo>

<EnableDefaultItems>false</EnableDefaultItems>

<BaseAddress>6488064</BaseAddress>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<DebugType>full</DebugType>
<DebugSymbols>true</DebugSymbols>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>

<PropertyGroup>
<OutputPath>..\ILSpy\bin\$(Configuration)\</OutputPath>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj">
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\ILSpy\ILSpy.csproj">
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\SharpTreeView\ICSharpCode.TreeView.csproj">
<Private>False</Private>
</ProjectReference>
</ItemGroup>

<ItemGroup>
<Reference Include="Iced">
<HintPath>..\..\iced\Iced\bin\Debug\netstandard2.0\Iced.dll</HintPath>
</Reference>
<Reference Include="ILCompiler.Reflection.ReadyToRun">
<HintPath>..\..\runtime\artifacts\bin\coreclr\Windows_NT.x64.Debug\ILCompiler.Reflection.ReadyToRun.dll</HintPath>
</Reference>
</ItemGroup>

<ItemGroup>
<Compile Include="ReadyToRunLanguage.cs" />
</ItemGroup>

<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.targets" />

<Target Name="RemoveTransitiveProjectReferences" AfterTargets="IncludeTransitiveProjectReferences">
<ItemGroup>
<ProjectReference Remove="@(_TransitiveProjectReferences)" />
</ItemGroup>
</Target>

</Project>
33 changes: 33 additions & 0 deletions ILSpy.ReadyToRun/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#region Using directives

using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

#endregion

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ILSpy.ReadyToRun.Plugin")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ILSpy.ReadyToRun.Plugin")]
[assembly: AssemblyCopyright("Copyright 2011")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// This sets the default COM visibility of types in the assembly to invisible.
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
[assembly: ComVisible(false)]

[assembly: InternalsVisibleTo("ILSpy.ReadyToRun.Tests")]

// The assembly version has following format :
//
// Major.Minor.Build.Revision
//
// You can specify all the values or you can use the default the Revision and
// Build Numbers by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")]
134 changes: 134 additions & 0 deletions ILSpy.ReadyToRun/ReadyToRunLanguage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// Copyright (c) 2018 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

using System;
using System.ComponentModel.Composition;
using Iced.Intel;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Solution;
using ICSharpCode.Decompiler.TypeSystem;
using ILCompiler.Reflection.ReadyToRun;

namespace ICSharpCode.ILSpy
{
[Export(typeof(Language))]
class ReadyToRunLanguage : Language
{
public override string Name => "ReadyToRun";

public override string FileExtension {
get { return ".asm"; }
}

public override ProjectId DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)
{
PEFile module = assembly.GetPEFileOrNull();
// TODO: avoid eager parsing
R2RReader reader = new R2RReader(new R2RAssemblyResolver(), module.Metadata, module.Reader, module.FileName);

output.WriteLine("// TODO - display ready to run information");
// TODO: display other header information
foreach (var method in reader.R2RMethods) {
output.WriteLine(method.SignatureString);
}

return base.DecompileAssembly(assembly, output, options);
}

public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options)
{
PEFile module = method.ParentModule.PEFile;
// TODO: avoid eager parsing in R2RReader
R2RReader reader = new R2RReader(new R2RAssemblyResolver(), module.Metadata, module.Reader, module.FileName);
foreach (var m in reader.R2RMethods) {
if (m.MethodHandle == method.MetadataToken) {
// TODO: Indexing
foreach (RuntimeFunction runtimeFunction in m.RuntimeFunctions) {
byte[] code = new byte[runtimeFunction.Size];
for (int i = 0; i < runtimeFunction.Size; i++) {
code[i] = reader.Image[reader.GetOffset(runtimeFunction.StartAddress) + i];
}
// TODO: Bitness
// TODO: RIP
DecoderFormatterExample(output, code, 64, 0);
}

}
}
}
private void DecoderFormatterExample(ITextOutput output, byte[] exampleCode, int exampleCodeBitness, ulong exampleCodeRIP)
{
// TODO: Decorate the disassembly with Unwind, GC and debug info
// You can also pass in a hex string, eg. "90 91 929394", or you can use your own CodeReader
// reading data from a file or memory etc
var codeBytes = exampleCode;
var codeReader = new ByteArrayCodeReader(codeBytes);
var decoder = Decoder.Create(exampleCodeBitness, codeReader);
decoder.IP = exampleCodeRIP;
ulong endRip = decoder.IP + (uint)codeBytes.Length;

// This list is faster than List<Instruction> since it uses refs to the Instructions
// instead of copying them (each Instruction is 32 bytes in size). It has a ref indexer,
// and a ref iterator. Add() uses 'in' (ref readonly).
var instructions = new InstructionList();
while (decoder.IP < endRip) {
// The method allocates an uninitialized element at the end of the list and
// returns a reference to it which is initialized by Decode().
decoder.Decode(out instructions.AllocUninitializedElement());
}

// Formatters: Masm*, Nasm*, Gas* (AT&T) and Intel* (XED)
// TODO: DecompilationOptions?
var formatter = new NasmFormatter();
formatter.Options.DigitSeparator = "`";
formatter.Options.FirstOperandCharIndex = 10;
var tempOutput = new StringBuilderFormatterOutput();
// Use InstructionList's ref iterator (C# 7.3) to prevent copying 32 bytes every iteration
foreach (var instr in instructions) {
// Don't use instr.ToString(), it allocates more, uses masm syntax and default options
formatter.Format(instr, tempOutput);
output.Write(instr.IP.ToString("X16"));
output.Write(" ");
int instrLen = instr.ByteLength;
int byteBaseIndex = (int)(instr.IP - exampleCodeRIP);
for (int i = 0; i < instrLen; i++)
output.Write(codeBytes[byteBaseIndex + i].ToString("X2"));
int missingBytes = 10 - instrLen;
for (int i = 0; i < missingBytes; i++)
output.Write(" ");
output.Write(" ");
output.WriteLine(tempOutput.ToStringAndReset());
}
}

private class R2RAssemblyResolver : ILCompiler.Reflection.ReadyToRun.IAssemblyResolver
{
public bool Naked => false;

public bool SignatureBinary => false;

public bool InlineSignatureBinary => false;

public string FindAssembly(string name, string filename)
{
throw new NotImplementedException();
}
}
}
}
6 changes: 6 additions & 0 deletions ILSpy.sln
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.Decompiler.PdbP
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.Tests", "ILSpy.Tests\ILSpy.Tests.csproj", "{B51C6636-B8D1-4200-9869-08F2689DE6C2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.ReadyToRun", "ILSpy.ReadyToRun\ILSpy.ReadyToRun.csproj", "{0313F581-C63B-43BB-AA9B-07615DABD8A3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -79,6 +81,10 @@ Global
{B51C6636-B8D1-4200-9869-08F2689DE6C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B51C6636-B8D1-4200-9869-08F2689DE6C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B51C6636-B8D1-4200-9869-08F2689DE6C2}.Release|Any CPU.Build.0 = Release|Any CPU
{0313F581-C63B-43BB-AA9B-07615DABD8A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0313F581-C63B-43BB-AA9B-07615DABD8A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0313F581-C63B-43BB-AA9B-07615DABD8A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0313F581-C63B-43BB-AA9B-07615DABD8A3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down

0 comments on commit 8add5ea

Please sign in to comment.