惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
Microsoft Security Blog
Microsoft Security Blog
Recent Announcements
Recent Announcements
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Last Week in AI
Last Week in AI
罗磊的独立博客
腾讯CDC
云风的 BLOG
云风的 BLOG
月光博客
月光博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
宝玉的分享
宝玉的分享
U
Unit 42
I
InfoQ
D
DataBreaches.Net
Blog — PlanetScale
Blog — PlanetScale
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
V2EX
美团技术团队
IT之家
IT之家
Stack Overflow Blog
Stack Overflow Blog
F
Fortinet All Blogs
GbyAI
GbyAI
S
SegmentFault 最新的问题

博客园 - Demon521

博文阅读密码验证 - 博客园 博文阅读密码验证 - 博客园 流浪歌手弹唱震撼心灵(很震撼心灵!) 爱,永远禁不起等待 好男人找不到女朋友的根源 男女交往必知15个真理 上海地铁车费没有必要大于6元 CLR探索系列:Windbg+SOS剖析揭示域世界 (转) CLR探索系列:Windbg+SOS动态调试分析托管代码 (转) WinDbg+SOS:Web服务器High CPU Hang(100%)实例分析 (转) 使用WinDbg+SOS及WinDbg Script寻找内存中DataTable第M行N列的值 (转) Windbg在Managed App中设置函数断点的几种方法 (转) 线程之间的通讯---SynchronizationContext (转) 世界顶级精英们的人生哲学! 各类搜索网站 快速找到并输入连接数据源的字符串 UML中依赖/泛化/关联/实现/聚合/组合的C#实现 [转] 最最常用的DOS Command 最常用的Windows快捷键
Windbg寻找Managed Founction参数值 (转)
Demon521 · 2009-01-13 · via 博客园 - Demon521

         问题源自一个Seminar,如何使用Windbg找到在函数调用的时候,所传递的参数的值。

         当使用live Debug模式attach到一个managed Process的时候,默认情况下并不显示函数内部之间的调用,这个时候,需要在这个函数没调用之间给下一个断点。

         基于对一个托管函数下断点的两种方法,在上面一片文章里面已经讲过了,这里就显的容易多了。首先还是找上篇文章里面的程序作为例子:

class Program

    {

        static void Main(string[] args)

        {

            System.Console.WriteLine("Show Params in Windbg");

            Program p = new Program();

            p.ShowParams(123456, "TestParams", 'L');

            System.Console.ReadLine();

        }

        public void ShowParams(int a, string b ,char c)

        {

        }

}

这里的目的,是把调用能够ShowParams这个方法的几个参数找到。如果使用live Debug的话,使用!Clrstack命令并不能得到这个结果:

0:000> !clrstack

OS Thread Id: 0x11a0 (0)

ESP       EIP    

0012f3e0 7c90eb94 [NDirectMethodFrameStandaloneCleanup: 0012f3e0]

                   System.IO.__ConsoleStream.ReadFile

(Microsoft.Win32.SafeHandles.SafeFileHandle, Byte*, Int32, Int32 ByRef, IntPtr)

0012f3fc 7948d2bb System.IO.__ConsoleStream.ReadFileNative

(Microsoft.Win32.SafeHandles.SafeFileHandle, Byte[], Int32, Int32, Int32, Int32 ByRef)

0012f428 7948d1ed System.IO.__ConsoleStream.Read(Byte[], Int32, Int32)

0012f448 793a3350 System.IO.StreamReader.ReadBuffer()

0012f458 793aaa2f System.IO.StreamReader.ReadLine()

0012f46c 79497b5a System.IO.TextReader+SyncTextReader.ReadLine()

0012f474 793e99f0 System.Console.ReadLine()

0012f478 00db00c7 FounctionParams.Program.Main(System.String[])

0012f69c 79e7c74b [GCFrame: 0012f69c]

可以看到,这里直接略过了函数内部的调用,从Main直接到了ReadLine(),而使用!Clrstack –p命令也是不能显示出内部函数调用的传递的参数的值的。

可以这样得到中间调用的函数传递的参数的值:

首先Dattach掉,然后加载Exe可执行模块,来进行动态调试:

0:000> sxe ld:mscorjit

0:000> g

ModLoad: 79060000 790b6000   C:"WINDOWS"Microsoft.NET"Framework"v2.0.50727"mscorjit.dll

eax=00000000 ebx=00000000 ecx=00d90000 edx=7c90eb94 esi=00000000 edi=00000000

eip=7c90eb94 esp=0012e554 ebp=0012e648 iopl=0 nv up ei ng nz ac pe nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000296

ntdll!KiFastSystemCallRet:

7c90eb94 c3              ret

这个时候可以加载SOS模块了,加载好了之后:

0:000> !thread

No export thread found

0:000> !threads

ThreadCount: 2

UnstartedThread: 0

BackgroundThread: 1

PendingThread: 0

DeadThread: 0

