回答
这是不可能的,因为在GDI任务量身打造的唯一调试器扩展gdikdx.dll不积极,因为W2K版本维护,我相信他们停止装运它,因为没有那么多的人都成侵入GDI内部 - 根据某人的说法我在一个新闻组中偶然发现 - 因此它不再投入。 只剩下几个选项,所有这些选项都不幸都是关于运行时故障排除的。
你可以与像nirsoft的GDIView工具开始从您的应用程序监控使用GDI资源,然后发展到任何的运行时间检测选项:
- gdi leaks detector tool MSDN上
- bug browser 描述
- leaktrap
PS你能更具体地了解你的特殊事故的真实原因吗?
我创建了一个脚本的Windbg倾倒所有GDI从GDI句柄表句柄。请参阅https://aloiskraus.wordpress.com/2016/06/25/show-gdi-handles-by-type-in-windbg/
当您转储它时两次你可以看到发生了什么变化有:
0:013> $$>a<"D:\GdiDump\DumpGdi.txt"
GDI Handle Table 00000000013e0000 0000000001561000
GDI Handle Count 14
DeviceContexts: 4
Regions: 2
Bitmaps: 2
Palettes: 0
Fonts: 3
Brushes: 3
Pens: 0
Uncategorized: 0
0:013> g
0:014> $$>a<"D:\GdiDump\DumpGdi.txt"
GDI Handle Table 00000000013e0000 0000000001561000
GDI Handle Count 1021
DeviceContexts: 8
Regions: 3
Bitmaps: 1003
Palettes: 0
Fonts: 3
Brushes: 4
Pens: 0
Uncategorized: 0
这里是被转储了GDI的替代文字处理来自GdiSharedHandleTable可以在现场用户模式/实时内核模式使用的脚本
$$ Run as: $$>a<DumpGdi.txt
$$ Written by Alois Kraus 2016
$$ uses pseudo registers r0-5 and r8-r14
r @$t1=0
r @$t8=0
r @$t9=0
r @$t10=0
r @$t11=0
r @$t12=0
r @$t13=0
r @$t14=0
$$ Increment count is 1 byte until we find a matching field with the current pid
r @$t4=1
r @$t0=$peb
$$ Get address of GDI handle table into t5
.foreach /pS 3 /ps 1 (@$GdiSharedHandleTable { dt ntdll!_PEB GdiSharedHandleTable @$t0 }) { r @$t5 = @$GdiSharedHandleTable }
$$ On first call !address produces more output. Do a warmup
.foreach /pS 50 (@$myStartAddress {!address @$t5}) { }
$$ Get start address of file mapping into t2
.foreach /pS 4 /ps 40 (@$myStartAddress {!address @$t5}) { r @$t2 = @$myStartAddress }
$$ Get end address of file mapping into t3
.foreach /pS 7 /ps 40 (@$myEndAddress {!address @$t5}) { r @$t3 = @$myEndAddress }
.printf "GDI Handle Table %p %p", @$t2, @$t3
.for(; @$t2 < @$t3; r @$t2 = @$t2 + @$t4)
{
$$ since we walk bytewise through potentially invalid memory we need first to check if it points to valid memory
.if($vvalid(@$t2,4) == 1)
{
$$ Check if pid matches
.if (wo(@$t2) == @$tpid)
{
$$ increase handle count stored in $t1 and increase step size by 0x18 because we know the cell structure GDICell has a size of 0x18 bytes.
r @$t1 = @$t1+1
r @$t4 = 0x18
$$ Access wType of GDICELL and increment per GDI handle type
.if (by(@$t2+6) == 0x1) { r @$t8 = @$t8+1 }
.if (by(@$t2+6) == 0x4) { r @$t9 = @$t9+1 }
.if (by(@$t2+6) == 0x5) { r @$t10 = @$t10+1 }
.if (by(@$t2+6) == 0x8) { r @$t11 = @$t11+1 }
.if (by(@$t2+6) == 0xa) { r @$t12 = @$t12+1 }
.if (by(@$t2+6) == 0x10) { r @$t13 = @$t13+1 }
.if (by(@$t2+6) == 0x30) { r @$t14 = @$t14+1 }
}
}
}
.printf "\nGDI Handle Count %d", @$t1
.printf "\n\tDeviceContexts: %d", @$t8
.printf "\n\tRegions: %d", @$t9
.printf "\n\tBitmaps: %d", @$t10
.printf "\n\tPalettes: %d", @$t11
.printf "\n\tFonts: %d", @$t12
.printf "\n\tBrushes: %d", @$t13
.printf "\n\tPens: %d", @$t14
.printf "\n\tUncategorized: %d\n", @$t1-(@[email protected][email protected][email protected][email protected][email protected][email protected]$t8)
嗨。你介意看看http://stackoverflow.com/questions/40920898/do-i-need-a-wow64-dump-for-gdi-handle-analysis?这是关于WOW64崩溃转储需求的后续。谢谢。 – 2016-12-01 21:42:01
这里/转储模式 它也可以在使用!for_each_process命令字符串转储GDI从所有正在运行的进程处理在内核模式调试
它采用了.catch块打印小结 在KD某些时候,GdiSharedhandleTable页面将被分页/截断为小于其分配大小peb头部页出等问题出现
因此,此脚本试图尽可能多地读取,并且当发生内存访问冲突时,会使catch块并打印的 总结这是什么能够挽救
顺便说一句这个脚本是32位64位的伪寄存器需要被调整为执行需要
r $t19=0;r $t18=0;r $t17=0;r $t16=0;r $t15=0;r $t14=0;r $t13=0;r $t12=0;
r $t0 = @@c++(@$Peb->GdiSharedHandleTable)
r $t1 = (@@c++(@$Peb->GdiSharedHandleTable) + 0xffffff)
r $t2 = 0
.catch {
.printf /D "<b>gdioffs Kaddr Pid Count Handle Type Tname
IsLive UAddr </b>\n";
.while(@$t0 < @$t1) {
.while(wo(@$t0+4) != @$tpid) {
r $t0 = @$t0+0x10 ; r $t2 = @$t2+1
}
.printf "%08x " , @$t0 ; .printf "%08x " , dwo(@$t0)
.printf "%08x " , wo(@$t0+4) ;.printf "%08x " , wo(@$t0+6)
.printf "%08x " , (wo(@$t0+8)<<0x10)[email protected]$t2 ; .printf "%08x " , by(@$t0+a)
.if( by(@$t0+a) == 1) {r [email protected]$t19+1;.printf "DC "}
.elsif( by(@$t0+a) == 4) {r [email protected]$t18+1;.printf "Region "}
.elsif( by(@$t0+a) == 5) {r [email protected]$t17+1;.printf "Bitmap "}
.elsif( by(@$t0+a) == 8) {r [email protected]$t16+1;.printf "Pallete "}
.elsif( by(@$t0+a) == a) {r [email protected]$t15+1;.printf "Font "}
.elsif( by(@$t0+a) == 10) {r [email protected]$t14+1;.printf "Brush "}
.elsif( by(@$t0+a) == 30) {r [email protected]$t13+1;.printf "Pen "}
.else {r [email protected]$t12+1;.printf "Unknown "}
.printf "%08x " , by(@$t0+b)
.printf "%08x\n" , dwo(@$t0+c)
r $t0 = @$t0+0x10
r $t2 = @$t2+1
}
}
r? @$t11 = @@c++(@$peb->ProcessParameters->ImagePathName.Buffer)
.printf /D "<b>Gdi Handles for %mu</b>\n", @$t11
.printf "Total Gdi Handles = %d\n", (@[email protected][email protected][email protected][email protected][email protected][email protected][email protected]$t12)
.printf "DC = %d\n" , @$t19 ; .printf "Font = %d\n" , @$t18
.printf "Region = %d\n" , @$t17 ; .printf "Brush = %d\n" , @$t16
.printf "Bitmap = %d\n" , @$t15 ; .printf "Pen = %d\n" , @$t14
.printf "Pallete = %d\n" , @$t13 ; .printf "Unknpown = %d\n" , @$t12
结果
0:000> $$>a< c:\wdscr\dumpgdi.txt
gdioffs Kaddr Pid Count Handle Type Tname ;IsLive UAddr
00472b30 fe6b5728 00000ca4 00000000 0d0102b3 00000001 DC 00000040 000e0cb0
00472be0 fdf73da8 00000ca4 00000000 420502be 00000005 Bitmap 00000040 00000000
004737b0 fddac108 00000ca4 00000000 9605037b 00000005 Bitmap 00000040 00000000
00474030 fe76eda8 00000ca4 00000000 eb050403 00000005 Bitmap 00000040 00000000
00474c90 fddde008 00000ca4 00000000 d70a04c9 0000000a Font 00000040 001fb1e8
0047ab80 fddab008 00000ca4 00000000 ba050ab8 00000005 Bitmap 00000040 00000000
0047f270 fddbcda8 00000ca4 00000000 16050f27 00000005 Bitmap 00000040 00000000
0047fef0 fdee4da8 00000ca4 00000000 cd050fef 00000005 Bitmap 00000040 00000000
004809f0 fe72eda8 00000ca4 00000000 3405109f 00000005 Bitmap 00000040 00000000
00480e50 fdda5aa8 00000ca4 00000000 0e0510e5 00000005 Bitmap 00000040 00000000
00481cf0 ffb0fda8 00000ca4 00000000 df0511cf 00000005 Bitmap 00000040 00000000
00481d70 fddb0da8 00000ca4 00000000 930511d7 00000005 Bitmap 00000040 00000000
00482020 ff4a1da8 00000ca4 00000000 d4051202 00000005 Bitmap 00000040 00000000
00482060 fddd4008 00000ca4 00000000 39051206 00000005 Bitmap 00000040 00000000
00482170 fddb6008 00000ca4 00000000 20051217 00000005 Bitmap 00000040 00000000
00483140 ff4a0008 00000ca4 00000000 4e051314 00000005 Bitmap 00000040 00000000
00483870 ff427980 00000ca4 00000000 6d051387 00000005 Bitmap 00000040 00000000
00483d80 fe7d04b0 00000ca4 00000000 bd0513d8 00000005 Bitmap 00000040 00000000
00484620 ff437eb8 00000ca4 00000000 0d101462 00000010 Brush 00000040 000f0fd8
004846a0 fddc2da8 00000ca4 00000000 d305146a 00000005 Bitmap 00000040 00000000
00484b80 fdf1a728 00000ca4 00000000 530114b8 00000001 DC 00000040 000e0ae0
Memory access error at ') != @$tpid) <-------- jumps out of catch block here
Gdi Handles for C:\Windows\system32\calc.exe
Total Gdi Handles = 21
DC = 2
Font = 0
Region = 17
Brush = 0
Bitmap = 1
Pen = 1
Pallete = 0
Unknpown = 0
- 1. gdi函数崩溃
- 2. 转到命令后BATCH程序崩溃
- 3. 我是否需要WOW64转储进行GDI句柄分析?
- 4. 从进程得到句柄
- 5. 转储崩溃转储
- 6. initWithAppID命令崩溃
- 7. Sencha命令崩溃
- 8. 从核心转储崩溃中恢复
- 9. 从崩溃转储中提取变量
- 10. Android崩溃转储
- 11. 崩溃转储分析:如何找到导致崩溃的模块和指令
- 12. 从IStream加载PNG时GDI +崩溃
- 13. 确定GDI中的句柄类型+
- 14. Wix 3.7:candle.exe从命令行崩溃
- 15. 我在哪里可以找到Windows崩溃转储(蓝屏崩溃转储)?
- 16. Windbg崩溃转储中的性能计数器
- 17. Bootstrap 3 div崩溃命令
- 18. 崩溃运行命令时
- 19. QT exec()命令崩溃
- 20. 从.NET分析崩溃转储(.dmp)
- 21. 如何从windows崩溃转储文件中获取窗口句柄和焦点窗口的列表?
- 22. perl中的转储文件句柄号
- 23. 批处理文件崩溃转到命令
- 24. Windbg崩溃转储分析
- 25. 崩溃生成转储
- 26. 如何获取GDI句柄的列表
- 27. 是否可以复制GDI句柄?
- 28. CreateProcess得到句柄无效
- 29. 得到窗口的句柄
- 30. 将自定义数据包含到iOS崩溃转储中
'!handles'将列出转储中的所有句柄,但我不认为它包含GDI,只列出了http://msdn.microsoft.com/en-us/library/ms724211(VS 0.85)的.aspx。 – 2009-10-26 20:01:43