有关 InvalidProgramException 的帮助(无效的 IL 代码?)

发布于 2024-10-19 06:32:01 字数 1725 浏览 0 评论 0原文

我在使用 System.Reflection.Emit 单声道导出的程序集中遇到了一个奇怪的错误。 当尝试运行我的程序集时,我收到一个 InvalidProgramException:无效的 IL 代码。

monodis 给了我这个 CIL 结果(与我使用 Emit 导出的结果一致):

.method public static hidebysig 
       default void f_main (class [Pine.Core]Pine.Core.Function A_0, class [Pine.Core]Pine.Core.ValueList A_1)  cil managed 
{
    // Method begins at RVA 0x2144
    // Code size 26 (0x1a)
    .maxstack 4
    .locals init (
        class [Pine.Core]Pine.Core.Function V_0,
        class [Pine.Core]Pine.Core.IScope   V_1,
        class [Pine.Core]Pine.Core.ValueList    V_2,
        class [Pine.Core]Pine.Core.IScope   V_3)
    IL_0000:  ldarg.0 
    IL_0001:  stloc.0 
    IL_0002:  ldarg.1 
    IL_0003:  stloc.2 
    IL_0004:  ldloc.0 
    IL_0005:  ldftn instance class [Pine.Core]Pine.Core.IScope class [Pine.Core]Pine.Core.Function::get_Scope()
    IL_000b:  stloc.1 
    IL_000c:  ldloc.1 
    IL_000d:  newobj instance void class [Pine.Core]Pine.Core.BlockScope::'.ctor'(class [Pine.Core]Pine.Core.IScope)
    IL_0012:  stloc.3 
    IL_0013:  ldloc.2 
    IL_0014:  call instance void class [Pine.Core]Pine.Core.ValueList::Clear()
    IL_0019:  ret 
} // end of method PineType::f_main

错误发生在 IL_000b: stloc.1 我不知道为什么。

我尝试用 pop 指令替换 stloc.1 。当我这样做时,错误发生在 IL_0019: ret 中,

我真的不知道为什么会这样。有什么想法吗?

附加信息:

  • IScope 是一个接口
  • BlockScope 实现 IScope
  • Function 有一个 public IScope Scope { get;私人套装; 我在 Mono 2.6.7( Boehm
  • , AMD64) 和 Mono 2.8(Boehm with typed GC and Parallel Mark, AMD64) 中都遇到了这个错误

I'm getting a weird bug in an assembly exported with System.Reflection.Emit with mono.
When attempting to run my assembly, I get an InvalidProgramException: Invalid IL code.

monodis gives me this CIL result(which is consistent with what I export with Emit):

.method public static hidebysig 
       default void f_main (class [Pine.Core]Pine.Core.Function A_0, class [Pine.Core]Pine.Core.ValueList A_1)  cil managed 
{
    // Method begins at RVA 0x2144
    // Code size 26 (0x1a)
    .maxstack 4
    .locals init (
        class [Pine.Core]Pine.Core.Function V_0,
        class [Pine.Core]Pine.Core.IScope   V_1,
        class [Pine.Core]Pine.Core.ValueList    V_2,
        class [Pine.Core]Pine.Core.IScope   V_3)
    IL_0000:  ldarg.0 
    IL_0001:  stloc.0 
    IL_0002:  ldarg.1 
    IL_0003:  stloc.2 
    IL_0004:  ldloc.0 
    IL_0005:  ldftn instance class [Pine.Core]Pine.Core.IScope class [Pine.Core]Pine.Core.Function::get_Scope()
    IL_000b:  stloc.1 
    IL_000c:  ldloc.1 
    IL_000d:  newobj instance void class [Pine.Core]Pine.Core.BlockScope::'.ctor'(class [Pine.Core]Pine.Core.IScope)
    IL_0012:  stloc.3 
    IL_0013:  ldloc.2 
    IL_0014:  call instance void class [Pine.Core]Pine.Core.ValueList::Clear()
    IL_0019:  ret 
} // end of method PineType::f_main

The error happens in IL_000b: stloc.1
I have no idea why.

I tried to replace the stloc.1 by a pop instruction. When I do that the error happens in IL_0019: ret

I really don't know why this is behaving like this. Any ideas?

Additional Information:

  • IScope is an interface
  • BlockScope implements IScope
  • Function has a public IScope Scope { get; private set; }
  • I get this error with both Mono 2.6.7(Boehm, AMD64) and Mono 2.8(Boehm with typed GC and Parallel Mark, AMD64)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

送君千里 2024-10-26 06:32:01

编辑:从代码来看,也许 IL_0005 应该是 call/callvirt 而不是 ldftn ?也许发射使用了错误的操作码?

Local 1 是 IScope。 ldftn 将函数指针(本机 int)推送到计算堆栈上。 IL_000b 处的存储指令无法验证,因为本机 int 不可验证程序分配给 IScope。

至于你的第二个问题,你已经使用 IL_0004 处的指令使评估堆栈不平衡。 ldftn 的堆栈转换为“... -> ..., ftn”。这意味着它不需要评估堆栈参数,只需要立即元数据标记。通过将 IL_000b 更改为 pop,可以弹出 ldftn 推送的内容,而不是 IL_0004 推送的内容。

我不清楚的是你想要做什么。您不能将单个函数指针视为接口(至少在概念上您可以将其视为指向 v 表的指针)。您需要实例化一个实现该接口的类型。您可以对函数指针执行的操作是从中创建一个委托 - 委托具有 .ctor 的 (object, native int) 重载。这就是我假设 IL_0004 推送的对象引用将发挥作用的地方(此 .ctor 的第一个参数)。当然,您也可以直接调用函数指针。由于我不熟悉您正在交互的对象模型,因此我无法说出正确的方法是什么。

Edit: judging from the code, perhaps IL_0005 is meant to be a call/callvirt and not a ldftn? Perhaps the emitting is using the wrong opcode?

Local 1 is an IScope. ldftn pushes a function pointer (native int) onto the evaluation stack. The store instruction at IL_000b fails verifiability, as a native int is not verifier-assignable-to IScope.

As for your second problem, you've unbalanced the evaluation stack with the instruction at IL_0004. ldftn's stack transition is " ... -> ..., ftn". Meaning it doesn't take an evaluation stack argument, only the immediate metadata token. By changing IL_000b to a pop, you pop what ldftn pushed, but not what IL_0004 pushed.

What isn't clear to me is what you're attempting to do. You can't treat a single function pointer as an interface (which you could think of, conceptually at least, as a pointer to a v-table). You would need to instantiate a type that implements the interface. What you could do with the function pointer is create a delegate from it - Delegate has an (object, native int) overload for .ctor. That would be where I assume the object reference pushed by IL_0004 would come into play (first argument to this .ctor). You could, of course, calli the function pointer directly as well. As I am unfamiliar with this object model you're interacting with, I can't say what the right approach is.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文