wenmo8 发布的文章

!cpuid扩展命令显示有关系统上处理器的信息。

语法

!cpuid[Processor]

参数

Processor

指定将显示其信息的处理器。如果忽略此参数,则显示所有处理器。

DLL

Windows 2000

Ext.dll

Windows XP and later

Ext.dll

备注

!cpuid扩展在实时用户模式或内核模式调试、本地内核调试和转储文件调试期间工作。但是,用户模式的小型转储文件仅包含有关活动处理器的信息。如果在用户模式下调试,则!cpuid扩展描述目标应用程序正在运行的计算机。在内核模式下,它描述目标计算机。
下面的示例显示了这个扩展。

0:000> !cpuid
CP  F/M/S  Manufacturer     MHz
 0  6,158,10 GenuineIntel    3192
 1  6,158,10 GenuineIntel    3192
 2  6,158,10 GenuineIntel    3192
 3  6,158,10 GenuineIntel    3192
 4  6,158,10 GenuineIntel    3192
 5  6,158,10 GenuineIntel    3192
 6  6,158,10 GenuineIntel    3192
 7  6,158,10 GenuineIntel    3192
 8  6,158,10 GenuineIntel    3192
 9  6,158,10 GenuineIntel    3192
10  6,158,10 GenuineIntel    3192
11  6,158,10 GenuineIntel    3192
CP列给出处理器编号。(这些数字总是连续的,从零开始)。制造商列指定处理器制造商。MHz列指定处理器速度(如果可用)。对于基于x86或基于x64的处理器,F列显示处理器系列号,M列显示处理器型号,S列显示步进大小。对于基于安腾的处理器,M列显示处理器型号,R列显示处理器修订号,F列显示处理器系列号,A列显示体系结构修订号。

十一、系统内存信息流(SystemMemoryInfoStream)

SystemMemoryInfoStream包含系统内存管理的一些信息,它紧随在UnloadedModuleListStream流的后面。UnloadedModuleListStream的信息如下:

0x91f8+0n324=0x933c

SystemMemoryInfoStream的相关信息如下:

 

可知SystemMemoryInfoStream的RVA 为0x933C,大小为492字节,数据如下:

 

对应的数据结构目前我还没找到,但我们可以通过Minidump Browser工具大概了解一下:

 

对照上面的图,感觉这些数据对应的是SYSTEM_INFO结构,如下:

