• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SamboyCoding / Cpp2IL / 17216182984

25 Aug 2025 05:35PM UTC coverage: 30.38% (-4.0%) from 34.352%
17216182984

Pull #481

github

web-flow
Merge b82763a24 into d5260685f
Pull Request #481: Decompiler

1804 of 7561 branches covered (23.86%)

Branch coverage included in aggregate %.

100 of 1839 new or added lines in 29 files covered. (5.44%)

41 existing lines in 6 files now uncovered.

4093 of 11850 relevant lines covered (34.54%)

165575.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.79
/Cpp2IL.Core/OutputFormats/AsmResolverDllOutputFormatIlRecovery.cs
1
using System;
2
using System.Collections.Generic;
3
using System.IO;
4
using System.Linq;
5
using System.Text;
6
using AsmResolver.DotNet;
7
using AsmResolver.PE.DotNet.Cil;
8
using AssetRipper.CIL;
9
using Cpp2IL.Core.Extensions;
10
using Cpp2IL.Core.Graphs;
11
using Cpp2IL.Core.Logging;
12
using Cpp2IL.Core.Model.Contexts;
13
using Cpp2IL.Core.Utils;
14

15
namespace Cpp2IL.Core.OutputFormats;
16

17
public class AsmResolverDllOutputFormatIlRecovery : AsmResolverDllOutputFormat
18
{
19
    public override string OutputFormatId => "dll_il_recovery";
1✔
20

21
    public override string OutputFormatName => "DLL files with IL Recovery";
×
22

23
    private MethodDefinition? _exceptionConstructor;
24

25
    protected override void FillMethodBody(MethodDefinition methodDefinition, MethodAnalysisContext methodContext)
26
    {
NEW
27
        if (_exceptionConstructor == null)
×
NEW
28
            FindExceptionConstructor(methodDefinition);
×
29

NEW
30
        var module = methodDefinition.Module!;
×
NEW
31
        var moduleName = module.Name!.ToString();
×
NEW
32
        var shouldSkip = moduleName.StartsWith("UnityEngine.") || moduleName.StartsWith("Unity.") ||
×
NEW
33
                         moduleName.StartsWith("System.") || moduleName == "System" ||
×
NEW
34
                         moduleName.StartsWith("mscorlib");
×
NEW
35
        var importer = new ReferenceImporter(module);
×
36

NEW
37
        if (!methodDefinition.IsManagedMethodWithBody())
×
NEW
38
            return;
×
39

NEW
40
        methodDefinition.CilMethodBody = new(methodDefinition);
×
NEW
41
        var instructions = methodDefinition.CilMethodBody.Instructions;
×
42

NEW
43
        if (shouldSkip)
×
44
        {
NEW
45
            methodDefinition.ReplaceMethodBodyWithMinimalImplementation();
×
NEW
46
            return;
×
47
        }
48

49
        try
50
        {
NEW
51
            TotalMethodCount++;
×
52

NEW
53
            methodContext.Analyze();
×
54

NEW
55
            if (methodContext.ConvertedIsil.Count == 0)
×
NEW
56
                methodDefinition.ReplaceMethodBodyWithMinimalImplementation();
×
57
            else
NEW
58
                IlGenerator.GenerateIl(methodContext, methodDefinition);
×
59

60
            //WriteControlFlowGraph(methodContext, Path.Combine(Environment.CurrentDirectory, "Cpp2IL", "bin", "Debug", "net9.0", "cpp2il_out", "cfg"));
61

NEW
62
            SuccessfulMethodCount++;
×
NEW
63
        }
×
NEW
64
        catch (Exception e)
×
65
        {
NEW
66
            Logger.ErrorNewline($"Decompiling {methodContext.FullName} failed: {e}");
×
67

68
            // throw new Exception(error);
NEW
69
            instructions.Add(CilOpCodes.Ldstr, e.ToString());
×
NEW
70
            instructions.Add(CilOpCodes.Newobj, importer.ImportMethod(_exceptionConstructor!));
×
UNCOV
71
            instructions.Add(CilOpCodes.Throw);
×
UNCOV
72
        }
×
73

NEW
74
        methodContext.ReleaseAnalysisData();
×
NEW
75
    }
×
76

77
    private void FindExceptionConstructor(MethodDefinition method)
78
    {
NEW
79
        var module = method.Module!;
×
NEW
80
        var mscorlibReference = module.AssemblyReferences.First(a => a.Name == "mscorlib");
×
NEW
81
        var mscorlib = mscorlibReference.Resolve()!.Modules[0];
×
82

NEW
83
        var exception = mscorlib.TopLevelTypes.First(t => t.FullName == "System.Exception");
×
NEW
84
        _exceptionConstructor = exception.Methods.First(m =>
×
NEW
85
            m.Name == ".ctor" && m.Parameters is [{ ParameterType.FullName: "System.String" }]);
×
NEW
86
    }
×
87

88
    public static void WriteControlFlowGraph(MethodAnalysisContext method, string outputPath)
89
    {
NEW
90
        var graph = method.ControlFlowGraph;
×
91

NEW
92
        var sb = new StringBuilder();
×
NEW
93
        var edges = new List<(int, int)>();
×
94

NEW
95
        sb.AppendLine("digraph ControlFlowGraph {");
×
NEW
96
        sb.AppendLine("    \"label\"=\"Control flow graph\"");
×
97

98
        // no instructions
NEW
99
        graph ??= new ISILControlFlowGraph([]);
×
100

NEW
101
        var methodText = $@"{CsFileUtils.GetKeyWordsForMethod(method)} {method.FullNameWithSignature}
×
NEW
102
parameter locals: {string.Join(", ", method.ParameterLocals)}
×
NEW
103
parameter operands: {string.Join(", ", method.ParameterOperands)}";
×
104

NEW
105
        foreach (var block in graph.Blocks)
×
106
        {
NEW
107
            if (block == graph.EntryBlock || block == graph.ExitBlock)
×
108
            {
NEW
109
                var isEntry = block == graph.EntryBlock;
×
NEW
110
                sb.AppendLine($"""
×
NEW
111
                                       {block.ID} [
×
NEW
112
                                               "color"="{(isEntry ? "green" : "red")}"
×
NEW
113
                                               "label"="{(isEntry ? $"Entry ({block.ID})\n{methodText}" : $"Exit ({block.ID})")}"
×
NEW
114
                                       ]
×
NEW
115
                               """);
×
116
            }
117
            else
118
            {
NEW
119
                sb.AppendLine($"""
×
NEW
120
                                       {block.ID} [
×
NEW
121
                                               "shape"="box"
×
NEW
122
                                               "label"="{block.ToString().EscapeString().Replace("\\r", "")}"
×
NEW
123
                                       ]
×
NEW
124
                               """);
×
125
            }
126

NEW
127
            edges.AddRange(block.Successors.Select(b => (block.ID, b.ID)));
×
128
        }
129

NEW
130
        foreach (var edge in edges)
×
NEW
131
            sb.AppendLine($"    {edge.Item1} -> {edge.Item2}");
×
132

NEW
133
        sb.AppendLine("}");
×
134

NEW
135
        var type = method.DeclaringType!;
×
NEW
136
        var assemblyName = MiscUtils.CleanPathElement(type.DeclaringAssembly.CleanAssemblyName);
×
NEW
137
        var typePath = Path.Combine(type.FullName.Split('.').Select(MiscUtils.CleanPathElement).ToArray());
×
NEW
138
        var directoryPath = Path.Combine(outputPath, assemblyName, typePath);
×
139

NEW
140
        var methodName = MiscUtils.CleanPathElement(method.Name + "_" + string.Join("_",
×
NEW
141
            method.Parameters.Select(p => MiscUtils.CleanPathElement(p.ParameterType.Name))));
×
NEW
142
        var path = Path.Combine(directoryPath, methodName) + ".dot";
×
143

NEW
144
        if (path.Length > 260)
×
145
        {
NEW
146
            path = path[..250];
×
NEW
147
            path += ".dot";
×
148
        }
149

NEW
150
        var directory = Path.GetDirectoryName(path)!;
×
NEW
151
        if (!Directory.Exists(directory))
×
NEW
152
            Directory.CreateDirectory(directory);
×
153

NEW
154
        File.WriteAllText(path, sb.ToString());
×
UNCOV
155
    }
×
156
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc