zoukankan      html  css  js  c++  java
  • Windbg学习20(!htrace) .

    1.!htrace

    !htrace(Handle Trace) 扩展用于显示一个或多个句柄的堆栈回溯信息。

    直接用!htrace -?可以看到简单使用说明:

    0:000> !htrace -?
    !htrace [handle [max_traces]]
    !htrace -enable [max_traces]
    !htrace -disable
    !htrace -snapshot
    !htrace -diff
    
    Handle
    指定要显示堆栈回溯的句柄。如果Handle 为0 或者省略,则显示进程中所有句柄的堆栈回溯。
    Process
    (仅内核模式) 指定要显示句柄的进程。如果Process 为0或者省略,则使用当前进程。用户模式下总是使用当前进程。
    Max_Traces
    指定要显示的堆栈回溯的最大层数。用户模式下如果省略该参数,则显示目标进程中的所有堆栈回溯。
    -enable
    (仅用户模式) 启用句柄跟踪,并且为-diff 选项使用的初始状态产生第一次句柄信息的快照。

    -snapshot
    (仅用户模式) 抓取当前的句柄信息的快照用作-diff 选项的初始状态。.

    -diff
    (仅用户模式) 将当前的句柄信息和上一次句柄快照的信息进行对比。显示所有仍然打开的句柄。

    -disable
    (仅用户模式;仅Windows Server 2003和之后的系统) 禁止句柄跟踪。在Windows XP中,只有结束目标进程才能禁用句柄跟踪。

    -?
    在调试器命令窗口中显示一些简要的帮助文本。

    首先需要用!htrace -enable来告诉操作系统启用栈回溯(这是前提)

    !htrace -snapshot
    !htrace -diff
    0:000> !htrace -enable
    Handle tracing enabled.
    Handle tracing information snapshot successfully taken.

    可以看到,-enable是一个两步操作,首先,启动栈回溯(Handle tracing enabled),

    然后,它根据句柄来抓取进程当前状态的快照(Handle tracing information snapshot successfully taken.)

    在栈回溯被启用后,windows将立即开始记录所有的句柄创建调用和句柄删除调用,在下一次抓取快照时(-snapshot),!htrace将向操作系统查询所有句柄

    创建调用和句柄删除调用的栈回溯,并且把它们显示出来,
    这时直接用!htrace会输出以下内容:

    0:001> !htrace
    --------------------------------------
    Handle = 0x000007bc - CLOSE
    Thread ID = 0x000014fc, Process ID = 0x000013f0
    
    0x7c8135dd: kernel32!GetLongPathNameW+0x00000249
    0x7854287c: MSVCR90!_check_manifest+0x0000009c
    0x78542c22: MSVCR90!__CRTDLL_INIT+0x0000008e
    0x78542d5e: MSVCR90!_CRTDLL_INIT+0x0000001e
    0x7c92118a: ntdll!LdrpCallInitRoutine+0x00000014
    0x7c93b5d2: ntdll!LdrpRunInitializeRoutines+0x00000344
    0x7c93fbdc: ntdll!LdrpInitializeProcess+0x0000114b
    0x7c93fad7: ntdll!_LdrpInitialize+0x00000183
    0x7c92e457: ntdll!KiUserApcDispatcher+0x00000007
    --------------------------------------
    Handle = 0x000007bc - OPEN
    Thread ID = 0x000014fc, Process ID = 0x000013f0
    
    0x7c80ef97: kernel32!FindFirstFileW+0x00000016
    0x7c8135c5: kernel32!GetLongPathNameW+0x00000231
    0x7854287c: MSVCR90!_check_manifest+0x0000009c
    0x78542c22: MSVCR90!__CRTDLL_INIT+0x0000008e
    0x78542d5e: MSVCR90!_CRTDLL_INIT+0x0000001e
    0x7c92118a: ntdll!LdrpCallInitRoutine+0x00000014
    0x7c93b5d2: ntdll!LdrpRunInitializeRoutines+0x00000344
    0x7c93fbdc: ntdll!LdrpInitializeProcess+0x0000114b
    0x7c93fad7: ntdll!_LdrpInitialize+0x00000183
    --------------------------------------
    Handle = 0x000007c0 - CLOSE
    Thread ID = 0x000014fc, Process ID = 0x000013f0
    
    0x7c8135dd: kernel32!GetLongPathNameW+0x00000249
    0x7854287c: MSVCR90!_check_manifest+0x0000009c
    0x78542c22: MSVCR90!__CRTDLL_INIT+0x0000008e
    0x78542d5e: MSVCR90!_CRTDLL_INIT+0x0000001e
    0x7c92118a: ntdll!LdrpCallInitRoutine+0x00000014
    0x7c93b5d2: ntdll!LdrpRunInitializeRoutines+0x000003
    .........................

    格式一般是句柄值,进程线程, OPEN表示打开句柄的栈回溯,CLOSE表示关闭句柄的栈回溯,那么关键是要找到那些栈回溯打开了句柄,却没有相应的栈回溯来关闭句柄,这可以通过!htrace -diff来实现:

    0:000> !htrace -diff
    Handle tracing information snapshot successfully taken.
    0xfa new stack traces since the previous snapshot.
    Ignoring handles that were already closed...
    Outstanding handles opened since the previous snapshot:
    --------------------------------------
    Handle = 0x000005b0 - OPEN
    Thread ID = 0x000007f4, Process ID = 0x000013f0
    
    0x00401657: test1!CServer::GetToken+0x00000047
    0x0040136f: test1!CServer::GetSID+0x0000001f
    0x004010de: test1!ThreadWorker+0x0000007e
    0x7c80b729: kernel32!BaseThreadStart+0x00000037
    --------------------------------------
    Handle = 0x000005b4 - OPEN
    Thread ID = 0x00000c34, Process ID = 0x000013f0
    
    0x00401657: test1!CServer::GetToken+0x00000047
    0x0040136f: test1!CServer::GetSID+0x0000001f
    0x004010de: test1!ThreadWorker+0x0000007e
    0x7c80b729: kernel32!BaseThreadStart+0x00000037
    --------------------------------------
    Handle = 0x000005b8 - OPEN
    Thread ID = 0x00001650, Process ID = 0x000013f0
    
    0x00401657: test1!CServer::GetToken+0x00000047
    


    很明显了,我们看到在GetToken中有句柄未关闭,所以在使用!htrace时采用的步骤一般是:

    1. 在重现泄漏问题之前,启用句柄跟踪(!htrace -enable)

    2.执行重现过程,并且让进程句柄泄漏

    3.通过!htrace -diff来找出有问题的栈


     


     

  • 相关阅读:
    Android学习进程 Java引用 Rxjava MVP
    小试 Xcode 逆向:App 内存监控原理初探
    春招路上孤独的iOSer的心路历程(面经)
    【译】4个你需要知道的Asset Catalog的秘密
    超全!iOS 面试题汇总
    整理 iOS 9 适配中出现的坑(图文)
    旧版Xcode下载地址
    xcode 自动添加注释,生成文档
    NDK_ROOT找不到的解决方法 MACOS
    13个小技巧帮你征服Xcode
  • 原文地址:https://www.cnblogs.com/hgy413/p/3693507.html
Copyright © 2011-2022 走看看