typedef struct_SYSTEM_INFO {
union {
DWORD dwOemId;
struct{
WORD wProcessorArchitecture;
WORD wReserved;
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME;
DWORD dwPageSize;
LPVOID lpMinimumApplicationAddress;
LPVOID lpMaximumApplicationAddress;
DWORD_PTR dwActiveProcessorMask;
DWORD dwNumberOfProcessors;
DWORD dwProcessorType;
DWORD dwAllocationGranularity;
WORD wProcessorLevel;
WORD wProcessorRevision;
} SYSTEM_INFO,
*LPSYSTEM_INFO;

有时在调试时,您希望知道某个特定进程是否使用 /LARGEADDRESSAWARE标志链接,从而能够使用高于2Gb边界的用户模式地址。我的解决方案是:
!address -summary将显示进程的有效用户模式地址空间:

0:022> !address –summary
..
       Tot: 7fff0000 (2097088 KB) Busy: 278fd000 (648180 KB) <<< 2Gb for non-large-address-aware EXE or large address aware EXE on x86 system without /3Gb in boot.ini


或者


Tot: bd7f0000 (3104704 KB) Busy: 23dee000 (587704 KB) <<< 3Gb for large-address-aware EXE on x86 system with /3Gb in boot.ini


或则


Tot: ffff0000 (4194240 KB) Busy: 268b2000 (631496 KB) <<< 4Gb for large-address-aware EXE running with WoW64 on x64 system


但是,由于第一种情况不明确,要实际查看EXE是否与/LargeAddressware链接,请执行以下操作:


    0:000> !dlls -c inetinfo    <<< inetinfo is the module name of the EXE in this case]
    Dump dll containing 0x01000000:

    0x00081eb0: C:WINDOWSsystem32inetsrvinetinfo.exe
          Base   0x01000000  EntryPoint  0x0100326e  Size        0x00006000
          Flags  0x00004000  LoadCount   0x0000ffff  TlsIndex    0x00000000
                 LDRP_ENTRY_PROCESSED
    0:000> .shell -i - -ci "!dlls -f 0x00081eb0" FIND "characteristics"
         12F characteristics
特征字段是:0x12f&0x20==0x20。这是IMAGE_FILE_LARGE_ADDRESS_AWARE的值。–有关此定义和相关定义,请参阅平台SDK中的winnt.h。
所以这个EXE可以识别大地址。
注意,上面使用的.shell命令(用于shell到另一个EXE,在本例中是“FIND”)是我一直用来过滤调试器命令输出的内容。非常方便。

如果您使用了WinDBG源代码调试功能,您可能会发现,每当您在调试中遇到一个与尚未打开的WinDBG文件中的源代码相关的点时,都会打开另一个源代码窗口,这很烦人。这导致了大量的源窗口和一组不断重新排列的窗口。

如果您进入View->Options,并将“打开此多个后重用”选项设置为1,而不是默认值(0):

 

然后你会发现它总是重用同一个源窗口来显示当前相关的源代码。
这意味着您可以将源窗口拖到WinDBG主窗口之外的某个位置(例如,拖到另一个监视器上),每次打开一个新的源文件时,它都会在那里打开,而不会扰乱WinDBG主区域中窗口的排列。

 

人们会问“为什么本机调试器不能调试托管代码?”.
原因是CLR提供了许多在典型的本地C++应用程序中所获得的酷服务,例如:运行在虚拟机/JITEN、动态类布局、类型系统、垃圾收集、反射等等。每一个都对调试器提出了特殊的挑战。换句话说,一个完成了所有这些功能的本地应用程序根本无法与传统的本地调试器进行调试。

1) 本机调试可以在硬件级别抽象,但是托管调试需要在IL级别抽象。托管代码不能仅仅被压缩成C/C++本地调试范例。一个原因是这可能会限制CLR执行IL的选项。例如,尽管目前(从v2.0起)jit-IL,我们还是希望为诸如解释IL、推销很少使用的jitted代码、甚至重新jitting代码等事情敞开大门。如果ICorDebug对所有内容都使用本机代码偏移量,它将无法调试解释的IL。
2) 托管调试需要很多信息,直到运行时才可用。对于托管代码,编译器只生成IL,真正的调试信息直到运行时才得到解析。例如,JIT将在运行时将IL编译为本机代码,加载程序将在运行时动态确定大多数类的布局。类型系统可以在运行时创建新类型. 对于本机代码,这都是在编译时确定的。托管调试器需要某种方法在运行时获取所有这些信息。一些解决方案包括:

a、 让CLR在运行时在信息确定时创建辅助pdb。这可能是一个巨大的性能命中率,如果没有附加调试器,我们不愿意这样做。但是如果我们在没有附加调试器的情况下不这样做,那么如果以后调试器附加了调试器,它可能就不可用了。
b、 让托管调试器检查相关的CLR数据结构(直接从进程外或通过进程内运行的“helper”线程)。这里的一个重要警告是确保当CLR数据结构处于不一致状态时,调试器不会请求此类信息。CLR当前使用帮助线程。

3) 托管调试器需要与垃圾回收器(GC)协调。CLR有一个标记-清除压缩GC。这意味着GC将移动对象来整理堆碎片,并在整个过程中相应地更新所有引用(“GC根”)。这会从几个方面影响调试:

a、 调试对象在GC期间暂时处于不一致的状态。调试器必须与GC协调,以确保在此窗口期间不会检查调试对象。
b、 调试器可以让用户更改变量的值。此更新必须与GC的更新相协调。
c、 没有方便的对象标识。在本机代码中,对象的原始指针值唯一地标识该对象,因为对象不会四处移动。