第一章 Windows 2000对调试技术的支持
翻译:Kendiv
更新:Friday, January 14, 2005
内核调试器的命令
尽管调试器的命令已经注意了易记性,但有时总是难以回忆起它们。因此,我把它们都整理到了附录A中。表A-1是其快速参考。这个表是调试器的help信息(使用?命令)的整理版。命令所需参数的类型汇总在表A-2。
前面提到过,内核调试器执行扩展命令时需要一个!号作为开始。只要命令前有个!号,调试器就会到已加载的扩展DLL的导出列表中进行查找。如果发现匹配的,就会跳转到相应的DLL中。图1-7显示了内核调试器加载了kdextx86.dll、userkdx.dll和dbghelp.dll扩展DLL。最后一个和i386kd.exe位于同一目录;前两个共有四个版本:针对Windows NT 4.0的free和checked版本(对应子目录为:nt4fr和nt4chk),针对Windows 2000的free和checked版本。通常,调试器在搜寻扩展命令是会采用一个默认的搜索顺序。然而,你可以改变这个默认设置,只需要在命令前指定模块名称即可,采用.符号作为分隔符。例如,kedxtx86.dll和userkdx.dll都导出了help命令,键入!help,在默认情况下,你会得到kdextx86.dll的帮助信息。要执行userdkx.dll的help命令,你必须输入!userkdx.help(或者!userkdx.help –V如果你想得到更详细的帮助信息的话)。按照此方法,只要你知道规则,你也可以编写自己的扩展命令。在The NT Insider(Open Systems Resources 1999a)中你能找到很棒的how-to文章。不过其针对的是WinDbg.exe而不是i386kd.exe,但两者使用相同的扩展DLL,大多数信息对于i386kd.exe也是有效的。
附录A中的表A-3和A-4分别列出了kdextx86.dll和userkdx.dll的help命令的输出信息。为了便于阅读作了些修改和整编。你会发现这些表中列出的命令多于Microsoft DDK文档中的,其中有些命令明显有DDK文档未提到的附加参数。
10大调试命令
表A-1到A-4列出了内核调试器及其标准扩展DLL提供的巨多的命令。因此,我将讨论其中一些常用命令的细节。
u: 反编译机器码
在检查crash dump是否正确时,你已经用过了此命令,u命令有三种格式:
1.u <from> 从地址<from>开始反编译8个机器码。
2.u <from> <to> 反编译<from>到<to>之间的所有机器码。
3.u 不提供任何参数时,从上次u命令停止的位置开始反编译。
当然,反编译打段代码是十分厌烦的,但如果你只想知道在特定地址发生的事情,那这是最便捷的方法。或许u命令最令人感兴趣的特性是它可以解析代码引用到的符号----即使是目标模块没有导出的符号。不过,使用本书光盘中的Multi-Format Visual Disassembler反编译完整的Windows 2000可执行体将是十分有趣的。在随后章节中,会有关该产品的更多信息。
db,dw和dd:Dump Memory BYTEs、WORDs和DWORDs
如果你当前感兴趣的内存数据是二进制的,那么调试器的16进制转储命令将能完成此任务。根据你对源地址(source address)数据类型的判断,来选择dd(针对BYTES)、dw(针对WORDS)、dd(针对DWORDS)。
l db 将指定内存范围里的数据显示为两个部分:左边是16进制表示(每2个8 bit一组),右边是对应的ASCI码。
l dw 仅按照16进制显示(16 bit一组)
l dw 仅按照16进制显示(32 bit一组)
此组命令可以使用与u命令相同的参数。注意,<to>所指示的地址内容,也会被显示出来。如果没有任何参数,将显示接下来的128个字节。
x:检查符号
x命令非常重要。它可以根据已安装的符号文件创建一个列表。典型的使用方式如下:
1.x *!* 显示所有可用符号的模块。在启动后,默认只有ntoskrnl.exe的符号是可用的。其他模块的符号可以使用.reload命令来加载。
2.x <module>!<filter> 显示模块<module>的符号文件中的符号名称,<filter>可以包括通配符?和*。<module>必须属于x *!*列出的模块名。例如,x nt!*将列出在内核符号文件ntoskrnl.dbg中找到的所有符号,x win32k!*将列出win32k.dbg提供的符号。如果调试器报告说“Couldn’t resolve ‘X….’”,尝试用.reload再次加载所有的符号文件。
3.x <filter> 显示所有可用符号的一个子集,该子集不匹配<filter>表达式。本质上,这是x <module>!<filter>的一个变形,在这里<module>!被省略了。
随符号名一起显示的,还有与其相关的虚拟地址。对于函数名,与其对应的就是函数的入口地址。对于变量,就是改变量的基地址。该命令值得的注意的地方是,它可以输出很多内部符号(internal symbols),这些在可执行文件的导出表中都是找不到的。
ln:列出最近的符号
ln是我最喜欢的一个命令。因为它可以快速且简单的访问已安装的符号文件。算是x命令的理想补充。不过后者适用于列出所有系统符号的地址。Ln命令则用于按照地址或名称查找符号。
l ln <address> 显示<address>指示的地址以及和其前后相邻的地址的符号信息。
l ln <symbol> 将符号名解析为与其对应的虚拟地址。其过程与ln <address>类似。
像x命令一样,调试器知道所有导出的以及一些内部的符号。因此,对于想弄清楚出现在反编译列表或16进制转储中的不明指针的确切含义的人有着非常大的帮助。注意,u、db、dw、dd也会使用符号文件。
!processfield:列出EPROCESS的成员
该命令前的!号,意味着它来自于调试器的扩展模块—kdextx86.dll。该命令可显示内核用来代表一个进程的EPROCESS结构(该结构并没有正式的说明文档)的成员及其偏移量。
尽管该命令仅列出了成员的偏移量,但你也能很容易的猜出其正确的类型。例如,LockEvent位于0x70处,其下一个成员的偏移量为0x80。则该成员占用了16个字节,这与KEVENT结构非常类似。如果你不知道什么是KEVENT,不要担心,我在第7章将会讨论之。
!threadfields:列出ETHREAD成员
这是kdextx86.dll提供的另一个强大的选项。和!processfields类似,它列出未文档化的ETHREAD结构的成员及其偏移量。内核使用它表示一个线程。参见示例1-2
!drivers:列出已加载的Drivers
kdextx86.dll真是太棒了。!drivers列出了当前运行的内核和文件系统模块的详细信息。如果检查crash dump,该命令会列出系统崩溃那一刻的系统状态。示例1-3是我机器上输出的摘要。注意,在输出的最后一行,导致Windows 2000崩溃的Driver的地址为0xBECC2000,这显然是w2k_kill.sys引发蓝屏后显示的地址。
译注:
在新的i386kd.exe(ver: 6.3.0017.0)中,!driver命令已不被支持。取而代之的是lm命令。该命令的一般用法是:lm t n
!sel:检查Selector的值
如果没有争议的话,!sel实现于kdextx86.dll。它用来显示16个连续的memory selector(按地址升序排列)。你可以反复的使用此命令直到出现“Selector is invalid”。在第4章将讨论Memory Selector,到时我会提供一个示列代码来演示如何在你的程序中crack selectors。
译注:
在新的调试器中,该命令已不被支持,取而代之的是:dg命令。其一般性用法为:dg.注意末尾的.符号。dg命令最多可列出256个Selector。调试器的Online Help中有详细说明
关闭调试器
你可以通过简单的关闭控制台窗口来关闭内核调试器。当然,更好的关闭办法是使用q命令,这儿“q”代表着quit。
更多的调试工具
在本书的光盘中,你可以找到两个由我的e-friends贡献的非常有价值的调试工具。我很高兴他们允许我将完整版本放入我的光盘中。Wayne J. Radburn的 PE and COFF文件浏览器(PEView)是本书读者的一个特殊免费工具。Jean-Louis Seigne的Multi-Format Visual Disassembler(MFVDasm)一个限时版本。本节将简单介绍这两个工具。
MFVDASM:可视化多格式反编译器
MFVDasm不仅仅是个汇编列表生成器。事实上,它比汇编代码浏览器增加了多个很不错的导航特性。如图1-8所示,那是我使用MFVDasm察看Windows 2000 I/O管理函数IoDetachDevice()的截图。图中并没有显示出屏幕上的颜色。例如,所有的函数表以及特定地址的jumps和calls都被显示为红色。针对其余地址(没有相关导出符号的地址)的jumps和calls显示为蓝色。引用了从其他模块动态导出的符号的显示为紫色。所有可到达的目标地址(reachable destinations)都加上了下划线,这意味着你可以通过单击他们来滚动代码窗口到达其地址。使用工具栏上的Back和Forward按钮,你能回顾看过的东东。这很像在IE中察看浏览过的网页。
在右边,你可以随意选择你想跳到的符号或目标地址。当然,通过单击列头你可以进行排序。在最底层,MFVDasm提供了Tab页来分别显示符号、16进制转储(HexDump)和重定位(Relocations)。对包含嵌入字符串的代码段进行反编译时16进制转储视图会显得很有用。在分析很大的文件如ntoskrnl.exe时,MFVDasm不会阻塞住,和其他流行的反编译工具一样,得到的汇编代码可以保存到文本文件中。
PEView --- PE和COFF文件察看器
尽管MFVDasm展示了PE(Portable Executable)文件的很多内部结构的细节,但其侧重于代码的查看。另一方面,PEView虽然不能展示比代码段的16进制码更进一步的细节,但它能非常详细的显示文件结构的细节。如图1-9所示。这是我用PEView察看ntoskrnl.exe的截图。可以看出PEView采用三种形式来显示ntoskrnl.exe的多个部分。如果你单击左边的一个叶结点,在右面就会显示与该项相关的所有信息。在图1-9种,我选择了IMAGE_OPTIONAL_HEADER结构,该结构是IMAGE_NT_HEADERS结构的成员之一。
译注:还有两段我没有译,和本书讨论的主题无关,感兴趣的话,去看原文吧。J
Windows 2000调试接口
对于喜欢研究系统内核的人来说,内核调试器是一个非常强大的工具。不过,它的界面有些简单。有时你可能希望有更强大的命令。很幸运,Windows 2000提供了两个完整的调试接口文档,使得你可以在你的程序中加入调试功能。这些接口远算不上豪华(但他们得到了微软官方文档的祝福 J)。在本节中,我将带你进行调试接口一日游,向你展示这些文档可以为你做什么以及你如何从这些文档中得到更多东东。
psapi.dll、imagehlp.dll和dbghelp.dll
长久以来,Windows NT由于缺乏对Windows 95的ToolHelp32接口的支持而备受指责。可能评论家们并不都知道Windows NT 4.0提供了其独有的调试接口---内建于系统组件psapi.dll(随Win32 SDK一起发布)中。随此DLL一起发布的还有imagehlp.dll和dbghelp.dll以及针对NT/2000的调试接口的官方文档。PSAPI是Process Status Application Programming Interface的首字母缩写,此接口提供了14个函数用于获取有关设备驱动程序、进程、进程的内存使用情况和其加载的模块、工作集、内存映射文件的系统信息。psapi.dll同时支持ANSI和Unicode字符串。
其余两个调试DLLs---imagehlp.dll和dgbhelp.dll涵盖了不同的工作范围。二者都导出了相似的函数集合,区别较大的是imagehlp.dll,它提供了更多函数,但dbghelp.dll提供了可重新发布的组件。这意味着微软允许你将dbghelp.dll放入你自己的调试程序的安装包中。如果选择使用imagehlp.dll,你必须获取在目标系统已安装的一个。这两个DLL都提供了丰富的函数来分析和维护PE文件。二者最显著的特性是能很好的使用符号文件(就是你为内核调试器准备的那些)。为了指导你该选择哪个DLL,我将这两个DLL的所有导出函数汇总到了表1-1,N/A表示不支持。
序号
函数名称
ImageHlp.DLL
DbgHelp.DLL
1
Bindlmage
N/A
2
BindlmageEx
N/A
3
CheckSumMappedFile
N/A
4
EnumerateLoadedModules
5
EnumerateLoadedModules64
6
ExtensionApiVersion
N/A
7
FindDebuglnfoFile
8
FindDebuglnfoFileEx
9
FindExecutablelmage
10
FindExecutablelmageEx
11
FindFilelnSearchPath
12
GetlmageConfiglnformation
N/A
13
GetlmageUnusedHeaderBytes
N/A
14
GetTimestampForLoadedLibrary
15
ImageAddCertificate
N/A
16
ImageDirectoryEntryToData
17
ImageDirectoryEntryToDataEx
18
ImageEnumerateCertificates
N/A
19
ImageGetCertificateData
N/A
20
ImageGetCertificateHeader
N/A
21
ImageGetDigestStream
N/A
22
ImagehlpApiVersion
23
ImagehlpApiVersionEx
24
ImageLoad
N/A
25
ImageNtHeader
26
ImageRemoveCertificate
N/A
27
ImageRvaToSection
28
ImageRvaToVa
29
ImageUnload
N/A
30
MakeSureDirectoryPathExists
31
MapAndLoad
N/A
32
MapDebuglnformation
33
MapFileAndCheckSumA
N/A
34
MapFileAndCheckSumW
N/A
35
ReBaselmage
N/A
36
ReBaseImage64
N/A
37
RemovePrivateCvSymbolic
N/A
38
RemovePrivateCvSymbolicEx
N/A
39
RemoveRelocations
N/A
40
SearchTreeForFile
41
SetlmageConfiglnformation
N/A
42
SplitSymbols
N/A
43
StackWalk
44
StackWalk64
45
Sym
N/A
46
SymCleanup
47
SymEnumerateModules
48
SymEnumerateModules64
49
SymEnumerateSymbols
50
SymEnumerateSymbols64
51
SymEnumerateSymbolsW
52
SymFunctionTableAccess
53
SymFunctionTa ble Access64
54
SymGetLineFromAddr
55
SymGetLineFromAddr64
56
SymGetLineFromName
57
SymGetLineFromName64
58
SymGetLineNext
59
SymGetLineNext64
60
SymGetLinePrev
61
SymGetLinePrev64
62
SymGetModuleBase
63
SymGetModuleBase64
64
SymGetModulelnfo
65
SymGetModuleInfo64
66
SymGetModulelnfo Ex
67
SymGetModulelnfo Ex64
68
SymGetModulelnfoW
69
SymGetModulelnfo W64
70
SymGetOptions
71
SymGetSearchPath
72
SymGetSymbolInfo
73
SymGetSymbolInfo64
74
SymGetSymFromAddr
75
SymGetSymFromAddr64
76
SymGetSymFromName
77
SymGetSymFromName64
78
SymGetSymNext
79
SymGetSymNext64
80
SymGetSymPrev
81
SymGetSymPrev64
82
Symlnitialize
83
SymLoadModule
84
SymLoadModule64
85
SymMatchFileName
86
SymEnumerateSymbolsW64
87
SymRegisterCallback
88
SymRegisterCallback64
89
SymRegisterFunctionEntryCallback
90
SymRegisterFunctionEntryCallback64
91
SymSetOptions
92
SymSetSearchPath
93
SymUnDName
94
SymUnDName64
95
SymUnloadModule
96
SymUnloadModule64
97
TouchFileTimes
N/A
98
UnDecorateSymbolName
99
UnMapAndLoad
N/A
100
UnmapDebuglnformation
101
UpdateDebuglnfoFile
N/A
102
UpdateDebuglnfoFileEx
N/A
103
WinDbgExtensionDllInit
N/A
在本节的示例代码中,我会演示如何使用psapi.dll和imagehlp.dll完成如下任务:
l 枚举所有内核组件和驱动程序
l 枚举系统当前管理的所有进程
l 枚举加载到进程地址空间的所有模块(modules)
l 枚举一个给定组件的所有符号(如果其符号文件可用的话)
psapi.dll的接口并不像其设计的那样好。它提供了最小的功能集,尽管它曾试图增加一些便利性。虽然,它能从内核获取一些信息但却扔掉了其中的大多数,只留下很少一部分。
由于psapi.dll和imagehlp.dll的函数并不是标准Win32 API的一部分,它们所需的头文件和导入库不会自动包括在Visual C/C++工程中。因此,列表1-2中列出的四个指示符(directives)应该在你的原文件中出现。第一部分是所需的头文件,剩余部分用于和这两个DLL中的导出函数建立动态链接。
#include <imagehlp.h>
#include <psapi.h>
#pragma comment (linker,”/defaultlib:imagehlp.dll”)
#pragma comment (linker,”/defaultlib:psapi.dll”)
列表1-2 增加psapi.dll和imagehlp.dll到Visual C/C++工程
译注:
其实,也可以采用静态链接,如下:
#pragma comment(lib,”psapi.lib”)
#pragma comment(lib,”imagehlp.lib”)
这样,就不需要目标平台必须有这两个DLL了。
光盘中的示列代码
在本书的附带光盘中,有两个工程是构建与psapi.dll和imagehlp.dll之上。其中一个示例工程是w2k_sym.exe----一个Windows 2000符号浏览器,它可以从任意符号文件中提取符号名称(假如你已经安装了的话)。它输出的符号表可以按照名称、地址和大小来排序,同时接受一个采用通配符的过滤器。作为附送功能,w2k_sym.exe还可列出当前活动的系统模块/驱动程序的名称,运行的进程和每个进程加载的模块。另一个示例工程是调试支持库w2k_dbg.dll,这个库包含几个便于使用的针对psapi.dll和imagehlp.dll的外包函数。w2k_sym.exe完全依赖这个DLL。这些工程的源代码分别位于光盘的\src\w2k_dbg和\src\w2k_sym目录。
表1-2列出了w2k_dbg.dll用到的函数名称。A./W列表示对ANSI和Unicode的支持情况。稍早提示过,psapi.dll同时支持ANSI和Unicode。不幸的是,imagehlp.dll和dbghelp.dll没有这么聪明,其中几个函数只能接受ANSI字符串。这有些烦人,因为Windows 2000的调试程序通常不能运行在Windows 9x上,所以不该限制使用Unicode。若将imagehlp.dll假如你的工程中,你就必须选择是使用ANSI还是来回转化Unicode字符串。因为我很讨厌在一个可处理16位字符串的系统中使用8位的字符串,所以我选择后一种方法。w2k_dbg.dll导出的所有函数中涉及的字符串默认都是Unicode。所以,如果你在自己的Windows 2000工程中使用这个DLL不需要再关心字符大小问题。
另一方面,imagehlp.dll和dbghelp.dll有一个psapi.dll没有的特性:他们同样适用于Win64----让每个开发人员恐惧的64位Windows,这是因为没人知道将Win32程序移植到Win64有多困难。这些DLL导出了Win64 API函数,好吧----或许有一天我们会用到他们。
名称
A/W
库
EnumDeviceDrivers
psapi.dll
EnumProcesses
psapi.dll
EnumProcessModules
psapi.dll
GetDeviceDriverFileName
A/W
psapi.dll
GetModuleFileNameEx
A/W
psapi.dll
GetModulelnformation
psapi.dll
ImageLoad
A
imagehlp.dll
ImageUnload
imagehlp.dll
SymCleanup
imagehlp.dll
SymEnumerateSymbols
A/W
imagehlp.dll
Symlnitialize
A
imagehlp.dll
SymLoadModule
A
imagehlp.dll
SymUnloadModule
imagehlp.dll
表1-2 w2k_dbg.dll使用的调试函数
我没有深入的探究psapi.dll和imagehlp.dll。本书的焦点在于未文档化的接口,而且在SDK中与这两个DLL的接口有关的文档还算不错。可是,我并不打算完全绕过它们,因为它们和Windows 2000 Native API(将在第2章讨论)紧密联系在一起。而且,psapi.dll是证明为什么未文档化的接口比文档化的那个更好的最佳实例。该DLL的接口不仅仅只是看上去的简单和笨拙---在某些地方它竟然会返回明显矛盾的数据。如果我不得不编写一个专业的调试工具来出售,我是不会指望这个DLL的。Windows 2000内核提供了强大、通用和更加合适的调试API函数。然而,这些几乎都没有文档化。幸运的是,微软提供的许多系统工具都广泛的使用了这些API,so it has undergone only slight changes across Windows NT versions。是的,如果你使用了这些API,每当发布了新版的NT,你就必须修订和小心的测试你的软件,但是它们带来的好处远大于这些障碍。
本章随后的大多数示例代码都来自w2k_dbg.dll,你可以在光盘的\src\w2k_dbg\w2k_dbg.c中发现它们。这个DLL封装了多个步骤,以返回更丰富的信息。数据会以合适的大小、链表(包括可选的索引值)返回,以便于对它们进行排序等操作。表1-3列出了w2k_dbg.dll导出的所有API函数。这些函数很多,详细讨论每个函数已经超出了本章的范围,因此我鼓励你去参考w2k_sym.exe的源代码(位于光盘\src\w2k_sym\x),来学习它们的典型用法。
表1-3
函数名称
描 述
dbgBaseDriver
Return the base address and size of a driver, given its path
dbgBaseModule
Return the base address and size of a DLL module
dbgCrc32Block
Compute the CRC32 of a memory block
dbgCrc32Byte
Bytewise computation of a CRC32
dbgCrc32Start
CRC32 preconditioning
dbgCrc32Stop
CRC32 postconditioning
dbgDriverAdd
Add a driver entry to a list of drivers
dbgDriverAddresses
Return an array of driver addresses (EnumDeviceDrivers ( ) wrapper)
dbgDriverlndex
Create an indexed (and optionally sorted) driver list
dbgDriverList
Create a flat driver list
dbgFileClose
Close a disk file
dbgFileLoad
Load the contents of a disk file to a memory block
dbgFileNew
Create a new disk file
dbgFileOpen
Open an existing disk file
dbgFileRoot
Get the offset of the root token in a file path
dbgFileSave
Save a memory block to a disk file
dbgFileUnload
Free a memory block created by dbgFileLoad ( )
dbglndexCompare
Compare two entries referenced by an index (used by dbgindexsort ( ) )
dbglndexCreate
Create a pointer index on an object list
dbglndexCreateEx
Create a sorted pointer index on an object list
dbglndexDestroy
Free the memory used by an index and its associated list
dbglndexDestroyEx
Free the memory used by a two-dimensional index and its associated lists
dbglndexList
Create a flat copy of a list from its index
dbglndexListEx
Create a flat copy of a two-dimensional list from its index
dbglndexReverse
Reverse the order of the list entries referenced by an index
dbglndexSave
Save the memory image of an indexed list to a disk file
dbglndexSaveEx
Save the memory image of a two-dimensional indexed list to a disk file
dbglndexSort
Sort the list entries referenced by an index by address, size, ID, or name
dbgListCreate
Create an empty list
dbgListCreateEx
Create an empty list with reserved space
dbgListDestroy
Free the memory used by a list
dbgListFinish
Terminate a sequentially built list and trim any unused memory
dbgListlndex
Create a pointer index on an object list
dbgListLoad
Create a list from a disk file image
dbgListNext
Update the list header after adding an entry
dbgListResize
Reserve memory for additional list entries
dbgListSave
Save the memory image of a list to a disk file
dbgMemory
Align Round up a byte count to the next 64-bit boundary
dbgMemoryAlignEx
Round up a string character count to the next 64-bit boundary
dbgMemoryBase
Query the internal base address of a heap memory block
dbgMemoryBaseEx
Query the internal base address of an individually tagged heap memory block
dbgMemoryCreate
Allocate a memory block from the heap
dbgMemoryCreateEx
Allocate an individually tagged memory block from the heap
dbgMemoryDestroy
Return a memory block to the heap
dbgMemoryDestroyEx
Return an individually tagged memory block to the heap
dbgMemoryReset
Reset the memory usage statistics
dbgMemoryResize
Change the allocated size of a heap memory block
dbgMemoryResizeEx
Change the allocated size of an individually tagged heap memory block
dbgMemoryStatus
Query the memory usage statistics
dbgMemory
Track Update the memory usage statistics
dbgModulelndex
Create an indexed (and optionally sorted) process module sub-list
dbgModuleList
Create a flat process module sub-list
dbgPathDriver
Build a default driver path specification
dbgPathFile
Get the offset of the file name token in a file path
dbgPrivilegeDebug
Request the debug privilege for the calling process
dbgPrivilegeSet
Request the specified privilege for the calling process
dbgProcessAdd
Add a process entry to a list of processes
dbgProcessGuess
Guess the default display name of an anonymous system process
dbgProcessIds
Return an array of process IDs (EnumProcesses ( ) wrapper)
dbgProcessIndex
Create an indexed (and optionally sorted) process list
dbgProcessIndexEx
Create a two-dimensional indexed (and optionally sorted) process/module list
dbgProcessList
Create a flat process list
dbgProcessModules
Return a list of process module handles (EnumProcessModules ( )wrapper)
dbgSizeDivide
Divide a byte count by a power of two, optionally rounding up or down
dbgSizeKB
Convert bytes to KB, optionally rounding up or down
dbgSizeMB
Convert bytes to MB, optionally rounding up or down
dbgStringAnsi
Convert a Unicode string to ANSI
dbgStringDay
Get the name of a day given a day-of-week number
dbgStringMatch
Apply a wildcard filter to a string
dbgSymbolCallback
Add a symbol entry to a list of symbols (called by SymEnumerateSymbols ( ) )
dbgSymbolIndex
Create an indexed (and optionally sorted) symbol list
dbgSymbolList
Create a flat symbol list
dbgSymbolLoad
Load a module's symbol table
dbgSymbolLookup
Look up a symbol name and optional offset given a memory address
dbgSymbolUnload
Unload a module's symbol table
本文地址:http://com.8s8s.com/it/it23602.htm