• 使用 windbg gflags dumpbin 排查应用程序启动错误


    使用 windbg gflags dumpbin 排查应用程序启动错误

    缘起

    前一阵子,更新完依赖库后,启动程序报错了。这已经不是第一次报错了。so…… let's dig in!

    初遇错误

    更新完依赖库,编译通过后,高高兴兴的在 vs 中使用 ctrl + F5,没想到却遇到了下面的错误提示框。

    entry-not-found-error
    entry-not-found-error

    好吧,几个小时的努力又白费了。应该是新更新的依赖库出问题了,但是需要找出问题出在哪,才好让客户更新依赖库。

    从错误提示来看,直观感觉好像是 PBBimCore.dll 缺少了 PK_POINT_create ,真的是吗?

    调查

    遇到这种问题的第一反映是使用 Dependency walker 查一下是哪个依赖库出问题了。奈何,Dependency Walker 在我机器上运行特别慢,等了好久都没反映。

    hang-dependency-walker
    hang-dependency-walker

    不能就这么傻等下去,上调试器吧。

    在使用调试器之前,需要开启 Show loader snaps,开启后可以把程序启动的整个过程详细的记录下来。可以通过 gflags 开启。

    gflags

    以管理员权限启动 cmd,执行 gflags.exe /i your_image_name.exe +sls 即可。

    有几点需要注意:

    1. 需要以管理员权限运行,因为会修改 HKLMSOFTWAREMicrosoftWindows NTCurrentVersionImage File Execution Options
    2. 只需要程序名,而不是程序的全路径。
    3. 注意文件名中需要带上 .exe 后缀。
    4. 如果想取消设置的话,只需要把 +sls 改成 -sls 即可。
    5. 需要保证能找到 gflags.exe,可以切换到 gflags.exe 所在的目录,或者把 gflags.exe 所在的目录加到 PATH 环境变量中。

    也可以通过 GUI 版本的 gflags 开启此选项。输入对应的程序名后,勾选 Show loader snaps,确定即可。如下图:

    turn-on-show-loader-snaps-by-gflags-gui
    turn-on-show-loader-snaps-by-gflags-gui

    使用 GUI 版本需要注意以下几点:

    1. 针对单个进程的设置在 Image File 选项卡。
    2. 输入程序名(注意带 .exe 后缀),按一下 TAB 键,才可以设置。

    设置好后,就可以请出 windbg 了。

    windbg

    小贴士:在执行任何操作之前,可以先通过 .logopen d:start.log 打开一个日志文件,等问题重现后,可以通过 .logclose 命令保存操作记录及输出结果到日志文件中。

    当然也可以通过命令行的形式指定要保存的日志文件路径。

    比如,windbg.exe -logo d:start.log,可以把操作记录输出到 d:start.log 中。

    使用 windbg 打开目标程序,按 g 或者 F5 使程序继续运行起来。把输出内容复制粘贴到记事本中(如果已经开启日志则不需要此步)。然后搜索 ERROR 或者 DgnAddInG.dll 。很快就找到了如下的错误提示:

    locating-export-error
    locating-export-error

    看完英文提示后,才恍然大悟,原来是 DgnAddInG.dll 依赖一个名为 PK_POINT_create 的外部符号,而不是 DgnAddInG.dll 会提供一个名为 PK_POINT_create 的符号。

    通过 dumpbin 查看 DgnAddInG.dll 的导入表,命令如下:

    "C:Program Files (x86)Microsoft Visual Studio 12.0VCindumpbin.exe" /imports DgnAddInG.dll > d:imports.log

    在输出结果中搜索 PK_POINT_create,很快就搜到了。

    search-PK_POINT_create-in-result-file
    search-PK_POINT_create-in-result-file

    经过确认,我本地的 Pskernel.dll 确实缺少这个导出符号。

    慢半拍的 Dependency Walker

    等我操作调查完后,Dependency Walker 的结果终于出来了,请看下图:

    dependency-result
    dependency-result

    总结

    • 无法定位程序输入点 xxx 于动态链接库 yyy 上,一般是 yyy 依赖其它模块的 xxx 函数,而不是 yyy 没提供 xxx 这个函数。

    • Dependency Walker 是解决 dll 加载问题的好帮手。

    • Show Loader Snaps 选项可以详细记录应用程序启动加载过程,也是排查加载问题的好帮手。

    • dumpbin 可以快速的查看导出表,导入表等信息,也是排查加载问题的好帮手。

    参考资料

  • 相关阅读:
    spring mvc中的@PathVariable
    JSP禁用缓存的方式 response.setHeader( "Pragma", "no-cache" ); setDateHeader("Expires", 0);
    request.getSession(true)和request.getSession(false)的区别
    Spring Mvc中DispatcherServlet和Servlet的区别小结
    web.xml中load-on-startup的作用
    Spring MVC过滤器-字符集过滤器(CharacterEncodingFilter)
    web.xml配置中的log4jRefreshInterval
    web.xml中webAppRootKey
    关于tolua的使用
    关于#pragma pack
  • 原文地址:https://www.cnblogs.com/bianchengnan/p/13744381.html
Copyright © 2020-2023  润新知