C# WinDbg从符号中获取所有函数的地址

C# WinDbg从符号中获取所有函数的地址,c#,windbg,C#,Windbg,正在执行命令x ShittyProject*我得到这样的输出 <MSIL:00250014 > ShittyProject!Main (void) <MSIL:00250098 > ShittyProject!.ctor (void) <MSIL:00250037 > ShittyProject!.ctor (void) <MSIL:002500ed > ShittyProject!g

正在执行命令
x ShittyProject*我得到这样的输出

<MSIL:00250014         > ShittyProject!Main (void)
<MSIL:00250098         > ShittyProject!.ctor (void)
<MSIL:00250037         > ShittyProject!.ctor (void)
<MSIL:002500ed         > ShittyProject!get_Default (void)
<MSIL:002500a1         > ShittyProject!get_ResourceManager (void)
<MSIL:002500f8         > ShittyProject!.cctor (void)
<MSIL:0025002a         > ShittyProject!Foo (void)
<MSIL:0025006e         > ShittyProject!InitializeComponent (void)
<MSIL:00250000         > ShittyProject!InitializeComponent (void)
<MSIL:002500da         > ShittyProject!get_Culture (void)
<MSIL:002500e5         > ShittyProject!set_Culture (void)
ShittyProject!主(空)
该死的项目!。行政主任(无效)
该死的项目!。行政主任(无效)
该死的计划!获取默认值(void)
该死的计划!获取资源管理器(无效)
该死的项目!。cctor(无效)
该死的计划!富(无效)
该死的计划!初始化组件(无效)
该死的计划!初始化组件(无效)
该死的计划!获取文化(无效)
该死的计划!设置区域性(无效)
如果我理解正确的
MSIL:
这是
pdb
文件中唯一的函数地址?
是否可能以某种方式获取函数的地址以在其上放置断点?

托管代码与本机代码不同。要将断点设置为“本机方式”(
bp
),您需要等待直到JIT编译该方法,然后使用该方法的本机地址

通常情况下,人们不会这样做,而是使用特定于.NET的等价物。有
!bpmd
或(可能不再维护)
!mbm

给定代码

using System;

namespace JittyProject
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine("You want to stop before this shows up.");
            Console.ReadLine();
        }
    }
}
您希望在初始断点处停止并告诉它等待.NET加载,例如

0:000> sxe ld clr
0:000> g
加载.NET运行时后,可以为.NET特定调试命令加载SOS扩展

0:000> .loadby sos clr
以及SOSEX扩展:

0:000> .load c:\wherever\SOSEX.dll
然后添加一个断点:

0:000> !mbm JittyProject.Program.Main
0:000> g
ModLoad: 76650000 766e2000   C:\Windows\SysWOW64\OLEAUT32.dll
Breakpoint: JIT notification received for method JittyProject.Program.Main() in AppDomain 00960db0.
Breakpoint set at JittyProject.Program.Main() in AppDomain 00960db0.
Breakpoint 2 hit

0:000> !clrstack
OS Thread Id: 0x3ff8 (0)
Child SP       IP Call Site
003eeda0 77601ffc [PrestubMethodFrame: 003eeda0] JittyProject.Program.Main() [C:\...\JittyProject\Program.cs @ 8]
003eef74 77601ffc [GCFrame: 003eef74] 
使用常规的
g
,您最终将到达断点:

0:000> !mbm JittyProject.Program.Main
0:000> g
ModLoad: 76650000 766e2000   C:\Windows\SysWOW64\OLEAUT32.dll
Breakpoint: JIT notification received for method JittyProject.Program.Main() in AppDomain 00960db0.
Breakpoint set at JittyProject.Program.Main() in AppDomain 00960db0.
Breakpoint 2 hit

0:000> !clrstack
OS Thread Id: 0x3ff8 (0)
Child SP       IP Call Site
003eeda0 77601ffc [PrestubMethodFrame: 003eeda0] JittyProject.Program.Main() [C:\...\JittyProject\Program.cs @ 8]
003eef74 77601ffc [GCFrame: 003eef74] 

在获得“正常”断点之前,需要对代码进行JIT编译,这发生在应用程序第一次执行时。您需要的是sos.dll的一部分,称为托管断点!bpmd。请参阅@AloisKraus,请提供我尝试过但调试器未停止的示例。非常感谢。!bpmd是实现这一点的常规(也是最简单)方法。但是,如果该方法已经JIT,则可以像本机代码一样在地址上手动放置断点。例如,使用!sos.name2ee!以列出方法的详细信息。如果JIT,则给出实际地址。然后您可以执行bp操作在其上放置断点。是否可以传递到
!bpmd
函数的地址而不是名称?提前谢谢。@A1919:a)不,我不知道如何使用MSIL地址来实现同样的目的b)我更改了答案,因为我无法连续4次复制调试会话!bpmd似乎不那么可靠