Hosted Runtime: no

                                         PreEmptive   GC Alloc        

       ID      GC       Context       Domain   Count APT Exception

   0    1 Enabled 013f16d0:013f1fe8  0015c410     2 MTA

   2    2 Enabled 00000000:00000000 0015c410     0 MTA (Finalizer)

好的,接下来dump domain

0:000> !dumpdomain 0015c410    

--------------------------------------

Domain 1: 0015c410

LowFrequencyHeap: 0015c434

HighFrequencyHeap: 0015c48c

StubHeap: 0015c4e4

Stage: OPEN

SecurityDescriptor: 0015d740

Name: FounctionParams.exe

Assembly: 0019f3f8

[C:"WINDOWS"assembly"GAC_32"mscorlib"2.0.0.0__b77a5c561934e089"mscorlib.dll]

ClassLoader: 0019f490

SecurityDescriptor: 0019be78

 Module Name

790c2000

C:"WINDOWS"assembly"GAC_32"mscorlib"2.0.0.0__b77a5c561934e089"mscorlib.dll

Assembly: 001a6e80

[E:"myProject"FounctionParams"FounctionParams"bin"Debug"FounctionParams.exe]

ClassLoader: 001a6f18

SecurityDescriptor: 001a6db0

 Module Name

00a82c3c

E:"myProject"FounctionParams"FounctionParams"bin"Debug"FounctionParams.exe

恩,接下来是module的信息:

0:000> !dumpmodule -mt 00a82c3c

Name: E:"myProject"FounctionParams"FounctionParams"bin"Debug"FounctionParams.exe

Attributes: PEFile

Assembly: 001a6e80

LoaderHeap: 00000000

TypeDefToMethodTableMap: 00a80038

TypeRefToMethodTableMap: 00a80040

MethodDefToDescMap: 00a8008c

FieldDefToDescMap: 00a8009c

MemberRefToDescMap: 00a800a0

FileReferencesMap: 00a800ec

AssemblyReferencesMap: 00a800f0

MetaData start address: 00402094 (1580 bytes)

Types defined in this module

      MT    TypeDef Name

------------------------------------------------------------------------------

00a83038 0x02000002 FounctionParams.Program

Types referenced in this module

      MT    TypeRef Name

------------------------------------------------------------------------------

790fd0f0 0x01000001 System.Object

好了,拿到MT了:

0:000> !dumpmt -md 00a83038

EEClass: 00a811d8

Module: 00a82c3c

Name: FounctionParams.Program

mdToken: 02000002 (E:"myProject"FounctionParams"FounctionParams"bin"Debug"FounctionParams.exe)

BaseSize: 0xc

ComponentSize: 0x0

Number of IFaces in IFaceMap: 0

Slots in VTable: 7

--------------------------------------

MethodDesc Table

   Entry MethodDesc      JIT Name

79371278   7914b928   PreJIT System.Object.ToString()

7936b3b0   7914b930   PreJIT System.Object.Equals(System.Object)

7936b3d0   7914b948   PreJIT System.Object.GetHashCode()

793624d0   7914b950   PreJIT System.Object.Finalize()

00a8c011   00a83020     NONE FounctionParams.Program.Main(System.String[])

00a8c015   00a83028     NONE FounctionParams.Program.ShowParams(Int32, System.String, Char)

00a8c019   00a83030     NONE FounctionParams.Program..ctor()

OK,看到希望了,可以下断点了:

0:000> !bpmd -md 00a83028

MethodDesc = 00a83028

Adding pending breakpoints...

OK,按以下F5

0:000> g

(8b4.1574): CLR notification exception - code e0444143 (first chance)

JITTED FounctionParams!FounctionParams.Program.ShowParams(Int32, System.String, Char)

Setting breakpoint: bp 00DC0110 [FounctionParams.Program.ShowParams(Int32, System.String, Char)]

Breakpoint 1 hit

恩,可以查看调用堆栈了:

0:000> !clrstack

OS Thread Id: 0x1574 (0)

ESP       EIP    

0012f46c 00dc0110 FounctionParams.Program.ShowParams(Int32, System.String, Char)

0012f478 00dc00c0 FounctionParams.Program.Main(System.String[])

0012f69c 79e7c74b [GCFrame: 0012f69c]

查看参数:

0:000> !clrstack -p

OS Thread Id: 0x1574 (0)

ESP       EIP    

0012f46c 00dc0110 FounctionParams.Program.ShowParams(Int32, System.String, Char)

    PARAMETERS:

        this = 0x013f34ac

        a = 0x0001e240

        b = 0x013f170c

        c = 0x0000004c

0012f478 00dc00c0 FounctionParams.Program.Main(System.String[])

    PARAMETERS:

        args = 0x013f16c0

0012f69c 79e7c74b [GCFrame: 0012f69c]

上面的蓝色的地方,分别显示了参变量abc的值。AC是值类型,对应的数值就是咱给的值。Bref type,显示的是Heap上面的一个地址了。

恩,到这里吧,就到这里吧。如果有空还写一片,就结合K命令,还有EIPESP来查看参数的方法,这个比较值得说说,不过比较麻烦。^_^