dump 分析模式之 INCORRECT STACK TRACE 翻译自 MDA-Anthology Page288 



初学者常犯的错误是认为 WinDbg 的 !analyze 和 kv 给出的信息是准确的. 



WinDbg 只是一个工具, 有时候会缺少一些必要的信息来得到正确的栈信息, 因此我们需要自己明辨正确的与错误的栈信息. 我称之为 Incorrect Stack Trace, 它通常有以下特征:

  • WinDbg给出警告: "Following frames may be wrong"
  • 栈底函数不是 kernel32!BaseThreadStart (用户模式)
  • 无意义的函数调用
  • 反汇编后的函数的代码很奇怪, 或不像编译器生成的代码
  • ChildEBP 和 RetAddr 的地址没有意义

考虑以下栈信息:

0:011> k 

ChildEBP RetAddr 

WARNING: Frame IP not in any known module. Following frames may be wrong. 

0184e434 7c830b10 0×184e5bf 

0184e51c 7c81f832 ntdll!RtlGetFullPathName_Ustr+0×15b 

0184e5f8 7c83b1dd ntdll!RtlpLowFragHeapAlloc+0xc6a 

00099d30 00000000 ntdll!RtlpLowFragHeapFree+0xa7

以上栈信息基本具备了错误栈信息的所有性质. 初看像是堆破坏, 因为运行时的堆分配与释放函数出现在了栈中. 但如果我们再想想就会发现 HeapFree 函数不应调用 HeapAlloc 函数, 而接下来更不应该调用 GetFullPathName. 所以这个栈信息是无意义的. 



那我们能怎样呢? 检视 raw 栈信息并构造出真正的栈. 我们可以轻松地从 BaseThreadStart+0×34 开始遍历所有帧直到没有任何函数调用了或都已到栈顶. 当一个函数被调用的时候 EBP 会像下图那样连起来 (如果没有被优化掉, 对于大多数编译成立). 



0:011> !teb 

TEB at 7ffd8000 

ExceptionList: 0184ebdc 

StackBase: 01850000 

StackLimit: 01841000 

... 

0:011> dds 01841000 01850000 

01841000 00000000 

… 

… 

… 

0184eef0 0184ef0c0184eef4 7615dff2 localspl!SplDriverEvent+0×21 

0184eef8 00bc3e08 

... 

0184ef0c 0184ef300184ef10 7615f9d0 

localspl!PrinterDriverEvent+0×46 

0184ef14 00bc3e08 

0184ef18 00000003 

... 

0184ef2c 00bafcc0 

0184ef30 0184f3f80184ef34 7614a9b4 localspl!SplAddPrinter+0×5f3 

0184ef38 00c3ec58 

... 

0184ff30 0184ff840184ff34 77c75286 RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0×3a 

0184ff38 0184ff4c 

0184ff3c 77c75296 RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0×4a 

0184ff40 7c82f2fc ntdll!RtlLeaveCriticalSection 

... 

0184ff84 0184ff8c0184ff88 77c5778f RPCRT4!RecvLotsaCallsWrapper+0xd 

0184ff8c 0184ffac0184ff90 77c5f7dd RPCRT4!BaseCachedThreadRoutine+0×9d 

... 

0184ffac 0184ffb80184ffb0 77c5de88 RPCRT4!ThreadStartRoutine+0×1b 

0184ffb4 00088258 

0184ffb8 0184ffec 

0184ffbc 77e6608b kernel32!BaseThreadStart+0×34

接下来我们需要用指定了基址的 k 命令来显示栈信息. 在本例中最后的有效 EBP 地址是 0184eef0.

0:011> k L=0184eef0 

ChildEBP RetAddr WARNING: Frame IP not in any known module. Following frames may be wrong. 

0184eef0 7615dff2 0×184e5bf 0184ef0c 7615f9d0 localspl!SplDriverEvent+0×21 

0184ef30 7614a9b4 localspl!PrinterDriverEvent+0×46 

0184f3f8 761482de localspl!SplAddPrinter+0×5f3 

0184f424 74067c8f localspl!LocalAddPrinterEx+0×2e 

0184f874 74067b76 SPOOLSS!AddPrinterExW+0×151 

0184f890 01007e29 SPOOLSS!AddPrinterW+0×17 

0184f8ac 01006ec3 spoolsv!YAddPrinter+0×75 

0184f8d0 77c70f3b spoolsv!RpcAddPrinter+0×37 

0184f8f8 77ce23f7 RPCRT4!Invoke+0×30 

0184fcf8 77ce26ed RPCRT4!NdrStubCall2+0×299 

