【问题标题】:Trouble examining byte code in MSVC++在 MSVC++ 中检查字节码时遇到问题
【发布时间】:2009-02-06 21:36:07
【问题描述】:

我在工作中一直在使用免费的 Digital Mars 编译器(我知道很淘气),并创建了一些代码来检查编译的函数并查看字节码以用于学习目的,看看我是否可以从中学到任何有价值的东西编译器构建它的函数。但是,在 MSVC++ 中重新创建相同的方法失败得很惨,我得到的结果非常混乱。我有这样的功能:

unsigned int __stdcall test()
{
  return 42;
}

然后我会这样做:

unsigned char* testCode = (unsigned char*)test;

在这种情况下,我似乎无法让 C++ static_cast 工作(它会引发编译器错误)......因此是 C 风格的强制转换,但除此之外......我也尝试过使用参考 &test,但这无济于事。

现在,当我检查 testCode 指向的内存内容时,我感到很困惑,因为我所看到的甚至看起来都不像有效代码,甚至还有一个调试断点卡在那里......看起来像这样(目标是 IA-32):

0xe9、0xbc、0x18、0x00、0x00、0xcc...

这显然是错误的,0xe9是相对跳转指令,看0xbc字节后是这样的:

0xcc、0xcc、0xcc...

即对于未分配或未使用的内存,内存初始化为调试断点操作码。

我对返回 42 的函数的期望是:

0x8b、0x2a、0x00、0x00、0x00、0xc3

或者至少有一些 mov 的味道,然后是 ret(0xc2、0xc3、0xca 或 0xcb),再往下一点

MSVC++ 是出于安全原因采取措施阻止我做这种事情,还是我做了一些愚蠢的事情而没有意识到?使用 DMC 作为编译器,此方法似乎可以正常工作...

我也遇到了其他问题(执行字节),但我怀疑根本原因是相同的。

任何帮助或提示将不胜感激。

【问题讨论】:

  • reinterpret_cast 用于投射指针; static_cast 用于转换不适合 dynamic_cast 的“相关”类型。

标签: c++ visual-c++ bytecode x86


【解决方案1】:

我只能猜测,但我很确定您正在检查调试版本。 在调试模式下,MSVC++ 编译器通过调用跳转存根替换所有调用。这意味着,每个函数都以跳转到实际函数开始,而这正是您在这里所面临的。
周围的 0xCC 字节确实是断点指令,以便在您执行不应该执行的代码时触发可能附加的调试器。
在发布版本中尝试相同的操作。这应该可以按预期工作。

编辑: 这实际上受链接器设置 /INCREMENTAL 的影响。您所描述的效果没有出现在发布版本中的原因是,如果打开了任何类型的优化(当然通常发布版本就是这种情况),这些跳转存根就会被简单地优化掉。

【讨论】:

    【解决方案2】:

    你想要的演员:

    unsigned char* testCode = reinterpret_cast<unsigned char*>( test );
    

    在项目 -> 属性 -> C/C++ -> 常规中将调试信息格式从“用于编辑和继续的程序数据库 (/ZI)”切换为“程序数据库 (/Zi)”。我相信正是这种设置导致编译器插入跳转代码,以便调试器可以在程序运行时重建函数并对其进行热补丁。也可能关闭“启用最小重建”。

    在 MSVC 中检查代码的一种更简单的方法是简单地设置一个断点并检查反汇编(右键单击该行并从弹出菜单中选择“转到反汇编”。它用源注释反汇编代码,这样你就可以看到每一行编译成什么。

    【讨论】:

    • 感谢您提供有用的信息,这解决了 C++ 转换的问题...我错误地认为重新解释仅用于解决继承问题。我知道“goto 反汇编”,但我正在寻找运行时的东西。非常感谢。好答案。 :)
    【解决方案3】:

    如果您想查看给定编译函数的汇编代码和机器代码,向编译器提供 /FAcs 命令行选项并查看随后的 .asm 文件会更容易。

    我不确定将函数指针转换为字节流的定义行为是什么——它甚至可能无法正常工作——但另一个可能造成混淆的原因是 x86 函数都是可变大小的,而且很少-endian 也是。

    【讨论】:

      【解决方案4】:

      如果这是打开增量链接,那么您看到的是jmp [destination]。您可以运行调试器并查看反汇编要验证的内容。

      【讨论】:

        猜你喜欢
        • 2016-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-04
        • 2021-12-18
        • 1970-01-01
        • 1970-01-01
        • 2013-12-17
        相关资源
        最近更新 更多