zoukankan      html  css  js  c++  java
  • WinDbg Script---显示RCW对象引用的COM对象

    在调试.NET应用程序中的转储文件时,有时我们可能会遇到这样的情况:我们希望得到引用RCW对象的System.__ComObject包装器引用的COM对象。
    你可能会认为抛弃这个系统。也许你能给出答案,但事实并非如此。

    如下例子

    Name: System.__ComObject
    
    MethodTable: 79307098
    
    EEClass: 790dfa34
    
    Size: 16(0x10) bytes
    
    GC Generation: 2
    
     (C:WINDOWSassemblyGAC_32mscorlib2.0.0.0__b77a5c561934e089mscorlib.dll)
    
    Fields:
    
          MT    Field  
    Offset                 Type
    VT     Attr    Value Name
    
    79330740  400018a        4       
    System.Object  0 instance 00000000
    __identity
    
    79333178  400027e        8 ...ections.Hashtable  0 instance 00000000 m_ObjectToDataMap

    Where is the COM object???

    因此,在使用私有符号时,我从《高级Windows调试和高级.NET调试》那里学到了一系列步骤。我首先想到的是,当需要再次使用该技术时,我会忘记这些步骤,所以我创建了一个脚本来完成这项工作。
    根据SOS 4.5的公开测试版,有一个命令可以做到:!DumpRCW <RCW address>

    此命令列出有关运行时可调用包装的信息。你可以用!DumpObj获取与托管对象对应的RCW地址。输出包含RCW保留的所有COM接口指针,这对于研究互操作性强的应用程序的生存期问题非常有用。

    如果COM对象被释放,而RCW引用计数器没有减少(例如,Marshal.FinalReleaseComObject未调用),您将知道,因为脚本将显示无效地址,例如:

    另一种情况:

    脚本源代码如下:

    $$
    $$ =============================================================================
    $$ COM_FROM_RCW_PUBLIC.TXT
    $$
    $$ Version: 1.2
    $$
    $$ Note: Create a folder called MyScripts where your WinDbg.exe is located and
    $$       save the script there.
    $$
    $$ This script gives you the COM object used by System.__ComObject
    $$
    $$ Note: This is the Public version.
    $$ Compatibility: Win32/Win64.
    $$ PSSCORx or SOS required.
    $$
    $$ Usage: $$>a<myscriptsCOM_FROM_RCW.txt  <address of System.__ComObject>
    $$
    $$ Mario Hewardt    
    $$ Roberto Alexis Farah - http://blogs.msdn.com/debuggingtoolbox/
    $$
    $$ 3/5/2012 - Fixed problem with x64.
    $$
    $$ All my scripts are provided "AS IS" with no warranties, and confer no rights.
    $$ =============================================================================
    $$
    $$ Checks if user is providing the argument.
    .if(0 == ${/d:$arg1})
    {
    
        .printf /D "
    <b> Please, provide the address of System.__ComObject as argument for the
    
    script.</b>
    
    "
        .printf  "Usage: $$>a<myscripts\COM_FROM_RCW_PUBLIC.txt <address of System.__ComObject>"
    }
    .else
    {
        .catch
        {
            .printf /D "
    <b> Make sure you are using Symbols and PSSCOR or SOS is loaded...</b>
    
    
    
    "
    
            $$ Let's get the address of the object - 0x4 and the low order WORD from that address.
            r @$t0 = wo(${$arg1}-0x4)
    
            $$ Gets Sync Block because we need the first syncblk field.
            $$ To do that we need to redirect the output to a file and parse the file.
            .logopen TEMP.LOG
    
            !syncblk @$t0
    
            .logclose
    
            $$ Now let's parse the output... We need token # 15
            $$ This is what we need:
            $$
            $$ Index SyncBlock MonitorHeld Recursion Owning Thread Info  SyncBlock Owner
            $$     3 100e502c <<<       0         0 00000000     none    12a32b3c System.__ComObject
         
            $$ Counter to count tokens. /pS didn't work as I expected...
            r @$t1 = 0
            r @$t2 = 0
              
            .foreach /f (obj "TEMP.LOG")
            {
                 r @$t1 = @$t1 + 1
    
                 $$ Is this field number 15? If yes we can ignore the other fields.    
                 .if(0n15 == @$t1)
                 {
                      .echo SyncBlock address = ${obj}
    
                      $$ Let's save our address. Keep in mind that this line can store
                      $$ garbage, like a field name from the output, if something goes wrong.
                      r @$t2 = ${obj}
    
                      .break
                 }
            }
    
            $$ Protection against invalid pointers.
            .catch
            {
                .if(0n4 == @$ptrsize)
                {
                    r @$t3 = poi(poi(poi(@$t2+0x1c)+@$ptrsize*0n3)+0x88)
                }
                .else
                {
                    r @$t3 = poi(poi(poi(@$t2+0x28)+@$ptrsize*0n3)+0x100)
                }
            }
    
            .printf /D "
    <b>This is the COM object referenced by the RCW object from address
    
    %p:</b>
    
    ", @$t2
    
            dps @$t3 L10
        }
    }
  • 相关阅读:
    将指定文件夹下所有图片转换成base64并返回数组
    SQL技巧
    yii 进行事务操作是不可以在一条sql里边放多条sql
    yii 直接执行sql
    按照特定方法排序
    表名为变量时的语法
    如何添加 actions
    触发器原理
    codeCeption 调试方法
    最长不下降子序列(LIS)
  • 原文地址:https://www.cnblogs.com/yilang/p/13932640.html
Copyright © 2011-2022 走看看