icsharpcode / ILSpy

.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform!
21.45k stars 3.35k forks source link

Add support for switch statement pattern using Hashtable #489

Closed greenozon closed 7 years ago

greenozon commented 10 years ago

Here is how ILSpy 2.2 decompiles some switch blocks:

public static BitArray getBoolArrayOfPermissions(ArrayList permissions) { if (.$$method0x600024f-1 == null) {

.$$method0x600024f-1 = new Hashtable(188, 0.5f) { ``` { "AgEdtRecord", 0 }, { "AgDelRecord", 1 }, ``` ........... object obj; if ((obj = text) != null && (obj = .$$method0x600024f-1[obj]) != null) { switch ((int)obj) { case 0: ................. and here is how old .Net Refletor 7.0 handles it: public static BitArray getBoolArrayOfPermissions(ArrayList permissions) { BitArray array = new BitArray(permCount); array.SetAll(false); for (int i = 0; i < permissions.Count; i++) { switch (((string) permissions[i])) { case "AgEdtRecord": array[iAgEdtRecord] = true; break; .................... The question is: it is possible to elaborate on this issue and make it more user-friendly like Reflector handles it? Thanks
dgrunwald commented 10 years ago

ILSpy has a step for decompiling switch on strings, but that only handles Dictionary<string, int>, not Hashtable.

greenozon commented 10 years ago

Could you point me to the right location in sources on the mentioned handler? I've encountered this type of decompilation and would like to see it in depth..... Thanks

dgrunwald commented 10 years ago

It's TransformSwitchOnString in PatternStatementTransform.cs. Unfortunately it's currently implemented as a C# transform which tries to detect a specific pattern with the if (dict.TryGetValue()) call. This is a problem in certain scenarios, as control flow analysis / goto-removal sometimes produces different patterns. It would be better to do this step earlier in the decompilation pipeline (in the ILAst, before the control flow transformations), but we haven't had the time to re-implement this step for the ILAst.

siegfriedpammer commented 7 years ago

Sorry for taking so long to work on this. With the rewrite of the decompiler engine we now reimplemented switch-on-string in the ILAst. We currently can only correctly handle C# switch-string patterns that either use Dictionary<string, int> (legacy C#) or a special hash function (Roslyn).

Could you provide a binary containing an example that uses Hashtable?