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编译后的函数上设置断点,有时候还需要在第一次调用函数时就设置断点,而此时函数通常还没有被编译。

  • 相关阅读:
    archlinux .bash_history
    Ubuntu环境下挂载新硬盘
    软碟通 UltraISO U启替代品 Win32DiskImager 无设备 无盘符 无u盘 无优盘 解决方案 之diskpart
    delphi Integer overflow
    MSBuild Tools offline
    delphi synedit免费的拼写检查器dll
    git 自定义命令行
    lua编译
    gcc ar
    Windows Subsystem for Linux (WSL)挂载移动硬盘U盘 卸载 c d 盘
  • 原文地址:https://www.cnblogs.com/dushu/p/2500814.html
Copyright © 2011-2022 走看看