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 宏