Hello, I make infographics, test compilers, and make things go fast.
- ⚡ Infographics: https://leveluppp.ghost.io/infographics/
- ⚡ Blog: https://leveluppp.ghost.io/
- ⚡ I occasionally do Youtube: https://www.youtube.com/c/LevelUppp/videos
⚡ Decompilation Tools and High Productivity Utilities ⚡
License: GNU Affero General Public License v3.0
Hello, I make infographics, test compilers, and make things go fast.
Good day!
Was trying to use your tool to see asm of generic method, but the tool is failing for me.
Input C#:
using System;
using System.Runtime.CompilerServices;
public class C
{
public bool M(string left, string right)
{
return IsSame(left, right);
}
public static bool IsSame<T>(T left, T right)
{
if(typeof(T) == typeof(string))
{
var leftStr = (string)(object)left;
var rightStr = (string)(object)right;
return string.Equals(leftStr, rightStr, StringComparison.Ordinal);
}
return false;
}
}
I've compiled the tool locally and run with the following args:
c:\Projects\PowerUp\src\PowerUp.Watcher\bin\Release\net6.0\PowerUp.Watcher.exe -cs .\checks.cs checks_out.asm
Output I'm getting:
System.ArgumentException: The given generic instantiation was invalid.
at System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(RuntimeMethodHandleInternal method, IntPtr* pInstantiation, Int32 cInstantiation)
at System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(RuntimeMethodHandle method, RuntimeTypeHandle[] instantiation)
at PowerUp.Core.Decompilation.JitExtensions.ToAsm(MethodInfo methodInfo, ILMethodMap[] sourceCodeMap) in C:\Projects_External\PowerUp\src\PowerUp.Core\Decompilation\JITExtensions.cs:line 214
at PowerUp.Core.Decompilation.JitExtensions.ToAsm(Type typeInfo, ILMethodMap[] sourceCodeMap, Boolean private) in C:\Projects_External\PowerUp\src\PowerUp.Core\Decompilation\JITExtensions.cs:line 161
at PowerUp.Watcher.CSharpWatcher.DecompileToASM(String code) in C:\Projects_External\PowerUp\src\PowerUp.Watcher\CSharpWatcher.cs:line 811
at PowerUp.Watcher.CSharpWatcher.<>c__DisplayClass10_0.<<WatchFile>b__0>d.MoveNext() in C:\Projects_External\PowerUp\src\PowerUp.Watcher\CSharpWatcher.cs:line 195
Here is output in console:
Input >> -cs .\checks.cs checks_out.asm
CSharp Watcher Initialize:
Input File: .\checks.cs
ASM File: checks_out.asm
IL File:
CS File:
[WARNING]: IL File doesnt exist
[WARNING]: Lowered CSharp File doesnt exist
Libs Path: C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.0-rc.1.21451.13\
.NET Enviromment variables:
Language Version: default
.NET Version: 6.0.10
[RELEASE]
App Configuration:
CppCompilerPath = [Invalid or Missing] Watchers might fail.
DotNetCoreDirPathDefault = C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.0-rc.1.21451.13\
DotNetCoreDirPathNet3 = C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.18\
DotNetCoreDirPathNet5 = C:\Program Files\dotnet\shared\Microsoft.NETCore.App\5.0.17\
DotNetCoreDirPathNet6 = C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.0-rc.1.21451.13\
DotNetCoreDirPathNet7 = C:\Program Files\dotnet\shared\Microsoft.NETCore.App\
FSharpCompilerPath = C:\Program Files\dotnet\sdk\6.0.100-rc.1.21458.32\FSharp\fsc.dll
GOCompilerPath = [Invalid or Missing] Watchers might fail.
RustCompilerPath = [Invalid or Missing] Watchers might fail.
I know that generics are tricky, so am curious whether it's a well-known limitation of the tool or whether I'm doing something wrong 🤔
The following code fails. Not sure why. It works fine with 1_000 iterations.
using PowerUp.Core;
namespace ConsoleApp1 {
class Program {
static void Main(string[] args) {
string txt = "12,34,56";
QuickBenchmark.Measure(() => {
for (int i = 0; i < 10_000; i++) {
string[] a = txt.Split(',');
int x = int.Parse(a[0]);
int y = int.Parse(a[1]);
int z = int.Parse(a[2]);
}
});
}
}
}
When running dotnet build -c Release
in the PowerUp.Watcher folder build fails with:
C:\src\PowerUp\src\PowerUp.Watcher\WatcherUtils.cs(17,29): error CS8773: Feature 'struct field initializers' is not available in C# 9.0. Please use language version 10.0 or greater. [C:\src\PowerUp\src\PowerUp.Watcher\PowerUp.Watcher.csproj]
This can be fixed by selecting the csproj to only support .NET 6.
Based on the docs here it seems that only .NET 6 supports C# 10 features.
https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10
Hello,
i used PowerUpWatcher (commit 894ffa4) on Windows 11 64-bit.
With test.cs
:
int M(int i)
{
if(i==1) return 1;
i++;
i++;
return i;
}
alwais write to test.asm
:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at PowerUp.Watcher.ILWriter.ToILString(DecompilationUnit unit) in C:\Users\**\Desktop\PowerUp-main\src\PowerUp.Watcher\ILWriter.cs:line 20
at PowerUp.Watcher.CSharpWatcher.<>c__DisplayClass10_0.<<WatchFile>b__0>d.MoveNext() in C:\Users\**\Desktop\PowerUp-main\src\PowerUp.Watcher\CSharpWatcher.cs:line 218
I compile project using dotnet publish -c Release -f net6.0
.
When I try to process the next code void a(){}
with command line arguments -cs input.cs output.asm output.il
I have the next error in the output.il file
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at PowerUp.Watcher.ILWriter.ToILString(DecompilationUnit unit) in E:\tools\PowerUp-main\src\PowerUp.Watcher\ILWriter.cs:line 100
at PowerUp.Watcher.CSharpWatcher.ToILString(DecompilationUnit unit) in E:\tools\PowerUp-main\src\PowerUp.Watcher\CSharpWatcher.cs:line 319
at PowerUp.Watcher.CSharpWatcher.TryWriteIL(DecompilationUnit unit, String& result) in E:\tools\PowerUp-main\src\PowerUp.Watcher\CSharpWatcher.cs:line 269
I managed to fix it by changing the line ILWriter.cs#L20 to the next one
var lines = unit.InputSouceCode.Replace("\r", string.Empty).Split('\n');
And I got the next result in the output.il
.class public auto ansi beforefieldinit CompilerGen
extends [System.Private.CoreLib]System.Object
{
.method private hidebysig
instance void a () cil managed
{
.maxstack 8
// void a(){}
IL_0000: ret
}
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [System.Private.CoreLib]System.Object::.ctor()
IL_0006: ret
}
}
Please, confirm that my change is okay and I'll create a PR. Or if I did something wrong, please let me know.
I use version from 16afbe9 commit with net 5 and Windows.
Input:
internal struct BitArray32Sized
{
private const int MAXBITSIZE = 32;
private Int32 value;
private readonly byte length;
}
internal struct BitArray64Sized
{
private const int MAXBITSIZE = 64;
private Int64 value;
private readonly byte length;
}
public class Q { private readonly BitArray32Sized my; }
public class QQ { private readonly BitArray64Sized my; }
Output with issues inline.
# CompilerGen+BitArray32Sized Memory Layout.
# (struct sizes might be wrong since they are boxed to extract layouts)
struct CompilerGen+BitArray32Sized
{
Fields:
[0-3] System.Int32 value (4 bytes)
[4-4] System.Byte length (1 bytes)
└──────────────────────────────────────────┘
Size: 5 # Estimated
Padding: 0 # Estimated
}
# CompilerGen+BitArray64Sized Memory Layout.
# (struct sizes might be wrong since they are boxed to extract layouts)
struct CompilerGen+BitArray64Sized
{
Fields:
[0-7] System.Int64 value (8 bytes)
[8-8] System.Byte length (1 bytes)
└──────────────────────────────────────────┘
Size: 9 # Estimated
Padding: 0 # Estimated
}
# CompilerGen+Q Memory Layout.
class CompilerGen+Q
{
Metadata:
┌──────────────────────────────────────────┐
│ [0-7] Object Header (8 bytes) │
│ [8-15] Method Table Ptr (8 bytes) │
└──────────────────────────────────────────┘
Fields:
[16-23] CompilerGen+BitArray32Sized my(8 bytes) // This seems correct, but then there should be padding added?
Size: 24 // This is correct, but maybe confusing if people don't know all objects have to be 24 bytes.
Padding: 0 // Shouldn't we have three bytes of padding or don't you count the padding necessary to get to 24 bytes?
}
# CompilerGen+QQ Memory Layout.
class CompilerGen+QQ
{
Metadata:
┌──────────────────────────────────────────┐
│ [0-7] Object Header (8 bytes) │
│ [8-15] Method Table Ptr (8 bytes) │
└──────────────────────────────────────────┘
Fields:
[16-23] CompilerGen+BitArray64Sized my(8 bytes)
Size: 32 // Math doesn't add up 8 + 8 + 8 = 24 so there has to be padding somewhere.
Padding: 0 // Shouldn't this have some padding?
}
I guess the confusion comes from padding is necessary to get to 8 byte boundary on x64, but it seems the padding is never really shown neither in struct nor class layout.
Just wanted to let you know that watcher is writing the following exception into the output file when trying to run on macOS:
System.NotSupportedException: Passive attach is not supported on OSX.s
at Microsoft.Diagnostics.Runtime.DataTarget.AttachToProcess(Int32 pid, UInt32 msecTimeout, AttachFlag attachFlag)
at PowerUp.Core.Decompilation.JitCodeDecompiler.DecompileMethod(MethodInfo method, String functionCallName) in /Users/d0pare/Projects/GitHub/PowerUp/src/PowerUp.Core/Decompilation/JITDecompiler.cs:line 275
at PowerUp.Core.Decompilation.JitExtensions.ToAsm(MethodInfo methodInfo, ILMethodMap[] sourceCodeMap) in /Users/d0pare/Projects/GitHub/PowerUp/src/PowerUp.Core/Decompilation/JITExtensions.cs:line 217
at PowerUp.Core.Decompilation.JitExtensions.ToAsm(Type typeInfo, ILMethodMap[] sourceCodeMap, Boolean private) in /Users/d0pare/Projects/GitHub/PowerUp/src/PowerUp.Core/Decompilation/JITExtensions.cs:line 162
at PowerUp.Watcher.CSharpWatcher.DecompileToASM(String code) in /Users/d0pare/Projects/GitHub/PowerUp/src/PowerUp.Watcher/CSharpWatcher.cs:line 612
at PowerUp.Watcher.CSharpWatcher.<>c__DisplayClass10_0.<<WatchFile>b__0>d.MoveNext() in /Users/d0pare/Projects/GitHub/PowerUp/src/PowerUp.Watcher/CSharpWatcher.cs:line 178
Seems like the latest clrmd
version of DataTarget is supporting macOS but with slightly modified API compared to the current one.
I cant get this tool working i keep getting this error message whenever i try to de-compilea cs file
System.IndexOutOfRangeException: Index was outside the bounds of the array. at PowerUp.Watcher.ILWriter.ToILString(DecompilationUnit unit) in D:\Compilers\PowerUp-main\src\PowerUp.Watcher\ILWriter.cs:line 20 at PowerUp.Watcher.CSharpWatcher.<>c__DisplayClass10_0.<<WatchFile>b__0>d.MoveNext() in D:\Compilers\PowerUp-main\src\PowerUp.Watcher\CSharpWatcher.cs:line 218
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.