0184fd14 77c709be RPCRT4!NdrServerCall2+0×19 

0184fd48 77c7093f RPCRT4!DispatchToStubInCNoAvrf+0×38 

0184fd9c 77c70865 RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0×117 

0184fdc0 77c734b1 RPCRT4!RPC_INTERFACE::DispatchToStub+0xa3 

0184fdfc 77c71bb3 RPCRT4!LRPC_SCALL::DealWithRequestMessage+0×42c 

0184fe20 77c75458 RPCRT4!LRPC_ADDRESS::DealWithLRPCRequest+0×127 

0184ff84 77c5778f RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0×430 

0184ff8c 77c5f7dd RPCRT4!RecvLotsaCallsWrapper+0xd

栈信息现在看起来有意义多了, 但我们仍然没有看到 BaseThreadStart+0×34. 默认情况下 WinDbg 只显示一定数量的栈帧. 所以我们需要指定栈帧的数量, 比如 100:

0:011> k L=0184eef0 100 

ChildEBP RetAddr WARNING: Frame IP not in any known module. Following frames may be wrong. 

0184eef0 7615dff2 0×184e5bf 

0184ef0c 7615f9d0 localspl!SplDriverEvent+0×21 

0184ef30 7614a9b4 localspl!PrinterDriverEvent+0×46 

... 

0184ffac 77c5de88 RPCRT4!BaseCachedThreadRoutine+0×9d 

0184ffb8 77e6608b RPCRT4!ThreadStartRoutine+0×1b 

0184ffec 00000000 kernel32!BaseThreadStart+0×34

现在我们的栈信息看起来更好了. 还有一个完整的示例在 Manual Stack Track Reconstruction, 本书第 157 页. 



此外, incorrect stack trace 也会发生在没有符号信息的时候. 这种情况下, 通常栈帧之间会有找不到符号的警告:

STACK_TEXT: 

WARNING: Stack unwind information not available. Following frames may be wrong. 

00b2f42c 091607aa mydll!foo+0×8338 

00b2f4cc 7c83ab9e mydll!foo+0×8fe3 

00b2f4ec 7c832d06 ntdll!RtlFindNextActivationContextSection+0×46 

00b2f538 001a5574 ntdll!RtlFindActivationContextSectionString+0xe1 

00b2f554 7c8302b3 0×1a5574 

00b2f560 7c82f9c1 ntdll!RtlpFreeToHeapLookaside+0×22 

00b2f640 7c832b7f ntdll!RtlFreeHeap+0×20e 

001dd000 00080040 ntdll!LdrUnlockLoaderLock+0xad 

001dd00c 0052005c 0×80040 

001dd010 00470045 0×52005c 

0052005c 00000000 0×470045

翻译自 MDA-Anthology1 page167, WINDBG TIPS AND TRICKS. 



WinDbg中有一些很好的命令像dpu (检视unicode字符串)和dpa (检视ASCII字符串)以及其它 d 开头的命令如dpp. 我们可以使用这些命令来看看栈上是否有指针指向了字符串. 



例如: 



0:143> !teb

TEB at 7ff2b000 

... 

StackBase: 05e90000 

StackLimit: 05e89000 

... 

... 

...

0:143> dpu 05e89000 05e90000

05e8f58c 00120010 ""

...

...

...

05e8f590 77e7723c "Debugger"

05e8f594 00000000

05e8f598 08dc0154

05e8f59c 01000040

05e8f5a0 05e8f5dc "G:\WINDOWS\system32\faultrep.dll"

05e8f5a4 0633adf0 ""

05e8f5a8 00000000

05e8f5ac 00000001

05e8f5b0 00000012

...

05e8f5d4 0633adfc "drwtsn32 -p %ld -e %ld -g"

...

...

...



当然这些命令不仅能对栈地址空间起作用, 也能用在普通的内存段上.

