分享
 
 
 

定制调试诊断工具和实用程序——摆脱DLL“地狱”(DLL Hell)的困扰(七)

王朝vc·作者佚名  2006-05-23
窄屏简体版  字體: |||超大  

定制调试诊断工具和实用程序

——摆脱DLL“地狱”(DLL Hell)的困扰(七)

原著:Christophe Nasarre

编译:NorthTibet

下载源代码:EscapeFromDLLHell.exe (588KB)

原文出处:Windows XP:Escape from DLL Hell with Custom Debugging and Instrumentation Tools and Utilities,Part 2

本文假设你熟悉 Win32,DLL

定制调试诊断工具和实用程序——摆脱DLL"地狱"(DLL Hell)的困扰(一)

定制调试诊断工具和实用程序——摆脱DLL"地狱"(DLL Hell)的困扰(二)

定制调试诊断工具和实用程序——摆脱DLL"地狱"(DLL Hell)的困扰(三)

定制调试诊断工具和实用程序——摆脱DLL"地狱"(DLL Hell)的困扰(四)

定制调试诊断工具和实用程序——摆脱DLL"地狱"(DLL Hell)的困扰(五)

定制调试诊断工具和实用程序——摆脱DLL"地狱"(DLL Hell)的困扰(六)

Windows Loader 知道一切

除了 Win32 调试 API 之外,Windows 还提供另外一种很好的关于 DLL

加载地址冲突的信息源。那就是在注册表中设置的一些全局标志(或 GFlags):

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options

从而改变 Windows 处理应用程序的方式。GFlags.exe (see Figure 8) 是一个微软调试工具之一,用它可以轻松更改上述的注册表项值。

Figure 8 全局标志

在 1999 九月的 “Under the Hood”专栏中, Matt Pietrek 解释了如何将 FLG_SHOW_LDR_SNAPS

与上述 GFlags 结合使用让 Windows Loader

产生一些有用的跟踪信息。如果你想捕获这些跟踪信息,你有两个选择:第一个是调试应用程序,然后象所做的 CApplicationDebugger

那样解释 OUTPUT_DEBUG_STRING_EVENT。另外一个方法比较容易:使用全局捕获工具。如果你想要生成自己的跟踪信息,使用

Sysinternals

或《Inside Windows 2000, Third Edition》CD 中的 DbgView,这个工具还可以显示内核跟踪信息。

在 LoadLibrarySpy 工具中,启动被调试程序之前,与被调试程序对应的 GFlags 值会被 CApplicationDebugger

的 PreLoadingProcess 更新,其以前的值会被保存在 PostMortem 中,也就是说,因为使用“LDR”作为前缀,所以调试器从

Windows Loader 得到的专用输出信息很容易在 OnOutputDebugStringDebugEvent 中过滤。

这种 Loader 日志的一个主要优点是输出信息前都有一个 LDR:自动化 DLL 重定位信息。它解释哪个 DLL 与另外的 DLL

有地址冲突。这既是 CModuleListCtrl 获取 Reason 栏数据的方法。不幸的是,Windows 2000 Loader

好像抑制这种特定的输出信息。如果你过去习惯于通过加载某个进程来存取其资源,如 explorer.exe 的动画或图标,0x400000

加载地址通常已经被你的程序使用,Loader 会自动进行重定位。在这种特殊情况下,即便是在 Windows NT 4.0,它都不会发出 LDR:为动态加载进程自动化

DLL 重定向。

另外一个解决方案是枚举每个加载的 DLL 并与专用的地址空间区域(从 hModule 开始)进行比较,从而找到冲突者(实现细节参见 CLoadLibraryDebugger::OnLoadDLLDebugEvent)。加载器还提供另外一个带前缀“LDR:Loading

(DYNAMIC)”的有趣的信息,同时其后跟随模块的全路径名。当某个 DLL 被显示通过 LoadLibrary 加载时,似乎就是这种情况。

使用这些来自 Windows Loader 的线索,LoadLibrarySpy 根据加载状态为每个 DLL 提供了一个专门的图标,详情参见

Figure 9

带方形图标的 DLLs

是在进程初始化期间加载的,称为静态加载。带圆形图标的则是在进程初始化之后加载的,因此称为动态加载。图标的颜色预示着是否有加载地址冲突,红色表示有,蓝色表示没有。

