Смещения IL неправильно изменяются при добавлении инструкций с помощью Mono Cecil

Возможный дубликат:
Mono.Cecil позаботится о филиалах и т. д.?

Я работаю над проектом, который требует, чтобы я вставил вызов статического метода после вызова определенных методов в моем приложении. Я использую для этого Mono Cecil, и по большей части все работает нормально. Однако я сталкиваюсь с некоторыми случаями, когда смещения ветвей искажаются, когда обновленная сборка записывается на диск. Вот как выглядит мой код:

public void InstrumentMethod(MethodDefinition method)
{
    var processor = method.Body.GetILProcessor();

    var instr = GetStaticInstrumentMethod();
    var instrument = method.Module.Import(instr);
    var call = method.Body.Instructions.First(i => i.IsCallImInterestedIn());
    processor.InsertBefore(call, instrument);
}

Таким образом, в 90% случаев этот код работает без проблем — целевой метод оснащен моим дополнительным вызовом, и все работает нормально.

В остальных 10% случаев инструментированный метод не может быть выполнен, и я получаю ошибки, пытаясь просмотреть его в ILSpy. Ошибка ILSpy:

ICSharpCode.Decompiler.DecompilerException: Error decompiling System.Object Savo.Utilities.Mapping.ReflectionMapper::MapTo(System.Object,System.Object)
 ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at ICSharpCode.Decompiler.ILAst.ILAstBuilder.c__DisplayClass33.b__26(ByteCode b)
   at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source, Func`2 predicate)
   at ICSharpCode.Decompiler.ILAst.ILAstBuilder.ConvertLocalVariables(List`1 body)
   at ICSharpCode.Decompiler.ILAst.ILAstBuilder.StackAnalysis(MethodDefinition methodDef)
   at ICSharpCode.Decompiler.Ast.AstMethodBodyBuilder.CreateMethodBody(IEnumerable`1 parameters)
   at ICSharpCode.Decompiler.Ast.AstMethodBodyBuilder.CreateMethodBody(MethodDefinition methodDef, DecompilerContext context, IEnumerable`1 parameters)
   --- End of inner exception stack trace ---
   at ICSharpCode.Decompiler.Ast.AstMethodBodyBuilder.CreateMethodBody(MethodDefinition methodDef, DecompilerContext context, IEnumerable`1 parameters)
   at ICSharpCode.Decompiler.Ast.AstBuilder.CreateMethod(MethodDefinition methodDef)
   at ICSharpCode.ILSpy.CSharpLanguage.DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
   at ICSharpCode.ILSpy.TextView.DecompilerTextView.DecompileNodes(DecompilationContext context, ITextOutput textOutput)
   at ICSharpCode.ILSpy.TextView.DecompilerTextView.c__DisplayClass10.b__f()

Я декомпилировал код с помощью ildasm и заметил, что возникают проблемы с обновлением смещений при сохранении сборки. Я ничего не делал со смещениями вызова (пытался установить их вручную, но видел те же проблемы). Предварительная приборная разборка для одного из моих проблемных методов выглядит так:

IL_000e:  br.s       IL_005e
IL_0010:  ldloca.s   CS$5$0000
IL_0012:  call       instance !0 valuetype         [mscorlib]System.Collections.Generic.List`1/Enumerator<class MyThing>::get_Current()
IL_0017:  stloc.0
IL_0018:  nop

... business logic ...    

IL_005d:  nop
IL_005e:  ldloca.s   CS$5$0000
IL_0060:  call       instance bool valuetype      [mscorlib]System.Collections.Generic.List`1/Enumerator<class MyThing>::MoveNext()
IL_0065:  stloc.3
IL_0066:  ldloc.3
IL_0067:  brtrue.s   IL_0010
IL_0069:  leave.s    IL_007a

Когда я смотрю на инструментальный дизассемблирование, строка, соответствующая IL_0067 в этом примере, выглядит так:

IL_00bc:    brtrue.s    IL_0129

который не может быть скомпилирован, так как IL_0129 не существует в текущем методе.

Я заметил, но еще не доказал, что это происходит только вокруг итераторов. Код C# для двух случаев, когда это происходит до сих пор, был циклами foreach, и обе неверные цели ветвления, по-видимому, связаны с конечным условием циклов foreach.

Итак, мой вопрос: мне нужно вручную управлять ссылками смещения, или я что-то еще делаю неправильно?


person thebeekeeper    schedule 18.09.2012    source источник
comment
На этот вопрос уже был дан ответ: уход за ветками и т. д.»> stackoverflow.com/questions/7267480/   -  person Jb Evain    schedule 19.09.2012
comment
О, чувак, я потратил час на поиск связанного вопроса и не нашел этого. Ну ладно, я добавил вызовы Simplify/Optimize и все работает. Спасибо!   -  person thebeekeeper    schedule 19.09.2012