如何最好地在 WinDBG 崩溃脚本中为可执行文件命名?
背景信息
为了保存故障转储,我将一个脚本传递给 AeDebug
注册表项的 Debugger
值中的 cdb.exe
:
C:\progra~1\debugg~1\cdb.exe -p %ld -e %ld -g -y SRV*c:\mss*http://msdl.microsoft.com/download/symbols -c "$<d:\tgticker\Dumps\RDFD.cdbscript"
这里是脚本的第一部分:
as /c CrashFirstModule .printf "%mu", @@c++((*(ntdll!_LDR_DATA_TABLE_ENTRY**)&@$peb->Ldr->InLoadOrderModuleList.Flink)->BaseDllName.Buffer)
.logopen /t d:\tgticker\dumps\${CrashFirstModule}_process.log
* (...)
符号问题
,这完全按照我想要的方式工作,我得到具有合理名称的日志文件,例如:
LHCBDRDT.exe_process_147c_2009-01-06_23-10-05-371.log
但是,如果符号不可用,我会得到如下日志文件名:
${CrashFirstModule}_process_17a8_2009-01-06_23-10-01-124.log
这是因为别名命令失败设置别名。 别名命令是我从 DumpAnalysis.org。 此命令使用 ntdll.dll
从图像的 PEB 标头中提取名称。 如果没有操作系统的符号,它就不知道在哪里可以找到它从 ntdll.dll 调用的函数。
问题
有谁知道或有一个命令来获取图像的名称作为在文件名中使用的别名,在这些情况下仍然有效?
Background Information
For saving out crash dumps, I have a script passed to cdb.exe
in the Debugger
value of the AeDebug
registry key:
C:\progra~1\debugg~1\cdb.exe -p %ld -e %ld -g -y SRV*c:\mss*http://msdl.microsoft.com/download/symbols -c "lt;d:\tgticker\Dumps\RDFD.cdbscript"
Here is the first portion of the script:
as /c CrashFirstModule .printf "%mu", @@c++((*(ntdll!_LDR_DATA_TABLE_ENTRY**)&@$peb->Ldr->InLoadOrderModuleList.Flink)->BaseDllName.Buffer)
.logopen /t d:\tgticker\dumps\${CrashFirstModule}_process.log
* (...)
The Problem
With symbols, this works exactly as I would like, I get log files with sensible names like:
LHCBDRDT.exe_process_147c_2009-01-06_23-10-05-371.log
However, if symbols are not available, I get a log file name like this:
${CrashFirstModule}_process_17a8_2009-01-06_23-10-01-124.log
This is because the alias command has failed to set the alias. The alias command is one that I harvested from DumpAnalysis.org. This command pulls the name out of the PEB Header for the image, using ntdll.dll
. Without symbols for the OS, it doesn't know where to find the function it is calling from ntdll.dll.
The Question
Does anyone know or have a command to get the name of the image as an alias for use in filenames which would still work in these situations?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
所以多年后我在这里给出了答案。
答案
在没有符号文件的情况下,这是我发现的获取崩溃的可执行文件的名称的最佳方法,以便可以在文件名中使用它来从脚本写入日志文件或故障转储:
在这些之后两行,
CrashFirstModule
将被别名为“UnknownModule”或可执行文件的名称。 仅当可执行文件以“.exe”结尾时,这才有效,但这对我来说似乎是合理的,并且在我使用它的情况下工作得很好。 如果您需要支持“.com”等内容,您可以添加另一个.if
来处理其他结尾。答案:解释
.imgscan
.imgscan
给出可执行模块的列表,其中包括 .exe、.dll、.drv 等。这是查找可执行文件名称的起点。.foreach
.foreach
用于遍历图像列表。/pS
指定第一个值在列表中的位置。/ps
指定值之间的距离。 (b = 11(十六进制))这是必要的,因为.foreach
将用空格分隔。 有了这些参数,列表就变成:$spat
$spat
是 MASM 通配符字符串匹配函数。 它将第一个参数与第二个参数中的模式进行匹配。 它不区分大小写,因此这将匹配 NOTEPAD.EXE 以及 NotePad.eXe 等。${}
${}
是别名解释器。 您可以将${}
嵌入到您希望将别名值写入字符串的位置。 如果您在命令中使用别名,则可以直接使用它,因此.echo CrashFirstmodule
将回显notepad.exe
。 在您实际指的是别名的情况下,您可以将其指定为${/v:}
,它将仅解析为别名。 重新分配别名时,这种扩展预防是必要的。aS CrashFirstModule "${name}"
会导致将别名UnknownModule
设置为notepad.exe
,如CrashFirstModule
> 在命令执行之前会被扩展为其值。aS
aS
是分配别名的命令之一。aS
由 ; 终止 或行尾,并将从条目中删除 "。以下行将CrashFirstModule
别名为UnknownModule
:.break
.break
结束找到匹配项后.foreach
End
这就是组成我正在使用的命令的所有部分,我希望其他人能从这个问题和答案中受益!
So here I am years later with an answer.
The Answer
In the absence of symbol files, this is the best way I've found to get the name of the executable that crashed so that it can be used in a filename for writing a log file or crash dump from a script:
After these two lines,
CrashFirstModule
will be aliased to either "UnknownModule" or the name of the executable. This only works if the executable ends in ".exe", but that seems reasonable to me, and works fine in the case where I'm using it. You could add another.if
to handle other ending if you need to support things like ".com".The Answer: Explained
.imgscan
.imgscan
gives a list of executable modules, which will include .exe, .dll, .drv etc. This is the starting point for finding the executable name..foreach
.foreach
is used to walk the list of images./pS
specifies how far into the list the first value is./ps
specifies the distance between values. (b = 11 in hex) This is necessary as.foreach
will separate on spaces. With these arguments, the list becomes:$spat
$spat
is the MASM wildcard string match function. It will match the first argument against the pattern in the second argument. It is not case sensitive, so this will match NOTEPAD.EXE as well as NotePad.eXe, etc.${}
${}
is the alias interpreter. You embed${<alias name>}
wherever you want the value of your alias written in a string. if you are using the alias in a command, you can just use it, so.echo CrashFirstmodule
would echo outnotepad.exe
. In those cases where you actually mean the name of the alias, you can specify it as${/v:<alias name>}
which will just resolve to the alias name. This expansion prevention is necessary when reassigning an alias.aS CrashFirstModule "${name}"
would have resulted in setting the aliasUnknownModule
tonotepad.exe
, asCrashFirstModule
would have been expanded to its value before the command was executed.aS
aS
is one of the commands to assign aliases.aS
is terminated by ; or the end of line and will strip the " from the entry. The following line will aliasCrashFirstModule
toUnknownModule
:.break
.break
ends the.foreach
after a match is found.End
That's all the pieces that make up the command I'm using. I hope someone else gets some benefit from this question and answer!
为什么不使用peb信息?
以下是您所需要的:
why not use peb info?
Below is what you need:
ntdll.dll
将出现在每个进程中,所以我猜测问题出在符号加载上。无论如何,这应该可以消除换行符:
ntdll.dll
will be present in every process, so I'm guessing the problem is symbol loading.Anyway, this should work to get rid of the line break: