├── .gitignore ├── Dekompiler.Core ├── Declaration │ ├── AddDeclaration.cs │ ├── EventDeclaration.cs │ ├── FieldDeclaration.cs │ ├── GetDeclaration.cs │ ├── IMemberDeclaration.cs │ ├── MethodDeclaration.cs │ ├── PropertyDeclaration.cs │ ├── RemoveDeclaration.cs │ ├── SetDeclaration.cs │ └── TypeDeclaration.cs ├── Dekompiler.Core.csproj ├── Extensions.cs ├── Icons.cs ├── Interface │ ├── CodeThemeColor.cs │ ├── CodeThemeConfiguration.cs │ └── ThemeConfiguration.cs ├── RendererConstants.cs ├── RendererManager.cs ├── Results │ ├── EventDecompilationResult.cs │ ├── FieldDecompilationResult.cs │ ├── IDecompilationResult.cs │ ├── MethodDecompilationResult.cs │ ├── PropertyDecompilationResult.cs │ └── TypeDecompilationResult.cs ├── Statements │ ├── Arguments │ │ ├── LdArgStatement.cs │ │ └── StArgStatement.cs │ ├── Arrays │ │ ├── LdElemStatement.cs │ │ ├── LdLenStatement.cs │ │ ├── NewArrStatement.cs │ │ └── StElemStatement.cs │ ├── CompleteStatement.cs │ ├── Constants │ │ ├── LdNullStatement.cs │ │ ├── LdStrStatement.cs │ │ ├── LdcI4Statement.cs │ │ ├── LdcI8Statement.cs │ │ ├── LdcR4Statement.cs │ │ └── LdcR8Statement.cs │ ├── Conversions │ │ └── ConvStatement.cs │ ├── IStatement.cs │ ├── MethodContext.cs │ ├── Miscellaneous │ │ ├── CommentStatement.cs │ │ ├── DupStatement.cs │ │ ├── KeywordStatement.cs │ │ ├── MkRefAnyStatement.cs │ │ ├── NopStatement.cs │ │ ├── PopStatement.cs │ │ ├── RetStatement.cs │ │ └── ThrowStatement.cs │ ├── Operators │ │ ├── AddStatement.cs │ │ ├── AndStatement.cs │ │ ├── BinaryOperatorStatement.cs │ │ ├── CeqStatement.cs │ │ ├── CgtStatement.cs │ │ ├── CltStatement.cs │ │ ├── DivStatement.cs │ │ ├── MulStatement.cs │ │ ├── NegStatement.cs │ │ ├── NotStatement.cs │ │ ├── OrStatement.cs │ │ ├── RemStatement.cs │ │ ├── ShlStatement.cs │ │ ├── ShrStatement.cs │ │ ├── SubStatement.cs │ │ ├── UnaryOperatorStatement.cs │ │ └── XorStatement.cs │ ├── Pointers │ │ ├── LdIndStatement.cs │ │ ├── LocAllocStatement.cs │ │ └── StIndStatement.cs │ ├── Prefixes │ │ └── PrefixStatement.cs │ ├── PushableStatement.cs │ ├── Statement.cs │ ├── TypeSystem │ │ ├── CallStatement.cs │ │ ├── CalliStatement.cs │ │ ├── CastStatement.cs │ │ ├── LdFldStatement.cs │ │ ├── LdFtnStatement.cs │ │ ├── LdTokenStatement.cs │ │ ├── NewObjStatement.cs │ │ ├── SizeOfStatement.cs │ │ └── StFldStatement.cs │ └── Variables │ │ ├── LdLocStatement.cs │ │ └── StLocStatement.cs └── TypeSystem │ ├── EventRenderer.cs │ ├── FieldRenderer.cs │ ├── MethodRenderer.cs │ ├── PropertyRenderer.cs │ ├── TypeRenderer.cs │ └── TypeSignatureRenderer.cs ├── Dekompiler.Desktop ├── App.xaml ├── App.xaml.cs ├── AssemblyInfo.cs ├── Dekompiler.Desktop.csproj ├── Main.razor ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── _Imports.razor ├── brand.ico └── wwwroot │ └── index.html ├── Dekompiler.sln ├── Dekompiler ├── App.razor ├── Components │ ├── CodeViewer │ │ ├── CodeView.razor │ │ └── CodeView.razor.cs │ ├── Icon.razor │ ├── NavigationMenu.razor │ └── TreeView │ │ ├── TreeView.razor │ │ ├── TreeViewNode.razor │ │ └── TreeViewNodeModel.cs ├── Dekompiler.csproj ├── MainLayout.razor ├── Pages │ ├── Index.razor │ ├── Index.razor.cs │ └── _Host.cshtml ├── Program.cs ├── Properties │ └── launchSettings.json ├── _Imports.razor ├── appsettings.Development.json ├── appsettings.json └── wwwroot │ └── site.css ├── LICENSE ├── README.md └── showcase ├── corlib_ginterface.png ├── dekompiler_core_ldnull.png ├── dekompiler_core_newarr.png ├── koi_config.png ├── koi_rt_cmpdwrd.png ├── koi_rt_vmctx.png ├── koi_vminstance.png ├── pointers.png ├── unsupported.png └── x86_decoded_expressions.png /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | .idea 13 | 14 | # User-specific files (MonoDevelop/Xamarin Studio) 15 | *.userprefs 16 | 17 | # Mono auto generated files 18 | mono_crash.* 19 | 20 | # Build results 21 | [Dd]ebug/ 22 | [Dd]ebugPublic/ 23 | [Rr]elease/ 24 | [Rr]eleases/ 25 | x64/ 26 | x86/ 27 | [Ww][Ii][Nn]32/ 28 | [Aa][Rr][Mm]/ 29 | [Aa][Rr][Mm]64/ 30 | bld/ 31 | [Bb]in/ 32 | [Oo]bj/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # Tye 67 | .tye/ 68 | 69 | # ASP.NET Scaffolding 70 | ScaffoldingReadMe.txt 71 | 72 | # StyleCop 73 | StyleCopReport.xml 74 | 75 | # Files built by Visual Studio 76 | *_i.c 77 | *_p.c 78 | *_h.h 79 | *.ilk 80 | *.meta 81 | *.obj 82 | *.iobj 83 | *.pch 84 | *.pdb 85 | *.ipdb 86 | *.pgc 87 | *.pgd 88 | *.rsp 89 | *.sbr 90 | *.tlb 91 | *.tli 92 | *.tlh 93 | *.tmp 94 | *.tmp_proj 95 | *_wpftmp.csproj 96 | *.log 97 | *.tlog 98 | *.vspscc 99 | *.vssscc 100 | .builds 101 | *.pidb 102 | *.svclog 103 | *.scc 104 | 105 | # Chutzpah Test files 106 | _Chutzpah* 107 | 108 | # Visual C++ cache files 109 | ipch/ 110 | *.aps 111 | *.ncb 112 | *.opendb 113 | *.opensdf 114 | *.sdf 115 | *.cachefile 116 | *.VC.db 117 | *.VC.VC.opendb 118 | 119 | # Visual Studio profiler 120 | *.psess 121 | *.vsp 122 | *.vspx 123 | *.sap 124 | 125 | # Visual Studio Trace Files 126 | *.e2e 127 | 128 | # TFS 2012 Local Workspace 129 | $tf/ 130 | 131 | # Guidance Automation Toolkit 132 | *.gpState 133 | 134 | # ReSharper is a .NET coding add-in 135 | _ReSharper*/ 136 | *.[Rr]e[Ss]harper 137 | *.DotSettings.user 138 | 139 | # TeamCity is a build add-in 140 | _TeamCity* 141 | 142 | # DotCover is a Code Coverage Tool 143 | *.dotCover 144 | 145 | # AxoCover is a Code Coverage Tool 146 | .axoCover/* 147 | !.axoCover/settings.json 148 | 149 | # Coverlet is a free, cross platform Code Coverage Tool 150 | coverage*.json 151 | coverage*.xml 152 | coverage*.info 153 | 154 | # Visual Studio code coverage results 155 | *.coverage 156 | *.coveragexml 157 | 158 | # NCrunch 159 | _NCrunch_* 160 | .*crunch*.local.xml 161 | nCrunchTemp_* 162 | 163 | # MightyMoose 164 | *.mm.* 165 | AutoTest.Net/ 166 | 167 | # Web workbench (sass) 168 | .sass-cache/ 169 | 170 | # Installshield output folder 171 | [Ee]xpress/ 172 | 173 | # DocProject is a documentation generator add-in 174 | DocProject/buildhelp/ 175 | DocProject/Help/*.HxT 176 | DocProject/Help/*.HxC 177 | DocProject/Help/*.hhc 178 | DocProject/Help/*.hhk 179 | DocProject/Help/*.hhp 180 | DocProject/Help/Html2 181 | DocProject/Help/html 182 | 183 | # Click-Once directory 184 | publish/ 185 | 186 | # Publish Web Output 187 | *.[Pp]ublish.xml 188 | *.azurePubxml 189 | # Note: Comment the next line if you want to checkin your web deploy settings, 190 | # but database connection strings (with potential passwords) will be unencrypted 191 | *.pubxml 192 | *.publishproj 193 | 194 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 195 | # checkin your Azure Web App publish settings, but sensitive information contained 196 | # in these scripts will be unencrypted 197 | PublishScripts/ 198 | 199 | # NuGet Packages 200 | *.nupkg 201 | # NuGet Symbol Packages 202 | *.snupkg 203 | # The packages folder can be ignored because of Package Restore 204 | **/[Pp]ackages/* 205 | # except build/, which is used as an MSBuild target. 206 | !**/[Pp]ackages/build/ 207 | # Uncomment if necessary however generally it will be regenerated when needed 208 | #!**/[Pp]ackages/repositories.config 209 | # NuGet v3's project.json files produces more ignorable files 210 | *.nuget.props 211 | *.nuget.targets 212 | 213 | # Microsoft Azure Build Output 214 | csx/ 215 | *.build.csdef 216 | 217 | # Microsoft Azure Emulator 218 | ecf/ 219 | rcf/ 220 | 221 | # Windows Store app package directories and files 222 | AppPackages/ 223 | BundleArtifacts/ 224 | Package.StoreAssociation.xml 225 | _pkginfo.txt 226 | *.appx 227 | *.appxbundle 228 | *.appxupload 229 | 230 | # Visual Studio cache files 231 | # files ending in .cache can be ignored 232 | *.[Cc]ache 233 | # but keep track of directories ending in .cache 234 | !?*.[Cc]ache/ 235 | 236 | # Others 237 | ClientBin/ 238 | ~$* 239 | *~ 240 | *.dbmdl 241 | *.dbproj.schemaview 242 | *.jfm 243 | *.pfx 244 | *.publishsettings 245 | orleans.codegen.cs 246 | 247 | # Including strong name files can present a security risk 248 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 249 | #*.snk 250 | 251 | # Since there are multiple workflows, uncomment next line to ignore bower_components 252 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 253 | #bower_components/ 254 | 255 | # RIA/Silverlight projects 256 | Generated_Code/ 257 | 258 | # Backup & report files from converting an old project file 259 | # to a newer Visual Studio version. Backup files are not needed, 260 | # because we have git ;-) 261 | _UpgradeReport_Files/ 262 | Backup*/ 263 | UpgradeLog*.XML 264 | UpgradeLog*.htm 265 | ServiceFabricBackup/ 266 | *.rptproj.bak 267 | 268 | # SQL Server files 269 | *.mdf 270 | *.ldf 271 | *.ndf 272 | 273 | # Business Intelligence projects 274 | *.rdl.data 275 | *.bim.layout 276 | *.bim_*.settings 277 | *.rptproj.rsuser 278 | *- [Bb]ackup.rdl 279 | *- [Bb]ackup ([0-9]).rdl 280 | *- [Bb]ackup ([0-9][0-9]).rdl 281 | 282 | # Microsoft Fakes 283 | FakesAssemblies/ 284 | 285 | # GhostDoc plugin setting file 286 | *.GhostDoc.xml 287 | 288 | # Node.js Tools for Visual Studio 289 | .ntvs_analysis.dat 290 | node_modules/ 291 | 292 | # Visual Studio 6 build log 293 | *.plg 294 | 295 | # Visual Studio 6 workspace options file 296 | *.opt 297 | 298 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 299 | *.vbw 300 | 301 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 302 | *.vbp 303 | 304 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 305 | *.dsw 306 | *.dsp 307 | 308 | # Visual Studio 6 technical files 309 | *.ncb 310 | *.aps 311 | 312 | # Visual Studio LightSwitch build output 313 | **/*.HTMLClient/GeneratedArtifacts 314 | **/*.DesktopClient/GeneratedArtifacts 315 | **/*.DesktopClient/ModelManifest.xml 316 | **/*.Server/GeneratedArtifacts 317 | **/*.Server/ModelManifest.xml 318 | _Pvt_Extensions 319 | 320 | # Paket dependency manager 321 | .paket/paket.exe 322 | paket-files/ 323 | 324 | # FAKE - F# Make 325 | .fake/ 326 | 327 | # CodeRush personal settings 328 | .cr/personal 329 | 330 | # Python Tools for Visual Studio (PTVS) 331 | __pycache__/ 332 | *.pyc 333 | 334 | # Cake - Uncomment if you are using it 335 | # tools/** 336 | # !tools/packages.config 337 | 338 | # Tabs Studio 339 | *.tss 340 | 341 | # Telerik's JustMock configuration file 342 | *.jmconfig 343 | 344 | # BizTalk build output 345 | *.btp.cs 346 | *.btm.cs 347 | *.odx.cs 348 | *.xsd.cs 349 | 350 | # OpenCover UI analysis results 351 | OpenCover/ 352 | 353 | # Azure Stream Analytics local run output 354 | ASALocalRun/ 355 | 356 | # MSBuild Binary and Structured Log 357 | *.binlog 358 | 359 | # NVidia Nsight GPU debugger configuration file 360 | *.nvuser 361 | 362 | # MFractors (Xamarin productivity tool) working folder 363 | .mfractor/ 364 | 365 | # Local History for Visual Studio 366 | .localhistory/ 367 | 368 | # Visual Studio History (VSHistory) files 369 | .vshistory/ 370 | 371 | # BeatPulse healthcheck temp database 372 | healthchecksdb 373 | 374 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 375 | MigrationBackup/ 376 | 377 | # Ionide (cross platform F# VS Code tools) working folder 378 | .ionide/ 379 | 380 | # Fody - auto-generated XML schema 381 | FodyWeavers.xsd 382 | 383 | # VS Code files for those working on multiple tools 384 | .vscode/* 385 | !.vscode/settings.json 386 | !.vscode/tasks.json 387 | !.vscode/launch.json 388 | !.vscode/extensions.json 389 | *.code-workspace 390 | 391 | # Local History for Visual Studio Code 392 | .history/ 393 | 394 | # Windows Installer files from build outputs 395 | *.cab 396 | *.msi 397 | *.msix 398 | *.msm 399 | *.msp 400 | 401 | # JetBrains Rider 402 | *.sln.iml 403 | 404 | ## 405 | ## Visual studio for Mac 406 | ## 407 | 408 | 409 | # globs 410 | Makefile.in 411 | *.userprefs 412 | *.usertasks 413 | config.make 414 | config.status 415 | aclocal.m4 416 | install-sh 417 | autom4te.cache/ 418 | *.tar.gz 419 | tarballs/ 420 | test-results/ 421 | 422 | # Mac bundle stuff 423 | *.dmg 424 | *.app 425 | 426 | # content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore 427 | # General 428 | .DS_Store 429 | .AppleDouble 430 | .LSOverride 431 | 432 | # Icon must end with two \r 433 | Icon 434 | 435 | 436 | # Thumbnails 437 | ._* 438 | 439 | # Files that might appear in the root of a volume 440 | .DocumentRevisions-V100 441 | .fseventsd 442 | .Spotlight-V100 443 | .TemporaryItems 444 | .Trashes 445 | .VolumeIcon.icns 446 | .com.apple.timemachine.donotpresent 447 | 448 | # Directories potentially created on remote AFP share 449 | .AppleDB 450 | .AppleDesktop 451 | Network Trash Folder 452 | Temporary Items 453 | .apdisk 454 | 455 | # content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore 456 | # Windows thumbnail cache files 457 | Thumbs.db 458 | ehthumbs.db 459 | ehthumbs_vista.db 460 | 461 | # Dump file 462 | *.stackdump 463 | 464 | # Folder config file 465 | [Dd]esktop.ini 466 | 467 | # Recycle Bin used on file shares 468 | $RECYCLE.BIN/ 469 | 470 | # Windows Installer files 471 | *.cab 472 | *.msi 473 | *.msix 474 | *.msm 475 | *.msp 476 | 477 | # Windows shortcuts 478 | *.lnk 479 | -------------------------------------------------------------------------------- /Dekompiler.Core/Declaration/AddDeclaration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Dekompiler.Core.Declaration; 4 | 5 | public class AddDeclaration : IMemberDeclaration 6 | { 7 | private RendererService _service; 8 | 9 | public AddDeclaration(RendererService service) 10 | { 11 | _service = service; 12 | } 13 | 14 | public RenderFragment BuildDeclaration() 15 | { 16 | return _service.Keyword("add"); 17 | } 18 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Declaration/EventDeclaration.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using AsmResolver.DotNet; 3 | using Dekompiler.Core.TypeSystem; 4 | using Microsoft.AspNetCore.Components; 5 | 6 | namespace Dekompiler.Core.Declaration; 7 | 8 | public class EventDeclaration : IMemberDeclaration 9 | { 10 | private RendererService _renderer; 11 | private EventDefinition _event; 12 | 13 | public EventDeclaration(RendererService renderer, EventDefinition @event) 14 | { 15 | _event = @event; 16 | _renderer = renderer; 17 | } 18 | 19 | public RenderFragment BuildDeclaration() 20 | { 21 | return _renderer.Join(_renderer.Constants.Space, RenderAccessibility(), _renderer.Keyword("event"), 22 | RenderKind(), RenderProperty()); 23 | } 24 | 25 | private RenderFragment RenderAccessibility() 26 | { 27 | var accessibility = () => 28 | { 29 | return (_event.AddMethod ?? _event.FireMethod ?? _event.RemoveMethod) switch 30 | { 31 | { IsPublic: true } => "public", 32 | { IsFamily: true } => "protected", 33 | { IsFamilyOrAssembly: true } => "internal", 34 | { IsFamilyAndAssembly: true } => "internal protected", 35 | { IsPrivate: true } => "private", 36 | _ => string.Empty, 37 | }; 38 | }; 39 | 40 | var modifier = () => 41 | { 42 | var sb = new StringBuilder(); 43 | 44 | if ((_event.AddMethod ?? _event.FireMethod ?? _event.RemoveMethod) is { IsStatic: true }) 45 | sb.Append("static "); 46 | 47 | return sb.ToString().TrimEnd(' '); 48 | }; 49 | 50 | var accessFragment = accessibility() is { Length: not 0 } s ? _renderer.Keyword(s) : null; 51 | var modifierFragment = modifier() is { Length: not 0 } s2 ? _renderer.Keyword(s2) : null; 52 | 53 | return _renderer.Join(_renderer.Constants.Space, accessFragment, modifierFragment); 54 | } 55 | 56 | private RenderFragment RenderKind() 57 | { 58 | return new TypeSignatureRenderer(_renderer, _event.EventType!.ToTypeSignature(), _event, _event.DeclaringType) 59 | .RenderMember(); 60 | } 61 | 62 | private RenderFragment RenderProperty() 63 | { 64 | return new EventRenderer(_renderer, _event).RenderMember(); 65 | } 66 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Declaration/FieldDeclaration.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using AsmResolver.DotNet; 3 | using AsmResolver.PE.DotNet.Metadata.Tables.Rows; 4 | using Dekompiler.Core.Statements.Miscellaneous; 5 | using Dekompiler.Core.TypeSystem; 6 | using Microsoft.AspNetCore.Components; 7 | 8 | namespace Dekompiler.Core.Declaration; 9 | 10 | public class FieldDeclaration : IMemberDeclaration 11 | { 12 | private RendererService _renderer; 13 | private FieldDefinition _field; 14 | 15 | public FieldDeclaration(RendererService renderer, FieldDefinition field) 16 | { 17 | _field = field; 18 | _renderer = renderer; 19 | } 20 | 21 | public RenderFragment BuildDeclaration() 22 | { 23 | if (_field is { DeclaringType: { BaseType: { FullName: "System.Enum" } } }) 24 | { 25 | return _renderer.Concat(RenderField(), _renderer.Constants.Comma); 26 | } 27 | 28 | return _renderer.Join(_renderer.Constants.Space, RenderAccessibility(), RenderKind(), RenderField()); 29 | } 30 | 31 | private RenderFragment RenderAccessibility() 32 | { 33 | var accessibility = () => 34 | { 35 | return _field switch 36 | { 37 | { IsPublic: true } => "public", 38 | { IsFamily: true } => "protected", 39 | { IsFamilyOrAssembly: true } => "internal", 40 | { IsFamilyAndAssembly: true } => "internal protected", 41 | { IsPrivate: true, IsPrivateScope: true } => $"private protected", 42 | { IsPrivate: true } => "private", 43 | _ => string.Empty, 44 | }; 45 | }; 46 | 47 | var modifier = () => 48 | { 49 | var sb = new StringBuilder(); 50 | 51 | if (_field.IsStatic) sb.Append("static "); 52 | 53 | if (_field.IsInitOnly) sb.Append("readonly "); 54 | 55 | if (_field.Constant is { }) sb.Append("const "); 56 | 57 | return sb.ToString().TrimEnd(' '); 58 | }; 59 | 60 | var accessFragment = accessibility() is { Length: not 0 } s ? _renderer.Keyword(s) : null; 61 | var modifierFragment = modifier() is { Length: not 0 } s2 ? _renderer.Keyword(s2) : null; 62 | 63 | return _renderer.Join(_renderer.Constants.Space, accessFragment, modifierFragment); 64 | } 65 | 66 | 67 | private RenderFragment RenderKind() 68 | { 69 | return new TypeSignatureRenderer(_renderer, _field.Signature!.FieldType, _field, _field.DeclaringType) 70 | .RenderMember(); 71 | } 72 | 73 | private RenderFragment RenderField() 74 | { 75 | RenderFragment? constValue = null; 76 | 77 | if (_field.Constant is { Value: not null } constant) 78 | { 79 | var buffer = constant.Value.Data; 80 | constValue = constant.Type switch 81 | { 82 | ElementType.Boolean => _renderer.Keyword(BitConverter.ToBoolean(buffer, 0).ToString().ToLower()), 83 | ElementType.Char => _renderer.Span($"'{BitConverter.ToChar(buffer, 0)}'", "string"), 84 | 85 | ElementType.I1 => _renderer.Span(buffer[0].ToString(), "number"), 86 | ElementType.I2 => _renderer.Span(BitConverter.ToInt16(buffer, 0).ToString(), "number"), 87 | ElementType.I4 => _renderer.Span(BitConverter.ToInt32(buffer, 0).ToString(), "number"), 88 | ElementType.I8 => _renderer.Span(BitConverter.ToInt64(buffer, 0).ToString(), "number"), 89 | 90 | ElementType.U1 => _renderer.Span($"{buffer[0].ToString()}U", "number"), 91 | ElementType.U2 => _renderer.Span($"{BitConverter.ToUInt16(buffer, 0).ToString()}U", "number"), 92 | ElementType.U4 => _renderer.Span($"{BitConverter.ToUInt32(buffer, 0).ToString()}U", "number"), 93 | ElementType.U8 => _renderer.Span($"{BitConverter.ToUInt64(buffer, 0).ToString()}UL", "number"), 94 | 95 | ElementType.R4 => _renderer.Span($"{BitConverter.ToSingle(buffer, 0):F}", "number"), 96 | ElementType.R8 => _renderer.Span($"{BitConverter.ToDouble(buffer, 0):G}", "number"), 97 | 98 | ElementType.String => _renderer.Span($"\"{Encoding.UTF8.GetString(buffer)}\"", "string"), 99 | _ => null 100 | }; 101 | 102 | constValue = _renderer.Concat(_renderer.Constants.Space, _renderer.Constants.Equal, 103 | _renderer.Constants.Space, constValue); 104 | } 105 | 106 | return _renderer.Concat(new FieldRenderer(_renderer, _field).RenderMember(), constValue); 107 | } 108 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Declaration/GetDeclaration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Dekompiler.Core.Declaration; 4 | 5 | public class GetDeclaration : IMemberDeclaration 6 | { 7 | private RendererService _service; 8 | 9 | public GetDeclaration(RendererService service) 10 | { 11 | _service = service; 12 | } 13 | 14 | public RenderFragment BuildDeclaration() 15 | { 16 | return _service.Keyword("get"); 17 | } 18 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Declaration/IMemberDeclaration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Dekompiler.Core.Declaration; 4 | 5 | public interface IMemberDeclaration 6 | { 7 | RenderFragment BuildDeclaration(); 8 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Declaration/MethodDeclaration.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using AsmResolver.DotNet; 3 | using AsmResolver.DotNet.Signatures.Types; 4 | using Dekompiler.Core.TypeSystem; 5 | using Microsoft.AspNetCore.Components; 6 | using Microsoft.AspNetCore.Components.RenderTree; 7 | 8 | namespace Dekompiler.Core.Declaration; 9 | 10 | public class MethodDeclaration : IMemberDeclaration 11 | { 12 | 13 | private RendererService _renderer; 14 | private MethodDefinition _method; 15 | 16 | public MethodDeclaration(RendererService renderer, MethodDefinition method) 17 | { 18 | _renderer = renderer; 19 | _method = method; 20 | } 21 | 22 | public RenderFragment BuildDeclaration() 23 | { 24 | return _renderer.Join(_renderer.Constants.Space, RenderAccessibility(), _method.IsConstructor ? null : RenderType(), RenderMethod()); 25 | } 26 | 27 | private RenderFragment RenderAccessibility() 28 | { 29 | var accessibility = () => 30 | { 31 | return _method switch 32 | { 33 | { IsPublic: true } => "public", 34 | { IsFamily: true } => "protected", 35 | { IsFamilyOrAssembly: true } => "internal", 36 | { IsFamilyAndAssembly: true } => "internal protected", 37 | { IsPrivate: true } => "private", 38 | _ => string.Empty, 39 | }; 40 | }; 41 | 42 | var modifier = () => 43 | { 44 | var sb = new StringBuilder(); 45 | 46 | if (_method is { IsStatic: true }) sb.Append("static "); 47 | 48 | return sb.ToString().TrimEnd(' '); 49 | }; 50 | 51 | var accessFragment = accessibility() is { Length: not 0 } s ? _renderer.Keyword(s) : null; 52 | var modifierFragment = modifier() is { Length: not 0 } s2 ? _renderer.Keyword(s2) : null; 53 | 54 | return _renderer.Join(_renderer.Constants.Space, accessFragment, modifierFragment); 55 | } 56 | 57 | private RenderFragment RenderType() 58 | { 59 | return new TypeSignatureRenderer(_renderer, _method.Signature!.ReturnType, _method, _method.DeclaringType).RenderMember(); 60 | } 61 | 62 | private RenderFragment RenderMethod() 63 | { 64 | var methodSpan = new MethodRenderer(_renderer, _method).RenderMember(); 65 | 66 | if (_method.IsConstructor) 67 | { 68 | methodSpan = RenderType(_method.DeclaringType!); 69 | } 70 | 71 | var parameterSpan = _renderer.Concat(_renderer.Constants.RightBracket, _renderer.Constants.LeftBracket); 72 | 73 | if (_method.Parameters.Count > 0) 74 | { 75 | parameterSpan = RenderMethodParameters(_method); 76 | } 77 | 78 | if (_method.GenericParameters.Count > 0) 79 | { 80 | var separator = _renderer.Concat(_renderer.Constants.Comma, _renderer.Constants.Space); 81 | 82 | var genericArgs = _renderer.Join(separator, 83 | _method.GenericParameters.Select(arg => _renderer.Span(arg.Name, "genericparameter")).ToArray()); 84 | 85 | parameterSpan = _renderer.Concat(_renderer.Concat(_renderer.Constants.RightThan, genericArgs, 86 | _renderer.Constants.LeftThan), parameterSpan); 87 | } 88 | 89 | return _renderer.Concat(methodSpan, parameterSpan); 90 | } 91 | 92 | private RenderFragment RenderMethodParameters(MethodDefinition method) 93 | { 94 | var separator = _renderer.Concat(_renderer.Constants.Comma, _renderer.Constants.Space); 95 | 96 | var renderedParameters = new List(); 97 | 98 | foreach (var parameter in method.Parameters) 99 | { 100 | if (parameter.MethodSignatureIndex is -1) continue; 101 | 102 | var getUnderlyingSignature = parameter.Definition is { IsOut: true } || parameter.Definition is { IsIn: true }; 103 | var isRef = parameter.ParameterType is ByReferenceTypeSignature && !getUnderlyingSignature; 104 | 105 | 106 | var parameterSpan = 107 | new TypeSignatureRenderer(_renderer, 108 | (getUnderlyingSignature || isRef) && parameter.ParameterType is TypeSpecificationSignature spec 109 | ? spec.BaseType 110 | : parameter.ParameterType, method, method.DeclaringType!) 111 | .RenderMember(); 112 | 113 | parameterSpan = _renderer.Join(_renderer.Constants.Space, parameterSpan, _renderer.Span(parameter.Name, "parameter")); 114 | 115 | if (isRef) 116 | parameterSpan = _renderer.Join(_renderer.Constants.Space, _renderer.Keyword("ref"), parameterSpan); 117 | 118 | if (parameter.Definition is { IsOut: true }) 119 | parameterSpan = _renderer.Join(_renderer.Constants.Space, _renderer.Keyword("out"), parameterSpan); 120 | 121 | if (parameter.Definition is { IsIn: true }) 122 | parameterSpan = _renderer.Join(_renderer.Constants.Space, _renderer.Keyword("in"), parameterSpan); 123 | 124 | renderedParameters.Add(parameterSpan); 125 | } 126 | 127 | var argTypes = _renderer.Join(separator, renderedParameters.ToArray()); 128 | 129 | return _renderer.Concat(_renderer.Constants.RightBracket, argTypes, _renderer.Constants.LeftBracket); 130 | } 131 | 132 | private RenderFragment RenderType(TypeDefinition type) 133 | { 134 | var typeSpan = new TypeRenderer(_renderer, type).RenderMember(); 135 | 136 | if (type.GenericParameters.Count > 0) 137 | { 138 | var separator = _renderer.Concat(_renderer.Constants.Comma, _renderer.Constants.Space); 139 | 140 | var genericArgs = _renderer.Join(separator, 141 | type.GenericParameters.Select(arg => _renderer.Span(arg.Name, "genericparameter")).ToArray()); 142 | 143 | return _renderer.Concat(typeSpan, _renderer.Constants.RightThan, genericArgs, 144 | _renderer.Constants.LeftThan); 145 | } 146 | 147 | return typeSpan; 148 | } 149 | } 150 | 151 | -------------------------------------------------------------------------------- /Dekompiler.Core/Declaration/PropertyDeclaration.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using AsmResolver.DotNet; 3 | using AsmResolver.DotNet.Signatures.Types; 4 | using Dekompiler.Core.TypeSystem; 5 | using Microsoft.AspNetCore.Components; 6 | 7 | namespace Dekompiler.Core.Declaration; 8 | 9 | public class PropertyDeclaration : IMemberDeclaration 10 | { 11 | private RendererService _renderer; 12 | private PropertyDefinition _property; 13 | 14 | public PropertyDeclaration(RendererService renderer, PropertyDefinition property) 15 | { 16 | _property = property; 17 | _renderer = renderer; 18 | } 19 | 20 | public RenderFragment BuildDeclaration() 21 | { 22 | return _renderer.Join(_renderer.Constants.Space, RenderAccessibility(), RenderKind(), RenderProperty()); 23 | } 24 | 25 | private RenderFragment RenderAccessibility() 26 | { 27 | var accessibility = () => 28 | { 29 | return (_property.SetMethod ?? _property.GetMethod) switch 30 | { 31 | { IsPublic: true } => "public", 32 | { IsFamily: true } => "protected", 33 | { IsFamilyOrAssembly: true } => "internal", 34 | { IsFamilyAndAssembly: true } => "internal protected", 35 | { IsPrivate: true } => "private", 36 | _ => string.Empty, 37 | }; 38 | }; 39 | 40 | var modifier = () => 41 | { 42 | var sb = new StringBuilder(); 43 | 44 | if ((_property.SetMethod ?? _property.GetMethod) is { IsStatic: true }) sb.Append("static "); 45 | 46 | return sb.ToString().TrimEnd(' '); 47 | }; 48 | 49 | var accessFragment = accessibility() is { Length: not 0 } s ? _renderer.Keyword(s) : null; 50 | var modifierFragment = modifier() is { Length: not 0 } s2 ? _renderer.Keyword(s2) : null; 51 | 52 | return _renderer.Join(_renderer.Constants.Space, accessFragment, modifierFragment); 53 | } 54 | 55 | private RenderFragment RenderKind() 56 | { 57 | return new TypeSignatureRenderer(_renderer, _property.Signature!.ReturnType, _property, _property.DeclaringType).RenderMember(); 58 | } 59 | 60 | private RenderFragment RenderProperty() 61 | { 62 | var propertySpan = new PropertyRenderer(_renderer, _property).RenderMember(); 63 | 64 | // indexer 65 | if (_property.Signature!.ParameterTypes.Count > 0) 66 | { 67 | propertySpan = _renderer.Keyword("this"); 68 | 69 | var method = _property.GetMethod!; 70 | var separator = _renderer.Concat(_renderer.Constants.Comma, _renderer.Constants.Space); 71 | 72 | var renderedParameters = new List(); 73 | 74 | foreach (var parameter in method.Parameters) 75 | { 76 | if (parameter.MethodSignatureIndex is -1) continue; 77 | 78 | var parameterSpan = 79 | new TypeSignatureRenderer(_renderer, parameter.ParameterType, method, method.DeclaringType!) 80 | .RenderMember(); 81 | 82 | parameterSpan = _renderer.Join(_renderer.Constants.Space, parameterSpan, _renderer.Span(parameter.Name, "parameter")); 83 | 84 | renderedParameters.Add(parameterSpan); 85 | } 86 | 87 | var argTypes = _renderer.Join(separator, renderedParameters.ToArray()); 88 | 89 | propertySpan = 90 | _renderer.Concat(propertySpan, _renderer.Constants.RightArrayBracket, argTypes, _renderer.Constants.LeftArrayBracket); 91 | } 92 | 93 | return propertySpan; 94 | } 95 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Declaration/RemoveDeclaration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Dekompiler.Core.Declaration; 4 | 5 | public class RemoveDeclaration : IMemberDeclaration 6 | { 7 | private RendererService _service; 8 | 9 | public RemoveDeclaration(RendererService service) 10 | { 11 | _service = service; 12 | } 13 | 14 | public RenderFragment BuildDeclaration() 15 | { 16 | return _service.Keyword("remove"); 17 | } 18 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Declaration/SetDeclaration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Dekompiler.Core.Declaration; 4 | 5 | public class SetDeclaration : IMemberDeclaration 6 | { 7 | private RendererService _service; 8 | 9 | public SetDeclaration(RendererService service) 10 | { 11 | _service = service; 12 | } 13 | 14 | public RenderFragment BuildDeclaration() 15 | { 16 | return _service.Keyword("set"); 17 | } 18 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Declaration/TypeDeclaration.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using AsmResolver.DotNet; 3 | using Dekompiler.Core.TypeSystem; 4 | using Microsoft.AspNetCore.Components; 5 | 6 | namespace Dekompiler.Core.Declaration; 7 | 8 | public class TypeDeclaration : IMemberDeclaration 9 | { 10 | private RendererService _renderer; 11 | private TypeDefinition _type; 12 | 13 | public TypeDeclaration(RendererService renderer, TypeDefinition type) 14 | { 15 | _type = type; 16 | _renderer = renderer; 17 | } 18 | 19 | public RenderFragment BuildDeclaration() 20 | { 21 | return _renderer.Join(_renderer.Constants.Space, RenderAccessibility(), RenderKind(), RenderType(), 22 | RenderInheritance()); 23 | } 24 | 25 | private RenderFragment RenderInheritance() 26 | { 27 | var temp = new List(); 28 | if (_type.BaseType is { FullName: not "System.Object", FullName: not "System.ValueType", FullName: not "System.Enum" }) 29 | { 30 | temp.Add(_type.BaseType); 31 | } 32 | 33 | temp.AddRange(_type.Interfaces.Select(i => i.Interface!)); 34 | 35 | var separator = _renderer.Concat(_renderer.Constants.Comma, _renderer.Constants.Space); 36 | 37 | var interfaces = _renderer.Join(separator, temp.Select(t => new TypeRenderer(_renderer, t).RenderMember()).ToArray()); 38 | 39 | if (temp.Count > 0) 40 | { 41 | return _renderer.Concat(_renderer.Constants.Column, _renderer.Constants.Space, interfaces); 42 | } 43 | 44 | return null!; 45 | } 46 | 47 | private RenderFragment RenderAccessibility() 48 | { 49 | var accessibility = () => 50 | { 51 | return _type switch 52 | { 53 | { IsPublic: true } => "public", 54 | { IsNestedFamily: true } => "protected", 55 | { IsNestedFamilyOrAssembly: true } => "internal", 56 | { IsNestedFamilyAndAssembly: true } => "internal protected", 57 | { IsNestedPrivate: true } => "private", 58 | _ => string.Empty, 59 | }; 60 | }; 61 | 62 | var modifier = () => 63 | { 64 | var sb = new StringBuilder(); 65 | 66 | if (_type is { IsSealed: true, IsAbstract: false, IsEnum: false, IsDelegate: false, IsValueType: false }) sb.Append("sealed "); 67 | 68 | if (_type is { IsSealed: true, IsAbstract: true }) sb.Append("static "); 69 | 70 | return sb.ToString().TrimEnd(' '); 71 | }; 72 | 73 | var accessFragment = accessibility() is { Length: not 0 } s ? _renderer.Keyword(s) : null; 74 | var modifierFragment = modifier() is { Length: not 0 } s2 ? _renderer.Keyword(s2) : null; 75 | 76 | return _renderer.Join(_renderer.Constants.Space, accessFragment, modifierFragment); 77 | } 78 | 79 | private RenderFragment RenderKind() 80 | { 81 | var typeKind = _type switch 82 | { 83 | { IsInterface: true } => "interface", 84 | { IsDelegate: true } => "delegate", 85 | { IsEnum: true } => "enum", 86 | { IsValueType: true } => "struct", 87 | _ => "class" 88 | }; 89 | 90 | return _renderer.Keyword(typeKind); 91 | } 92 | 93 | private RenderFragment RenderType() 94 | { 95 | var typeSpan = new TypeRenderer(_renderer, _type).RenderMember(); 96 | 97 | if (_type.GenericParameters.Count > 0) 98 | { 99 | var separator = _renderer.Concat(_renderer.Constants.Comma, _renderer.Constants.Space); 100 | 101 | var genericArgs = _renderer.Join(separator, 102 | _type.GenericParameters.Select(arg => _renderer.Span(arg.Name, "genericparameter")).ToArray()); 103 | 104 | return _renderer.Concat(typeSpan, _renderer.Constants.RightThan, genericArgs, 105 | _renderer.Constants.LeftThan); 106 | } 107 | 108 | return typeSpan; 109 | } 110 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Dekompiler.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Dekompiler.Core/Extensions.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver; 2 | using AsmResolver.DotNet; 3 | using AsmResolver.DotNet.Signatures.Types; 4 | using AsmResolver.PE.DotNet.Cil; 5 | using AsmResolver.PE.DotNet.Metadata.Tables.Rows; 6 | using Dekompiler.Core.Statements; 7 | using Dekompiler.Core.Statements.Constants; 8 | using Dekompiler.Core.Statements.Miscellaneous; 9 | using Dekompiler.Core.Statements.TypeSystem; 10 | 11 | namespace Dekompiler.Core; 12 | 13 | public static class Extensions 14 | { 15 | public static IStatement TryCast(this IStatement statement, TypeSignature signature) 16 | { 17 | return signature switch 18 | { 19 | { FullName: "System.Boolean" } _ when statement is LdcI4Statement value => 20 | new KeywordStatement(value.GetContext(), value.Value > 0 ? "true" : "false", signature), 21 | TypeDefOrRefSignature { } typeDefOrRef when statement is LdcI4Statement value => 22 | ConstantField(typeDefOrRef, value), 23 | _ => statement 24 | }; 25 | 26 | IStatement ConstantField(TypeDefOrRefSignature typeDefOrRef, LdcI4Statement value) 27 | { 28 | if (typeDefOrRef.Type.Resolve() is { IsEnum: true } enumType) 29 | { 30 | // var constant = BitConverter.GetBytes(value.Value); 31 | 32 | var fld = enumType.Fields.FirstOrDefault(enumItem => 33 | enumItem.Constant is { Value: not null } content && 34 | GetInt(content) == value.Value); 35 | 36 | if (fld is { } enumField) 37 | { 38 | var fldStatement = new LdFldStatement(value.GetContext()); 39 | 40 | fldStatement.Deserialize(new CilInstruction(CilOpCodes.Ldsfld, enumField)); 41 | 42 | return fldStatement; 43 | } 44 | else 45 | { 46 | return statement; 47 | } 48 | } 49 | else 50 | { 51 | return statement; 52 | } 53 | } 54 | } 55 | 56 | private static int GetInt(Constant constant) 57 | { 58 | var valueData = constant.Value!.Data; 59 | return constant.Type switch 60 | { 61 | ElementType.I1 or ElementType.U1 => valueData[0], 62 | ElementType.I2 => BitConverter.ToInt16(valueData), 63 | ElementType.U2 => BitConverter.ToUInt16(valueData), 64 | ElementType.I4 => BitConverter.ToInt32(valueData), 65 | ElementType.U4 => (int)BitConverter.ToUInt32(valueData), 66 | ElementType.I8 => (int)BitConverter.ToInt64(valueData), 67 | ElementType.U8 => (int)BitConverter.ToUInt64(valueData), 68 | ElementType.R4 => (int)BitConverter.ToSingle(valueData), 69 | ElementType.R8 => (int)BitConverter.ToDouble(valueData), 70 | _ => throw new ArgumentOutOfRangeException() 71 | }; 72 | } 73 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Icons.cs: -------------------------------------------------------------------------------- 1 | using Dekompiler.Core.Statements; 2 | 3 | namespace Dekompiler.Core; 4 | 5 | public static class Icons 6 | { 7 | public static IconInfo CaretRight = new("0 0 320 512", new ISvgChild[] 8 | { 9 | new PathInfo("M112 96L256 256 112 416l-48 0L64 96l48 0z") 10 | }); 11 | 12 | public static IconInfo CaretDown = new("0 0 320 512", new ISvgChild[] 13 | { 14 | new PathInfo("M320 240L160 384 0 240l0-48 320 0 0 48z") 15 | }); 16 | 17 | public static IconInfo XMark = new("0 0 320 512", new ISvgChild[] 18 | { 19 | new PathInfo( 20 | "M313 137c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0l-119 119L41 103c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l119 119L7 375c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l119-119L279 409c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-119-119L313 137z") 21 | }); 22 | 23 | public static IconInfo VerticalGrip = new("0 0 192 512", new ISvgChild[] 24 | { 25 | new PathInfo( 26 | "M32 128a32 32 0 1 0 0-64 32 32 0 1 0 0 64zm0 160a32 32 0 1 0 0-64 32 32 0 1 0 0 64zM64 416A32 32 0 1 0 0 416a32 32 0 1 0 64 0zm96-288a32 32 0 1 0 0-64 32 32 0 1 0 0 64zm32 128a32 32 0 1 0 -64 0 32 32 0 1 0 64 0zM160 448a32 32 0 1 0 0-64 32 32 0 1 0 0 64z") 27 | }); 28 | 29 | public static IconInfo AddFile = new("0 0 384 512", new ISvgChild[] 30 | { 31 | new PathInfo( 32 | "M48 448V64c0-8.8 7.2-16 16-16H224v80c0 17.7 14.3 32 32 32h80V448c0 8.8-7.2 16-16 16H64c-8.8 0-16-7.2-16-16zM64 0C28.7 0 0 28.7 0 64V448c0 35.3 28.7 64 64 64H320c35.3 0 64-28.7 64-64V154.5c0-17-6.7-33.3-18.7-45.3L274.7 18.7C262.7 6.7 246.5 0 229.5 0H64z"), 33 | new PathInfo( 34 | "M192 208c-13.3 0-24 10.7-24 24v48H120c-13.3 0-24 10.7-24 24s10.7 24 24 24h48v48c0 13.3 10.7 24 24 24s24-10.7 24-24V328h48c13.3 0 24-10.7 24-24s-10.7-24-24-24H216V232c0-13.3-10.7-24-24-24z", 35 | "fill-green-600") 36 | }); 37 | 38 | public static IconInfo Brand = new("0 0 576 512", new ISvgChild[] 39 | { 40 | new PathInfo( 41 | "M64 32H96h96 32V96H192 128v96 13.3l-9.4 9.4L77.3 256l41.4 41.4 9.4 9.4V320v96h64 32v64H192 96 64V448 333.3L9.4 278.6 0 269.3V242.7l9.4-9.4L64 178.7V64 32zm448 0V64 178.7l54.6 54.6 9.4 9.4v26.5l-9.4 9.4L512 333.3V448v32H480 384 352V416h32 64V320 306.7l9.4-9.4L498.7 256l-41.4-41.4-9.4-9.4V192 96H384 352V32h32 96 32z") 42 | }); 43 | 44 | public static IconInfo Assembly = new("0 0 16 16", new ISvgChild[] 45 | { 46 | new PathInfo("M16,16H0V0H16Z", "fill-none opacity-0"), 47 | new PathInfo("M9.5,5.5v8h-8v-8Z", "fill-[#212121] opacity-10"), 48 | new PathInfo("M9.5,5h-8L1,5.5v8l.5.5h8l.5-.5v-8ZM9,13H2V6H9Z", "fill-[#212121] opacity-100"), 49 | new PathInfo("M13.5,9.5h-2v2H10v-6L9.5,5h-6V3.5h2v-2h8Z", "fill-[#212121] opacity-10"), 50 | new PathInfo("M13.5,1h-8L5,1.5V3H3.5L3,3.5V5H4V4h7v7H10v1h1.5l.5-.5V10h1.5l.5-.5v-8ZM13,9H12V3.5L11.5,3H6V2h7Z", 51 | "fill-[#212121] opacity-75"), 52 | }); 53 | 54 | public static IconInfo Module = new("0 0 16 16", new ISvgChild[] 55 | { 56 | new PathInfo("M16,16H0V0H16Z", "fill-none opacity-0"), 57 | new GInfo(new[] 58 | { 59 | new PathInfo("M2.5,9.5v5h12v-5Z", "fill-[#6936aa] opacity-10"), 60 | new PathInfo("M14.5,9H2.5L2,9.5v5l.5.5h12l.5-.5v-5ZM14,14H3V10H14Z", "fill-[#6936aa] opacity-100"), 61 | }, "opacity-75"), 62 | new PathInfo("M14.5,2.5v5h-5v-5Zm-12,5h5v-5h-5Z", "fill-[#6936aa] opacity-10"), 63 | new PathInfo("M14.5,2h-5L9,2.5v5l.5.5h5l.5-.5v-5ZM14,7H10V3h4ZM2.5,2,2,2.5v5l.5.5h5L8,7.5v-5L7.5,2ZM7,7H3V3H7Z", 64 | "fill-[#6936aa] opacity-100"), 65 | }); 66 | 67 | public static IconInfo Type = new IconInfo("0 0 16 16", new ISvgChild[] 68 | { 69 | new PathInfo("M16,16H0V0H16Z", "fill-none opacity-0"), 70 | new PathInfo("M5.5.5l3,3-5,5-3-3Zm10,6-2-2-3,3,2,2Zm-5,7,2,2,3-3-2-2Z", "fill-[#996f00] opacity-10"), 71 | new PathInfo( 72 | "M10.146,7.854l2,2h.708l3-3V6.146l-2-2h-.708L11.293,6H6.707L8.854,3.854V3.146l-3-3H5.146l-5,5v.708l3,3h.708L5.707,7H8v5.5l.5.5h1.793l-.147.146v.708l2,2h.708l3-3v-.708l-2-2h-.708L11.293,12H9V7h1.293l-.147.146ZM3.5,7.793,1.207,5.5,5.5,1.207,7.793,3.5Zm10,3.414L14.793,12.5,12.5,14.793,11.207,13.5Zm0-6L14.793,6.5,12.5,8.793,11.207,7.5Z", 73 | "fill-[#996f00] opacity-100") 74 | }); 75 | 76 | public static IconInfo ValueType = new IconInfo("0 0 16 16", new ISvgChild[] 77 | { 78 | new PathInfo("M16,16H0V0H16Z", "fill-none opacity-0"), 79 | new GInfo(new[] 80 | { 81 | new PathInfo("M4.5,9.5v3h-3v-3Zm10,0v3h-3v-3Z", "fill-[#005dba] opacity-10"), 82 | new PathInfo( 83 | "M14.5,9h-3l-.5.5v3l.5.5h3l.5-.5v-3ZM14,12H12V10h2ZM1.5,9,1,9.5v3l.5.5h3l.5-.5v-3L4.5,9ZM4,12H2V10H4Z", 84 | "fill-[#005dba] opacity-100") 85 | }, "opacity-75"), 86 | new PathInfo("M14.5,4.5v3H1.5v-3Z", "fill-[#005dba] opacity-10"), 87 | new PathInfo("M14.5,4H1.5L1,4.5v3l.5.5h13l.5-.5v-3ZM14,7H2V5H14Z", "fill-[#005dba] opacity-100") 88 | }); 89 | 90 | public static IconInfo Enum = new IconInfo("0 0 16 16", new ISvgChild[] 91 | { 92 | new PathInfo("M16,16H0V0H16Z", "fill-none opacity-0"), 93 | new GInfo(new[] 94 | { 95 | new PathInfo("M14.5,2.5v6H9V7H6.5V2.5Z", "fill-[#005dba] opacity-10"), 96 | new PathInfo("M12.5,4V5h-4V4Zm-4,3h4V6h-4ZM15,2.5v6l-.5.5H10V8h4V3H7V7H6V2.5L6.5,2h8Z", "fill-[#005dba]") 97 | }, "opacity-75"), 98 | new PathInfo("M9.5,7h-8L1,7.5v6l.5.5h8l.5-.5v-6Z", "fill-[#005dba]"), 99 | new PathInfo("M8,11H3V10H8Z", "fill-[#ffffff]") 100 | }); 101 | 102 | public static IconInfo Delegate = new IconInfo("0 0 16 16", new ISvgChild[] 103 | { 104 | new PathInfo("M16,16H0V0H16Z", "fill-none opacity-0"), 105 | new PathInfo("M14.5,4.5v9H1.5v-9Z", "fill-[#6936aa] opacity-10"), 106 | new PathInfo("M14.5,4H1.5L1,4.5v9l.5.5h13l.5-.5v-9ZM12,5v8H4V5ZM2,5H3v8H2Zm12,8H13V5h1Z", "fill-[#6936aa]"), 107 | new PathInfo("M11,2.5V4H10V3H6V4H5V2.5L5.5,2h5Z", "fill-[#212121]") 108 | }); 109 | 110 | public static IconInfo Interface = new IconInfo("0 0 16 16", new ISvgChild[] 111 | { 112 | new PathInfo("M16,16H0V0H16Z", "fill-none opacity-0"), 113 | new GInfo(new[] 114 | { 115 | new PathInfo("M8.5,7V8h-4V7Z", "fill-[#005dba]") 116 | }, "opacity-75"), 117 | new PathInfo("M4.5,7.5a2,2,0,1,1-2-2A2,2,0,0,1,4.5,7.5Zm10,0a3,3,0,1,1-3-3A3,3,0,0,1,14.5,7.5Z", 118 | "fill-[#005dba] opacity-10"), 119 | new PathInfo( 120 | "M2.5,5A2.5,2.5,0,1,0,5,7.5,2.5,2.5,0,0,0,2.5,5Zm0,4A1.5,1.5,0,1,1,4,7.5,1.5,1.5,0,0,1,2.5,9Zm9-5A3.5,3.5,0,1,0,15,7.5,3.5,3.5,0,0,0,11.5,4Zm0,6A2.5,2.5,0,1,1,14,7.5,2.5,2.5,0,0,1,11.5,10Z", 121 | "fill-[#005dba]") 122 | }); 123 | 124 | public static IconInfo AssemblyReference = new IconInfo("0 0 16 16", new ISvgChild[] 125 | { 126 | new PathInfo("M16,16H0V0H16Z", "fill-none opacity-0"), 127 | new GInfo(new[] 128 | { 129 | new PathInfo("M9,7V8H5V7Z", "fill-[#212121] opacity-75") 130 | }, "opacity-75"), 131 | new PathInfo("M4.5,5.5v4H.5v-4Z", "fill-[#212121] opacity-10"), 132 | new PathInfo("M4.5,10H.5L0,9.5v-4L.5,5h4l.5.5v4ZM1,9H4V6H1Z", "fill-[#212121]"), 133 | new PathInfo("M15.5,4.5v6h-6v-6Z", "fill-[#212121] opacity-10"), 134 | new PathInfo("M15.5,11h-6L9,10.5v-6L9.5,4h6l.5.5v6ZM10,10h5V5H10Z", "fill-[#212121]") 135 | }); 136 | 137 | public static IconInfo Namespace = new IconInfo("0 0 16 16", new ISvgChild[] 138 | { 139 | new PathInfo("M16,16H0V0H16Z", "fill-none opacity-0"), 140 | new PathInfo( 141 | "M4.9,2,5,2v.9l-.092,0a.94.94,0,0,0-.745.332,1.784,1.784,0,0,0-.229,1.025V6.23a1.741,1.741,0,0,1-.888,1.786c.57.2.888.819.888,1.8v1.89a3.406,3.406,0,0,0,.053.646,1.071,1.071,0,0,0,.164.417.7.7,0,0,0,.29.24A1.246,1.246,0,0,0,4.9,13.1l.1,0V14l-.1,0a2.079,2.079,0,0,1-1.478-.538,2.187,2.187,0,0,1-.5-1.577v-2a1.948,1.948,0,0,0-.249-1.079A.914.914,0,0,0,1.963,8.4L1.875,8.39V7.61L1.962,7.6c.645-.07.959-.541.959-1.438V4.132a2.206,2.206,0,0,1,.5-1.586A2.062,2.062,0,0,1,4.9,2ZM14.03,7.6c-.64-.063-.951-.533-.951-1.438V4.132a2.2,2.2,0,0,0-.5-1.591A2.069,2.069,0,0,0,11.1,2L11,2v.9l.093,0A1.357,1.357,0,0,1,11.531,3a.693.693,0,0,1,.29.218A1.174,1.174,0,0,1,12,3.622a2.779,2.779,0,0,1,.064.644V6.23c0,.95.319,1.559.892,1.754a1.8,1.8,0,0,0-.892,1.833v1.89a3.181,3.181,0,0,1-.061.675,1.07,1.07,0,0,1-.178.416.671.671,0,0,1-.29.219,1.291,1.291,0,0,1-.442.081l-.1,0V14l.1,0a2.069,2.069,0,0,0,1.477-.538,2.184,2.184,0,0,0,.5-1.577v-2c0-.929.311-1.415.952-1.485l.087-.009V7.609Z", 142 | "fill-[#212121]") 143 | }); 144 | 145 | public static IconInfo Method = new IconInfo("0 0 16 16", new ISvgChild[] 146 | { 147 | new PathInfo("M16,16H0V0H16Z", "fill-none opacity-0"), 148 | new GInfo(new[] 149 | { 150 | new PathInfo("M13.5,5.045v7L8,14.545l-5.5-2.5v-7l5.5-3Z", "fill-[#6936aa] opacity-10"), 151 | new PathInfo( 152 | "M14,5.045v7l-.293.455L8.207,15H7.793l-5.5-2.5L2,12.045v-7l.261-.439.032.894L3,5.821v5.9l4.5,2.045,0-5.9.3.135h.414l.288-.131,0,5.9L13,11.723v-5.9l.707-.321.032-.894Z", 153 | "fill-[#6936aa]"), 154 | }, "opacity-75"), 155 | new PathInfo("M13.5,5.045,8,7.545l-5.5-2.5,5.5-3Z", "fill-[#6936aa] opacity-10"), 156 | new PathInfo("M8.239,1.606H7.761l-5.5,3,.032.894L7.793,8h.414l5.5-2.5.032-.894ZM8,7,3.619,5,8,2.614,12.381,5Z", 157 | "fill-[#6936aa]"), 158 | }); 159 | 160 | public static IconInfo Property = new IconInfo("0 0 16 16", new ISvgChild[] 161 | { 162 | new PathInfo("M16,16H0V0H16Z", "fill-none opacity-0"), 163 | new GInfo(new[] 164 | { 165 | new PathInfo( 166 | "M10.242,7.167c-1.722,1.75-5.418,5.45-7.191,7.1-.861.75-2.076-.651-1.418-1.4,1.671-1.75,5.418-5.449,7.14-7.1a1.078,1.078,0,0,1,.659-.25A1.026,1.026,0,0,1,10.242,7.167Z", 167 | "fill-[#212121] opacity-10"), 168 | new PathInfo( 169 | "M10.828,5.938a1.508,1.508,0,0,0-1.4-.921,1.628,1.628,0,0,0-1.005.388c-1.714,1.643-5.473,5.355-7.17,7.131a1.444,1.444,0,0,0,.187,1.973,1.5,1.5,0,0,0,1.056.47,1.352,1.352,0,0,0,.892-.346C5.254,12.9,9.051,9.09,10.61,7.506A1.45,1.45,0,0,0,10.828,5.938Zm-.942.878C8.344,8.384,4.561,12.178,2.723,13.89a.4.4,0,0,1-.571-.087C2,13.653,1.86,13.365,2,13.212c1.673-1.753,5.417-5.448,7.076-7.044a.575.575,0,0,1,.361-.151.513.513,0,0,1,.48.322A.465.465,0,0,1,9.886,6.816Z", 170 | "fill-[#212121]"), 171 | }, "opacity-75"), 172 | new PathInfo( 173 | "M14.974,5a4,4,0,0,1-8,0,3.961,3.961,0,0,1,4-4,4.19,4.19,0,0,1,1.441.241L9.534,4.2l2.24,2.241,2.96-2.882A4.19,4.19,0,0,1,14.974,5Z", 174 | "fill-[#212121]"), 175 | }); 176 | 177 | public static IconInfo Event = new IconInfo("0 0 16 16", new ISvgChild[] 178 | { 179 | new PathInfo("M16,16H0V0H16Z", "fill-none opacity-0"), 180 | new PathInfo("M12.5,6.5l-8,8H3l3.5-6H3l4-7h5.387L8,6.5Z", "fill-[#996f00] opacity-25"), 181 | new PathInfo( 182 | "M12.5,6H9.1l3.659-4.17L12.387,1H7l-.434.252-4,7L3,9H5.629L2.568,14.248,3,15H4.5l.354-.146,8-8ZM4.293,14H3.871L6.932,8.752,6.5,8H3.862L7.29,2h3.993L7.624,6.17,8,7h3.293Z", 183 | "fill-[#996f00]"), 184 | }); 185 | 186 | public static IconInfo EnumItem = new IconInfo("0 0 16 16", new ISvgChild[] 187 | { 188 | new PathInfo("M16,16H0V0H16Z", "fill-none opacity-0"), 189 | new GInfo(new[] 190 | { 191 | new PathInfo("M14.5,2.5v6H9V7H6.5V2.5Z", "fill-[#005dba] opacity-10"), 192 | new PathInfo("M12.5,4V5h-4V4Zm-4,3h4V6h-4ZM15,2.5v6l-.5.5H10V8h4V3H7V7H6V2.5L6.5,2h8Z", "fill-[#005dba]"), 193 | }, "opacity-75"), 194 | new PathInfo("M9.5,7h-8L1,7.5v6l.5.5h8l.5-.5v-6Z", "fill-[#005dba]"), 195 | new PathInfo("M8,11H3V10H8Z", "fill-[#ffffff]"), 196 | }); 197 | 198 | public static IconInfo Field = new IconInfo("0 0 16 16", new ISvgChild[] 199 | { 200 | new PathInfo("M16,16H0V0H16Z", "fill-none opacity-0"), 201 | new GInfo(new[] 202 | { 203 | new PathInfo("M14.5,5.5V10l-9,5-4-4V6.5l9-5Z", "fill-[#005dba] opacity-10"), 204 | new PathInfo( 205 | "M14.854,5.146l-4-4-.6-.083-9,5L1,6.5V11l.146.354,4,4,.6.083,9-5L15,10V5.5ZM14,9.706,6,14.15V10.5H5v3.293l-3-3v-4L10.413,2.12,14,5.707Z", 206 | "fill-[#005dba]"), 207 | }, "opacity-0.75"), 208 | new PathInfo("M14.5,5.5l-9,5-4-4,9-5Z", "fill-[#005dba] opacity-10"), 209 | new PathInfo( 210 | "M10.854,1.146l-.6-.083-9,5-.111.791,4,4,.6.083,9-5,.111-.791ZM5.587,9.88,2.322,6.615,10.413,2.12l3.265,3.265Z", 211 | "fill-[#005dba]"), 212 | }); 213 | 214 | public static IconInfo Constant = new IconInfo("0 0 16 16", new ISvgChild[] 215 | { 216 | new PathInfo("M16,16H0V0H16Z", "fill-none opacity-0"), 217 | new PathInfo("M3,13V4h9v9H3Z", "fill-[#212121] opacity-10"), 218 | new PathInfo("M12.5,3H2.5L2,3.5v10l.5.5h10l.5-.5V3.5ZM12,13H3V4h9Z", "fill-[#212121] opacity-100"), 219 | new PathInfo("M9.991,8h-5V7h5Zm0,1h-5v1h5Z", "fill-[#005dba] opacity-100") 220 | }); 221 | 222 | 223 | public record struct IconInfo(string ViewBox, ISvgChild[] PathInfos); 224 | 225 | public interface ISvgChild 226 | { 227 | } 228 | 229 | public record struct PathInfo(string Data, string? Class = null) : ISvgChild; 230 | 231 | public record struct GInfo(PathInfo[] PathInfos, string? Class = null) : ISvgChild; // :/ 232 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Interface/CodeThemeColor.cs: -------------------------------------------------------------------------------- 1 | namespace Dekompiler.Core.Interface; 2 | 3 | public class CodeThemeColor 4 | { 5 | public CodeThemeColor(string foreground, string? background = null, bool italic = false, bool bold = false) 6 | { 7 | Foreground = foreground; 8 | Background = background; 9 | Italic = italic; 10 | Bold = bold; 11 | } 12 | 13 | public string Foreground 14 | { 15 | get; 16 | } 17 | 18 | public string? Background 19 | { 20 | get; 21 | } 22 | 23 | public bool Bold 24 | { 25 | get; 26 | } 27 | 28 | public bool Italic 29 | { 30 | get; 31 | } 32 | 33 | public override string ToString() 34 | { 35 | return string.Join(' ', $"text-[{Foreground}]", 36 | Italic ? "italic" : "not-italic", 37 | Bold ? "font-semibold" : "font-normal", 38 | Background is null ? null : $"bg-[{Background}]"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Dekompiler.Core/Interface/CodeThemeConfiguration.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable StringLiteralTypo 2 | 3 | namespace Dekompiler.Core.Interface; 4 | 5 | public class CodeThemeConfiguration 6 | { 7 | // https://github.com/dnSpy/dnSpy/blob/master/dnSpy/dnSpy/Themes/light.dntheme 8 | public static readonly CodeThemeConfiguration Default = new() 9 | { 10 | Colors = new Dictionary 11 | { 12 | { "defaulttext", new CodeThemeColor("#212121") }, 13 | { "operator", new CodeThemeColor("#000000") }, 14 | { "punctuation", new CodeThemeColor("#000000") }, 15 | { "number", new CodeThemeColor("#5B2DA8") }, 16 | { "comment", new CodeThemeColor("#008000") }, 17 | { "keyword", new CodeThemeColor("#0000FF") }, 18 | { "string", new CodeThemeColor("#A31515") }, 19 | { "verbatimstring", new CodeThemeColor("#800000") }, 20 | { "char", new CodeThemeColor("#A31515") }, 21 | { "namespace", new CodeThemeColor("#9E7E00") }, 22 | { "type", new CodeThemeColor("#2B91AF") }, 23 | { "sealedtype", new CodeThemeColor("#2B91AF") }, 24 | { "statictype", new CodeThemeColor("#1B5D70") }, 25 | { "delegate", new CodeThemeColor("#6666FF") }, 26 | { "enum", new CodeThemeColor("#336600") }, 27 | { "interface", new CodeThemeColor("#1E667A") }, 28 | { "valuetype", new CodeThemeColor("#009933") }, 29 | { "module", new CodeThemeColor("#1B5D70") }, 30 | { "genericparameter", new CodeThemeColor("#2B91AF") }, 31 | { "instancemethod", new CodeThemeColor("#880000") }, 32 | { "staticmethod", new CodeThemeColor("#880000") }, 33 | { "extensionmethod", new CodeThemeColor("#960000", italic: true) }, 34 | { "instancefield", new CodeThemeColor("#CC3399") }, 35 | { "enumfield", new CodeThemeColor("#6F008A") }, 36 | { "literalfield", new CodeThemeColor("#9900FF") }, 37 | { "staticfield", new CodeThemeColor("#990099") }, 38 | { "instanceevent", new CodeThemeColor("#990033") }, 39 | { "staticevent", new CodeThemeColor("#660033") }, 40 | { "instanceproperty", new CodeThemeColor("#996633") }, 41 | { "staticproperty", new CodeThemeColor("#7A5229") }, 42 | { "local", new CodeThemeColor("#000000") }, 43 | { "parameter", new CodeThemeColor("#000000", bold: true) }, 44 | { "preprocessorkeyword", new CodeThemeColor("#FF808080") }, 45 | { "preprocessortext", new CodeThemeColor("#FF000000") }, 46 | { "label", new CodeThemeColor("#663300") }, 47 | { "opcode", new CodeThemeColor("#993366") }, 48 | { "ildirective", new CodeThemeColor("#009900") }, 49 | { "ilmodule", new CodeThemeColor("#6936AA") }, 50 | { "excludedcode", new CodeThemeColor("#808080") } 51 | } 52 | }; 53 | 54 | // https://github.com/dnSpy/dnSpy/blob/master/dnSpy/dnSpy/Themes/dark.dntheme 55 | public static readonly CodeThemeConfiguration Dark = new() 56 | { 57 | Colors = new Dictionary 58 | { 59 | { "defaulttext", new CodeThemeColor("#DCDCDC") }, 60 | { "operator", new CodeThemeColor("#B4B4B4") }, 61 | { "punctuation", new CodeThemeColor("#DCDCDC") }, 62 | { "number", new CodeThemeColor("#B5CEA8") }, 63 | { "comment", new CodeThemeColor("#57A64A") }, 64 | { "keyword", new CodeThemeColor("#569CD6") }, 65 | { "string", new CodeThemeColor("#D69D85") }, 66 | { "verbatimstring", new CodeThemeColor("#D69D85") }, 67 | { "char", new CodeThemeColor("#D69D85") }, 68 | { "namespace", new CodeThemeColor("#FFD700") }, 69 | { "type", new CodeThemeColor("#4EC9B0") }, 70 | { "sealedtype", new CodeThemeColor("#4EC9B0") }, 71 | { "statictype", new CodeThemeColor("#378D7B") }, 72 | { "delegate", new CodeThemeColor("#33CCFF") }, 73 | { "enum", new CodeThemeColor("#B8D7A3") }, 74 | { "interface", new CodeThemeColor("#9B9B82") }, 75 | { "valuetype", new CodeThemeColor("#009933") }, 76 | { "module", new CodeThemeColor("#378D7B") }, 77 | { "genericparameter", new CodeThemeColor("#4B8595") }, 78 | { "instancemethod", new CodeThemeColor("#FF8000") }, 79 | { "staticmethod", new CodeThemeColor("#E67300") }, 80 | { "extensionmethod", new CodeThemeColor("#CC6600", italic: true) }, 81 | { "instancefield", new CodeThemeColor("#AA70FF") }, 82 | { "enumfield", new CodeThemeColor("#BD63C5") }, 83 | { "literalfield", new CodeThemeColor("#C266FF") }, 84 | { "staticfield", new CodeThemeColor("#8D8DC6") }, 85 | { "instanceevent", new CodeThemeColor("#CC6699") }, 86 | { "staticevent", new CodeThemeColor("#DB94B8") }, 87 | { "instanceproperty", new CodeThemeColor("#248F8F") }, 88 | { "staticproperty", new CodeThemeColor("#1F8E8E") }, 89 | { "local", new CodeThemeColor("#DCDCDC") }, 90 | { "parameter", new CodeThemeColor("#DCDCDC", bold: true) }, 91 | { "preprocessorkeyword", new CodeThemeColor("#FF9B9B9B") }, 92 | { "preprocessortext", new CodeThemeColor("#FFDCDCDC") }, 93 | { "label", new CodeThemeColor("#806F4D") }, 94 | { "opcode", new CodeThemeColor("#AD5C85") }, 95 | { "ildirective", new CodeThemeColor("#9999FF") }, 96 | { "ilmodule", new CodeThemeColor("#666699") }, 97 | { "excludedcode", new CodeThemeColor("#9B9B4B4") } 98 | } 99 | }; 100 | 101 | public CodeThemeConfiguration() 102 | { 103 | Colors = new Dictionary(); 104 | } 105 | 106 | public Dictionary Colors 107 | { 108 | get; 109 | set; 110 | } 111 | 112 | public CodeThemeColor GetThemeColor(string codename) 113 | { 114 | return Colors[codename]; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Dekompiler.Core/Interface/ThemeConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace Dekompiler.Core.Interface; 2 | 3 | public class ThemeConfiguration 4 | { 5 | public static readonly ThemeConfiguration Default = new() 6 | { 7 | Branding = "#3b82f6", 8 | Primary = "#ffffff", 9 | Secondary = "#f7f8fa", 10 | Border = "#e5e4ec", 11 | Icon = "#212121", 12 | CodeTheme = CodeThemeConfiguration.Default 13 | }; 14 | 15 | public static readonly ThemeConfiguration Dark = new() 16 | { 17 | Branding = "#3b82f6", 18 | Primary = "#141517", 19 | Secondary = "#161718", 20 | Border = "#404040", 21 | Icon = "#f5f5f5", 22 | CodeTheme = CodeThemeConfiguration.Dark 23 | }; 24 | 25 | public string Icon { get; set; } = "#212121"; 26 | public string Branding { get; set; } = "#3b82f6"; 27 | 28 | public string Primary { get; set; } = "#ffffff"; 29 | 30 | public string Secondary { get; set; } = "#f7f8fa"; 31 | 32 | public string Border { get; set; } = "#e5e4ec"; 33 | 34 | public CodeThemeConfiguration CodeTheme { get; set; } = CodeThemeConfiguration.Default; 35 | } -------------------------------------------------------------------------------- /Dekompiler.Core/RendererConstants.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Dekompiler.Core; 4 | 5 | public class RendererConstants 6 | { 7 | private readonly RendererService _service; 8 | 9 | public RendererConstants(RendererService service) 10 | { 11 | _service = service; 12 | } 13 | 14 | public RenderFragment RightCurlyBracket => _service.Text("{"); 15 | 16 | public RenderFragment LeftCurlyBracket => _service.Text("}"); 17 | 18 | public RenderFragment RightBracket => _service.Text("("); 19 | public RenderFragment LeftBracket => _service.Text(")"); 20 | 21 | public RenderFragment RightArrayBracket => _service.Text("["); 22 | public RenderFragment LeftArrayBracket => _service.Text("]"); 23 | 24 | 25 | 26 | public RenderFragment Dot => _service.Text("."); 27 | public RenderFragment Comma => _service.Text(","); 28 | public RenderFragment Equal => _service.Text("="); 29 | public RenderFragment Space => _service.Text(" "); 30 | public RenderFragment SemiColumn => _service.Text(";"); 31 | public RenderFragment Column => _service.Text(":"); 32 | 33 | public RenderFragment RightThan => _service.Text("<"); 34 | public RenderFragment LeftThan => _service.Text(">"); 35 | 36 | public RenderFragment Star => _service.Text("*"); 37 | public RenderFragment Slash => _service.Text("/"); 38 | } -------------------------------------------------------------------------------- /Dekompiler.Core/RendererManager.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver; 2 | using Dekompiler.Core.Interface; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core; 6 | 7 | public class RendererService 8 | { 9 | public RendererService(ThemeConfiguration themeConfiguration) 10 | { 11 | Theme = themeConfiguration; 12 | Constants = new RendererConstants(this); 13 | } 14 | 15 | public ThemeConfiguration Theme { get; } 16 | 17 | public RendererConstants Constants { get; } 18 | 19 | public RenderFragment Concat(params RenderFragment?[] fragments) 20 | { 21 | fragments = fragments.Where(f => f is not null).ToArray(); 22 | return builder => 23 | { 24 | builder.OpenElement(0, "span"); 25 | for (var i = 1; i < fragments.Length + 1; i++) 26 | builder.AddContent(i, fragments[i - 1]); 27 | builder.CloseElement(); 28 | }; 29 | } 30 | 31 | public RenderFragment Join(RenderFragment separator, params RenderFragment?[] fragments) 32 | { 33 | var sequence = 1; 34 | fragments = fragments.Where(f => f is not null).ToArray(); 35 | return builder => 36 | { 37 | builder.OpenElement(0, "span"); 38 | for (var i = 0; i < fragments.Length; i++) 39 | { 40 | var content = fragments[i]; 41 | 42 | if (content is null) 43 | continue; 44 | 45 | builder.AddContent(sequence++, content); 46 | if (i != fragments.Length - 1) 47 | builder.AddContent(sequence++, separator); 48 | } 49 | 50 | builder.CloseElement(); 51 | }; 52 | } 53 | 54 | public RenderFragment Span(Utf8String? content, string themeColor) => Span((string?)content, themeColor); 55 | 56 | public RenderFragment Span(Utf8String? content, CodeThemeColor themeColor) => Span((string?)content, themeColor); 57 | 58 | public RenderFragment Span(string? content, string themeColor) => 59 | Span(content, Theme.CodeTheme.GetThemeColor(themeColor)); 60 | 61 | public RenderFragment Span(string? content, CodeThemeColor themeColor) 62 | { 63 | return builder => 64 | { 65 | builder.OpenElement(0, "span"); 66 | builder.AddAttribute(1, "class", themeColor.ToString()); 67 | builder.AddContent(2, content); 68 | builder.CloseElement(); 69 | }; 70 | } 71 | 72 | public RenderFragment Keyword(string? keyword) => Span(keyword, "keyword"); 73 | public RenderFragment Text(string? text) => Span(text, "defaulttext"); 74 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Results/EventDecompilationResult.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using Dekompiler.Core.Declaration; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Results; 6 | 7 | public class EventDecompilationResult : IDecompilationResult 8 | { 9 | private readonly RendererService _service; 10 | private EventDefinition _event; 11 | 12 | public EventDecompilationResult(Icons.IconInfo icon, RenderFragment header, IMemberDeclaration declaration, 13 | MethodDecompilationResult? addDecompilationResult, MethodDecompilationResult? removeDecompilationResult, 14 | RendererService service, EventDefinition @event) 15 | { 16 | _service = service; 17 | _event = @event; 18 | Icon = icon; 19 | Header = header; 20 | Declaration = declaration; 21 | AddDecompilationResult = addDecompilationResult; 22 | RemoveDecompilationResult = removeDecompilationResult; 23 | } 24 | 25 | public Icons.IconInfo Icon { get; } 26 | public RenderFragment Header { get; } 27 | public IMemberDefinition Member => _event; 28 | public IMemberDeclaration Declaration { get; } 29 | 30 | public MethodDecompilationResult? AddDecompilationResult { get; } 31 | public MethodDecompilationResult? RemoveDecompilationResult { get; } 32 | 33 | 34 | public RenderFragment RenderResult() 35 | { 36 | return builder => 37 | { 38 | builder.OpenElement(0, "p"); 39 | 40 | builder.AddContent(1, Declaration.BuildDeclaration()); 41 | 42 | builder.AddContent(2, IDecompilationResult.NewLine()); 43 | 44 | builder.AddContent(3, _service.Constants.RightCurlyBracket); 45 | 46 | var sequence = 4; 47 | 48 | if (AddDecompilationResult is not null) 49 | { 50 | builder.AddContent(sequence++, IDecompilationResult.Indent(AddDecompilationResult.RenderResult())); 51 | } 52 | 53 | if (RemoveDecompilationResult is not null) 54 | { 55 | builder.AddContent(sequence++, IDecompilationResult.Indent(RemoveDecompilationResult.RenderResult())); 56 | } 57 | 58 | 59 | 60 | builder.AddContent(sequence++, _service.Constants.LeftCurlyBracket); 61 | 62 | builder.CloseElement(); 63 | }; 64 | } 65 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Results/FieldDecompilationResult.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using Dekompiler.Core.Declaration; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Results; 6 | 7 | public class FieldDecompilationResult : IDecompilationResult 8 | { 9 | private FieldDefinition _field; 10 | private readonly RendererService _service; 11 | 12 | public FieldDecompilationResult(Icons.IconInfo icon, RenderFragment header, IMemberDeclaration declaration, 13 | FieldDefinition field, RendererService service) 14 | { 15 | Icon = icon; 16 | Header = header; 17 | Declaration = declaration; 18 | _field = field; 19 | _service = service; 20 | } 21 | 22 | public Icons.IconInfo Icon { get; } 23 | public RenderFragment Header { get; } 24 | public IMemberDefinition Member => _field; 25 | public IMemberDeclaration Declaration { get; } 26 | 27 | public RenderFragment RenderResult() 28 | { 29 | return _service.Concat( 30 | _service.Span($"// Token: 0x{_field.MetadataToken.ToInt32():x8} RID: {_field.MetadataToken.Rid}", 31 | "comment"), IDecompilationResult.NewLine(), Declaration.BuildDeclaration()); 32 | } 33 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Results/IDecompilationResult.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using Dekompiler.Core.Declaration; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Results; 6 | 7 | public interface IDecompilationResult 8 | { 9 | Icons.IconInfo Icon { get; } 10 | 11 | RenderFragment Header { get; } 12 | 13 | IMemberDefinition Member { get; } 14 | 15 | IMemberDeclaration Declaration { get; } 16 | 17 | RenderFragment RenderResult(); 18 | 19 | internal static RenderFragment NewLine() 20 | { 21 | return builder => 22 | { 23 | builder.OpenElement(0, "br"); 24 | builder.CloseElement(); 25 | }; 26 | } 27 | 28 | internal static RenderFragment Indent(RenderFragment fragment, int indent = 10) 29 | { 30 | return builder => 31 | { 32 | builder.OpenElement(0, "p"); 33 | builder.AddAttribute(1, "class", $"ml-{indent}"); 34 | builder.AddContent(2, fragment); 35 | builder.CloseElement(); 36 | }; 37 | } 38 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Results/MethodDecompilationResult.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using Dekompiler.Core.Declaration; 3 | using Dekompiler.Core.Statements; 4 | using Microsoft.AspNetCore.Components; 5 | 6 | namespace Dekompiler.Core.Results; 7 | 8 | public class MethodDecompilationResult : IDecompilationResult 9 | { 10 | private readonly MethodContext _ctx; 11 | 12 | public MethodDecompilationResult(Icons.IconInfo icon, RenderFragment header, IMemberDeclaration declaration, 13 | MethodContext ctx) 14 | { 15 | _ctx = ctx; 16 | Icon = icon; 17 | Header = header; 18 | Declaration = declaration; 19 | } 20 | 21 | public Icons.IconInfo Icon { get; } 22 | public RenderFragment Header { get; } 23 | public IMemberDefinition Member => _ctx.Method; 24 | public IMemberDeclaration Declaration { get; } 25 | 26 | public bool Empty => _ctx.Empty; 27 | 28 | public RenderFragment RenderResult() 29 | { 30 | return builder => 31 | { 32 | builder.OpenElement(0, "p"); 33 | builder.AddAttribute(1, "methodToken", _ctx.Method.MetadataToken.ToString()); 34 | 35 | builder.AddContent(2, _ctx.Renderer.Concat(_ctx.Renderer.Span($"// Token: 0x{_ctx.Method.MetadataToken.ToInt32():x8} RID: {_ctx.Method.MetadataToken.Rid}" + (_ctx.Method.CilMethodBody is not null ? $" RVA: 0x{_ctx.Method.MethodBody?.Address?.Rva:x8}" : string.Empty), "comment"), IDecompilationResult.NewLine())); 36 | 37 | if (_ctx.Empty) 38 | { 39 | // null method body/multi cast delegate impl/interface 40 | builder.AddContent(3, 41 | _ctx.Renderer.Concat(Declaration.BuildDeclaration(), _ctx.Renderer.Constants.SemiColumn)); 42 | } 43 | else 44 | { 45 | builder.AddContent(3, Declaration.BuildDeclaration()); 46 | 47 | builder.AddContent(4, IDecompilationResult.NewLine()); 48 | 49 | builder.AddContent(5, _ctx.Renderer.Constants.RightCurlyBracket); 50 | 51 | builder.AddContent(6, IDecompilationResult.NewLine()); 52 | 53 | var sequence = 6; 54 | 55 | foreach (var statement in _ctx.CompleteStatements) 56 | { 57 | builder.AddContent(sequence++, 58 | IDecompilationResult.Indent(_ctx.Renderer.Concat(statement.Render(), 59 | _ctx.Renderer.Constants.SemiColumn))); 60 | } 61 | 62 | builder.AddContent(sequence, _ctx.Renderer.Constants.LeftCurlyBracket); 63 | } 64 | 65 | builder.CloseElement(); 66 | }; 67 | } 68 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Results/PropertyDecompilationResult.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using Dekompiler.Core.Declaration; 3 | using Dekompiler.Core.Statements; 4 | using Microsoft.AspNetCore.Components; 5 | 6 | namespace Dekompiler.Core.Results; 7 | 8 | public class PropertyDecompilationResult : IDecompilationResult 9 | { 10 | private readonly RendererService _service; 11 | private PropertyDefinition _property; 12 | 13 | public PropertyDecompilationResult(Icons.IconInfo icon, RenderFragment header, IMemberDeclaration declaration, 14 | MethodDecompilationResult? getDecompilationResult, MethodDecompilationResult? setDecompilationResult, 15 | RendererService service, PropertyDefinition property) 16 | { 17 | _service = service; 18 | _property = property; 19 | Icon = icon; 20 | Header = header; 21 | Declaration = declaration; 22 | GetDecompilationResult = getDecompilationResult; 23 | SetDecompilationResult = setDecompilationResult; 24 | } 25 | 26 | public Icons.IconInfo Icon { get; } 27 | public RenderFragment Header { get; } 28 | public IMemberDefinition Member => _property; 29 | public IMemberDeclaration Declaration { get; } 30 | 31 | public MethodDecompilationResult? GetDecompilationResult { get; } 32 | public MethodDecompilationResult? SetDecompilationResult { get; } 33 | 34 | 35 | public RenderFragment RenderResult() 36 | { 37 | return builder => 38 | { 39 | builder.OpenElement(0, "p"); 40 | 41 | builder.AddContent(2, _service.Concat(_service.Span($"// Token: 0x{_property.MetadataToken.ToInt32():x8} RID: {_property.MetadataToken.Rid}", "comment"), IDecompilationResult.NewLine())); 42 | 43 | builder.AddContent(2, Declaration.BuildDeclaration()); 44 | 45 | builder.AddContent(3, IDecompilationResult.NewLine()); 46 | 47 | builder.AddContent(4, _service.Constants.RightCurlyBracket); 48 | 49 | var sequence = 5; 50 | 51 | if (GetDecompilationResult is not null) 52 | { 53 | builder.AddContent(sequence++, IDecompilationResult.Indent(GetDecompilationResult.RenderResult())); 54 | } 55 | 56 | if (SetDecompilationResult is not null) 57 | { 58 | builder.AddContent(sequence++, IDecompilationResult.Indent(SetDecompilationResult.RenderResult())); 59 | } 60 | 61 | 62 | 63 | builder.AddContent(sequence++, _service.Constants.LeftCurlyBracket); 64 | 65 | builder.CloseElement(); 66 | }; 67 | } 68 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Results/TypeDecompilationResult.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using AsmResolver.DotNet; 3 | using Dekompiler.Core.Declaration; 4 | using Microsoft.AspNetCore.Components; 5 | 6 | namespace Dekompiler.Core.Results; 7 | 8 | public class TypeDecompilationResult : IDecompilationResult 9 | { 10 | private readonly TypeDefinition _type; 11 | private readonly RendererService _service; 12 | 13 | public TypeDecompilationResult(Icons.IconInfo icon, RenderFragment header, IMemberDeclaration declaration, 14 | TypeDefinition type, RendererService service) 15 | { 16 | _type = type; 17 | _service = service; 18 | Icon = icon; 19 | Header = header; 20 | Declaration = declaration; 21 | } 22 | 23 | public Icons.IconInfo Icon { get; } 24 | public RenderFragment Header { get; } 25 | public IMemberDefinition Member => _type; 26 | public IMemberDeclaration Declaration { get; } 27 | public List MethodResults { get; } = new(); 28 | public List PropertyResults { get; } = new(); 29 | public List EventResults { get; } = new(); 30 | public List NestedTypeResults { get; } = new(); 31 | public List FieldResults { get; } = new(); 32 | 33 | 34 | public RenderFragment RenderResult() 35 | { 36 | var internalRender = InternalRender(); 37 | 38 | if (!string.IsNullOrEmpty(_type.Namespace) && !_type.IsNested) 39 | { 40 | return builder => 41 | { 42 | var ns = _service.Join(_service.Constants.Dot, 43 | _type.Namespace.Value.Split('.').Select(n => _service.Span(n, "namespace")).ToArray()); 44 | var nsKeyword = _service.Keyword("namespace"); 45 | 46 | builder.OpenElement(0, "p"); 47 | 48 | builder.AddContent(1, _service.Concat(nsKeyword, _service.Constants.Space, ns)); 49 | 50 | builder.AddContent(2, IDecompilationResult.NewLine()); 51 | 52 | builder.AddContent(3, _service.Constants.RightCurlyBracket); 53 | 54 | builder.AddContent(4, IDecompilationResult.Indent(internalRender)); 55 | 56 | builder.AddContent(5, _service.Constants.LeftCurlyBracket); 57 | 58 | builder.CloseElement(); 59 | }; 60 | } 61 | else 62 | { 63 | return internalRender; 64 | } 65 | } 66 | 67 | 68 | private RenderFragment InternalRender() 69 | { 70 | return builder => 71 | { 72 | builder.OpenElement(0, "p"); 73 | builder.AddAttribute(1, "typeToken", _type.MetadataToken.ToString()); 74 | 75 | builder.AddContent(2, _service.Concat(_service.Span($"// Token: 0x{_type.MetadataToken.ToInt32():x8} RID: {_type.MetadataToken.Rid}", "comment"), IDecompilationResult.NewLine())); 76 | 77 | builder.AddContent(3, Declaration.BuildDeclaration()); 78 | 79 | builder.AddContent(4, IDecompilationResult.NewLine()); 80 | 81 | builder.AddContent(5, _service.Constants.RightCurlyBracket); 82 | 83 | builder.AddContent(6, IDecompilationResult.NewLine()); 84 | 85 | var sequence = 6; 86 | 87 | foreach (var methodResult in MethodResults) 88 | { 89 | builder.AddContent(sequence++, 90 | IDecompilationResult.Indent(methodResult.RenderResult())); 91 | builder.AddContent(sequence++, 92 | IDecompilationResult.NewLine()); 93 | } 94 | 95 | foreach (var propertyResult in PropertyResults) 96 | { 97 | builder.AddContent(sequence++, 98 | IDecompilationResult.Indent(propertyResult.RenderResult())); 99 | builder.AddContent(sequence++, 100 | IDecompilationResult.NewLine()); 101 | } 102 | 103 | foreach (var eventResult in EventResults) 104 | { 105 | builder.AddContent(sequence++, 106 | IDecompilationResult.Indent(eventResult.RenderResult())); 107 | builder.AddContent(sequence++, 108 | IDecompilationResult.NewLine()); 109 | } 110 | 111 | foreach (var fieldResult in FieldResults) 112 | { 113 | if ((FieldDefinition)fieldResult.Member is 114 | { DeclaringType: { BaseType: { FullName: "System.Enum" } } }) 115 | { 116 | builder.AddContent(sequence++, 117 | IDecompilationResult.Indent(fieldResult.RenderResult())); 118 | } 119 | else 120 | { 121 | builder.AddContent(sequence++, 122 | IDecompilationResult.Indent(_service.Concat(fieldResult.RenderResult(), 123 | _service.Constants.SemiColumn))); 124 | builder.AddContent(sequence++, 125 | IDecompilationResult.NewLine()); 126 | } 127 | } 128 | 129 | foreach (var nestedTypeResult in NestedTypeResults) 130 | { 131 | builder.AddContent(sequence++, 132 | IDecompilationResult.Indent(nestedTypeResult.RenderResult())); 133 | builder.AddContent(sequence++, 134 | IDecompilationResult.NewLine()); 135 | } 136 | 137 | builder.AddContent(sequence, _service.Constants.LeftCurlyBracket); 138 | 139 | builder.CloseElement(); 140 | }; 141 | } 142 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Arguments/LdArgStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Collections; 2 | using AsmResolver.DotNet.Signatures.Types; 3 | using AsmResolver.PE.DotNet.Cil; 4 | using Microsoft.AspNetCore.Components; 5 | 6 | namespace Dekompiler.Core.Statements.Arguments; 7 | 8 | public class LdArgStatement : PushableStatement 9 | { 10 | private bool _loadAddr; 11 | private Parameter? _parameter; 12 | 13 | public LdArgStatement(MethodContext context) 14 | : base(context) 15 | { 16 | } 17 | 18 | public override CilCode[] Codes => new[] 19 | { 20 | CilCode.Ldarg, 21 | CilCode.Ldarg_0, 22 | CilCode.Ldarg_1, 23 | CilCode.Ldarg_2, 24 | CilCode.Ldarg_3, 25 | CilCode.Ldarg_S, 26 | CilCode.Ldarga, 27 | CilCode.Ldarga_S 28 | }; 29 | 30 | public override TypeSignature Type => _parameter!.ParameterType; 31 | 32 | public override void Deserialize(CilInstruction instruction) 33 | { 34 | _parameter = (Parameter)instruction.Operand!; 35 | 36 | _loadAddr = instruction.OpCode.Code is CilCode.Ldarga or CilCode.Ldarga_S; 37 | } 38 | 39 | public override RenderFragment Render() 40 | { 41 | var parameterSpan = _parameter!.Index is -1 42 | ? Context.Renderer.Keyword("this") 43 | : Context.Renderer.Span(_parameter!.Name, "parameter"); 44 | 45 | if (_loadAddr) 46 | { 47 | var loadAddrSpan = Context.Renderer.Span("ldarga", "opcode"); 48 | 49 | return Context.Renderer.Concat(loadAddrSpan, Context.Renderer.Constants.RightBracket, parameterSpan, 50 | Context.Renderer.Constants.LeftBracket); 51 | } 52 | 53 | return parameterSpan; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Arguments/StArgStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Collections; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Statements.Arguments; 6 | 7 | public class StArgStatement : CompleteStatement 8 | { 9 | private Parameter? _parameter; 10 | private IStatement? _value; 11 | 12 | public StArgStatement(MethodContext context) 13 | : base(context) 14 | { 15 | } 16 | 17 | public override CilCode[] Codes => new[] 18 | { 19 | CilCode.Starg, 20 | CilCode.Starg_S 21 | }; 22 | 23 | public override void Deserialize(CilInstruction instruction) 24 | { 25 | _parameter = (Parameter)instruction.Operand!; 26 | _value = Context.Stack.Pop(); 27 | } 28 | 29 | public override RenderFragment Render() 30 | { 31 | var parameter = _parameter!.Index is -1 32 | ? Context.Renderer.Keyword("this") 33 | : Context.Renderer.Span(_parameter!.Name, "parameter"); 34 | var value = _value!.Render(); 35 | 36 | return Context.Renderer.Concat(parameter, Context.Renderer.Constants.Space, Context.Renderer.Constants.Equal, 37 | Context.Renderer.Constants.Space, value); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Arrays/LdElemStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using AsmResolver.DotNet.Signatures.Types; 3 | using AsmResolver.PE.DotNet.Cil; 4 | using Microsoft.AspNetCore.Components; 5 | 6 | namespace Dekompiler.Core.Statements.Arrays; 7 | 8 | public class LdElemStatement : PushableStatement 9 | { 10 | private IStatement? _index; 11 | private IStatement? _instance; 12 | private TypeSignature? _ldElemType; 13 | private bool _loadAddr; 14 | 15 | public LdElemStatement(MethodContext context) 16 | : base(context) 17 | { 18 | } 19 | 20 | public override CilCode[] Codes => new[] 21 | { 22 | CilCode.Ldelema, 23 | CilCode.Ldelem, 24 | CilCode.Ldelem_I1, 25 | CilCode.Ldelem_U1, 26 | CilCode.Ldelem_I2, 27 | CilCode.Ldelem_U2, 28 | CilCode.Ldelem_I4, 29 | CilCode.Ldelem_U4, 30 | CilCode.Ldelem_I8, 31 | CilCode.Ldelem_I, 32 | CilCode.Ldelem_R4, 33 | CilCode.Ldelem_R8, 34 | CilCode.Ldelem_Ref 35 | }; 36 | 37 | public override TypeSignature Type => _ldElemType!; 38 | 39 | public override void Deserialize(CilInstruction instruction) 40 | { 41 | var corLib = Context.Method.Module!.CorLibTypeFactory; 42 | 43 | _index = Context.Stack.Pop(); 44 | _instance = Context.Stack.Pop(); 45 | 46 | _ldElemType = instruction.OpCode.Code switch 47 | { 48 | CilCode.Ldelem_I1 => corLib.SByte, 49 | CilCode.Ldelem_U1 => corLib.Byte, 50 | CilCode.Ldelem_I2 => corLib.Int16, 51 | CilCode.Ldelem_U2 => corLib.UInt16, 52 | CilCode.Ldelem_I4 => corLib.Int32, 53 | CilCode.Ldelem_U4 => corLib.UInt32, 54 | CilCode.Ldelem_I8 => corLib.Int64, 55 | CilCode.Ldelem_I => corLib.IntPtr, 56 | CilCode.Ldelem_R4 => corLib.Single, 57 | CilCode.Ldelem_R8 => corLib.Double, 58 | CilCode.Ldelem_Ref => corLib.Object, 59 | CilCode.Ldelem => ((ITypeDefOrRef)instruction.Operand!).ToTypeSignature(), 60 | CilCode.Ldelema => ((ITypeDefOrRef)instruction.Operand!).ToTypeSignature(), 61 | _ => throw new ArgumentOutOfRangeException() 62 | }; 63 | 64 | _loadAddr = instruction.OpCode.Code is CilCode.Ldelema; 65 | } 66 | 67 | public override RenderFragment Render() 68 | { 69 | var instanceSpan = _instance!.Render(); 70 | var indexSpan = _index!.Render(); 71 | 72 | var ldElemSpan = Context.Renderer.Concat(instanceSpan, Context.Renderer.Constants.RightArrayBracket, indexSpan, 73 | Context.Renderer.Constants.LeftArrayBracket); 74 | 75 | if (_loadAddr && !_ldElemType!.IsValueType) 76 | { 77 | var loadAddrSpan = Context.Renderer.Span("ldelema", "opcode"); 78 | 79 | return Context.Renderer.Concat(loadAddrSpan, Context.Renderer.Constants.RightBracket, ldElemSpan, 80 | Context.Renderer.Constants.LeftBracket); 81 | } 82 | 83 | return ldElemSpan; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Arrays/LdLenStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Statements.Arrays; 6 | 7 | public class LdLenStatement : PushableStatement 8 | { 9 | private IStatement? _instance; 10 | 11 | public LdLenStatement(MethodContext context) 12 | : base(context) 13 | { 14 | } 15 | 16 | public override CilCode[] Codes => new[] 17 | { 18 | CilCode.Ldlen 19 | }; 20 | 21 | public override TypeSignature Type => Context.Method.Module!.CorLibTypeFactory.Int32; 22 | 23 | public override void Deserialize(CilInstruction instruction) 24 | { 25 | _instance = Context.Stack.Pop(); 26 | } 27 | 28 | public override RenderFragment Render() 29 | { 30 | var instanceSpan = _instance!.Render(); 31 | 32 | return Context.Renderer.Concat(instanceSpan, Context.Renderer.Constants.Dot, 33 | Context.Renderer.Span("Length", "instanceproperty")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Arrays/NewArrStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using AsmResolver.DotNet.Signatures.Types; 3 | using AsmResolver.PE.DotNet.Cil; 4 | using Dekompiler.Core.TypeSystem; 5 | using Microsoft.AspNetCore.Components; 6 | 7 | namespace Dekompiler.Core.Statements.Arrays; 8 | 9 | public class NewArrStatement : PushableStatement 10 | { 11 | private IStatement? _arrayLength; 12 | private TypeSignature? _arrayType; 13 | 14 | public NewArrStatement(MethodContext context) 15 | : base(context) 16 | { 17 | } 18 | 19 | public override CilCode[] Codes => new[] 20 | { 21 | CilCode.Newarr 22 | }; 23 | 24 | public override TypeSignature Type => _arrayType!.MakeSzArrayType(); 25 | 26 | public override void Deserialize(CilInstruction instruction) 27 | { 28 | _arrayLength = Context.Stack.Pop(); 29 | _arrayType = ((ITypeDefOrRef)instruction.Operand!).ToTypeSignature(); 30 | } 31 | 32 | public override RenderFragment Render() 33 | { 34 | var lengthSpan = _arrayLength!.Render(); 35 | var newSpan = Context.Renderer.Keyword("new"); 36 | 37 | return Context.Renderer.Concat(newSpan, Context.Renderer.Constants.Space, 38 | new TypeSignatureRenderer(Context.Renderer, _arrayType!, Context.Method, Context.Method.DeclaringType) 39 | .RenderMember(), 40 | Context.Renderer.Constants.RightArrayBracket, lengthSpan, 41 | Context.Renderer.Constants.LeftArrayBracket); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Arrays/StElemStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Arrays; 5 | 6 | public class StElemStatement : CompleteStatement 7 | { 8 | private IStatement? _index; 9 | private IStatement? _instance; 10 | private IStatement? _value; 11 | 12 | public StElemStatement(MethodContext context) 13 | : base(context) 14 | { 15 | } 16 | 17 | public override CilCode[] Codes => new[] 18 | { 19 | CilCode.Stelem_I, 20 | CilCode.Stelem_I1, 21 | CilCode.Stelem_I2, 22 | CilCode.Stelem_I4, 23 | CilCode.Stelem_I8, 24 | CilCode.Stelem_R4, 25 | CilCode.Stelem_R8, 26 | CilCode.Stelem_Ref, 27 | CilCode.Stelem 28 | }; 29 | 30 | public override void Deserialize(CilInstruction instruction) 31 | { 32 | _value = Context.Stack.Pop(); 33 | _index = Context.Stack.Pop(); 34 | _instance = Context.Stack.Pop(); 35 | 36 | _value = _value.TryCast(_instance.Type.GetUnderlyingTypeDefOrRef().ToTypeSignature()); 37 | } 38 | 39 | public override RenderFragment Render() 40 | { 41 | var instanceSpan = _instance!.Render(); 42 | var indexSpan = _index!.Render(); 43 | var valueSpan = _value!.Render(); 44 | 45 | return Context.Renderer.Concat(instanceSpan, Context.Renderer.Constants.RightArrayBracket, indexSpan, 46 | Context.Renderer.Constants.LeftArrayBracket, Context.Renderer.Constants.Space, 47 | Context.Renderer.Constants.Equal, Context.Renderer.Constants.Space, valueSpan); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/CompleteStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | 3 | namespace Dekompiler.Core.Statements; 4 | 5 | public abstract class CompleteStatement : Statement 6 | { 7 | protected CompleteStatement(MethodContext context) 8 | : base(context) 9 | { 10 | } 11 | 12 | public override TypeSignature Type => null!; 13 | 14 | public override void InterpretStack() 15 | { 16 | Context.CompleteStatements.Add(this); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Constants/LdNullStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Statements.Constants; 6 | 7 | public class LdNullStatement : PushableStatement 8 | { 9 | public LdNullStatement(MethodContext context) 10 | : base(context) 11 | { 12 | } 13 | 14 | public override CilCode[] Codes => new[] 15 | { 16 | CilCode.Ldnull 17 | }; 18 | 19 | public override TypeSignature Type => null!; 20 | 21 | public override void Deserialize(CilInstruction instruction) 22 | { 23 | } 24 | 25 | public override RenderFragment Render() 26 | { 27 | return Context.Renderer.Keyword("null"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Constants/LdStrStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Statements.Constants; 6 | 7 | public class LdStrStatement : PushableStatement 8 | { 9 | private string _value; 10 | 11 | public LdStrStatement(MethodContext context) 12 | : base(context) 13 | { 14 | } 15 | 16 | public override CilCode[] Codes => new[] 17 | { 18 | CilCode.Ldstr 19 | }; 20 | 21 | public override TypeSignature Type => Context.Method.Module!.CorLibTypeFactory.String; 22 | 23 | public override void Deserialize(CilInstruction instruction) 24 | { 25 | _value = (string)instruction.Operand!; 26 | } 27 | 28 | public override RenderFragment Render() 29 | { 30 | var str = _value 31 | .Replace("\\", "\\\\") 32 | .Replace("\"", "\\\"") 33 | .Replace("\r", "\\r") 34 | .Replace("\n", "\\n"); 35 | 36 | return Context.Renderer.Span(string.Format("\"{0}\"", str), "string"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Constants/LdcI4Statement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Statements.Constants; 6 | 7 | public class LdcI4Statement : PushableStatement 8 | { 9 | private int _value; 10 | 11 | public LdcI4Statement(MethodContext context) 12 | : base(context) 13 | { 14 | } 15 | 16 | public override CilCode[] Codes => new[] 17 | { 18 | CilCode.Ldc_I4_M1, 19 | CilCode.Ldc_I4_0, 20 | CilCode.Ldc_I4_1, 21 | CilCode.Ldc_I4_2, 22 | CilCode.Ldc_I4_3, 23 | CilCode.Ldc_I4_4, 24 | CilCode.Ldc_I4_5, 25 | CilCode.Ldc_I4_6, 26 | CilCode.Ldc_I4_7, 27 | CilCode.Ldc_I4_8, 28 | CilCode.Ldc_I4_S, 29 | CilCode.Ldc_I4 30 | }; 31 | 32 | public override TypeSignature Type => Context.Method.Module!.CorLibTypeFactory.Int32; 33 | 34 | public int Value => _value; 35 | 36 | public override void Deserialize(CilInstruction instruction) 37 | { 38 | _value = instruction.GetLdcI4Constant(); 39 | } 40 | 41 | public override RenderFragment Render() 42 | { 43 | return Context.Renderer.Span(_value.ToString(), "number"); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Constants/LdcI8Statement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Statements.Constants; 6 | 7 | public class LdcI8Statement : PushableStatement 8 | { 9 | private long _value; 10 | 11 | public LdcI8Statement(MethodContext context) 12 | : base(context) 13 | { 14 | } 15 | 16 | public override CilCode[] Codes => new[] 17 | { 18 | CilCode.Ldc_I8 19 | }; 20 | 21 | public override TypeSignature Type => Context.Method.Module!.CorLibTypeFactory.Int64; 22 | 23 | public override void Deserialize(CilInstruction instruction) 24 | { 25 | _value = (long)instruction.Operand!; 26 | } 27 | 28 | public override RenderFragment Render() 29 | { 30 | return Context.Renderer.Span(string.Format("{0}L", _value), "number"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Constants/LdcR4Statement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Statements.Constants; 6 | 7 | public class LdcR4Statement : PushableStatement 8 | { 9 | private float _value; 10 | 11 | public LdcR4Statement(MethodContext context) 12 | : base(context) 13 | { 14 | } 15 | 16 | public override CilCode[] Codes => new[] 17 | { 18 | CilCode.Ldc_R4 19 | }; 20 | 21 | public override TypeSignature Type => Context.Method.Module!.CorLibTypeFactory.Single; 22 | 23 | public override void Deserialize(CilInstruction instruction) 24 | { 25 | _value = (float)instruction.Operand!; 26 | } 27 | 28 | public override RenderFragment Render() 29 | { 30 | return Context.Renderer.Span(string.Format("{0}f", _value), "number"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Constants/LdcR8Statement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Statements.Constants; 6 | 7 | public class LdcR8Statement : PushableStatement 8 | { 9 | private double _value; 10 | 11 | public LdcR8Statement(MethodContext context) 12 | : base(context) 13 | { 14 | } 15 | 16 | public override CilCode[] Codes => new[] 17 | { 18 | CilCode.Ldc_R8 19 | }; 20 | 21 | public override TypeSignature Type => Context.Method.Module!.CorLibTypeFactory.Double; 22 | 23 | public override void Deserialize(CilInstruction instruction) 24 | { 25 | _value = (double)instruction.Operand!; 26 | } 27 | 28 | public override RenderFragment Render() 29 | { 30 | return Context.Renderer.Span(string.Format("{0}f", _value), "number"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Conversions/ConvStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Dekompiler.Core.Statements.Operators; 4 | using Dekompiler.Core.TypeSystem; 5 | using Microsoft.AspNetCore.Components; 6 | 7 | namespace Dekompiler.Core.Statements.Conversions; 8 | 9 | public class ConvStatement : PushableStatement 10 | { 11 | private IStatement? _value; 12 | private TypeSignature? _convType; 13 | 14 | public ConvStatement(MethodContext context) 15 | : base(context) 16 | { 17 | } 18 | 19 | public override CilCode[] Codes => new[] 20 | { 21 | CilCode.Conv_I1, 22 | CilCode.Conv_I2, 23 | CilCode.Conv_I4, 24 | CilCode.Conv_I8, 25 | CilCode.Conv_R4, 26 | CilCode.Conv_R8, 27 | CilCode.Conv_U4, 28 | CilCode.Conv_U1, 29 | CilCode.Conv_U2, 30 | CilCode.Conv_U8, 31 | CilCode.Conv_I, 32 | CilCode.Conv_U, 33 | CilCode.Conv_R_Un, 34 | CilCode.Conv_Ovf_I1, 35 | CilCode.Conv_Ovf_U1, 36 | CilCode.Conv_Ovf_I2, 37 | CilCode.Conv_Ovf_U2, 38 | CilCode.Conv_Ovf_I4, 39 | CilCode.Conv_Ovf_U4, 40 | CilCode.Conv_Ovf_I8, 41 | CilCode.Conv_Ovf_U8, 42 | CilCode.Conv_Ovf_I, 43 | CilCode.Conv_Ovf_U, 44 | CilCode.Conv_Ovf_I1_Un, 45 | CilCode.Conv_Ovf_I2_Un, 46 | CilCode.Conv_Ovf_I4_Un, 47 | CilCode.Conv_Ovf_I8_Un, 48 | CilCode.Conv_Ovf_U1_Un, 49 | CilCode.Conv_Ovf_U2_Un, 50 | CilCode.Conv_Ovf_U4_Un, 51 | CilCode.Conv_Ovf_U8_Un, 52 | CilCode.Conv_Ovf_I_Un, 53 | CilCode.Conv_Ovf_U_Un, 54 | }; 55 | 56 | public override TypeSignature Type => _convType!; 57 | 58 | public override void Deserialize(CilInstruction instruction) 59 | { 60 | _value = Context.Stack.Pop(); 61 | 62 | var corLib = Context.Method.Module!.CorLibTypeFactory; 63 | 64 | _convType = instruction.OpCode.Code switch 65 | { 66 | CilCode.Conv_I or CilCode.Conv_Ovf_I or CilCode.Conv_Ovf_I_Un => corLib.IntPtr, 67 | CilCode.Conv_I1 or CilCode.Conv_Ovf_I1 or CilCode.Conv_Ovf_I1_Un => corLib.SByte, 68 | CilCode.Conv_I2 or CilCode.Conv_Ovf_I2 or CilCode.Conv_Ovf_I2_Un => corLib.Int16, 69 | CilCode.Conv_I4 or CilCode.Conv_Ovf_I4 or CilCode.Conv_Ovf_I4_Un => corLib.Int32, 70 | CilCode.Conv_I8 or CilCode.Conv_Ovf_I8 or CilCode.Conv_Ovf_I8_Un => corLib.Int64, 71 | CilCode.Conv_U or CilCode.Conv_Ovf_U or CilCode.Conv_Ovf_U_Un => corLib.UIntPtr, 72 | CilCode.Conv_U1 or CilCode.Conv_Ovf_U1 or CilCode.Conv_Ovf_U1_Un => corLib.Byte, 73 | CilCode.Conv_U2 or CilCode.Conv_Ovf_U2 or CilCode.Conv_Ovf_U2_Un => corLib.UInt16, 74 | CilCode.Conv_U4 or CilCode.Conv_Ovf_U4 or CilCode.Conv_Ovf_U4_Un => corLib.UInt32, 75 | CilCode.Conv_U8 or CilCode.Conv_Ovf_U8 or CilCode.Conv_Ovf_U8_Un => corLib.UInt64, 76 | CilCode.Conv_R4 => corLib.Single, 77 | CilCode.Conv_R8 or CilCode.Conv_R_Un => corLib.Double, 78 | _ => throw new ArgumentOutOfRangeException(nameof(instruction.OpCode.Code)) 79 | }; 80 | } 81 | 82 | public override RenderFragment Render() 83 | { 84 | var valueSpan = _value!.Render(); 85 | 86 | var convSpan = 87 | new TypeSignatureRenderer(Context.Renderer, _convType!, Context.Method, Context.Method.DeclaringType) 88 | .RenderMember(); 89 | 90 | if (_value is BinaryOperatorStatement or UnaryOperatorStatement) 91 | { 92 | valueSpan = Context.Renderer.Concat(Context.Renderer.Constants.RightBracket, valueSpan, 93 | Context.Renderer.Constants.LeftBracket); 94 | } 95 | 96 | return Context.Renderer.Concat(Context.Renderer.Constants.RightBracket, convSpan, 97 | Context.Renderer.Constants.LeftBracket, valueSpan); 98 | } 99 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/IStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Statements; 6 | 7 | public interface IStatement 8 | { 9 | CilCode[] Codes 10 | { 11 | get; 12 | } 13 | 14 | TypeSignature Type 15 | { 16 | get; 17 | } 18 | 19 | void InterpretStack(); 20 | void Deserialize(CilInstruction instruction); 21 | RenderFragment Render(); 22 | } 23 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/MethodContext.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using AsmResolver.DotNet.Code.Cil; 3 | 4 | namespace Dekompiler.Core.Statements; 5 | 6 | public class MethodContext 7 | { 8 | private readonly UniqueNameGenerator _generator = new(); 9 | private readonly Dictionary _generatorCache = new(); 10 | 11 | #pragma warning disable CS8618 12 | private MethodContext() 13 | { 14 | } 15 | #pragma warning restore CS8618 16 | 17 | public MethodContext(MethodDefinition methodDefinition, RendererService renderer) 18 | { 19 | Method = methodDefinition; 20 | Renderer = renderer; 21 | InitializedVariable = methodDefinition.CilMethodBody?.LocalVariables.ToDictionary(loc => loc, _ => false) ?? new(); 22 | Stack = new Stack(); 23 | CompleteStatements = new List(); 24 | } 25 | 26 | public Dictionary InitializedVariable { get; } 27 | 28 | public RendererService Renderer { get; } 29 | 30 | public Stack Stack { get; } 31 | 32 | public List CompleteStatements { get; } 33 | 34 | public MethodDefinition Method { get; } 35 | 36 | public static MethodContext Null => new(); 37 | 38 | public bool Empty { get; set; } 39 | 40 | public string GenerateName(CilLocalVariable variable) 41 | { 42 | var type = (variable.VariableType.Resolve()?.Name ?? variable.VariableType.Name)!.Value; 43 | 44 | var index = type.LastIndexOf('`'); 45 | var name = index is not -1 46 | ? type.Substring(0, index) 47 | : type; 48 | 49 | if (_generatorCache.TryGetValue(variable, out var generateName)) 50 | return generateName; 51 | return _generatorCache[variable] = _generator.GenerateUniqueName(name); 52 | } 53 | } 54 | 55 | public class UniqueNameGenerator 56 | { 57 | private readonly Dictionary nameCache; 58 | 59 | public UniqueNameGenerator() 60 | { 61 | nameCache = new Dictionary(); 62 | } 63 | 64 | public string GenerateUniqueName(string name) 65 | { 66 | if (nameCache.ContainsKey(name)) 67 | { 68 | var count = nameCache[name] + 1; 69 | nameCache[name] = count; 70 | name = $"{name}{count}"; 71 | } 72 | else 73 | { 74 | nameCache.Add(name, 0); 75 | } 76 | 77 | name = CamelCase(name); 78 | return name; 79 | } 80 | 81 | private string CamelCase(string word) 82 | { 83 | if (string.IsNullOrEmpty(word)) 84 | return word; 85 | 86 | return char.ToLowerInvariant(word[0]) + word.Substring(1); 87 | } 88 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Miscellaneous/CommentStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Miscellaneous; 5 | 6 | public class CommentStatement : CompleteStatement 7 | { 8 | private string _comment; 9 | 10 | public CommentStatement(MethodContext context, string comment) : base(context) 11 | { 12 | _comment = comment; 13 | } 14 | 15 | public override CilCode[] Codes => Array.Empty(); 16 | 17 | public override void Deserialize(CilInstruction instruction) 18 | { 19 | } 20 | 21 | public override RenderFragment Render() 22 | { 23 | return Context.Renderer.Span($@"/* {_comment} */", "comment"); 24 | } 25 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Miscellaneous/DupStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Code.Cil; 2 | using AsmResolver.DotNet.Signatures.Types; 3 | using AsmResolver.PE.DotNet.Cil; 4 | using Dekompiler.Core.Statements.Arguments; 5 | using Dekompiler.Core.Statements.Variables; 6 | using Microsoft.AspNetCore.Components; 7 | 8 | namespace Dekompiler.Core.Statements.Miscellaneous; 9 | 10 | public class DupStatement : Statement 11 | { 12 | private bool _createVariable = true; 13 | private IStatement? _value; 14 | 15 | public DupStatement(MethodContext context) 16 | : base(context) 17 | { 18 | } 19 | 20 | public override CilCode[] Codes => new[] 21 | { 22 | CilCode.Dup 23 | }; 24 | 25 | public override TypeSignature Type => _value!.Type; 26 | 27 | public override void InterpretStack() 28 | { 29 | if (_createVariable) 30 | { 31 | var variable = new CilLocalVariable(Type); 32 | 33 | Context.InitializedVariable[variable] = false; 34 | 35 | var stInstruction = new CilInstruction(CilOpCodes.Stloc, variable); 36 | var stLoc = new StLocStatement(Context); 37 | 38 | Context.Stack.Push(_value!); 39 | 40 | stLoc.Deserialize(stInstruction); 41 | stLoc.InterpretStack(); 42 | 43 | var ldInstruction = new CilInstruction(CilOpCodes.Ldloc, variable); 44 | var ldLoc = new LdLocStatement(Context); 45 | 46 | ldLoc.Deserialize(ldInstruction); 47 | ldLoc.InterpretStack(); 48 | ldLoc.InterpretStack(); 49 | 50 | return; 51 | } 52 | 53 | Context.Stack.Push(_value!); 54 | Context.Stack.Push(_value!); 55 | } 56 | 57 | public override void Deserialize(CilInstruction instruction) 58 | { 59 | var value = Context.Stack.Pop(); 60 | 61 | if (value is LdArgStatement or LdLocStatement) 62 | _createVariable = false; 63 | 64 | _value = value; 65 | } 66 | 67 | public override RenderFragment Render() 68 | { 69 | throw new NotImplementedException(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Miscellaneous/KeywordStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Statements.Miscellaneous; 6 | 7 | public class KeywordStatement : PushableStatement 8 | { 9 | private string? _keyword; 10 | private TypeSignature? _type; 11 | 12 | public KeywordStatement(MethodContext context, string keyword, TypeSignature? type) : base(context) 13 | { 14 | _keyword = keyword; 15 | _type = type; 16 | } 17 | 18 | public override CilCode[] Codes => Array.Empty(); 19 | public override TypeSignature Type => _type!; 20 | 21 | public override void Deserialize(CilInstruction instruction) 22 | { 23 | } 24 | 25 | public override RenderFragment Render() 26 | { 27 | return Context.Renderer.Keyword(_keyword); 28 | } 29 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Miscellaneous/MkRefAnyStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Statements.Miscellaneous; 6 | 7 | public class MkRefAnyStatement : PushableStatement 8 | { 9 | private IStatement? _value; 10 | 11 | public MkRefAnyStatement(MethodContext context) : base(context) 12 | { 13 | } 14 | 15 | public override CilCode[] Codes => new[] 16 | { 17 | CilCode.Mkrefany 18 | }; 19 | 20 | public override TypeSignature Type => Context.Method.Module!.CorLibTypeFactory.TypedReference; 21 | 22 | public override void Deserialize(CilInstruction instruction) 23 | { 24 | _value = Context.Stack.Pop(); 25 | } 26 | 27 | public override RenderFragment Render() 28 | { 29 | var makeRefKeyword = Context.Renderer.Keyword("__makeref"); 30 | 31 | var valueSpan = _value!.Render(); 32 | 33 | return Context.Renderer.Concat(makeRefKeyword, Context.Renderer.Constants.RightBracket, valueSpan, 34 | Context.Renderer.Constants.LeftBracket); 35 | } 36 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Miscellaneous/NopStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Statements.Miscellaneous; 6 | 7 | public class NopStatement : Statement 8 | { 9 | public NopStatement(MethodContext context) 10 | : base(context) 11 | { 12 | } 13 | 14 | public override CilCode[] Codes => new[] 15 | { 16 | CilCode.Nop 17 | }; 18 | 19 | public override TypeSignature Type => null!; 20 | 21 | public override void InterpretStack() 22 | { 23 | } 24 | 25 | public override void Deserialize(CilInstruction instruction) 26 | { 27 | } 28 | 29 | public override RenderFragment Render() 30 | { 31 | throw new NotImplementedException(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Miscellaneous/PopStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Miscellaneous; 5 | 6 | public class PopStatement : CompleteStatement 7 | { 8 | private IStatement? _value; 9 | 10 | public PopStatement(MethodContext context) 11 | : base(context) 12 | { 13 | } 14 | 15 | public override CilCode[] Codes => new[] 16 | { 17 | CilCode.Pop 18 | }; 19 | 20 | public override void Deserialize(CilInstruction instruction) 21 | { 22 | _value = Context.Stack.Pop(); 23 | } 24 | 25 | public override RenderFragment Render() 26 | { 27 | return _value!.Render(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Miscellaneous/RetStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Statements.Miscellaneous; 6 | 7 | public class RetStatement : Statement 8 | { 9 | private TypeSignature? _retType; 10 | private IStatement? _retValue; 11 | 12 | public RetStatement(MethodContext context) 13 | : base(context) 14 | { 15 | } 16 | 17 | public override CilCode[] Codes => new[] 18 | { 19 | CilCode.Ret 20 | }; 21 | 22 | public override TypeSignature Type => _retType!; 23 | 24 | public override void InterpretStack() 25 | { 26 | if (Context.Method.Signature!.ReturnsValue) 27 | Context.CompleteStatements.Add(this); 28 | } 29 | 30 | public override void Deserialize(CilInstruction instruction) 31 | { 32 | if (Context.Method.Signature!.ReturnsValue) 33 | { 34 | _retValue = Context.Stack.Pop().TryCast(Context.Method.Signature.ReturnType); 35 | _retType = _retValue.Type; 36 | } 37 | } 38 | 39 | public override RenderFragment Render() 40 | { 41 | var keyword = Context.Renderer.Keyword("return"); 42 | if (_retValue is null) 43 | return keyword; 44 | return Context.Renderer.Concat(keyword, Context.Renderer.Constants.Space, _retValue.Render()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Miscellaneous/ThrowStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Miscellaneous; 5 | 6 | public class ThrowStatement : CompleteStatement 7 | { 8 | private IStatement? _exception; 9 | 10 | public ThrowStatement(MethodContext context) : base(context) 11 | { 12 | } 13 | 14 | public override CilCode[] Codes => new[] 15 | { 16 | CilCode.Throw 17 | }; 18 | 19 | public override void Deserialize(CilInstruction instruction) 20 | { 21 | _exception = Context.Stack.Pop(); 22 | } 23 | 24 | public override RenderFragment Render() 25 | { 26 | var throwSpan = Context.Renderer.Keyword("throw"); 27 | 28 | return Context.Renderer.Join(Context.Renderer.Constants.Space, throwSpan, _exception!.Render()); 29 | } 30 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Operators/AddStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Operators; 5 | 6 | public class AddStatement : BinaryOperatorStatement 7 | { 8 | public AddStatement(MethodContext context) 9 | : base(context) 10 | { 11 | } 12 | 13 | public override CilCode[] Codes => new[] 14 | { 15 | CilCode.Add, 16 | CilCode.Add_Ovf, 17 | CilCode.Add_Ovf_Un 18 | }; 19 | 20 | public override RenderFragment Operator => Context.Renderer.Text("+"); 21 | } 22 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Operators/AndStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Operators; 5 | 6 | public class AndStatement : BinaryOperatorStatement 7 | { 8 | public AndStatement(MethodContext context) 9 | : base(context) 10 | { 11 | } 12 | 13 | public override CilCode[] Codes => new[] 14 | { 15 | CilCode.And 16 | }; 17 | 18 | public override RenderFragment Operator => Context.Renderer.Text("&"); 19 | } 20 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Operators/BinaryOperatorStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Statements.Operators; 6 | 7 | public abstract class BinaryOperatorStatement : PushableStatement 8 | { 9 | private IStatement? _left; 10 | private IStatement? _right; 11 | 12 | protected BinaryOperatorStatement(MethodContext context) 13 | : base(context) 14 | { 15 | } 16 | 17 | public abstract RenderFragment Operator 18 | { 19 | get; 20 | } 21 | 22 | public override TypeSignature Type => _left!.Type; 23 | 24 | public override void Deserialize(CilInstruction instruction) 25 | { 26 | _right = Context.Stack.Pop(); 27 | _left = Context.Stack.Pop(); 28 | } 29 | 30 | public override RenderFragment Render() 31 | { 32 | var leftSpan = _left!.Render(); 33 | var rightSpan = _right!.Render(); 34 | 35 | if (_right is BinaryOperatorStatement) 36 | { 37 | rightSpan = Context.Renderer.Concat(Context.Renderer.Constants.RightBracket, rightSpan, 38 | Context.Renderer.Constants.LeftBracket); 39 | } 40 | 41 | return Context.Renderer.Concat(leftSpan, Context.Renderer.Constants.Space, Operator, 42 | Context.Renderer.Constants.Space, rightSpan); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Operators/CeqStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Operators; 5 | 6 | public class CeqStatement : BinaryOperatorStatement 7 | { 8 | public CeqStatement(MethodContext context) 9 | : base(context) 10 | { 11 | } 12 | 13 | public override CilCode[] Codes => new[] 14 | { 15 | CilCode.Ceq 16 | }; 17 | 18 | public override RenderFragment Operator => Context.Renderer.Text("=="); 19 | } 20 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Operators/CgtStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Operators; 5 | 6 | public class CgtStatement : BinaryOperatorStatement 7 | { 8 | public CgtStatement(MethodContext context) 9 | : base(context) 10 | { 11 | } 12 | 13 | public override CilCode[] Codes => new[] 14 | { 15 | CilCode.Cgt, 16 | CilCode.Cgt_Un 17 | }; 18 | 19 | public override RenderFragment Operator => Context.Renderer.Text(">"); 20 | } 21 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Operators/CltStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Operators; 5 | 6 | public class CltStatement : BinaryOperatorStatement 7 | { 8 | public CltStatement(MethodContext context) 9 | : base(context) 10 | { 11 | } 12 | 13 | public override CilCode[] Codes => new[] 14 | { 15 | CilCode.Clt, 16 | CilCode.Clt_Un 17 | }; 18 | 19 | public override RenderFragment Operator => Context.Renderer.Text("<"); 20 | } 21 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Operators/DivStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Operators; 5 | 6 | public class DivStatement : BinaryOperatorStatement 7 | { 8 | public DivStatement(MethodContext context) 9 | : base(context) 10 | { 11 | } 12 | 13 | public override CilCode[] Codes => new[] 14 | { 15 | CilCode.Div, 16 | CilCode.Div_Un 17 | }; 18 | 19 | public override RenderFragment Operator => Context.Renderer.Text("/"); 20 | } 21 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Operators/MulStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Operators; 5 | 6 | public class MulStatement : BinaryOperatorStatement 7 | { 8 | public MulStatement(MethodContext context) 9 | : base(context) 10 | { 11 | } 12 | 13 | public override CilCode[] Codes => new[] 14 | { 15 | CilCode.Mul, 16 | CilCode.Mul_Ovf, 17 | CilCode.Mul_Ovf_Un 18 | }; 19 | 20 | public override RenderFragment Operator => Context.Renderer.Text("*"); 21 | } 22 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Operators/NegStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Operators; 5 | 6 | public class NegStatement : UnaryOperatorStatement 7 | { 8 | public NegStatement(MethodContext context) 9 | : base(context) 10 | { 11 | } 12 | 13 | public override CilCode[] Codes => new[] 14 | { 15 | CilCode.Neg 16 | }; 17 | 18 | public override RenderFragment Operator => Context.Renderer.Text("-"); 19 | } 20 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Operators/NotStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Operators; 5 | 6 | public class NotStatement : UnaryOperatorStatement 7 | { 8 | public NotStatement(MethodContext context) 9 | : base(context) 10 | { 11 | } 12 | 13 | public override CilCode[] Codes => new[] 14 | { 15 | CilCode.Not 16 | }; 17 | 18 | public override RenderFragment Operator => Context.Renderer.Text("~"); 19 | } 20 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Operators/OrStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Operators; 5 | 6 | public class OrStatement : BinaryOperatorStatement 7 | { 8 | public OrStatement(MethodContext context) 9 | : base(context) 10 | { 11 | } 12 | 13 | public override CilCode[] Codes => new[] 14 | { 15 | CilCode.Or 16 | }; 17 | 18 | public override RenderFragment Operator => Context.Renderer.Text("|"); 19 | } 20 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Operators/RemStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Operators; 5 | 6 | public class RemStatement : BinaryOperatorStatement 7 | { 8 | public RemStatement(MethodContext context) 9 | : base(context) 10 | { 11 | } 12 | 13 | public override CilCode[] Codes => new[] 14 | { 15 | CilCode.Rem, 16 | CilCode.Rem_Un 17 | }; 18 | 19 | public override RenderFragment Operator => Context.Renderer.Text("%"); 20 | } 21 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Operators/ShlStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Operators; 5 | 6 | public class ShlStatement : BinaryOperatorStatement 7 | { 8 | public ShlStatement(MethodContext context) 9 | : base(context) 10 | { 11 | } 12 | 13 | public override CilCode[] Codes => new[] 14 | { 15 | CilCode.Shl 16 | }; 17 | 18 | public override RenderFragment Operator => Context.Renderer.Text("<<"); 19 | } 20 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Operators/ShrStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Operators; 5 | 6 | public class ShrStatement : BinaryOperatorStatement 7 | { 8 | public ShrStatement(MethodContext context) 9 | : base(context) 10 | { 11 | } 12 | 13 | public override CilCode[] Codes => new[] 14 | { 15 | CilCode.Shr, 16 | CilCode.Shr_Un 17 | }; 18 | 19 | public override RenderFragment Operator => Context.Renderer.Text(">>"); 20 | } 21 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Operators/SubStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Operators; 5 | 6 | public class SubStatement : BinaryOperatorStatement 7 | { 8 | public SubStatement(MethodContext context) 9 | : base(context) 10 | { 11 | } 12 | 13 | public override CilCode[] Codes => new[] 14 | { 15 | CilCode.Sub, 16 | CilCode.Sub_Ovf, 17 | CilCode.Sub_Ovf_Un 18 | }; 19 | 20 | public override RenderFragment Operator => Context.Renderer.Text("-"); 21 | } 22 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Operators/UnaryOperatorStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Statements.Operators; 6 | 7 | public abstract class UnaryOperatorStatement : PushableStatement 8 | { 9 | private IStatement? _right; 10 | 11 | protected UnaryOperatorStatement(MethodContext context) 12 | : base(context) 13 | { 14 | } 15 | 16 | public abstract RenderFragment Operator 17 | { 18 | get; 19 | } 20 | 21 | public override TypeSignature Type => _right!.Type; 22 | 23 | public override void Deserialize(CilInstruction instruction) 24 | { 25 | _right = Context.Stack.Pop(); 26 | } 27 | 28 | public override RenderFragment Render() 29 | { 30 | var rightSpan = _right!.Render(); 31 | 32 | return Context.Renderer.Concat(Operator, rightSpan); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Operators/XorStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.PE.DotNet.Cil; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.Statements.Operators; 5 | 6 | public class XorStatement : BinaryOperatorStatement 7 | { 8 | public XorStatement(MethodContext context) 9 | : base(context) 10 | { 11 | } 12 | 13 | public override CilCode[] Codes => new[] 14 | { 15 | CilCode.Xor 16 | }; 17 | 18 | public override RenderFragment Operator => Context.Renderer.Text("^"); 19 | } 20 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Pointers/LdIndStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Dekompiler.Core.Statements.Operators; 4 | using Dekompiler.Core.TypeSystem; 5 | using Microsoft.AspNetCore.Components; 6 | 7 | namespace Dekompiler.Core.Statements.Pointers; 8 | 9 | public class LdIndStatement : PushableStatement 10 | { 11 | private IStatement? _address; 12 | private TypeSignature? _ldIndType; 13 | 14 | public LdIndStatement(MethodContext context) 15 | : base(context) 16 | { 17 | } 18 | 19 | public override CilCode[] Codes => new[] 20 | { 21 | CilCode.Ldind_I1, 22 | CilCode.Ldind_U1, 23 | CilCode.Ldind_I2, 24 | CilCode.Ldind_U2, 25 | CilCode.Ldind_I4, 26 | CilCode.Ldind_U4, 27 | CilCode.Ldind_I8, 28 | CilCode.Ldind_I, 29 | CilCode.Ldind_R4, 30 | CilCode.Ldind_R8, 31 | CilCode.Ldind_Ref 32 | }; 33 | 34 | public override TypeSignature Type => _ldIndType!; 35 | 36 | public override void Deserialize(CilInstruction instruction) 37 | { 38 | var corLib = Context.Method.Module!.CorLibTypeFactory; 39 | 40 | _address = Context.Stack.Pop(); 41 | 42 | _ldIndType = instruction.OpCode.Code switch 43 | { 44 | CilCode.Ldind_I1 => corLib.SByte, 45 | CilCode.Ldind_U1 => corLib.Byte, 46 | CilCode.Ldind_I2 => corLib.Int16, 47 | CilCode.Ldind_U2 => corLib.UInt16, 48 | CilCode.Ldind_I4 => corLib.Int32, 49 | CilCode.Ldind_U4 => corLib.UInt32, 50 | CilCode.Ldind_I8 => corLib.Int64, 51 | CilCode.Ldind_I => corLib.IntPtr, 52 | CilCode.Ldind_R4 => corLib.Single, 53 | CilCode.Ldind_R8 => corLib.Double, 54 | CilCode.Ldind_Ref => corLib.Object, 55 | _ => throw new ArgumentOutOfRangeException() 56 | }; 57 | } 58 | 59 | public override RenderFragment Render() 60 | { 61 | var castAddrSpan = Context.Renderer.Concat(Context.Renderer.Constants.Star, 62 | Context.Renderer.Constants.RightBracket, 63 | new TypeSignatureRenderer(Context.Renderer, _ldIndType!, Context.Method, Context.Method.DeclaringType) 64 | .RenderMember(), 65 | Context.Renderer.Constants.Star, Context.Renderer.Constants.LeftBracket); 66 | 67 | var addressSpan = _address!.Render(); 68 | 69 | // *(TYPE*)(ADDRESS + SIZE) 70 | if (_address is BinaryOperatorStatement) 71 | addressSpan = Context.Renderer.Concat(Context.Renderer.Constants.RightBracket, addressSpan, 72 | Context.Renderer.Constants.LeftBracket); 73 | 74 | return Context.Renderer.Concat(castAddrSpan, addressSpan); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Pointers/LocAllocStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using AsmResolver.DotNet.Signatures.Types; 3 | using AsmResolver.PE.DotNet.Cil; 4 | using Dekompiler.Core.TypeSystem; 5 | using Microsoft.AspNetCore.Components; 6 | 7 | namespace Dekompiler.Core.Statements.Pointers; 8 | 9 | // TODO: Use dfg (Data flow graph) to indicate this instruction type before deserializing process. Example: locAlloc, stLoc.0 (int32*, PointerTypeSignature). 10 | public class LocAllocStatement : PushableStatement 11 | { 12 | private IStatement? _size; 13 | 14 | public LocAllocStatement(MethodContext context) 15 | : base(context) 16 | { 17 | } 18 | 19 | public override CilCode[] Codes => new[] 20 | { 21 | CilCode.Localloc 22 | }; 23 | 24 | public override TypeSignature Type => Context.Method.Module!.CorLibTypeFactory.Byte; 25 | 26 | public override void Deserialize(CilInstruction instruction) 27 | { 28 | _size = Context.Stack.Pop(); 29 | } 30 | 31 | public override RenderFragment Render() 32 | { 33 | var sizeSpan = _size!.Render(); 34 | var allocSpan = Context.Renderer.Keyword("stackalloc"); 35 | 36 | return Context.Renderer.Concat(allocSpan, Context.Renderer.Constants.Space, 37 | new TypeSignatureRenderer(Context.Renderer, Type, Context.Method, Context.Method.DeclaringType) 38 | .RenderMember(), Context.Renderer.Constants.RightArrayBracket, sizeSpan, 39 | Context.Renderer.Constants.LeftArrayBracket); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Pointers/StIndStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using AsmResolver.DotNet.Signatures.Types; 3 | using AsmResolver.PE.DotNet.Cil; 4 | using Dekompiler.Core.Statements.Operators; 5 | using Dekompiler.Core.TypeSystem; 6 | using Microsoft.AspNetCore.Components; 7 | 8 | namespace Dekompiler.Core.Statements.Pointers; 9 | 10 | public class StIndStatement : CompleteStatement 11 | { 12 | private IStatement? _address; 13 | private TypeSignature? _stIndType; 14 | private IStatement? _value; 15 | 16 | public StIndStatement(MethodContext context) 17 | : base(context) 18 | { 19 | } 20 | 21 | public override CilCode[] Codes => new[] 22 | { 23 | CilCode.Stind_I1, 24 | CilCode.Stind_I2, 25 | CilCode.Stind_I4, 26 | CilCode.Stind_I8, 27 | CilCode.Stind_I, 28 | CilCode.Stind_R4, 29 | CilCode.Stind_R8, 30 | CilCode.Stind_Ref, 31 | CilCode.Stobj 32 | }; 33 | 34 | public override void Deserialize(CilInstruction instruction) 35 | { 36 | var corLib = Context.Method.Module!.CorLibTypeFactory; 37 | _value = Context.Stack.Pop(); 38 | _address = Context.Stack.Pop(); 39 | 40 | _stIndType = instruction.OpCode.Code switch 41 | { 42 | CilCode.Stind_I1 => corLib.SByte, 43 | CilCode.Stind_I2 => corLib.Int16, 44 | CilCode.Stind_I4 => corLib.Int32, 45 | CilCode.Stind_I8 => corLib.Int64, 46 | CilCode.Stind_I => corLib.IntPtr, 47 | CilCode.Stind_R4 => corLib.Single, 48 | CilCode.Stind_R8 => corLib.Double, 49 | CilCode.Stind_Ref => corLib.Object, 50 | CilCode.Stobj => ((ITypeDefOrRef)instruction.Operand!).ToTypeSignature(), 51 | _ => throw new ArgumentOutOfRangeException() 52 | }; 53 | } 54 | 55 | public override RenderFragment Render() 56 | { 57 | var castAddrSpan = Context.Renderer.Concat(Context.Renderer.Constants.Star, 58 | Context.Renderer.Constants.RightBracket, 59 | new TypeSignatureRenderer(Context.Renderer, _stIndType!, Context.Method, Context.Method.DeclaringType) 60 | .RenderMember(), 61 | Context.Renderer.Constants.Star, Context.Renderer.Constants.LeftBracket); 62 | 63 | var addressSpan = _address!.Render(); 64 | var valueSpan = _value!.Render(); 65 | 66 | // *(TYPE*)(ADDRESS + SIZE) = ... 67 | if (_address is BinaryOperatorStatement) 68 | addressSpan = Context.Renderer.Concat(Context.Renderer.Constants.RightBracket, addressSpan, 69 | Context.Renderer.Constants.LeftBracket); 70 | 71 | return Context.Renderer.Concat(castAddrSpan, addressSpan, Context.Renderer.Constants.Space, 72 | Context.Renderer.Constants.Equal, Context.Renderer.Constants.Space, valueSpan); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Prefixes/PrefixStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Statements.Prefixes; 6 | 7 | public class PrefixStatement : Statement 8 | { 9 | public PrefixStatement(MethodContext context) : base(context) 10 | { 11 | } 12 | 13 | public override CilCode[] Codes => new[] 14 | { 15 | CilCode.Volatile, 16 | CilCode.Unaligned, 17 | CilCode.Constrained, 18 | CilCode.Readonly, 19 | CilCode.Tailcall, 20 | CilCode.Prefix7, 21 | CilCode.Prefix6, 22 | CilCode.Prefix5, 23 | CilCode.Prefix4, 24 | CilCode.Prefix3, 25 | CilCode.Prefix2, 26 | CilCode.Prefix1, 27 | CilCode.Prefixref, 28 | }; 29 | 30 | public override TypeSignature Type => null!; 31 | 32 | public override void InterpretStack() 33 | { 34 | } 35 | 36 | public override void Deserialize(CilInstruction instruction) 37 | { 38 | } 39 | 40 | public override RenderFragment Render() 41 | { 42 | throw new NotImplementedException(); 43 | } 44 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/PushableStatement.cs: -------------------------------------------------------------------------------- 1 | namespace Dekompiler.Core.Statements; 2 | 3 | public abstract class PushableStatement : Statement 4 | { 5 | protected PushableStatement(MethodContext context) 6 | : base(context) 7 | { 8 | } 9 | 10 | public override void InterpretStack() 11 | { 12 | Context.Stack.Push(this); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Statement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Signatures.Types; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.Statements; 6 | 7 | public abstract class Statement : IStatement 8 | { 9 | protected Statement(MethodContext context) 10 | { 11 | Context = context; 12 | } 13 | 14 | protected MethodContext Context 15 | { 16 | get; 17 | } 18 | 19 | public abstract CilCode[] Codes 20 | { 21 | get; 22 | } 23 | 24 | public abstract TypeSignature Type 25 | { 26 | get; 27 | } 28 | 29 | public abstract void InterpretStack(); 30 | public abstract void Deserialize(CilInstruction instruction); 31 | public abstract RenderFragment Render(); 32 | 33 | public virtual MethodContext GetContext() => Context; 34 | } 35 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/TypeSystem/CallStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using AsmResolver.DotNet.Signatures; 3 | using AsmResolver.DotNet.Signatures.Types; 4 | using AsmResolver.PE.DotNet.Cil; 5 | using Dekompiler.Core.TypeSystem; 6 | using Microsoft.AspNetCore.Components; 7 | 8 | namespace Dekompiler.Core.Statements.TypeSystem; 9 | 10 | public class CallStatement : Statement 11 | { 12 | private IStatement[]? _arguments; 13 | private IStatement? _instance; 14 | private IMethodDescriptor? _method; 15 | private CallType _type; 16 | private IHasSemantics? _association; 17 | 18 | public CallStatement(MethodContext context) 19 | : base(context) 20 | { 21 | } 22 | 23 | public override CilCode[] Codes => new[] 24 | { 25 | CilCode.Call, 26 | CilCode.Callvirt 27 | }; 28 | 29 | public override TypeSignature Type => _method!.Signature!.ReturnType; 30 | 31 | public override void InterpretStack() 32 | { 33 | if (_method!.Signature!.ReturnsValue) 34 | Context.Stack.Push(this); 35 | else 36 | Context.CompleteStatements.Add(this); 37 | } 38 | 39 | public override void Deserialize(CilInstruction instruction) 40 | { 41 | var method = (IMethodDescriptor)instruction.Operand!; 42 | 43 | 44 | var arguments = new List(); 45 | 46 | var totalArguments = method.Signature!.ParameterTypes.Count; 47 | 48 | var ctx = GenericContext.FromMember(method); 49 | 50 | for (var i = totalArguments; i-- > 0;) 51 | { 52 | var t = method.Signature!.ParameterTypes[i]; 53 | if (t is GenericParameterSignature genericParameter) 54 | { 55 | arguments.Add(Context.Stack.Pop().TryCast(ctx.GetTypeArgument(genericParameter))); 56 | } 57 | else 58 | { 59 | arguments.Add(Context.Stack.Pop().TryCast(t)); 60 | } 61 | } 62 | 63 | arguments.Reverse(); 64 | 65 | if (method.Signature!.HasThis) 66 | { 67 | _instance = Context.Stack.Pop(); 68 | } 69 | 70 | var resolved = method.Resolve(); 71 | 72 | _type = resolved switch 73 | { 74 | { IsGetMethod: true } when resolved.Signature!.ParameterTypes.Count >= 1 => CallType.IndexerGetter, 75 | { IsSetMethod: true } when resolved.Signature!.ParameterTypes.Count >= 2 => CallType.IndexerSetter, 76 | { IsGetMethod: true } when resolved.Signature!.ParameterTypes.Count <= 0 => CallType.Getter, 77 | { IsSetMethod: true } when resolved.Signature!.ParameterTypes.Count <= 1 => CallType.Setter, 78 | _ => CallType.Normal 79 | }; 80 | 81 | if (_type is not CallType.Normal) 82 | { 83 | _association = resolved!.Semantics!.Association; 84 | } 85 | 86 | _method = method; 87 | _arguments = arguments.ToArray(); 88 | } 89 | 90 | public override RenderFragment Render() 91 | { 92 | var instanceSpan = _instance is not null 93 | ? _instance.Render() 94 | : new TypeSignatureRenderer(Context.Renderer, _method!.DeclaringType!.ToTypeSignature(), _method, 95 | _method!.DeclaringType!.ToTypeDefOrRef()).RenderMember(); 96 | 97 | var methodSpan = _type switch 98 | { 99 | CallType.Normal => new MethodRenderer(Context.Renderer, _method!).RenderMember(), 100 | _ => new PropertyRenderer(Context.Renderer, (PropertyDefinition)_association!).RenderMember() 101 | }; 102 | 103 | var argumentsSpans = 104 | Context.Renderer.Join( 105 | Context.Renderer.Concat(Context.Renderer.Constants.Comma, Context.Renderer.Constants.Space), 106 | _arguments!.Select(arg => arg.Render()).ToArray()); 107 | 108 | return _type switch 109 | { 110 | CallType.IndexerGetter => IndexerGet(), 111 | CallType.IndexerSetter => IndexerSet(), 112 | CallType.Getter => Get(), 113 | CallType.Setter => Set(), 114 | CallType.Normal => Call(), 115 | _ => throw new ArgumentOutOfRangeException() 116 | }; 117 | 118 | RenderFragment Call() 119 | { 120 | return Context.Renderer.Concat(instanceSpan, Context.Renderer.Constants.Dot, methodSpan, 121 | Context.Renderer.Constants.RightBracket, argumentsSpans, Context.Renderer.Constants.LeftBracket); 122 | } 123 | 124 | RenderFragment IndexerGet() 125 | { 126 | return Context.Renderer.Concat(instanceSpan, 127 | Context.Renderer.Constants.RightArrayBracket, argumentsSpans, 128 | Context.Renderer.Constants.LeftArrayBracket); 129 | } 130 | 131 | RenderFragment IndexerSet() 132 | { 133 | var value = _arguments!.Last().Render(); 134 | 135 | argumentsSpans = 136 | Context.Renderer.Join( 137 | Context.Renderer.Concat(Context.Renderer.Constants.Comma, Context.Renderer.Constants.Space), 138 | _arguments!.SkipLast(1).Select(arg => arg.Render()).ToArray()); 139 | 140 | return Context.Renderer.Concat(instanceSpan, 141 | Context.Renderer.Constants.RightArrayBracket, argumentsSpans, 142 | Context.Renderer.Constants.LeftArrayBracket, Context.Renderer.Constants.Space, 143 | Context.Renderer.Constants.Equal, Context.Renderer.Constants.Space, value); 144 | } 145 | 146 | RenderFragment Get() 147 | { 148 | return Context.Renderer.Concat(instanceSpan, Context.Renderer.Constants.Dot, methodSpan); 149 | } 150 | 151 | RenderFragment Set() 152 | { 153 | return Context.Renderer.Concat(instanceSpan, Context.Renderer.Constants.Dot, methodSpan, 154 | Context.Renderer.Constants.Space, Context.Renderer.Constants.Equal, Context.Renderer.Constants.Space, 155 | _arguments!.Last().Render()); 156 | } 157 | } 158 | 159 | // TODO: EventAdd, EventFire, EventRemove 160 | internal enum CallType 161 | { 162 | IndexerGetter, 163 | IndexerSetter, 164 | Getter, 165 | Setter, 166 | Normal 167 | } 168 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/TypeSystem/CalliStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using AsmResolver.DotNet.Signatures; 3 | using AsmResolver.DotNet.Signatures.Types; 4 | using AsmResolver.PE.DotNet.Cil; 5 | using Microsoft.AspNetCore.Components; 6 | 7 | namespace Dekompiler.Core.Statements.TypeSystem; 8 | 9 | public class CalliStatement : Statement 10 | { 11 | private MethodSignature? _signature; 12 | private IStatement[]? _arguments; 13 | private IStatement? _address; 14 | 15 | public CalliStatement(MethodContext context) : base(context) 16 | { 17 | } 18 | 19 | public override CilCode[] Codes => new[] 20 | { 21 | CilCode.Calli 22 | }; 23 | 24 | public override TypeSignature Type => _signature!.ReturnType; 25 | 26 | public override void InterpretStack() 27 | { 28 | if (_signature!.ReturnsValue) 29 | Context.Stack.Push(this); 30 | else 31 | Context.CompleteStatements.Add(this); 32 | } 33 | 34 | public override void Deserialize(CilInstruction instruction) 35 | { 36 | _signature = (MethodSignature?)((StandAloneSignature)instruction.Operand!).Signature; 37 | 38 | var arguments = new List(); 39 | 40 | var totalArguments = _signature!.ParameterTypes.Count; 41 | 42 | _address = Context.Stack.Pop(); 43 | 44 | for (var i = 0; i < totalArguments; i++) 45 | arguments.Add(Context.Stack.Pop()); 46 | 47 | if (_signature.HasThis) 48 | { 49 | arguments.Add(Context.Stack.Pop()); 50 | } 51 | 52 | arguments.Reverse(); 53 | 54 | _arguments = arguments.ToArray(); 55 | } 56 | 57 | public override RenderFragment Render() 58 | { 59 | var calliSpan = Context.Renderer.Span("calli", "opcode"); 60 | 61 | var sigSpan = Context.Renderer.Text(_signature!.ToString()); 62 | 63 | var separator = Context.Renderer.Concat(Context.Renderer.Constants.Comma, Context.Renderer.Constants.Space); 64 | 65 | var arguments = new List(); 66 | 67 | arguments.Add(sigSpan); 68 | arguments.AddRange(_arguments!.Select(arg => arg.Render())); 69 | arguments.Add(_address!.Render()); 70 | 71 | return Context.Renderer.Concat(calliSpan, Context.Renderer.Constants.RightBracket, 72 | Context.Renderer.Join(separator, arguments.ToArray()), Context.Renderer.Constants.LeftBracket); 73 | } 74 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/TypeSystem/CastStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using AsmResolver.DotNet.Signatures.Types; 3 | using AsmResolver.PE.DotNet.Cil; 4 | using Dekompiler.Core.Statements.Operators; 5 | using Dekompiler.Core.TypeSystem; 6 | using Microsoft.AspNetCore.Components; 7 | 8 | namespace Dekompiler.Core.Statements.TypeSystem; 9 | 10 | public class CastStatement : PushableStatement 11 | { 12 | private IStatement? _value; 13 | private TypeSignature? _castType; 14 | 15 | public CastStatement(MethodContext context) : base(context) 16 | { 17 | } 18 | 19 | public override CilCode[] Codes => new[] 20 | { 21 | CilCode.Box, 22 | CilCode.Castclass, 23 | CilCode.Unbox, 24 | CilCode.Unbox_Any 25 | }; 26 | 27 | public override TypeSignature Type => _castType!; 28 | 29 | public override void Deserialize(CilInstruction instruction) 30 | { 31 | _value = Context.Stack.Pop(); 32 | 33 | var type = ((ITypeDefOrRef)instruction.Operand!).ToTypeSignature(); 34 | 35 | _castType = type; 36 | } 37 | 38 | public override RenderFragment Render() 39 | { 40 | var valueSpan = _value!.Render(); 41 | 42 | // redundant cast 43 | if (_value.Type == _castType) 44 | { 45 | return valueSpan; 46 | } 47 | 48 | var convSpan = 49 | new TypeSignatureRenderer(Context.Renderer, _castType!, Context.Method, Context.Method.DeclaringType) 50 | .RenderMember(); 51 | 52 | return Context.Renderer.Concat(Context.Renderer.Constants.RightBracket, convSpan, 53 | Context.Renderer.Constants.LeftBracket, valueSpan); 54 | } 55 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/TypeSystem/LdFldStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using AsmResolver.DotNet.Signatures.Types; 3 | using AsmResolver.PE.DotNet.Cil; 4 | using Dekompiler.Core.TypeSystem; 5 | using Microsoft.AspNetCore.Components; 6 | 7 | namespace Dekompiler.Core.Statements.TypeSystem; 8 | 9 | public class LdFldStatement : PushableStatement 10 | { 11 | private IFieldDescriptor? _field; 12 | private IStatement? _instance; 13 | private bool _loadAddr; 14 | 15 | public LdFldStatement(MethodContext context) 16 | : base(context) 17 | { 18 | } 19 | 20 | public override CilCode[] Codes => new[] 21 | { 22 | CilCode.Ldfld, 23 | CilCode.Ldflda, 24 | CilCode.Ldsfld, 25 | CilCode.Ldsflda 26 | }; 27 | 28 | public override TypeSignature Type => _field!.Signature!.FieldType; 29 | 30 | public override void Deserialize(CilInstruction instruction) 31 | { 32 | var fieldRef = (IFieldDescriptor)instruction.Operand!; 33 | 34 | var hasInstance = instruction.OpCode.Code is CilCode.Ldfld or CilCode.Ldflda; 35 | 36 | if (hasInstance) 37 | _instance = Context.Stack.Pop(); 38 | 39 | _field = fieldRef; 40 | _loadAddr = instruction.OpCode.Code is CilCode.Ldflda or CilCode.Ldsflda; 41 | } 42 | 43 | public override RenderFragment Render() 44 | { 45 | var instanceSpan = _instance is null 46 | ? new TypeSignatureRenderer(Context.Renderer, _field!.DeclaringType!.ToTypeSignature(), Context.Method, 47 | _field!.DeclaringType!.Resolve()!).RenderMember() 48 | : _instance.Render(); 49 | 50 | var fieldSpan = new FieldRenderer(Context.Renderer, _field!).RenderMember(); 51 | 52 | var ldFldSpan = Context.Renderer.Concat(instanceSpan, Context.Renderer.Constants.Dot, fieldSpan); 53 | 54 | if (_loadAddr) 55 | { 56 | var loadAddrSpan = Context.Renderer.Span("ld(s)flda", "opcode"); 57 | 58 | return Context.Renderer.Concat(loadAddrSpan, Context.Renderer.Constants.RightBracket, ldFldSpan, 59 | Context.Renderer.Constants.LeftBracket); 60 | } 61 | 62 | return ldFldSpan; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/TypeSystem/LdFtnStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using AsmResolver.DotNet.Signatures.Types; 3 | using AsmResolver.PE.DotNet.Cil; 4 | using Dekompiler.Core.TypeSystem; 5 | using Microsoft.AspNetCore.Components; 6 | 7 | namespace Dekompiler.Core.Statements.TypeSystem; 8 | 9 | public class LdFtnStatement : PushableStatement 10 | { 11 | private IMethodDescriptor? _method; 12 | private bool _virtual = false; 13 | 14 | public LdFtnStatement(MethodContext context) : base(context) 15 | { 16 | } 17 | 18 | public override CilCode[] Codes => new[] 19 | { 20 | CilCode.Ldftn, 21 | CilCode.Ldvirtftn 22 | }; 23 | 24 | public override TypeSignature Type => Context.Method.Module!.CorLibTypeFactory.IntPtr; 25 | 26 | public override void Deserialize(CilInstruction instruction) 27 | { 28 | _method = (IMethodDescriptor)instruction.Operand!; 29 | _virtual = instruction.OpCode.Code is CilCode.Ldvirtftn; 30 | } 31 | 32 | public override RenderFragment Render() 33 | { 34 | var ftnSpan = Context.Renderer.Span(_virtual ? "ldvirtftn" : "ldftn", "opcode"); 35 | 36 | return Context.Renderer.Concat(ftnSpan, Context.Renderer.Constants.RightBracket, 37 | new MethodRenderer(Context.Renderer, _method!).RenderMember(), Context.Renderer.Constants.LeftBracket); 38 | } 39 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/TypeSystem/LdTokenStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using AsmResolver.DotNet.Signatures.Types; 3 | using AsmResolver.PE.DotNet.Cil; 4 | using Dekompiler.Core.TypeSystem; 5 | using Microsoft.AspNetCore.Components; 6 | 7 | namespace Dekompiler.Core.Statements.TypeSystem; 8 | 9 | public class LdTokenStatement : PushableStatement 10 | { 11 | private TypeSignature? _ldTokenType; 12 | private IMemberDescriptor? _member; 13 | private LdTok? _tokenType; 14 | 15 | public LdTokenStatement(MethodContext context) 16 | : base(context) 17 | { 18 | } 19 | 20 | public override CilCode[] Codes => new[] 21 | { 22 | CilCode.Ldtoken 23 | }; 24 | 25 | public override TypeSignature Type => _ldTokenType!; 26 | 27 | public override void Deserialize(CilInstruction instruction) 28 | { 29 | var member = (IMemberDescriptor)instruction.Operand!; 30 | var scope = Context.Method.Module!.CorLibTypeFactory.CorLibScope; 31 | 32 | (_ldTokenType, _tokenType) = member switch 33 | { 34 | IFieldDescriptor => ( 35 | scope.CreateTypeReference(nameof(System), nameof(RuntimeFieldHandle)).ToTypeSignature(), LdTok.Field), 36 | IMethodDescriptor => ( 37 | scope.CreateTypeReference(nameof(System), nameof(RuntimeMethodHandle)).ToTypeSignature(), LdTok.Method), 38 | ITypeDescriptor => (scope.CreateTypeReference(nameof(System), nameof(RuntimeTypeHandle)).ToTypeSignature(), 39 | LdTok.Type), 40 | _ => throw new ArgumentOutOfRangeException() 41 | }; 42 | 43 | 44 | _member = member; 45 | } 46 | 47 | public override RenderFragment Render() 48 | { 49 | var (keyword, property) = _tokenType switch 50 | { 51 | LdTok.Field => ("fieldof", "FieldHandle"), 52 | LdTok.Method => ("methodof", "MethodHandle"), 53 | LdTok.Type => ("typeof", "TypeHandle"), 54 | _ => throw new ArgumentOutOfRangeException() 55 | }; 56 | 57 | var memberSpan = _tokenType switch 58 | { 59 | LdTok.Field => new FieldRenderer(Context.Renderer, ((IFieldDescriptor)_member!).Resolve()!).RenderMember(), 60 | LdTok.Method => new MethodRenderer(Context.Renderer, ((IMethodDescriptor)_member!).Resolve()!).RenderMember(), 61 | LdTok.Type => new TypeRenderer(Context.Renderer, ((ITypeDescriptor)_member!).Resolve()!).RenderMember(), 62 | _ => throw new ArgumentOutOfRangeException() 63 | }; 64 | 65 | if (_member.DeclaringType is not null) 66 | { 67 | var declaringSpan = new TypeSignatureRenderer(Context.Renderer, _member.DeclaringType.ToTypeSignature(), 68 | _member, _member.DeclaringType.ToTypeDefOrRef()).RenderMember(); 69 | 70 | return Context.Renderer.Concat(Context.Renderer.Keyword(keyword), Context.Renderer.Constants.RightBracket, 71 | declaringSpan, Context.Renderer.Constants.Dot, memberSpan, Context.Renderer.Constants.LeftBracket, 72 | Context.Renderer.Constants.Dot, 73 | Context.Renderer.Span(property, "instanceproperty")); 74 | } 75 | 76 | return Context.Renderer.Concat(Context.Renderer.Keyword(keyword), Context.Renderer.Constants.RightBracket, 77 | memberSpan, Context.Renderer.Constants.LeftBracket, Context.Renderer.Constants.Dot, 78 | Context.Renderer.Span(property, "instanceproperty")); 79 | } 80 | 81 | internal enum LdTok 82 | { 83 | Type, 84 | Method, 85 | Field 86 | } 87 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/TypeSystem/NewObjStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using AsmResolver.DotNet.Signatures; 3 | using AsmResolver.DotNet.Signatures.Types; 4 | using AsmResolver.PE.DotNet.Cil; 5 | using Dekompiler.Core.TypeSystem; 6 | using Microsoft.AspNetCore.Components; 7 | 8 | namespace Dekompiler.Core.Statements.TypeSystem; 9 | 10 | public class NewObjStatement : PushableStatement 11 | { 12 | private IStatement[]? _arguments; 13 | private IMethodDescriptor? _constructor; 14 | 15 | public NewObjStatement(MethodContext context) 16 | : base(context) 17 | { 18 | } 19 | 20 | public override CilCode[] Codes => new[] 21 | { 22 | CilCode.Newobj 23 | }; 24 | 25 | public override TypeSignature Type => _constructor!.DeclaringType!.ToTypeSignature(); 26 | 27 | public override void Deserialize(CilInstruction instruction) 28 | { 29 | var method = (IMethodDescriptor)instruction.Operand!; 30 | 31 | 32 | var arguments = new List(); 33 | 34 | var totalArguments = method.Signature!.ParameterTypes.Count; 35 | 36 | var ctx = GenericContext.FromMember(method); 37 | 38 | for (var i = totalArguments; i-- > 0;) 39 | { 40 | var t = method.Signature!.ParameterTypes[i]; 41 | if (t is GenericParameterSignature genericParameter) 42 | { 43 | arguments.Add(Context.Stack.Pop().TryCast(ctx.GetTypeArgument(genericParameter))); 44 | } 45 | else 46 | { 47 | arguments.Add(Context.Stack.Pop().TryCast(t)); 48 | } 49 | } 50 | 51 | arguments.Reverse(); 52 | 53 | _constructor = method; 54 | _arguments = arguments.ToArray(); 55 | } 56 | 57 | public override RenderFragment Render() 58 | { 59 | var methodSpan = 60 | new TypeSignatureRenderer(Context.Renderer, _constructor!.DeclaringType!.ToTypeSignature(), _constructor, 61 | _constructor.DeclaringType.Resolve()!).RenderMember(); 62 | 63 | var argumentsSpans = _arguments!.SelectMany(arg => 64 | { 65 | if (arg != _arguments!.Last()) 66 | return new[] { arg.Render(), Context.Renderer.Constants.Comma, Context.Renderer.Constants.Space }; 67 | return new[] { arg.Render() }; 68 | }); 69 | 70 | var temp = new List(); 71 | 72 | temp.Add(Context.Renderer.Keyword("new")); 73 | temp.Add(Context.Renderer.Constants.Space); 74 | temp.Add(methodSpan); 75 | temp.Add(Context.Renderer.Constants.RightBracket); 76 | temp.AddRange(argumentsSpans); 77 | temp.Add(Context.Renderer.Constants.LeftBracket); 78 | 79 | return Context.Renderer.Concat(temp.ToArray()); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/TypeSystem/SizeOfStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using AsmResolver.DotNet.Signatures.Types; 3 | using AsmResolver.PE.DotNet.Cil; 4 | using Dekompiler.Core.TypeSystem; 5 | using Microsoft.AspNetCore.Components; 6 | 7 | namespace Dekompiler.Core.Statements.TypeSystem; 8 | 9 | public class SizeOfStatement : PushableStatement 10 | { 11 | private ITypeDefOrRef? _type; 12 | 13 | public SizeOfStatement(MethodContext context) 14 | : base(context) 15 | { 16 | } 17 | 18 | public override CilCode[] Codes => new[] 19 | { 20 | CilCode.Sizeof 21 | }; 22 | 23 | public override TypeSignature Type => Context.Method.Module!.CorLibTypeFactory.Int32; 24 | 25 | public override void Deserialize(CilInstruction instruction) 26 | { 27 | _type = (ITypeDefOrRef)instruction.Operand!; 28 | } 29 | 30 | public override RenderFragment Render() 31 | { 32 | var sizeOfSpan = Context.Renderer.Keyword("sizeof"); 33 | 34 | return Context.Renderer.Concat(sizeOfSpan, Context.Renderer.Constants.RightBracket, 35 | new TypeSignatureRenderer(Context.Renderer, _type!.ToTypeSignature(), Context.Method, Context.Method.DeclaringType!).RenderMember(), 36 | Context.Renderer.Constants.LeftBracket); 37 | } 38 | } -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/TypeSystem/StFldStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Dekompiler.Core.TypeSystem; 4 | using Microsoft.AspNetCore.Components; 5 | 6 | namespace Dekompiler.Core.Statements.TypeSystem; 7 | 8 | public class StFldStatement : CompleteStatement 9 | { 10 | private IFieldDescriptor? _field; 11 | private IStatement? _instance; 12 | private IStatement? _value; 13 | 14 | public StFldStatement(MethodContext context) 15 | : base(context) 16 | { 17 | } 18 | 19 | public override CilCode[] Codes => new[] 20 | { 21 | CilCode.Stfld, 22 | CilCode.Stsfld 23 | }; 24 | 25 | public override void Deserialize(CilInstruction instruction) 26 | { 27 | var fieldRef = (IFieldDescriptor)instruction.Operand!; 28 | var value = Context.Stack.Pop().TryCast(fieldRef.Signature!.FieldType); 29 | 30 | var hasInstance = instruction.OpCode.Code is CilCode.Stfld; 31 | 32 | if (hasInstance) 33 | _instance = Context.Stack.Pop(); 34 | 35 | _value = value; 36 | _field = fieldRef; 37 | } 38 | 39 | public override RenderFragment Render() 40 | { 41 | var valueSpan = _value!.Render(); 42 | 43 | var instanceSpan = _instance is null 44 | ? new TypeSignatureRenderer(Context.Renderer, ((ITypeDefOrRef)_field?.DeclaringType!).ToTypeSignature(), 45 | Context.Method, Context.Method.DeclaringType!).RenderMember() 46 | : _instance.Render(); 47 | 48 | var fieldSpan = new FieldRenderer(Context.Renderer, _field!).RenderMember(); 49 | 50 | var fldSpan = Context.Renderer.Concat(instanceSpan, Context.Renderer.Constants.Dot, fieldSpan); 51 | 52 | 53 | return Context.Renderer.Concat(fldSpan, Context.Renderer.Constants.Space, Context.Renderer.Constants.Equal, 54 | Context.Renderer.Constants.Space, valueSpan); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Variables/LdLocStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Code.Cil; 2 | using AsmResolver.DotNet.Signatures.Types; 3 | using AsmResolver.PE.DotNet.Cil; 4 | using Microsoft.AspNetCore.Components; 5 | 6 | namespace Dekompiler.Core.Statements.Variables; 7 | 8 | public class LdLocStatement : PushableStatement 9 | { 10 | private bool _loadAddr; 11 | private CilLocalVariable? _variable; 12 | 13 | public LdLocStatement(MethodContext context) 14 | : base(context) 15 | { 16 | } 17 | 18 | public override CilCode[] Codes => new[] 19 | { 20 | CilCode.Ldloc_0, 21 | CilCode.Ldloc_1, 22 | CilCode.Ldloc_2, 23 | CilCode.Ldloc_3, 24 | CilCode.Ldloc_S, 25 | CilCode.Ldloc, 26 | CilCode.Ldloca, 27 | CilCode.Ldloca_S 28 | }; 29 | 30 | public override TypeSignature Type => _variable!.VariableType; 31 | 32 | public override void Deserialize(CilInstruction instruction) 33 | { 34 | _variable = (CilLocalVariable)instruction.Operand!; 35 | 36 | _loadAddr = instruction.OpCode.Code is CilCode.Ldloca or CilCode.Ldloca_S; 37 | } 38 | 39 | public override RenderFragment Render() 40 | { 41 | var variableSpan = Context.Renderer.Span(Context.GenerateName(_variable!), "local"); 42 | 43 | if (_loadAddr && !Type.IsValueType) 44 | { 45 | var loadAddrSpan = Context.Renderer.Span("ldloca", "opcode"); 46 | 47 | return Context.Renderer.Concat(loadAddrSpan, Context.Renderer.Constants.RightBracket, variableSpan, 48 | Context.Renderer.Constants.LeftBracket); 49 | } 50 | 51 | return variableSpan; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Dekompiler.Core/Statements/Variables/StLocStatement.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet.Code.Cil; 2 | using AsmResolver.PE.DotNet.Cil; 3 | using Dekompiler.Core.TypeSystem; 4 | using Microsoft.AspNetCore.Components; 5 | 6 | namespace Dekompiler.Core.Statements.Variables; 7 | 8 | public class StLocStatement : CompleteStatement 9 | { 10 | private IStatement? _value; 11 | private CilLocalVariable? _variable; 12 | 13 | public StLocStatement(MethodContext context) 14 | : base(context) 15 | { 16 | } 17 | 18 | public override CilCode[] Codes => new[] 19 | { 20 | CilCode.Stloc_0, 21 | CilCode.Stloc_1, 22 | CilCode.Stloc_2, 23 | CilCode.Stloc_3, 24 | CilCode.Stloc_S, 25 | CilCode.Stloc 26 | }; 27 | 28 | public override void Deserialize(CilInstruction instruction) 29 | { 30 | _variable = (CilLocalVariable)instruction.Operand!; 31 | _value = Context.Stack.Pop(); 32 | } 33 | 34 | public override RenderFragment Render() 35 | { 36 | var variableSpan = Context.Renderer.Span(Context.GenerateName(_variable!), "local"); 37 | var value = _value!.Render(); 38 | 39 | if (!Context.InitializedVariable[_variable!]) 40 | { 41 | variableSpan = Context.Renderer.Concat( 42 | new TypeSignatureRenderer(Context.Renderer, _variable!.VariableType, Context.Method, 43 | Context.Method.DeclaringType).RenderMember(), 44 | Context.Renderer.Constants.Space, variableSpan); 45 | Context.InitializedVariable[_variable] = true; 46 | } 47 | 48 | return Context.Renderer.Concat(variableSpan, Context.Renderer.Constants.Space, Context.Renderer.Constants.Equal, 49 | Context.Renderer.Constants.Space, value); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Dekompiler.Core/TypeSystem/EventRenderer.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.TypeSystem; 5 | 6 | public class EventRenderer 7 | { 8 | private readonly RendererService _service; 9 | private EventDefinition? _event; 10 | 11 | public EventRenderer(RendererService service, EventDefinition @event) 12 | { 13 | _event = @event; 14 | _service = service; 15 | } 16 | 17 | public RenderFragment RenderMember() 18 | { 19 | var tmp = _event!.AddMethod ?? _event!.FireMethod ?? _event!.RemoveMethod; 20 | 21 | var themeColor = tmp!.IsStatic ? "staticevent" : "instanceevent"; 22 | 23 | return _service.Span(_event.Name, themeColor); 24 | } 25 | } -------------------------------------------------------------------------------- /Dekompiler.Core/TypeSystem/FieldRenderer.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using AsmResolver.PE.DotNet.Metadata.Tables.Rows; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Dekompiler.Core.TypeSystem; 6 | 7 | public class FieldRenderer 8 | { 9 | private readonly RendererService _service; 10 | private IFieldDescriptor? _member; 11 | 12 | public FieldRenderer(RendererService service, IFieldDescriptor field) 13 | { 14 | _member = field; 15 | _service = service; 16 | } 17 | 18 | public RenderFragment RenderMember() 19 | { 20 | 21 | var member = _member switch 22 | { 23 | FieldDefinition fieldDefinition => RenderFieldDefinition(fieldDefinition), 24 | MemberReference memberReference => new FieldRenderer(_service, (IFieldDescriptor)memberReference.Resolve()!).RenderMember(), 25 | _ => throw new ArgumentOutOfRangeException(nameof(_member)) 26 | }; 27 | 28 | return member; 29 | } 30 | 31 | private RenderFragment RenderFieldDefinition(FieldDefinition field) 32 | { 33 | var themeColor = field switch 34 | { 35 | { DeclaringType: { BaseType: { FullName: "System.Enum" } } } => "enumfield", 36 | { IsLiteral: true } => "literalfield", 37 | { IsStatic: true } => "staticfield", 38 | { IsStatic: false } => "instancefield" 39 | }; 40 | 41 | return _service.Span(field.Name, themeColor); 42 | } 43 | } -------------------------------------------------------------------------------- /Dekompiler.Core/TypeSystem/MethodRenderer.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.TypeSystem; 5 | 6 | public class MethodRenderer 7 | { 8 | private readonly RendererService _service; 9 | private IMethodDescriptor? _member; 10 | 11 | public MethodRenderer(RendererService service, IMethodDescriptor method) 12 | { 13 | _member = method; 14 | _service = service; 15 | } 16 | 17 | public RenderFragment RenderMember() 18 | { 19 | return _member switch 20 | { 21 | MemberReference memberReference => new MethodRenderer(_service, 22 | (IMethodDescriptor)memberReference.Resolve()!).RenderMember(), 23 | MethodDefinition methodDefinition => RenderMethodDefinition(methodDefinition), 24 | MethodSpecification methodSpecification => RenderMethodSpecification(methodSpecification), 25 | _ => throw new ArgumentOutOfRangeException(nameof(_member)) 26 | }; 27 | } 28 | 29 | private RenderFragment RenderMethodDefinition(MethodDefinition method) 30 | { 31 | var themeColor = method switch 32 | { 33 | { IsStatic: true } staticMethod => staticMethod.Signature!.HasThis ? "extensionmethod" : "staticmethod", 34 | { IsStatic: false } => "instancemethod" 35 | }; 36 | 37 | return _service.Span(method.Name, themeColor); 38 | } 39 | 40 | private RenderFragment RenderMethodSpecification(MethodSpecification method) 41 | { 42 | var methodSpan = RenderMethodDefinition(method.Resolve()!); 43 | 44 | var typeArgs = method.Signature!.TypeArguments 45 | .Select(arg => 46 | new TypeSignatureRenderer(_service, arg, _member!, _member!.DeclaringType!.ToTypeDefOrRef()) 47 | .RenderMember()).ToArray(); 48 | 49 | var separator = _service.Concat(_service.Constants.Comma, _service.Constants.Space); 50 | 51 | return _service.Concat(methodSpan, _service.Constants.RightThan, _service.Join(separator, typeArgs), 52 | _service.Constants.LeftThan); 53 | } 54 | } -------------------------------------------------------------------------------- /Dekompiler.Core/TypeSystem/PropertyRenderer.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.TypeSystem; 5 | 6 | public class PropertyRenderer 7 | { 8 | private readonly RendererService _service; 9 | private PropertyDefinition? _property; 10 | 11 | public PropertyRenderer(RendererService service, PropertyDefinition property) 12 | { 13 | _property = property; 14 | _service = service; 15 | } 16 | 17 | public RenderFragment RenderMember() 18 | { 19 | var themeColor = _property!.Signature!.HasThis ? "instanceproperty" : "staticproperty"; 20 | 21 | return _service.Span(_property.Name, themeColor); 22 | } 23 | } -------------------------------------------------------------------------------- /Dekompiler.Core/TypeSystem/TypeRenderer.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Core.TypeSystem; 5 | 6 | public class TypeRenderer 7 | { 8 | private readonly RendererService _service; 9 | private ITypeDefOrRef? _member; 10 | 11 | public TypeRenderer(RendererService service, ITypeDefOrRef type) 12 | { 13 | _member = type; 14 | _service = service; 15 | } 16 | 17 | public RenderFragment RenderMember() 18 | { 19 | return _member switch 20 | { 21 | TypeDefinition typeDefinition => RenderTypeDefinition(typeDefinition), 22 | TypeReference typeReference => RenderTypeReference(typeReference), 23 | TypeSpecification typeSpecification => RenderTypeSpecification(typeSpecification), 24 | _ => throw new ArgumentOutOfRangeException(nameof(_member)) 25 | }; 26 | } 27 | 28 | private RenderFragment RenderTypeSpecification(TypeSpecification type) 29 | { 30 | return new TypeSignatureRenderer(_service, type.Signature!, type).RenderMember(); 31 | } 32 | 33 | private RenderFragment RenderTypeReference(TypeReference type) 34 | { 35 | return RenderTypeDefinition(type.Resolve()!); 36 | } 37 | 38 | private RenderFragment RenderTypeDefinition(TypeDefinition type) 39 | { 40 | var themeColor = type switch 41 | { 42 | { IsInterface: true } => "interface", 43 | { IsDelegate: true } => "delegate", 44 | { IsEnum: true } => "enum", 45 | { IsValueType: true } => "valuetype", 46 | { IsSealed: true, IsAbstract: true } => "statictype", 47 | { IsSealed: true } => "sealedtype", 48 | _ => "type" 49 | }; 50 | 51 | var index = type.Name!.LastIndexOf('`'); 52 | return _service.Span(type.GenericParameters.Any() && index is not -1 53 | ? type.Name?.Value.Substring(0, index) 54 | : type.Name?.Value, themeColor); 55 | } 56 | } -------------------------------------------------------------------------------- /Dekompiler.Core/TypeSystem/TypeSignatureRenderer.cs: -------------------------------------------------------------------------------- 1 | using AsmResolver.DotNet; 2 | using AsmResolver.DotNet.Signatures; 3 | using AsmResolver.DotNet.Signatures.Types; 4 | using Microsoft.AspNetCore.Components; 5 | 6 | namespace Dekompiler.Core.TypeSystem; 7 | 8 | public class TypeSignatureRenderer 9 | { 10 | private readonly ITypeDefOrRef? _declaringType; 11 | private readonly IMemberDescriptor _member; 12 | private readonly RendererService _service; 13 | private TypeSignature _signature; 14 | private bool _declare; 15 | 16 | public TypeSignatureRenderer(RendererService service, TypeSignature signature, IMemberDescriptor member, 17 | ITypeDefOrRef? declaringType = null, bool declare = true) 18 | { 19 | _service = service; 20 | _member = member; 21 | _declaringType = declaringType; 22 | _signature = signature; 23 | _declare = declare; 24 | } 25 | 26 | public RenderFragment RenderMember() 27 | { 28 | var renderedSignature = _signature switch 29 | { 30 | PointerTypeSignature pointerType => RenderPointerTypeSignature(pointerType), 31 | CorLibTypeSignature corLibType => RenderCorLibTypeSignature(corLibType), 32 | ArrayTypeSignature arrayType => RenderArrayTypeSignature(arrayType), 33 | BoxedTypeSignature boxedType => RenderBoxedTypeSignature(boxedType), 34 | ByReferenceTypeSignature byReferenceType => RenderByReferenceTypeSignature(byReferenceType), 35 | SzArrayTypeSignature szArrayType => RenderSzArrayTypeSignature(szArrayType), 36 | GenericInstanceTypeSignature genericInstanceType => RenderGenericInstanceTypeSignature(genericInstanceType), 37 | GenericParameterSignature genericParameter => RenderGenericParameterSignature(genericParameter), 38 | TypeDefOrRefSignature typeDefOrRef => RenderTypeDefOrRefSignature(typeDefOrRef), 39 | TypeSpecificationSignature typeSpecification => RenderTypeSpecificationSignature(typeSpecification), 40 | /* 41 | PinnedTypeSignature pinnedType => ... 42 | ArrayBaseTypeSignature arrayBaseType => ... 43 | CustomModifierTypeSignature customModifierType => ... 44 | FunctionPointerTypeSignature functionPointerType => ..., 45 | SentinelTypeSignature sentinelType => ..., 46 | */ 47 | _ => throw new ArgumentOutOfRangeException(nameof(_signature)) 48 | }; 49 | 50 | // nested signatures. 51 | if (_signature.DeclaringType is not null && _declare) 52 | { 53 | renderedSignature = 54 | _service.Concat( 55 | new TypeSignatureRenderer(_service, _signature.DeclaringType.ToTypeSignature(), _member, 56 | _declaringType).RenderMember(), _service.Constants.Dot, renderedSignature); 57 | } 58 | 59 | return renderedSignature; 60 | } 61 | 62 | 63 | private RenderFragment RenderBoxedTypeSignature(BoxedTypeSignature boxedType) 64 | { 65 | throw new NotImplementedException(); 66 | } 67 | 68 | private RenderFragment RenderByReferenceTypeSignature(ByReferenceTypeSignature byReferenceType) 69 | { 70 | var baseType = new TypeSignatureRenderer(_service, byReferenceType.BaseType, _member, _declaringType, false) 71 | .RenderMember(); 72 | 73 | return _service.Concat(baseType, _service.Text("&")); 74 | } 75 | 76 | private RenderFragment RenderArrayTypeSignature(ArrayTypeSignature arrayType) 77 | { 78 | throw new NotImplementedException(); 79 | } 80 | 81 | private RenderFragment RenderTypeSpecificationSignature(TypeSpecificationSignature typeSpecification) 82 | { 83 | var baseType = new TypeSignatureRenderer(_service, typeSpecification.BaseType, _member, _declaringType, false) 84 | .RenderMember(); 85 | return baseType; 86 | } 87 | 88 | private RenderFragment RenderSzArrayTypeSignature(SzArrayTypeSignature szArrayType) 89 | { 90 | var baseType = new TypeSignatureRenderer(_service, szArrayType.BaseType, _member, _declaringType, false) 91 | .RenderMember(); 92 | 93 | return _service.Concat(baseType, _service.Text("[]")); 94 | } 95 | 96 | private RenderFragment RenderCorLibTypeSignature(CorLibTypeSignature corLibType) 97 | { 98 | if (corLibType.FullName is "System.TypedReference" or "System.IntPtr" or "System.UIntPtr") 99 | { 100 | return new TypeRenderer(_service, corLibType.ToTypeDefOrRef()).RenderMember(); 101 | } 102 | 103 | var keyword = corLibType.FullName switch 104 | { 105 | "System.Boolean" => "bool", 106 | "System.Byte" => "byte", 107 | "System.SByte" => "sbyte", 108 | "System.Char" => "char", 109 | "System.Decimal" => "decimal", 110 | "System.Double" => "double", 111 | "System.Single" => "float", 112 | "System.Int32" => "int", 113 | "System.UInt32" => "uint", 114 | "System.Int64" => "long", 115 | "System.UInt64" => "ulong", 116 | "System.Int16" => "short", 117 | "System.UInt16" => "ushort", 118 | "System.String" => "string", 119 | "System.Object" => "object", 120 | "System.Void" => "void", 121 | _ => throw new ArgumentOutOfRangeException() 122 | }; 123 | 124 | return _service.Keyword(keyword); 125 | } 126 | 127 | private RenderFragment RenderTypeDefOrRefSignature(TypeDefOrRefSignature typeDefOrRef) 128 | { 129 | var memberSpan = new TypeRenderer(_service, typeDefOrRef.Resolve()!) 130 | .RenderMember(); 131 | 132 | return memberSpan; 133 | } 134 | 135 | 136 | private RenderFragment RenderGenericParameterSignature(GenericParameterSignature genericParameter) 137 | { 138 | 139 | var name = genericParameter.ParameterType switch 140 | { 141 | GenericParameterType.Type => (_declaringType is null 142 | ? (TypeDefinition)_member.Resolve()! 143 | : _declaringType.Resolve())!.GenericParameters[genericParameter.Index].Name, 144 | 145 | GenericParameterType.Method => ((MethodDefinition)_member.Resolve()!) 146 | .GenericParameters[genericParameter.Index].Name, 147 | 148 | _ => throw new ArgumentOutOfRangeException() 149 | }; 150 | 151 | return _service.Span(name, "genericparameter"); 152 | } 153 | 154 | private RenderFragment RenderGenericInstanceTypeSignature(GenericInstanceTypeSignature genericInstanceType) 155 | { 156 | var genericType = new TypeRenderer(_service, genericInstanceType.GenericType).RenderMember(); 157 | 158 | var separator = _service.Concat(_service.Constants.Comma, _service.Constants.Space); 159 | 160 | var genericArgs = _service.Join(separator, 161 | genericInstanceType.TypeArguments 162 | .Select(arg => new TypeSignatureRenderer(_service, arg, _member, _declaringType).RenderMember()) 163 | .ToArray()); 164 | 165 | return _service.Concat(genericType, _service.Constants.RightThan, genericArgs, _service.Constants.LeftThan); 166 | } 167 | 168 | private RenderFragment RenderPointerTypeSignature(PointerTypeSignature pointerType) 169 | { 170 | var baseType = new TypeSignatureRenderer(_service, pointerType.BaseType, _member, _declaringType, false) 171 | .RenderMember(); 172 | 173 | return _service.Concat(baseType, _service.Constants.Star); 174 | } 175 | } -------------------------------------------------------------------------------- /Dekompiler.Desktop/App.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Dekompiler.Desktop/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace Dekompiler.Desktop { 10 | /// 11 | /// Interaction logic for App.xaml 12 | /// 13 | public partial class App : Application { 14 | private void StartupSetup(object sender, StartupEventArgs e) { 15 | AppDomain.CurrentDomain.UnhandledException += (_, error) => { 16 | MessageBox.Show(error.ExceptionObject.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error); 17 | }; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Dekompiler.Desktop/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | [assembly: ThemeInfo( 4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 5 | //(used if a resource is not found in the page, 6 | // or application resource dictionaries) 7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 8 | //(used if a resource is not found in the page, 9 | // app, or any theme specific resource dictionaries) 10 | )] -------------------------------------------------------------------------------- /Dekompiler.Desktop/Dekompiler.Desktop.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net7.0-windows 6 | enable 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Dekompiler.Desktop/Main.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | Home | 4 | Other 5 |
6 | 7 |
8 | 9 |

