zoukankan      html  css  js  c++  java
  • 在JIT编译生成的函数上设置断点

    在前面已经介绍过,JIT编译器编译了一个函数并将其放在内存中。如果我们知道JIT编译器保存机器代码的位置,就可以使用调试器的bp命令来设置 断点。我们再次使用在前面介绍过的03breakpoint.exe程序,并且试验能否在AddAndPrint函数上设置一个断点。具体来说,我们希望 在第二次调用这个函数时设置一个断点,以便分析其中潜在的错误。在调试器下启动03breakpoint.exe,并继续执行直到程序提示按任意键。按下 任意键,等待并直到第二次提示按下任意键。此时,按下CTRL-C进入调试器。这是在第二个AddAndPrint函数中设置断点的起始位置。第一个任务 就是判断这个函数是否已经被JIT编译器编译,这可以通过SOS命令name2ee来进行判断。命令name2ee的形式如下所示:

     

    参数module name是需要分析的模块,而type or method name则表示需要获得信息的类型名或者方法名。在这里,module name是03breakpoint.exe,而type name为Advanced.NET.Debugging.Chapter3.Breakpoint.AddAndPrint。

     

    可以看到,在最后一行输出中,这个方法的状态为JITTED(表示已经被JIT编译器编译过了),并且编译之后的地址为003e0178。我们可以通过命令U对这段代码做一个简单的完整性检查(sanity check,在后面将进一步讨论),如清单3-9所示。

    清单3-9通过反编译JIT生成的代码对JIT地址进行完整性检查

     


    在反汇编代码的第一部分很清楚地表明了传递给命令U的地址参数是正确的。命令U告诉我们,位 于这个地址上的代码是JIT生成代码。此外,下一行则告诉我们与这段代码相对应的方法名(这里是 Advanced.NET.Debugging.Chapter3.Breakpoint.AddAndPrint)。最后,第三行是起始地址 (003e0178)和生成代码的大小(80)。在这些初始信息之后是反汇编后的指令。现在,我们可以找到动态生成代码的正确地址,并且在这个地址上设置 一个断点。如果恢复程序执行(不要忘记按下任意键来启动第二次调用),可以很快地触发断点,如下所示:

     

    在触发断点后,可以使用ClrStack命令来确保触发的是正确的代码位置。

    之前,我们希望在第二次调用AddAndPrint时设置一个断点,因为这次的调用中存在一个错误。而现在,我相信你已经知道了为什么要在第二次调 用时设置一个断点,就是因为在一个由JIT编译的函数上设置断点是很容易的(在前一次调用该函数时会使这个函数被JIT编译)。我们可以通过 name2ee命令来找出JIT编译后代码的地址,然后在这个地址上使用bp命令。

    这是在设置断点时可以使用的另一种方法。SOS调试器扩展包含了一个命令bpmd,这个命令能够极大地简化工作,它能自动找出被JIT编译后代码的正确地址,并且可以仅根据完整的方法名来设置断点。

    接下来,我们来看看如何在还没有被JIT编译的函数上设置断点。毕竟,我们不能总在被JIT编译后的函数上设置断点,有时候还需要在第一次调用函数时就设置断点,而此时函数通常还没有被编译。

  • 相关阅读:
    C++对象模型
    Session、Application、Cache
    JavaScript事件的几个细节
    algorithm(算法)
    【REST WCF】30分钟理论到实践
    实践Scrum
    调试PostSharp DEMO 遇到的问题
    6.8 按字符串中的部分内容排序
    QObject就有eventFilter,功能很强(随心所欲的进行处理,比如用来QLineEdit分词)
    QPainter就是手里的作图工具,只需要三洋东西:笔(颜色,宽度,样式),字体(写字),刷子(大面积作画),这里有三个典型例子
  • 原文地址:https://www.cnblogs.com/dushu/p/2500814.html
Copyright © 2011-2022 走看看