MSVC _penter 和 _pexit 钩子可以在每个函数的基础上禁用吗?

Posted

技术标签:

【中文标题】MSVC _penter 和 _pexit 钩子可以在每个函数的基础上禁用吗?【英文标题】:Can MSVC _penter and _pexit hooks be disabled on a per function basis? 【发布时间】:2010-10-13 16:53:24 【问题描述】:

MSVC 中有一些编译器选项可以在进入和退出函数时自动生成检测调用。这些钩子称为 _penter() 和 _pexit()。编译器的选项是:

/Gh 启用_penter挂钩功能

/GH 启用_pexit挂钩功能

是否有编译指示或某种函数声明会在每个函数的基础上关闭检测?我知道使用 __declspec(naked) 函数不会被检测,但这并不总是一个非常实用的选择。我在 PC 和非 X86 平台上都使用 MSVC,非 X86 平台在汇编程序中手动编写 Epilog/prolog 很痛苦(更不用说它会弄乱调试器堆栈跟踪)。

如果这仅基于每个文件(编译器选项),我想我将不得不将特殊功能拆分到一个单独的文件中以关闭该选项,但如果我可以控制它会容易得多以每个文件为基础。

如果无法做到这一点,后备计划是将函数移动到它们自己的 CPP 翻译单元并在没有选项的情况下单独编译。

【问题讨论】:

我认为最好有东西可以打开它。我相信它应该对个人资料非常有用。 【参考方案1】:

我看不出有什么方法可以做到这一点。鉴于无论如何您都必须找到并处理每个受影响的函数,也许将它们移到自己的模块中并不是什么大问题。

【讨论】:

我希望有一个简单的东西,比如 __declspec(dontinstrument) 或类似的东西。 @Adisak - 对 - 不过,我认为没有什么可做的。 是的...我自己没有看到另一种方法。但问也无妨。 您可以通过删除该 .cpp 文件的编译器选项来为每个文件执行此操作 @paulm - 问题的范围更窄(每个功能设置)【参考方案2】:

Asker 知道,但值得写出不合格的方法以供将来参考。 /Gh 和 /GH 不检测裸函数。您可以将要退出的函数声明为裸函数并手动提供standard prolog/epilog,如下所示,

void instrumented_fn(void *p)

    /* Function body */


__declspec(naked) void uninstrumented_fn(void *p)

    __asm
          
        /* prolog */
        push    ebp
        mov     ebp, esp
        sub     esp, __LOCAL_SIZE
    

    /* Function body */

    __asm
       
        /* epilog */
        mov     esp, ebp
        pop     ebp
        ret
    

一个示例检测函数反汇编,显示对 penter 和 pexit 的调用,

   537b0:   e8 7c d9 ff ff          call   0x51131
   537b5:   55                      push   %ebp
   537b6:   8b ec                   mov    %esp,%ebp
   537b8:   83 ec 40                sub    $0x40,%esp
   537bb:   53                      push   %ebx
   537bc:   56                      push   %esi
   537bd:   57                      push   %edi
   537be:   90                      nop
   537bf:   90                      nop
   537c0:   90                      nop
   537c1:   5f                      pop    %edi
   537c2:   5e                      pop    %esi
   537c3:   5b                      pop    %ebx
   537c4:   8b e5                   mov    %ebp,%esp
   537c6:   5d                      pop    %ebp
   537c7:   e8 01 d9 ff ff          call   0x510cd
   537cc:   c3                      ret    

等价的uninstrumented函数反汇编(裸身加标准prolog/epilog)

   51730:   55                      push   %ebp
   51731:   8b ec                   mov    %esp,%ebp
   51733:   83 ec 40                sub    $0x40,%esp
   51736:   90                      nop
   51737:   90                      nop
   51738:   90                      nop
   51739:   8b e5                   mov    %ebp,%esp
   5173b:   5d                      pop    %ebp
   5173c:   c3                      ret   

【讨论】:

以上是关于MSVC _penter 和 _pexit 钩子可以在每个函数的基础上禁用吗?的主要内容,如果未能解决你的问题,请参考以下文章

用于 penter 和 pexit 的 Visual Studio 宏

C++ - 从结束地址获取函数的起始地址/获取函数的大小

最有用的 MSVC++ 非标准宏

CMake区分MSVC版本

为啥在 __assume 中使用函数调用时 MSVC 不报错?

MSVC2015:找不到 __vcrt_UnhandledException