.NET Framework Developer Center > .NET Development Forums > Building Development and Diagnostic Tools for .Net > Very strange MSIL Disassembler output - this looks like be a bug in ildasm
Ask a questionAsk a question
 

AnswerVery strange MSIL Disassembler output - this looks like be a bug in ildasm

  • Sunday, November 01, 2009 5:32 PMBitFlipper Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    I am disassbling/assembling my C# DLL to make some custom tweaks to the compiled code (to enable reverse P/Invoke, but this is really not relevant to this particular issue). But now I ran into a strange problem when disassembling a C# DLL after it has been compiled. Below is a short snippet of what I see in the IL file right after it has been decompiled. I see the same thing repeated a few times in the IL file. The strange thing is that this only happens sometimes, and if I comment/uncomment various completely unrelated lines of code, I can make it go away/appear. Also, if I add switches like /source when disassembling, I can randomly make it work/not work. Very strange. I believe the DLL right after I compile it works, but when I try to decompile it, I get the resulting IL file below (before I even tweak anything). When I try to run ilasm on the output IL file (without making any changes to it), ilasm chokes with a ayntax error on the corrupted lines.

    BTW, I am using VS 2008 and .Net 3.5 SP1

    Some additional observations after I wrote the above:

    - I tried to disassemble the DLL from within the ildasm UI itself, and it works fine.
    - I tried to disassemble the DLL using Reflector, and it works fine.

    My suspicion is that in the above two cases, the /linenum switch is not specified when disassembling the DLL, so they don't run into this problem.

    A possible clue might be that there is a problem with the symbol server maybe? The corrupted lines are always right after a statement like class [mscorlib]System.Collections.IEnumerable where it is trying to add the line number. I don't know where ildasm gets the line numbers from for .Net types, and if I can control any of it.

    Since this is a showstopper issue for me (my project doesn't run if I can't go through the ildasm/ilasm sequence), I am willing to try anything. One hack I am going to try is when I read the IL file for parsing, is to check whether the line contains any non-ASCII characters, and ignore the whole line if it does. A nasty hack, but what else can I try...?

    Any ideas what could be causing the garbled characters?

    --------------------------------------------------------------------------

      .method public hidebysig instance class [mscorlib]System.Collections.IEnumerable
              RecordsFrom(class Plugin.Records/Record startRecord,
                          bool forward,
                          bool contiguousPosition,
                          bool contiguousVoice,
                          bool contiguousNote) cil managed
      {
        // Code size       58 (0x3a)
        .maxstack  2
        .locals init ([0] class Plugin.Records/'<RecordsFrom>d__0' V_0,
                 [1] class [mscorlib]System.Collections.IEnumerable V_1)
        .line 121,0 : 134218193,0 '??????'????????????????????????????????????????????????????††????›???†††????†??†††??????†††????†?????†††????†????†??????†††????†????†??????†††????†????†??????†††??????'›?????†††????†????†††????†?????††????›???†††??????††??????????????††????›?????†††????†?????††????›???†††???????????????????????????????????????†††????†?????††??????????????††????›???†††???????›??‰??†††????†?????††????›?????††????›???†††???????????????????????????????????†††††††††††††††††††††††††††††††††????????????????††????›??????††????›???†††????†????†??????†††????†????†??????†††????†????†??????†††???????›?????†††????†????†††????†?????††????›????††??????††??????????????††????›?????†††????†???????????†††????'
        IL_0000:  ldc.i4.s   -2
        IL_0002:  newobj     instance void Plugin.Records/'<RecordsFrom>d__0'::.ctor(int32)
        IL_0007:  stloc.0
        IL_0008:  ldloc.0
        IL_0009:  ldarg.0
        IL_000a:  stfld      class Plugin.Records Plugin.Records/'<RecordsFrom>d__0'::'<>4__this'
        IL_000f:  ldloc.0
        IL_0010:  ldarg.1
        IL_0011:  stfld      class Plugin.Records/Record Plugin.Records/'<RecordsFrom>d__0'::'<>3__startRecord'
        IL_0016:  ldloc.0
        IL_0017:  ldarg.2
        IL_0018:  stfld      bool Plugin.Records/'<RecordsFrom>d__0'::'<>3__forward'
        IL_001d:  ldloc.0
        IL_001e:  ldarg.3
        IL_001f:  stfld      bool Plugin.Records/'<RecordsFrom>d__0'::'<>3__contiguousPosition'
        IL_0024:  ldloc.0
        IL_0025:  ldarg.s    contiguousVoice
        IL_0027:  stfld      bool Plugin.Records/'<RecordsFrom>d__0'::'<>3__contiguousVoice'
        IL_002c:  ldloc.0
        IL_002d:  ldarg.s    contiguousNote
        IL_002f:  stfld      bool Plugin.Records/'<RecordsFrom>d__0'::'<>3__contiguousNote'
        IL_0034:  ldloc.0
        IL_0035:  stloc.1
        IL_0036:  br.s       IL_0038

        IL_0038:  ldloc.1
        IL_0039:  ret
      } // end of method Records::RecordsFrom

    ----------------------------------------------------------------------------------

    • Edited byBitFlipper Tuesday, November 03, 2009 4:41 PM
    •  

