我已经编写了一个小代码覆盖实用程序来记录在x86可执行文件中命中哪些基本块。它运行时没有源代码或调试目标的符号,只是丢失了它监视的基本块。如何加快我的代码覆盖率工具?
但是,它正在成为我的应用程序中的瓶颈,它涉及单个可执行映像的重复覆盖快照。
它已经经历了几个阶段,因为我试图加快速度。我开始时只是在每个基本块的开始处放置一个INT3,作为调试器附加,并记录命中。然后,我尝试通过在计数器中修补任何大于5个字节的块(JMP REL32的大小)来提高性能。我在进程内存空间中写了一个小存根('mov [blah],1/jmp backToTheBasicBlockWeCameFrom')并将JMP打补丁。这大大加快了速度,因为没有例外,也没有调试器中断,但我想加快速度。
我想以下之一:
1)预仪器,目标二进我的修补计数器(目前我做这在运行时)。我可以在PE中创建一个新的部分,将我的计数器放入其中,修补所需的所有钩子,然后在每次执行后使用调试器从同一部分中读取数据。这会让我获得一些速度(根据我的估计,这个速度大约为16%),但是仍然有那些令人讨厌的INT3,我需要在更小的区块中使用,这实际上会削弱性能。
2)将该二进制文件包含其自己的UnhandledExceptionFilter,并处理它自己的int3与上述内容一起使用。这意味着每个int3都没有从调试对象到我的覆盖工具的过程切换,但是仍然会出现断点异常和随后的内核转换 - 我认为这实际上不会获得太多的性能吗?
3)尝试使用英特尔的硬件分支分析说明来做一些巧妙的事情。这听起来很棒,但我不清楚我会怎么做 - 它甚至可以在Windows用户模式应用程序?如果它非常简单,我可以尽可能编写一个内核模式驱动程序,但我不是内核编码器(我讨论了一点),可能会让我感到头疼。有没有其他项目使用这种方法?我看到Linux内核有它来监视内核本身,这让我认为监视特定的用户模式应用程序将会很困难。
4)使用现成的应用程序。它需要在没有任何源代码或调试符号的情况下工作,可以编写脚本(所以我可以批量运行),并且最好是免费的(我很吝啬)。然而,付费工具并未脱颖而出(如果我可以在工具上花费更少,并且增加足够的性能以避免购买新硬件,那就是很好的理由)。
5)别的东西。我在Windows XP上运行VMWare,在相当陈旧的硬件上运行(Pentium 4-ish) - 是否有任何我错过的或者我应该阅读的任何线索?我可以让我的JMP REL32下降到少于5个字节(并且在不需要int3的情况下捕获更小的块)?
谢谢。
投票结束为“非建设性”?令我惊讶的是,有多少SO人投票结束完全合法的问题,并给出了完全合理的答案。你们给了这个糟糕的味道。 – 2013-02-08 20:41:45
我很好奇。如果你没有来源或符号,你如何检查结果?你只是计算一个百分比覆盖值?如果百分比很低,你如何确定你的测试缺失了哪些部分? – 2013-02-08 22:53:09
我实际上在做黑盒fuzzing找安全漏洞。我的想法是,我稍微改变一个输入文件,观察任何打开的新块,然后'下降'以更多地突变该输入,如果它打开我们以前没有看到的块。(如果你有一个小时左右的空余时间,我发现Travis Ormandy的演讲“制作软件笨拙”令人着迷 - http://www.youtube.com/watch?v=YqZRuvdbR64) – randomdude 2013-02-09 07:28:07