【c#】使用WinDbg查看方法表

背景

        《C#从现象到本质》第四章提到了方法表,感觉是语言里很精华的部分,比光学语法规则有趣多了。书里直奔主题(其实是人菜瘾大还爱跳读),被绊了几天,好气哇(书的第二章有提到如何使用WinDbg)。

安装WinDbg

方法一:通过Windows Software Development Kit

旧是旧了点,也能用。方法二里的WinDbg Preview是新版,这是旧版。

 参考 Download Debugging Tools for Windows - WinDbg - Windows drivers | Microsoft Docs

 【c#】使用WinDbg查看方法表_第1张图片【c#】使用WinDbg查看方法表_第2张图片

方法二:通过Micorsoft Store下载

打开Microsoft Store,搜索windbg,

【c#】使用WinDbg查看方法表_第3张图片

 点击安装,用了全局代理才安装到,这里大家就八仙过海的下一句。

实操:查看方法表

测试代码

创建项目-c#控制台应用(.Net Framework),名为ConsoleApp2

项目保存路径为:E:\c#\ConsoleApp2

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    class A
    {
        public virtual void Foo()
        {
            Console.WriteLine("A.Foo");
        }
    }
    class B:A
    {
        public virtual void Foo()
        {
            Console.WriteLine("B.Foo");
        }
    }
    class C : B
    {
        public override void Foo()
        {
            Console.WriteLine("C.Foo");
        }
    }
    internal class Program
    {
        static void Main(string[] args)
        {
            A a = new A();
            a.Foo();

            A b = new B();
            b.Foo();

            A c = new C();
            c.Foo();

            Console.WriteLine(typeof(A).FullName); 
        }
    }
}

方法一:使用WinDbg查看

参考:Windbg 32位版本和64位版本的选择_ithzhang的博客-CSDN博客_windbg64

打开WinDbg-File-Open Executable

【c#】使用WinDbg查看方法表_第4张图片

选中需要调试的程序,打开 

【c#】使用WinDbg查看方法表_第5张图片

 输入lm,回车,看看加载了什么模块

lm

【c#】使用WinDbg查看方法表_第6张图片

使用sympath命令,设置pdb所在路径,回车

.sympath E:\c#\ConsoleApp2\bin\Debug

【c#】使用WinDbg查看方法表_第7张图片

 调用g命令运行程序,回车

g

【c#】使用WinDbg查看方法表_第8张图片

使用load命令加载sos.dll,(注意sos.dll的路径和上面一步画线的clr.dll路径是一致的,C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll)

.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll

如果没加载 sos.dll,使用name2ee命令,会输出No export name2ee found

【c#】使用WinDbg查看方法表_第9张图片

查看类A方法表

使用name2ee获取类A方法表地址,输入以下命令,回车

!name2ee ConsoleApp2 ConsoleApp2.A

【c#】使用WinDbg查看方法表_第10张图片

使用dumpmt命令, 查看方法表。输入以下命令,回车

!dumpmt -md 00704dd0

【c#】使用WinDbg查看方法表_第11张图片

方法二:使用WinDbg Preview 查看

打开winDbg Preview -文件

【c#】使用WinDbg查看方法表_第12张图片【c#】使用WinDbg查看方法表_第13张图片

 选择Launch executable【c#】使用WinDbg查看方法表_第14张图片

 选择需要调试的程序

【c#】使用WinDbg查看方法表_第15张图片

 【c#】使用WinDbg查看方法表_第16张图片

输入lm,查看进程中加载的代码模块列表【c#】使用WinDbg查看方法表_第17张图片

 此时并没有加载没有clr模块【c#】使用WinDbg查看方法表_第18张图片

 按Go按钮,或者使用g命令,回车,发现加载了clr模块

【c#】使用WinDbg查看方法表_第19张图片

查看类A方法表

参考SOS.dll (SOS Debugging Extension) - .NET Framework | Microsoft Docs

使用name2ee命令,获取类的EEClass地址。

【c#】使用WinDbg查看方法表_第20张图片

输入以下命令,回车。

!name2ee ConsoleApp2 ConsoleApp2.A

【c#】使用WinDbg查看方法表_第21张图片

 使用!dumpmt命令,查看方法表

【c#】使用WinDbg查看方法表_第22张图片

输入以下命令,回车

!dumpmt -md 00ff4dd0

【c#】使用WinDbg查看方法表_第23张图片

常用命令

 参考 WinDbg 入门(用户模式) - Windows drivers | Microsoft Docs​​​​​​c

命令 描述 参考
.load

加载新的扩展 DLL 到调试器中

格式:.load DLLName

例子:.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll

.load、.loadby(加载扩展 DLL) - Windows drivers | Microsoft Docs
.loadby

加载新的扩展 DLL 到调试器中

格式:.loadby DLLName ModuleName

例子:.loadby sos clr

.load、.loadby(加载扩展 DLL) - Windows drivers | Microsoft Docs
.sympath

指定 WinDbg 查找符号 (PDB) 文件的位置;

格式:.sympath[+] [Path [; ...]]

例子:.sympath E:\c#\ConsoleApp2\bin\Debug

.sympath(设置符号路径) - Windows drivers | Microsoft Docs
.reload 通知 WinDbg 进行符号文件的初始查找和加载 .reload(重新加载模块) - Windows drivers | Microsoft Docs
bu

设置断点;

格式:bu 程序名!函数名

例子:bu notepad!wWinMain

bp、bu、bm(设置断点) - Windows drivers | Microsoft Docs
lm 查看进程中加载的代码模块列表 lm(列出已加载的模块) - Windows drivers | Microsoft Docs
g 运行 g(转到) - Windows drivers | Microsoft Docs
k 查看堆栈跟踪 k、kb、kc、kd、kp、kP、kv(显示堆栈回溯) - Windows drivers | Microsoft Docs
q 退出进程 q、qq(退出) - Windows drivers | Microsoft Docs
qd 退出调试并从进程分离 qd(退出和分离) - Windows drivers | Microsoft Docs

  

参考SOS.dll (SOS Debugging Extension) - .NET Framework | Microsoft Docs

语法格式:![command] [options] 

命令 描述 格式 例子
Name2EE 

显示指定模块中指定类型或方法的MethodTable结构和结构。

指定的模块必须在进程中加载。

要获得正确的类型名称,请使用Ildasm.exe (IL Disassembler)浏览模块。

Name2EE <模块名称> <类型或方法名称> -或 !name2ee ConsoleApp2 ConsoleApp2.A
DumpMT

显示有关指定地址的方法表的信息。

指定-MD选项会显示使用对象定义的所有方法的列表。

DumpMT [ -MD ] <方法表地址> !dumpmt -md 00704dd0

 其他

c#类的方法表的建立和方法的调用 - seeseaatsea - 博客园对于方法的调用,很是令我头疼,什么静态方法,实例方法,实例虚方法,这里查了很多资料,总结如下: 这里声明,我也是菜鸟,这里只讨论方法的调用相关的技术,属于个人理解,如有错误,请指正 思路: 1 clrhttps://www.cnblogs.com/OneRipple/p/7093876.html

上面链接的内容对我理解方法表帮助蛮大的,在这里马一下。

 方法在方法表中的排列顺序:
继承的实例虚方法、实例虚方法、构造函数、静态方法、实例方法

为什么把“继承的实例虚方法”和“实例虚方法”放在方法表的开头位置?

结论:方法表中虚方法的排序,可以在类的层次结构中保持虚方法的层次结构,这是实现多态的基础,也就是为什么说继承是实现多态的基础了。

你可能感兴趣的:(工具,c#,开发语言)