那些带黑色背景与其它动态 DLLs 之间的区别很微妙:带黑色图标的 DLL 已被加载,要么是用 LoadLibrary

显式加载,要么是用其它类似 CoCreateInstance 的 API 函数加载。没有黑色背景图标的 DLL 已被加载,因为另外一个

DLL需要它。例如,在 Figure 4 中,BROWSEUI.dll 有一个黑色图标,因为它已被动态加载。而 SHDOCVW.dll

图标没有黑色背景,因为它已被 Windows 自动加载。理由很简单:BROWSEUI.dll 是静态链接到 SHDOCVW.dll

的,所以为了加载 BROWSEUI,Windows 也得加载 SHDOCVW。

另一种“盗取”信息的途径

在结束 Win32 调试 API 的讨论之前,我想用一点点时间讨论异常处理机制。当被调试程序中有异常发生时,调试器通过 EXCEPTION_DEBUG_EVENT

收到通知,并且 u.Exception.ExceptionRecord.ExceptionCode 域中会包含此异常编码。异常编码都分布在 WINNT.H

和 WINBASE.H 文件中,因此要获得一个全面而且清晰易读的异常编码清单并不是件容易的事。CApplicationDebugger 的 GetExceptionDescription

方法将这些异常编码转换成可读性更强的字符串。

另一个异常编码清单信息源是 Visual C++

本身。在调试应用程序时,“Debug”菜单中有一个“Exception”菜单项,它允许你选择调试器处理异常的方式,如 Figure 10 所示:

Figure 10 Exceptions Dialog

你可能会感到惊讶,在这里能发现没有定义过的异常编码。不用动手拷贝,从这个列表框“盗取”信息不是很好吗。这便是 WindowDump

的目的。它允许你用鼠标拾取某个窗口(通过其句柄值)并将信息 dump 到一个编辑框中。此外,它还能收集类信息和式样描述信息,如 Figure

11 所示。

Figure 11 WindowDump 中的异常编码

WindowDump 的背后并没有什么玄机。唯一有趣的地方是 Windows 通常允许 GetWindowText 和 WM_GETTEXT

操作不同的进程。但对于列表视图和树型视图这样的公用控件除外。Jeffrey Richter 在他的

Q&A Win32(MSJ September 1997)专栏中解释了如何 dump 另外一个进程中列表视图的内容,附带一个范例程序

LV2Clip。下面是一些 WindowDump 能盗取其内容的窗口类:Edit、ScrollBar、ListBox、ComboBox、ListView

和 TreeView。根据这些类的窗口内容,你还能得到

Figure 12 所列出的信息。

有关 WindowsDump 实现的最后一个重点是进程 ID。从窗口句柄入手,使用 GetWindowThreadProcessId

不难确定线程以及负责创建该线程的进程。如果你还想知道模块名,用 GetWindowModuleFileName

可能会碰壁。与在文档中给出的信息相反,这个 API 函数在 Windows NT、Windows 2000 或 Windows XP

下调用失败。你得钻研知识库的文章

Q228469 查明原因。

在这样情况下,你应该用 PSAPI 及其 GetModuleFileNameEx 函数。它以进程和 hModule

模块句柄为参数,返回对应的路径名。为了查出某一个进程的可执行文件路径名,hModule 应该为 0。不要使用

0x400000:某些进程被加载到不同的地址,如 winlogon 和 Task Manager 在 0x1000000,ntvdm 在

f000000 以及Microsoft Word 2000 在 0x30000000。

参考资料

The Win32 Debugging Application Programming Interface

Bugslayer: Windows 2000 and LDR Messages, A COM Symbol Engine, Finding Bloated Functions, and MoreDEB Sample: Debug Event Browser

Spawn Console Processes with Redirected Standard Handles

GetWindowModuleFileName & GetModuleFileName Work Only with the Calling Process

在后续文章中,我将介绍 CreateRemoteThread,命令行及其它。

(待续)

作者简介

Christophe Nasarre 是法国 Business Objects 公司的技术经理(technical

manager)。他在 Windows 平台上(3.0 以后的版本)编写了若干个低级工具。他的联系方式:cnasarre@montataire.net.

.

本文出自 MSDN Magazine

August 2002 期刊,可通过当地报摊获得,或者最好是

订阅

本文由 VCKBASE MTT 翻译

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有