缘起
前一阵子,更新完依赖库后,启动程序报错了。这已经不是第一次报错了。so…… let's dig in!
初遇错误
更新完依赖库,编译通过后,高高兴兴的在 vs
中使用 ctrl + F5
,没想到却遇到了下面的错误提示框。
好吧,几个小时的努力又白费了。应该是新更新的依赖库出问题了,但是需要找出问题出在哪,才好让客户更新依赖库。
从错误提示来看,直观感觉好像是 PBBimCore.dll
缺少了 PK_POINT_create
,真的是吗?
调查
遇到这种问题的第一反映是使用 Dependency walker
查一下是哪个依赖库出问题了。奈何,Dependency Walker
在我机器上运行特别慢,等了好久都没反映。
不能就这么傻等下去,上调试器吧。
在使用调试器之前,需要开启 Show loader snaps
,开启后可以把程序启动的整个过程详细的记录下来。可以通过 gflags
开启。
gflags
以管理员权限启动 cmd
,执行 gflags.exe /i your_image_name.exe +sls
即可。
有几点需要注意:
- 需要以管理员权限运行,因为会修改
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\
。 - 只需要程序名,而不是程序的全路径。
- 注意文件名中需要带上
.exe
后缀。 - 如果想取消设置的话,只需要把
+sls
改成-sls
即可。 - 需要保证能找到
gflags.exe
,可以切换到gflags.exe
所在的目录,或者把gflags.exe
所在的目录加到PATH
环境变量中。
也可以通过 GUI
版本的 gflags
开启此选项。输入对应的程序名后,勾选 Show loader snaps
,确定即可。如下图:
使用 GUI
版本需要注意以下几点:
- 针对单个进程的设置在
Image File
选项卡。 - 输入程序名(注意带
.exe
后缀),按一下TAB
键,才可以设置。
设置好后,就可以请出 windbg
了。
windbg
小贴士:在执行任何操作之前,可以先通过
.logopen d:\start.log
打开一个日志文件,等问题重现后,可以通过.logclose
命令保存操作记录及输出结果到日志文件中。当然也可以通过命令行的形式指定要保存的日志文件路径。
比如,windbg.exe -logo d:\start.log,可以把操作记录输出到 d:\start.log 中。
使用 windbg
打开目标程序,按 g
或者 F5
使程序继续运行起来。把输出内容复制粘贴到记事本中(如果已经开启日志则不需要此步)。然后搜索 ERROR
或者 DgnAddInG.dll
。很快就找到了如下的错误提示:
看完英文提示后,才恍然大悟,原来是 DgnAddInG.dll
依赖一个名为 PK_POINT_create
的外部符号,而不是 DgnAddInG.dll
会提供一个名为 PK_POINT_create
的符号。
通过 dumpbin
查看 DgnAddInG.dll
的导入表,命令如下:
"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\dumpbin.exe" /imports DgnAddInG.dll > d:\imports.log
在输出结果中搜索 PK_POINT_create
,很快就搜到了。
经过确认,我本地的 Pskernel.dll
确实缺少这个导出符号。
慢半拍的 Dependency Walker
等我操作调查完后,Dependency Walker
的结果终于出来了,请看下图:
总结
无法定位程序输入点
xxx
于动态链接库yyy
上,一般是yyy
依赖其它模块的xxx
函数,而不是yyy
没提供xxx
这个函数。Dependency Walker
是解决dll
加载问题的好帮手。Show Loader Snaps
选项可以详细记录应用程序启动加载过程,也是排查加载问题的好帮手。dumpbin
可以快速的查看导出表,导入表等信息,也是排查加载问题的好帮手。
参考资料
- https://ofekshilon.com/2013/06/22/entry-point-not-found-and-other-dll-loading-problems/
- https://stackoverflow.com/questions/17883886/show-loader-snaps-in-gflags-exe-fails-to-capture-any-output-in-windbg
- https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/show-loader-snaps?redirectedfrom=MSDN