【问题标题】:How to get source code information from a raw address of jitted .Net function?如何从 jited .Net 函数的原始地址获取源代码信息?
【发布时间】:2018-02-28 16:34:48
【问题描述】:

我正在开发一个调试器,当某个函数(例如,kernel32.dll!CreateFileW)在被调试进程的上下文中被调用时,它应该存储当前堆栈跟踪。

调试器将一些代码注入到进程中,安装一个钩子。然后钩子使用RtlCaptureStackBackTrace 获取堆栈跟踪并将其保存在某处。

然后调试器使用函数 SymFromAddr 解析每个堆栈跟踪的条目。

它适用于非托管代码。

今天我已经为一个使用 CLR 支持构建的 MFC 应用程序尝试了这种方法。现在它是非托管代码。钩子仍然获得堆栈跟踪,但调试器无法解析某些堆栈条目。我猜这些条目属于 JIT 编译器生成的代码。

我对 CLR 分析器有点熟悉,可以收到类似JITCompilationStarted 的通知。

问题是JIT编译器生成的代码如何解析(即获取源文件名和行号)地址?

我不能只调用DoStackSnapshot,因为被挂钩的函数可以调用很多时间,所以 DoStackSnapshot 会使进程变慢。

我可以使用FunctionEnter2/FunctionLeave,但是当执行进入/离开函数时会调用它们,我无法获取有关确切代码行的信息。

谢谢!

【问题讨论】:

    标签: .net debugging profiling clr


    【解决方案1】:

    尽管已明确说明,但听起来您的问题归结为从托管分析器中的指令指针获取源位置。

    获取模块、元数据令牌和 IL 偏移量。

    1. 第一步是获取FunctionID,在大多数情况下已经给你了,但如果没有,你可以使用ICorProfilerInfo::GetFunctionFromIP从指令指针中获取它

    2. 接下来,您可以通过将 FunctionID 传递给 ICorProfilerInfo::GetILToNativeMapping 来获取函数的本机 IL 映射。我依稀记得映射是按顺序返回的,所以你也许可以在这里执行二进制搜索。

    3. 将 FunctionID 传递到 ICorProfilerInfo::GetFunctionInfo 以获取 ModuleID 和方法元数据令牌。

    4. 将 ModuleID 传递到 ICorProfilerInfo3::GetModuleInfo2 以获取路径。 IIRC,路径将通过name 参数返回,但您应该检查pdwModuleFlags 以确保模块存在于磁盘上,否则名称将没有意义(例如,如果模块已发出)。

    获取文件名和行号。

    这是使用symbol store api 执行的,我建议在监控应用程序或后处理步骤中执行此部分,以避免阻止分析器。

    1. 获取模块的 IMetaDataImport。如果您在分析器中执行此操作,则可以使用 CorProfilerInfo::GetModuleMetaData;如果您不在分析器中,则可以使用 IMetaDataDispenser

    2. 使用ISymUnmanagedBinder::GetReaderForFileISymUnmanagedReader::GetMethodISymUnmanagedMethod::GetSequencePoints 获取IL 源映射。

    【讨论】:

      猜你喜欢
      • 2017-04-14
      • 1970-01-01
      • 1970-01-01
      • 2019-12-12
      • 2021-12-16
      • 2022-06-12
      • 1970-01-01
      • 2019-08-29
      • 2010-09-14
      相关资源
      最近更新 更多