我正在研究一个 DLL(用 C++ 编写)的源代码,它是另一个程序的插件。没有文档,我也没有主程序的源代码。我试图找出主程序调用 DLL 的位置和时间。有超过 100 个函数被标记为 DllExport
,因此仅此一项并没有多大帮助。
为此,如果我每次执行到我的 DLL 中的代码时都可以触发一个断点,那就太好了。那或将其记录在某处。这可能吗?如何实现?
最佳答案
呸,这是你的要求。但老实说,这可能是非常有用的东西,即使对于其他场景也是如此。
我认为您可以实现此目的的最简单方法是使用 WinDbg 并在那里设置断点。使用 WinDbg 你可以做这样的事情(假设你的图像被命名为 myplugin.dll
):
- 打开WinDbg
- 文件 -> 符号文件路径(添加插件的 .pdb 所在的路径)
- 文件 -> 源文件路径(添加插件源所在的路径)
- 文件 -> 图像文件路径(添加插件 DLL 本身所在的路径)
- 文件 -> 打开可执行文件(或附加到现有进程,选择主应用程序)
- 在命令行:
bm myplugin!*
- 运行程序 (F5)
第 6 步将在 myplugin.dll
中的每个符号处添加一个断点。但这里要小心:这实际上会在每个 函数处添加一个断点,即使是在您可能没有自己定义但通过 header (如 STL)包含的函数处也是如此。这是在模块中各处设置断点的最激进的方法。如果插件的编程方式是所有导出的函数都位于命名空间中或带有前缀,则您可以减少搜索模式并获得更准确的断点。假设您感兴趣的所有这些函数都以 PLG_
为前缀,那么您会这样写:
bm myplugin!PLG_*
相应地设置每个断点 - 非常简单。
缺点当然是您必须使用外部调试器。 Visual Studio 确实支持功能类似的函数断点,但据我所知,它们要么在所有情况下都无法很好地使用通配符,要么在 VS2013+ 中对其进行了更改,其中之一。
这是我所知道的最简单的方法(不是说没有,而是我根本不知道)。第二个最简单的方法:手动添加一次断点并保存您的 .suo 文件,如果您稍后再次需要断点。这是一项繁琐的任务,但寻找更快的解决方案可能比手动完成需要更长的时间(以一个工作日计算)。
其他情况是您编写了一个程序,在导出函数的最开头添加了一个蹦床(读取 PE header 并获取函数的 RVA),其中包含 int 3
和原始指令,但这太过分了——在你这样做之前,你很容易在 1000 个函数中手动设置断点。
另一种方法是更改存储断点的 .suo 解决方案选项文件。但是,据我所知,这些只能通过 Visual Studio 的可扩展性 API 获得,这意味着您必须为 Visual Studio 本身编写插件或宏。
我对这个也很感兴趣。所以我会观察这个问题一段时间,也许有人知道有很多更简单的解决方案。如果您是 WinDbg 的新手,只需添加评论,我将尝试解释您如何获得它以及它是如何工作的:)
关于c++ - 如何在 Visual Studio 中的 DLL 上设置断点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27090478/