Not found

10 |

Sorry, there's nothing here.

11 |
12 |
-------------------------------------------------------------------------------- /Dekompiler.Desktop/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Dekompiler.Desktop/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using Dekompiler.Core; 4 | using Dekompiler.Core.Interface; 5 | using Microsoft.Extensions.DependencyInjection; 6 | 7 | namespace Dekompiler.Desktop 8 | { 9 | /// 10 | /// Interaction logic for MainWindow.xaml 11 | /// 12 | public partial class MainWindow : Window 13 | { 14 | public MainWindow() 15 | { 16 | InitializeComponent(); 17 | 18 | var serviceCollection = new ServiceCollection(); 19 | serviceCollection.AddWpfBlazorWebView(); 20 | serviceCollection.AddSingleton(ThemeConfiguration.Default); // change to .Dark to get dark-theme. 21 | serviceCollection.AddSingleton(); 22 | Resources.Add("services", serviceCollection.BuildServiceProvider()); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Dekompiler.Desktop/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using Microsoft.AspNetCore.Components.Web.Virtualization 7 | @using Microsoft.JSInterop -------------------------------------------------------------------------------- /Dekompiler.Desktop/brand.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CursedLand/Dekompiler/5511fb14b62057f2401d0aa05a32c7a7ffff6023/Dekompiler.Desktop/brand.ico -------------------------------------------------------------------------------- /Dekompiler.Desktop/wwwroot/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Blazor WPF app 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 |
18 | An unhandled error has occurred. 19 | Reload 20 | 🗙 21 |
22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Dekompiler.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.4.33213.308 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dekompiler", "Dekompiler\Dekompiler.csproj", "{7BFFF268-222A-48EE-922D-C3762B363EE2}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dekompiler.Core", "Dekompiler.Core\Dekompiler.Core.csproj", "{6F4AB40B-39AA-4086-8330-12FEBC3A6284}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dekompiler.Desktop", "Dekompiler.Desktop\Dekompiler.Desktop.csproj", "{DFF2E637-A833-4912-8663-A81D1DB7C1AB}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {7BFFF268-222A-48EE-922D-C3762B363EE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {7BFFF268-222A-48EE-922D-C3762B363EE2}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {7BFFF268-222A-48EE-922D-C3762B363EE2}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {7BFFF268-222A-48EE-922D-C3762B363EE2}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {6F4AB40B-39AA-4086-8330-12FEBC3A6284}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {6F4AB40B-39AA-4086-8330-12FEBC3A6284}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {6F4AB40B-39AA-4086-8330-12FEBC3A6284}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {6F4AB40B-39AA-4086-8330-12FEBC3A6284}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {DFF2E637-A833-4912-8663-A81D1DB7C1AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {DFF2E637-A833-4912-8663-A81D1DB7C1AB}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {DFF2E637-A833-4912-8663-A81D1DB7C1AB}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {DFF2E637-A833-4912-8663-A81D1DB7C1AB}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {AACB073B-014C-4D2B-A9FD-73931838B5FB} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /Dekompiler/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | @**@ 5 | 6 | 7 | Not found 8 | 9 |

Sorry, there's nothing at this address.

10 |
11 |
12 |
-------------------------------------------------------------------------------- /Dekompiler/Components/CodeViewer/CodeView.razor: -------------------------------------------------------------------------------- 1 | @inject ThemeConfiguration Theme 2 | 3 | @if (Result is null) 4 | { 5 |
16 |
17 | 18 | Select Member to decompile 19 |
20 |
21 | } 22 | else 23 | { 24 |
34 | 35 |
36 |
37 | 38 | 39 | @Result.Header 40 | 41 |
42 |
43 |
44 | 45 |
46 | @Result.RenderResult() 47 |
48 | 49 |
50 | } -------------------------------------------------------------------------------- /Dekompiler/Components/CodeViewer/CodeView.razor.cs: -------------------------------------------------------------------------------- 1 | using Dekompiler.Core.Results; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Components.CodeViewer; 5 | 6 | public partial class CodeView : ComponentBase 7 | { 8 | private IDecompilationResult? _result; 9 | 10 | public IDecompilationResult? Result 11 | { 12 | get => _result; 13 | set 14 | { 15 | _result = value; 16 | StateHasChanged(); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Dekompiler/Components/Icon.razor: -------------------------------------------------------------------------------- 1 |  2 | @foreach (var svgChild in Data.PathInfos) 3 | { 4 | if (svgChild is Icons.PathInfo p) 5 | { 6 | @RenderPath(p) 7 | } 8 | else 9 | { 10 | @RenderG((Icons.GInfo)svgChild) 11 | } 12 | } 13 | 14 | 15 | 16 | @code { 17 | 18 | [Parameter] 19 | public Icons.IconInfo Data { get; set; } 20 | 21 | [Parameter(CaptureUnmatchedValues = true)] 22 | public IReadOnlyDictionary? AdditionalAttributes { get; set; } 23 | 24 | private RenderFragment RenderPath(Icons.PathInfo pathInfo) 25 | { 26 | if (pathInfo.Class is null) 27 | { 28 | return @; 29 | } 30 | else 31 | { 32 | return @; 33 | } 34 | } 35 | 36 | private RenderFragment RenderG(Icons.GInfo gInfo) 37 | { 38 | return builder => 39 | { 40 | builder.OpenElement(0, "g"); 41 | builder.AddAttribute(1, "class", gInfo.Class); 42 | for (var i = 0; i < gInfo.PathInfos.Length; i++) 43 | { 44 | builder.AddContent(i + 2, RenderPath(gInfo.PathInfos[i])); 45 | } 46 | builder.CloseElement(); 47 | }; 48 | } 49 | } -------------------------------------------------------------------------------- /Dekompiler/Components/NavigationMenu.razor: -------------------------------------------------------------------------------- 1 | @inject ThemeConfiguration Theme 2 | 3 | -------------------------------------------------------------------------------- /Dekompiler/Components/TreeView/TreeView.razor: -------------------------------------------------------------------------------- 1 | @using Index = Dekompiler.Pages.Index 2 | @using System.Diagnostics.CodeAnalysis 3 | @inject ThemeConfiguration Theme 4 | 5 |
19 | 20 |
21 | Assembly Explorer 22 |
23 |
24 |
29 |
30 | 31 |
32 | @foreach (var node in Nodes) 33 | { 34 | 35 | } 36 |
37 | 38 |
39 | 40 | @code { 41 | 42 | [CascadingParameter] 43 | private Index? Parent { get; set; } 44 | 45 | private List _nodes = new(); 46 | 47 | [Parameter] 48 | public List Nodes 49 | { 50 | get => _nodes; 51 | set => _nodes = value; 52 | } 53 | 54 | public void SetNodes(List nodes) 55 | { 56 | Nodes = nodes; 57 | StateHasChanged(); 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /Dekompiler/Components/TreeView/TreeViewNode.razor: -------------------------------------------------------------------------------- 1 | @using System.Diagnostics.CodeAnalysis 2 | @inject ThemeConfiguration Theme 3 | 4 |
6 | 7 |
8 | @* gives important boundary when child content overflows. *@ 9 |
10 | @if (Model.Nodes.Count > 0) 11 | { 12 | 13 | } 14 | else 15 | { 16 | 17 | } 18 |
19 | @* gives important boundary when child content overflows. *@ 20 |
21 | 22 |
23 | 24 | @Model.ChildContent() 25 | 26 |
27 | 28 | @if (Model.Nodes.Count > 0 && Model.Toggled) 29 | { 30 |
31 | @foreach (var node in Model.Nodes) 32 | { 33 | 34 | } 35 |
36 | } 37 | 38 |
39 | 40 | @code { 41 | 42 | [Parameter] 43 | public int Indent { get; set; } = 10; 44 | 45 | [Parameter] 46 | [NotNull] 47 | public TreeViewNodeModel? Model { get; set; } 48 | 49 | private void InvokeAction() => Model.Action(); 50 | 51 | private void Toggle() 52 | { 53 | Model.Toggled = !Model.Toggled; 54 | StateHasChanged(); 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /Dekompiler/Components/TreeView/TreeViewNodeModel.cs: -------------------------------------------------------------------------------- 1 | using Dekompiler.Core; 2 | using Microsoft.AspNetCore.Components; 3 | 4 | namespace Dekompiler.Components.TreeView; 5 | 6 | public class TreeViewNodeModel 7 | { 8 | public TreeViewNodeModel(Icons.IconInfo icon, Action action, Func childContent) : 9 | this(icon, action, 10 | childContent, new()) 11 | { 12 | } 13 | 14 | public TreeViewNodeModel(Icons.IconInfo icon, Func childContent) : 15 | this(icon, Nothing, 16 | childContent, new()) 17 | { 18 | } 19 | 20 | public TreeViewNodeModel(Icons.IconInfo icon, Func childContent, List nodes) : 21 | this(icon, Nothing, 22 | childContent, nodes) 23 | { 24 | } 25 | 26 | public TreeViewNodeModel(Icons.IconInfo icon, Action action, Func childContent, 27 | List nodes) : this(false, action, icon, 28 | childContent, nodes) 29 | { 30 | } 31 | 32 | public TreeViewNodeModel(bool toggled, Action action, Icons.IconInfo icon, Func childContent, 33 | List nodes) 34 | { 35 | Toggled = toggled; 36 | Action = action; 37 | Icon = icon; 38 | ChildContent = childContent; 39 | Nodes = nodes; 40 | } 41 | 42 | public bool Toggled { get; set; } 43 | 44 | public Action Action { get; } 45 | 46 | public Icons.IconInfo Icon { get; } 47 | 48 | public Func ChildContent { get; } 49 | 50 | public List Nodes { get; } 51 | 52 | private static void Nothing() 53 | { 54 | } 55 | } -------------------------------------------------------------------------------- /Dekompiler/Dekompiler.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net7.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | <_ContentIncludedByDefault Remove="wwwroot\images\class.png" /> 15 | <_ContentIncludedByDefault Remove="wwwroot\images\delegate.png" /> 16 | <_ContentIncludedByDefault Remove="wwwroot\images\enum.png" /> 17 | <_ContentIncludedByDefault Remove="wwwroot\images\event.png" /> 18 | <_ContentIncludedByDefault Remove="wwwroot\images\field.png" /> 19 | <_ContentIncludedByDefault Remove="wwwroot\images\interface.png" /> 20 | <_ContentIncludedByDefault Remove="wwwroot\images\method.png" /> 21 | <_ContentIncludedByDefault Remove="wwwroot\images\namespace.png" /> 22 | <_ContentIncludedByDefault Remove="wwwroot\images\property.png" /> 23 | <_ContentIncludedByDefault Remove="wwwroot\images\struct.png" /> 24 | 25 | 26 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Dekompiler/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 | Dekompiler 4 | 5 |
6 | 7 |
8 | @Body 9 |
10 |
-------------------------------------------------------------------------------- /Dekompiler/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | 3 | @inject RendererService Renderer 4 | 5 | 6 |
10 | 11 | 12 | 13 | 14 |
15 |
-------------------------------------------------------------------------------- /Dekompiler/Pages/_Host.cshtml: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @using Dekompiler.Core.Interface 3 | @using Microsoft.AspNetCore.Components.Web 4 | @namespace Dekompiler.Pages 5 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 6 | @inject ThemeConfiguration Theme 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | An error has occurred. This application may no longer respond until reloaded. 23 | 24 | 25 | An unhandled exception has occurred. See browser dev tools for details. 26 | 27 | Reload 28 | 🗙 29 |
30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Dekompiler/Program.cs: -------------------------------------------------------------------------------- 1 | using Dekompiler.Core.Interface; 2 | using Dekompiler.Core; 3 | using Microsoft.AspNetCore.Hosting.StaticWebAssets; 4 | 5 | var builder = WebApplication.CreateBuilder(args); 6 | builder.Services.AddRazorPages(); 7 | builder.Services.AddServerSideBlazor(); 8 | builder.Services.AddSingleton(ThemeConfiguration.Default); // change to .Dark to get dark-theme. 9 | builder.Services.AddSingleton(); 10 | 11 | var app = builder.Build(); 12 | 13 | StaticWebAssetsLoader.UseStaticWebAssets(builder.Environment, builder.Configuration); 14 | 15 | if (!app.Environment.IsDevelopment()) 16 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 17 | app.UseHsts(); 18 | 19 | app.UseHttpsRedirection(); 20 | 21 | app.UseStaticFiles(); 22 | 23 | app.UseRouting(); 24 | 25 | app.MapBlazorHub(); 26 | app.MapFallbackToPage("/_Host"); 27 | 28 | app.Run(); -------------------------------------------------------------------------------- /Dekompiler/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "iisExpress": { 4 | "applicationUrl": "http://localhost:29847", 5 | "sslPort": 44350 6 | } 7 | }, 8 | "profiles": { 9 | "http": { 10 | "commandName": "Project", 11 | "dotnetRunMessages": true, 12 | "launchBrowser": true, 13 | "applicationUrl": "http://localhost:5258", 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "https": { 19 | "commandName": "Project", 20 | "dotnetRunMessages": true, 21 | "launchBrowser": true, 22 | "applicationUrl": "https://localhost:7287;http://localhost:5258", 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | } 26 | }, 27 | "IIS Express": { 28 | "commandName": "IISExpress", 29 | "launchBrowser": true, 30 | "environmentVariables": { 31 | "ASPNETCORE_ENVIRONMENT": "Development" 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Dekompiler/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Routing 2 | @using Microsoft.AspNetCore.Components.Web 3 | @using Microsoft.JSInterop 4 | @using Dekompiler 5 | @using Dekompiler.Components 6 | @using Dekompiler.Components.CodeViewer 7 | @using Dekompiler.Components.TreeView 8 | @using Dekompiler.Core 9 | @using Dekompiler.Core.Interface 10 | @using Microsoft.AspNetCore.Components.Forms -------------------------------------------------------------------------------- /Dekompiler/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "DetailedErrors": true, 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft.AspNetCore": "Warning" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Dekompiler/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /Dekompiler/wwwroot/site.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,400;1,500&display=swap'); 2 | 3 | * { 4 | font-family: 'JetBrains Mono', monospace; 5 | } 6 | 7 | html, body { 8 | height: 100%; 9 | } 10 | 11 | #blazor-error-ui { 12 | background: lightyellow; 13 | bottom: 0; 14 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); 15 | display: none; 16 | left: 0; 17 | padding: 0.6rem 1.25rem 0.7rem 1.25rem; 18 | position: fixed; 19 | width: 100%; 20 | z-index: 1000; 21 | } 22 | 23 | #blazor-error-ui .dismiss { 24 | cursor: pointer; 25 | position: absolute; 26 | right: 3.5rem; 27 | top: 0.5rem; 28 | } 29 | 30 | .blazor-error-boundary { 31 | background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; 32 | padding: 1rem 1rem 1rem 3.7rem; 33 | color: white; 34 | } 35 | 36 | .blazor-error-boundary::after { 37 | content: "An error has occurred." 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 CursedLand 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dekompiler 2 | Dekompiler is work-in-progress .NET decompiler that converts Cil to C# code. 3 | 4 | 5 | # Showcase 6 | 7 | ![corlib_ginterface](https://github.com/CursedLand/Dekompiler/blob/main/showcase/corlib_ginterface.png) 8 | ![dekompiler_core_ldnull](https://github.com/CursedLand/Dekompiler/blob/main/showcase/dekompiler_core_ldnull.png) 9 | ![dekompiler_core_newarr](https://github.com/CursedLand/Dekompiler/blob/main/showcase/dekompiler_core_newarr.png) 10 | ![koi_config](https://github.com/CursedLand/Dekompiler/blob/main/showcase/koi_config.png) 11 | ![koi_rt_cmpdwrd](https://github.com/CursedLand/Dekompiler/blob/main/showcase/koi_rt_cmpdwrd.png) 12 | ![koi_rt_vmctx](https://github.com/CursedLand/Dekompiler/blob/main/showcase/koi_rt_vmctx.png) 13 | ![koi_vminstance](https://github.com/CursedLand/Dekompiler/blob/main/showcase/koi_vminstance.png) 14 | ![pointers](https://github.com/CursedLand/Dekompiler/blob/main/showcase/pointers.png) 15 | ![unsupported](https://github.com/CursedLand/Dekompiler/blob/main/showcase/unsupported.png) 16 | ![x86_decoded_expressions](https://github.com/CursedLand/Dekompiler/blob/main/showcase/x86_decoded_expressions.png) 17 | 18 | # Issues 19 | - Dekompiler do not use Ast to process the assemblies. 20 | - Dekompiler do not optimize CompilerGenerated members. 21 | - Dekompiler do not support loading assemblies from disk (this means you need to load the dependencies as-well). 22 | - Dekompiler do not support control-flow codes. 23 | - Dekompiler do not support exception-handlers codes. 24 | - Dekompiler do not support nullability. 25 | - Dekompiler do not support operator methods (i.e op_Explicit, op_Add, op_Implicit). 26 | - Dekompiler do not support using-section in decompilation result. 27 | - Dekompiler do not support rendering of couple TypeSignatures. 28 | - Dekompiler do not support basic code inlining nor optimization. 29 | - Dekompiler do not support dead code removal. 30 | - Dekompiler do not support any Attributes applied to member-definition(s). 31 | - Dekompiler might introduce mistakes in member-definition(s) accessibility flags. 32 | - Dekompiler might fails to render Generics in some cases due to incorrect implementation. 33 | 34 | # Credits 35 | [Washi](https://github.com/Washi1337) for [AsmResolver](https://github.com/Washi1337/AsmResolver) 36 |
37 | [0xd4d](https://github.com/0xd4d) for [dnSpy](https://github.com/0xd4d/dnSpy) CodeTheme palettes. 38 | -------------------------------------------------------------------------------- /showcase/corlib_ginterface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CursedLand/Dekompiler/5511fb14b62057f2401d0aa05a32c7a7ffff6023/showcase/corlib_ginterface.png -------------------------------------------------------------------------------- /showcase/dekompiler_core_ldnull.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CursedLand/Dekompiler/5511fb14b62057f2401d0aa05a32c7a7ffff6023/showcase/dekompiler_core_ldnull.png -------------------------------------------------------------------------------- /showcase/dekompiler_core_newarr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CursedLand/Dekompiler/5511fb14b62057f2401d0aa05a32c7a7ffff6023/showcase/dekompiler_core_newarr.png -------------------------------------------------------------------------------- /showcase/koi_config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CursedLand/Dekompiler/5511fb14b62057f2401d0aa05a32c7a7ffff6023/showcase/koi_config.png -------------------------------------------------------------------------------- /showcase/koi_rt_cmpdwrd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CursedLand/Dekompiler/5511fb14b62057f2401d0aa05a32c7a7ffff6023/showcase/koi_rt_cmpdwrd.png -------------------------------------------------------------------------------- /showcase/koi_rt_vmctx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CursedLand/Dekompiler/5511fb14b62057f2401d0aa05a32c7a7ffff6023/showcase/koi_rt_vmctx.png -------------------------------------------------------------------------------- /showcase/koi_vminstance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CursedLand/Dekompiler/5511fb14b62057f2401d0aa05a32c7a7ffff6023/showcase/koi_vminstance.png -------------------------------------------------------------------------------- /showcase/pointers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CursedLand/Dekompiler/5511fb14b62057f2401d0aa05a32c7a7ffff6023/showcase/pointers.png -------------------------------------------------------------------------------- /showcase/unsupported.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CursedLand/Dekompiler/5511fb14b62057f2401d0aa05a32c7a7ffff6023/showcase/unsupported.png -------------------------------------------------------------------------------- /showcase/x86_decoded_expressions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CursedLand/Dekompiler/5511fb14b62057f2401d0aa05a32c7a7ffff6023/showcase/x86_decoded_expressions.png --------------------------------------------------------------------------------