【发布时间】:2017-12-29 00:40:11
【问题描述】:
我正在尝试将两种方法合并在一起(一种来自我的项目,一种来自 dll)并将它们写入 dll。原始代码如下所示:
.method public hidebysig static class Storage.DataMap
Create() cil managed
{
.maxstack 8
// [22 7 - 22 70]
IL_0000: call unmanaged stdcall native int Storage.DataMapPlugin::DataMap_CreateEmptyDataMap()
IL_0005: newobj instance void Storage.DataMap::.ctor(native int)
IL_000a: ret
} // end of method DataMap::Create
我想在这段代码中添加一个简单的 Console.WriteLine,我最终得到以下内容:(来自反编译器)
.method public hidebysig static class Storage.DataMap
Create() cil managed
{
.maxstack 8
// [22 7 - 22 44]
IL_0000: ldstr "Hello World"
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
// [23 7 - 23 70]
IL_000a: call unmanaged stdcall native int Storage.DataMapPlugin::DataMap_CreateEmptyDataMap()
IL_000f: newobj instance void Storage.DataMap::.ctor(native int)
IL_0014: ret
} // end of method DataMap::Create
我的反编译器无法反编译(dotPeek),所以我假设我生成的 IL 无效。但是,我不确定我生成的 IL 有什么问题。
我使用 dnlib 和 C# 来获取方法的 IL 代码,然后将两个代码块连接在一起(我剥离了 nop 和 ret 语句(最后一个除外))。为了重新编译我使用 ModuleDef#Write(String) 函数的代码,我在编写自己的 IL 语句时已经成功,但在合并已经存在的语句时却没有。
(下面的IL都是从控制台打印出来的,不是反编译的)
原始第 1 部分 IL:
IL_0000: nop
IL_0001: ldstr "Hello World"
IL_0006: call System.Void System.Console::WriteLine(System.String)
IL_000B: nop
IL_000C: ret
原版第 2 部分 IL:
IL_0000: call System.IntPtr Storage.DataMapPlugin::DataMap_CreateEmptyDataMap()
IL_0005: newobj System.Void Storage.DataMap::.ctor(System.IntPtr)
IL_000A: ret
合并 IL:
IL_0001: ldstr "Hello World"
IL_0006: call System.Void System.Console::WriteLine(System.String)
IL_0000: call System.IntPtr Storage.DataMapPlugin::DataMap_CreateEmptyDataMap()
IL_0005: newobj System.Void Storage.DataMap::.ctor(System.IntPtr)
IL_000A: ret
【问题讨论】:
-
C# 级别太高? :-) 无论如何,我不得不想知道为什么
nop首先会在那里。对于您和编译器来说,这似乎是一个容易删除的候选者,因此可能出于某种原因需要它。 -
这似乎没有什么区别,我在反编译器错误时尝试的第一件事是删除
nop,但这并没有帮助。 @paxdiablo -
实际上,合并后的 IL 的标签都搞砸了 (1,6,0,5,a)。会不会是个问题?
-
如果您使用的是 dnlib,您需要在您的问题中包含一个很好的 minimal reproducible example,以准确显示您如何使用它。您在上面显示的只是 data,在要求人们帮助您调试 code 时几乎没有用处。
-
如果 IL 无效,那么 peverify 应该能够告诉你哪里出了问题。老实说,您确实需要显示用于进行合并的代码。一个可能的问题是您正在尝试加载必须在模块元数据中定义的字符串。您是否正确更新了目标程序集的元数据以包含新的元数据令牌?您需要更改方法的 IL 和目标模块的元数据。