dump 分析模式之 INCORRECT STACK TRACE - djm2005dy的专栏 - 博客频道 - CSDN.NET的更多相关文章

  1. Salt Stack 官方文档翻译 - 一个想做dba的sa - 博客频道 - CSDN.NET

    OSNIT_百度百科 Salt Stack 官方文档翻译 - 一个想做dba的sa - 博客频道 - CSDN.NET Salt Stack 官方文档翻译 分类: 自动运维 2013-04-02 11 ...

  2. 鸿蒙内核源码分析(系统调用篇) | 开发者永远的口头禅 | 百篇博客分析OpenHarmony源码 | v37.03

    百篇博客系列篇.本篇为: v37.xx 鸿蒙内核源码分析(系统调用篇) | 开发者永远的口头禅 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度谁 ...

  3. 鸿蒙源码分析系列(总目录) | 百万汉字注解 百篇博客分析 | 深入挖透OpenHarmony源码 | v8.23

    百篇博客系列篇.本篇为: v08.xx 鸿蒙内核源码分析(总目录) | 百万汉字注解 百篇博客分析 | 51.c.h .o 百篇博客.往期回顾 在给OpenHarmony内核源码加注过程中,整理出以下 ...

  4. v82.01 鸿蒙内核源码分析 (协处理器篇) | CPU 的好帮手 | 百篇博客分析 OpenHarmony 源码

    本篇关键词:CP15 .MCR.MRC.ASID.MMU 硬件架构相关篇为: v65.01 鸿蒙内核源码分析(芯片模式) | 回顾芯片行业各位大佬 v66.03 鸿蒙内核源码分析(ARM架构) | A ...

  5. 鸿蒙内核源码分析(调度队列篇) | 内核有多少个调度队列 | 百篇博客分析OpenHarmony源码 | v6.05

    百篇博客系列篇.本篇为: v06.xx 鸿蒙内核源码分析(调度队列篇) | 内核有多少个调度队列 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度 ...

  6. Java 抓取 thread dump (Full Thread Stack Trace) 方法汇总

    顾名思义,表示一个时间点上,显示进程里面每一个线程的 stack trace,以及线程之间关联,比如等待 常用来定位一些 不响应,CPU 很高,内存使用很高问题 汇总表格如下 工具 操作系统 Java ...

  7. 三、jdk工具之jstack(Java Stack Trace)

    目录 一.jdk工具之jps(JVM Process Status Tools)命令使用 二.jdk命令之javah命令(C Header and Stub File Generator) 三.jdk ...

  8. 性能分析之-- JAVA Thread Dump 分析综述

    性能分析之-- JAVA Thread Dump 分析综述       一.Thread Dump介绍 1.1什么是Thread Dump? Thread Dump是非常有用的诊断Java应用问题的工 ...

  9. 性能分析之– JAVA Thread Dump 分析

    最近在做性能测试,需要对线程堆栈进行分析,在网上收集了一些资料,学习完后,将相关知识整理在一起,输出文章如下. 一.Thread Dump介绍 1.1什么是Thread Dump? Thread Du ...

随机推荐

  1. sublime插件使用整理

    考虑到后续要有更多的时间来写js,周末好好的把sublime整理了下,很多插件非常好.下面一一来说 1.  注释生成插件 DocBlockr 之前每次写函数的注释都要复制其他函数的注释,然后在写,非常 ...

  2. XML组成结构以及C#通过DTD验证规范性

    XML 文档包含元素和属性等,它们提供一种灵活且功能强大的方法,为应用程序和组织之间交换数据.所有的 XML 文档(以及 HTML 文档)均由以下简单的构建模块构成: 1.元素 元素是XML的主要构建 ...

  3. 从头开始db-oracle

    rpm -ivh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-7.noarch.rpmrpm -ivh http: ...

  4. [PHP] - mysql 数据库操作

    使用PHP操作数据库有两种方式 使用mysql_XXXX()方法 使用这种方式,需要先把php.ini里的extension=php_mysql.dll去掉注释 使用PDO 使用这种试,需要把php. ...

  5. MVC4 +EasyUI 使用TreeGrid 方法

    用easyui已经有2年了,换了新环境,要求用mvc开发,所以想把原来的项目直接用mvc重构. 在使用TreeGird的时候出现了问题,发现在转换为treegrid的json 很费劲,一直都是用的ea ...

  6. ajaxReturn

    controller:$info=array('error'=>0,'msg'=>'');if($user_info){    if($user_info['is_lock']){     ...

  7. Mongo集合操作Aggregate

    最近一直在用mongodb,有时候会需要用到统计,在网上查了一些资料,最适合用的就是用aggregate,以下介绍一下自己运用的心得.. 别人写过的我就不过多描述了,大家一搜能搜索到N多一样的,我写一 ...

  8. EF 分组查询

    var result = from m in userPrefers.GroupBy(t => new { t.Pet_Preferential.Merchant.MerchantId, t.P ...

  9. Ubuntu1404 (1)

    0.初始设置 (1)开户root账号并重启系统: sudo gedit /usr/share/lightdm/lightdm.conf.d/50-ubuntu.conf, 添加greeter-show ...

  10. Win8.1安装Visual Studio 2015提示需要KB2919355

    http://www.microsoft.com/zh-cn/download/details.aspx?id=42335 安装说明: 1.若要开始下载,请单击“下载”按钮,然后执行以下操作之一,或者 ...