Answers

  • Wednesday, November 04, 2009 8:36 PMKarel ZikmundMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    Hello,
    I have tracked it down to a known bug in ildasm with /linenum switch which has already been fixed in .NET Framework 4.0 (you can try it on Beta1 or Beta2 release).

    As a workaround I would recommend:
      - Use .NET Fx 4.0 ildasm
      - Avoid using /linenum switch

    Short-term workarounds might be:
      - Modify the code so that it doesn't crash ildasm
      - Play with other ildasm command line switches so that it doesn't crash (e.g. in the second repro when I used additional /tok argument, it didn't crash or when I ran it under debugger it didn't crash)

    I hope this helps,
    -Karel

  • Thursday, November 05, 2009 4:45 PMKarel ZikmundMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    To use 4.0 Beta2 ildasm you really have to install .NET Framework redist and Windows SDK (which I think ships only as part of VS 2010 Beta2 for 4.0 Beta2 release).
    However this bug was fixed long time before 4.0 Beta1, therefore if you see it crashing on Beta1, please let me know ASAP.

    Thanks,
    -Karel

All Replies

  • Monday, November 02, 2009 12:36 AMKarel ZikmundMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Please try to create a repro (ideally as small as possible) that we can take a look at. Paste it here or share it somewhere where we can access it. Also please specify full ildasm command line you are using.
    If you can make sure that it repros on another machine and not just your machine, that would be great to rule out weird hardware errors.

    AFAIK ildasm doesn't search symbol server for PDBs. I think it should use just one PSDB of the assembly you are disassembling. You can easily confirm that in procmon tool. If that's the case try to compare 2 recompiled versions of the same PDB file. How much do they differ? Is it possbile that C# compiler produced some garbage into the PDB?

    When you mentioned that it is random - do you mean that when you run ildasm on the same assembly several times (without rcompiling it), it will sometimes fail and sometimes it will work? If that's the case then it is likely either a hardware issue or a bug in ildasm / PDB reader (if it happens on more than 1 computer).

    -Karel
  • Monday, November 02, 2009 12:57 AMBitFlipper Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Please try to create a repro (ideally as small as possible) that we can take a look at. Paste it here or share it somewhere where we can access it. Also please specify full ildasm command line you are using.
    If you can make sure that it repros on another machine and not just your machine, that would be great to rule out weird hardware errors.

    AFAIK ildasm doesn't search symbol server for PDBs. I think it should use just one PSDB of the assembly you are disassembling. You can easily confirm that in procmon tool. If that's the case try to compare 2 recompiled versions of the same PDB file. How much do they differ? Is it possbile that C# compiler produced some garbage into the PDB?

    When you mentioned that it is random - do you mean that when you run ildasm on the same assembly several times (without rcompiling it), it will sometimes fail and sometimes it will work? If that's the case then it is likely either a hardware issue or a bug in ildasm / PDB reader (if it happens on more than 1 computer).

    -Karel
    OK I will try to set up a reproducible case and post the DLL with instructions somewhere.

    What I mean by random is that it would work 100% every time, then when I add a new unrelated method into a random class in my project, it would then stop working 100% of the time. Then later when I add new methods or make other changes, it would start working 100% of the time again.  It seems that certain combinations of methods etc is causing the problem to manifest.

    I found a work-around in that when I now read in the disassembled IL file before I parse it, I check each line to see if it contains any characters with values above 127. If it does, I just ignore the whole line. So far this works but it is obviously a horrible hack.

    When I get a chance I will try your suggestions and post back here with any results.
  • Monday, November 02, 2009 1:14 AMKarel ZikmundMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Thanks for the details, in that case it is unlikely a hardware error. It is far more likely a bug in C# compiler, PDB writer, PDB reader or ildasm.
    If you can get some subset of your project that still manifests the error and post also its source, that would be great. It will help us to chase it down in case it is a C# compiler / PDB writer bug.

    Thanks,
    -Karel
  • Monday, November 02, 2009 3:52 PMBitFlipper Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    I posted files that can be used to reproduce this problem here:

    www.alienworks.com\files\IL\Corrupt_IL.zip

    I included:

    1. The C# DLL that I disassemble.
    2. The pdb file that goes with the above DLL.
    3. The IL file that I disassembled that shows the corrupt output.
    4. A Readme.txt file with brief instructions on the steps required to reproduce this.

    The steps in the ReadMe are:

    1. Disassemble:
         ildasm /nobar /linenum "VocalTrainer 2.dll" /out:"VocalTrainer 2.il"

    2. Search for:
         ".locals init ([0] class Plugin.Records/'<RecordsByPosition>d__4' V_0,"
         (line 53474)

    3. Notice the corrupt line 2 lines down from the above line

    4. Instructions for contacting me.

    If you need any additional info from me, please let me know. Unfortunately it would be difficult to extract just the part of the project that fails. I think the DLL, pdb and IL files might give you enough information. If not, let me know and we can go from there.

    BTW, the version of ildasm I am using is the one that comes with VS 2008 SP1, v3.5.30729.1

  • Monday, November 02, 2009 5:05 PMBitFlipper Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    OK it gets worse. Now I have a case where ildasm crashes when I try to disassemble. This is the exact same project but all I did was add a new class, and now instead of the corrupted IL output file, ildasm simply crashes. The zip file below contains the DLL, pdb and readme.txt files that can be used to reproduce this.

    www.alienworks.com\files\IL\Crash_Ildasm.zip
  • Monday, November 02, 2009 5:28 PMBitFlipper Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Another update:

    I moved the project into a different folder using a shorter path. I can now run ildasm without the IL file getting corrupted or ildasm crashing. BUT, this does not mean too much at this point since the problem seems to be very intermittend and one change can bring it back again. I will keep testing and and see if I can reproduce it in the new project location.

    BTW, in the old project location, the max source file name length is around 100 characters, so I don't think this has anything to do with filenames being too long.
  • Tuesday, November 03, 2009 2:44 AMBitFlipper Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    And another update:

    Arrggg!! Looks like it is back to crashing now again (even in the new location). Not sure what else I can do at this point. I can't use ildasm to disassemble my DLL any more, causing my project to be blocled from any further development.

    Are there any other ways in addition to ildasm to disassemble my DLL?
  • Wednesday, November 04, 2009 8:36 PMKarel ZikmundMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    Hello,
    I have tracked it down to a known bug in ildasm with /linenum switch which has already been fixed in .NET Framework 4.0 (you can try it on Beta1 or Beta2 release).

    As a workaround I would recommend:
      - Use .NET Fx 4.0 ildasm
      - Avoid using /linenum switch

    Short-term workarounds might be:
      - Modify the code so that it doesn't crash ildasm
      - Play with other ildasm command line switches so that it doesn't crash (e.g. in the second repro when I used additional /tok argument, it didn't crash or when I ran it under debugger it didn't crash)

    I hope this helps,
    -Karel

  • Thursday, November 05, 2009 1:11 AMBitFlipper Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Karel,

    Thank you very much for the update. It is good to know that this is a known issue and that it has been fixed in the next versions. I have been playing with various command line switches to stop it from crashing, but it only lasts so long before I need to tweak them again to make it work.

    So if I don't use the /linenum switch, I assume I won't be able to debug the DLL, right? If that is the case then I can't use that workaround.

    I have VS 2010 Beta1 installed, and I thought I did try to use its ildasm and that it also crashed, but I will give it another try to make sure I didn't do something wrong there. Is it possible to get just the 4.0 Beta2 ildasm from somewhere without installing the full beta? Probably not... 
  • Thursday, November 05, 2009 4:45 PMKarel ZikmundMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    To use 4.0 Beta2 ildasm you really have to install .NET Framework redist and Windows SDK (which I think ships only as part of VS 2010 Beta2 for 4.0 Beta2 release).
    However this bug was fixed long time before 4.0 Beta1, therefore if you see it crashing on Beta1, please let me know ASAP.

    Thanks,
    -Karel