【问题标题】:Get source line number from map file for a DLL从映射文件中获取 DLL 的源代码行号
【发布时间】:2011-06-29 07:29:05
【问题描述】:

当一个EXE抛出“地址XXXXXXXX的访问冲突...”这样的异常信息时,地址XXXXXXXX是一个十六进制值,我们可以通过查看映射文件得到导致异常的源代码行号.详情如下(by madshi at EE):

你需要减去图片库, 这很可能是 400000 美元。 此外,您需要减去 “代码基础”地址,即 存储在每个图像的nt头中 模块(exe/dll)。通常是 1000 美元。 您可以通过以下方式检查它的值 使用免费软件工具“PEProwse Pro”。它是“代码基础”中的字段 “可选”的“详细信息” 标头”。您还将找到图像 那里的基地址。

我的问题是:如何获取 DLL 的源代码行号?是否适用相同的计算?谢谢!

注意 1:地图文件是由 Delphi 生成的,我不确定这是否重要。

注意 2:我一直在使用 JCL DEBUG,但它无法捕获似乎在 DLL(实际上是 Office 加载项)启动时发生的异常。

【问题讨论】:

    标签: delphi debugging exception-handling stack


    【解决方案1】:

    不能在同一个地址加载两个二进制文件。因此,存储在 DLL/EXE 中的映像基地址只是针对二进制优化的建议。二进制文件实际加载到内存中的位置取决于许多因素,例如首先在进程中加载​​的其他二进制文件、Windows 版本、注入的第 3 方 dll 等。

    按照建议,您可以使用调试器或 Process Explorer 之类的工具来找出当时加载 DLL 的地址。或者,如果您想从代码中了解,您可以通过从 DLL since both are the same 获取 HInstance 或 HModule 以及加载 DLL 的内存中的地址。 Delphi 通过 GetModuleHandle 方法为您获取其他 DLL 的 HModule。较新的 Delphi 版本还有其他查找 HInstance 的方法。

    【讨论】:

    • 在实践中,您总是可以使用$IMAGEBASE 来安排您的 DLL 在其首选地址加载,而无需加载时间变基,这样做是明智的。
    • 确定一个“免费”地址可能很困难,因为如果您的任何进程的其他 dll 大小发生变化,或者某些 3rd 方应用程序(如屏幕捕获程序)将 dll 注入您的进程,它可能会发生变化等等
    • 感谢 Lars,有任何将 hInstance 转换为“基本映像”地址的代码示例吗?谢谢!
    【解决方案2】:

    同样的计算也适用,但需要注意的是:您需要获取加载 DLL 的实际地址,而不是 EXE 的图像基地址。 DLL 的代码库应采用与 EXE 相同的方式(存储在 PE 的 IMAGE_OPTIONAL_HEADER 中)。

    顺便说一句,从PE格式的角度来看,EXE和DLL实际上是一回事。

    【讨论】:

    • 我还想推荐一个工具来简化任务 - 如果你处理 x64 - dumpbin 足够强大。如果您只考虑 32 位图像 - Total Commander 有非常方便的 PEViewer 插件,这使得 PE 标头分析变得非常容易。
    • 这确实是正确的。只需确保 DLL 没有在加载过程中重新设置基础 - 您可以使用 {$IMAGEBASE } 选项(例如在 .dpr 文件中)执行此操作,并选择一个不会与您的进程中的其他 DLL 冲突的位置。
    • 如果需要一个用于 Delphi DLL 的 x64 工具就好了,不是吗!
    • 调试时,IDE 在其“事件日志”(调试器选项 -> 事件日志)中显示已加载 dll 的基地址。如果静态链接,“模块”视图也有此信息。
    • 找到加载 DLL 的实际地址的最简单方法 - SysInternals'Process Explorer正确的工具
    猜你喜欢
    • 2016-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多