winapi - 如何将 Win32 C + MASM "solution"从 Visual Studio 2015 升级到 VS 2017/2019

标签 winapi configuration visual-studio-2017 masm32

总结:一个VS2015混合C和Assembler的解决方案,升级到VS2017或VS2019后调试时不显示汇编代码中的符号)。
[2109 年 10 月:问题已解决,请参阅末尾的注释]。

长细节:

我有一个由 VS 2015 编译器编译的带有 32 位 C 代码的 VS 2015 xxx.sln,以及一个由自定义命令行组装的大型 32 位汇编代码 parlanse0.asm:

parlanse0.asm 属性页

Item Type:   Custom Build Tool

Command Line: ml /D SANITYCHECKS="1" /D EVENTBUFFERENABLE="1" /D TESTING="1" /D PROFILE="0"  /Sg /Sl132 /Sx /Zd /Zi /c /Cx /coff /Zd /Fl "%(FullPath)"
Outputs: parlanse0.obj;%(Outputs)
Additional Dependencies:  <list of MASM include file>
Link Objects:  Yes
Treat Output As Content: No

我不确定这是否相关,但这是链接器选项:
/OUT:"Debug\run.exe" /MANIFEST /PROFILE /NXCOMPAT:NO /PDB:"Debug/erun.pdb" /DYNAMICBASE:NO "odbc32.lib" "odbccp32.lib" "netapi32.lib" "iphlpapi.lib" "psapi.lib" "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" /LARGEADDRESSAWARE /MACHINE:X86 /SAFESEH:NO /INCREMENTAL:NO /PGD:".\Debug\run.pgd" /SUBSYSTEM:CONSOLE",5.01" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:".\Debug\run.exe.intermediate.manifest" /MAP":.\Debug/run.map" /ORDER:@"RTSCFunctionOrder.txt" /ERRORREPORT:PROMPT /NOLOGO /LIBPATH:"C:\Program Files\Microsoft Platform SDK\Lib" /DELAYLOAD:"iphlpapi.dll" /DELAYLOAD:"comdlg32.dll" /TLBID:1 

[如果这是链接器命令行,它从哪里获得它处理的 .obj 文件的名称?]

此解决方案在 VS 2015 下编译/构建/运行良好。

我正在尝试升级到 VS 2017(更新:2019 年 9 月,问题从未解决,所以我只是用 VS 2019 再次尝试......同样的问题)。

升级似乎微不足道:我只是启动了 VS 2017 并将其指向 VS 2015 解决方案文件。显然
没有任何变化,至少我的源代码控制(通过各种 MS 构建文件,如 .sln 看不到任何变化)。神奇的是,几乎一切正常:我可以编译/运行/调试应用程序。

但是,当我在调试器中并尝试“转到源代码”时,汇编源代码不再可见。来自汇编程序的“转到源代码”在 VS 2015 中工作正常。同样,如果在调试期间我选择一个汇编语言源代码行并尝试“转到反汇编”,我会得到一个弹出窗口“无法显示反汇编......那里没有与此位置关联的可执行代码”,这显然是错误的。还有在 VS 2015 下发现的行为。

我需要改变什么?是否有文件描述了不同之处?

[附加:汇编源代码与 .C 源代码位于不同的目录中。这会导致汇编代码的 .sbr 文件在与 C 代码的 .sbr 文件不同的目录中生成。显然,汇编代码 .sbr 没有在构建过程中使用;在其中一个日志文件中,我可以看到 C 代码的所有 .sbr 文件,但不能看到汇编程序的所有 .sbr 文件。
所以这看起来不对。但是,我的理解是 .sbr 文件支持 VisualStudio 标记查找,而不是对象位置到源线映射,所以我认为这是一个红鲱鱼。对象位置到源线图是在哪里产生的?链接器会这样做吗?]

[附加:按照评论中的建议查看另一个答案,我将/DEBUG 选项更改为/DEBUG:FULL 对问题没有明显影响。]

[我找到了一些关于 PDB 文件的文章,以及 C++ 编译器如何按原样“更新”它来编译单个 .cpp (.c?) 文件。 MASM 是否应该生成 PDB 文件?那么... MASM 将如何更新编译器的目标 PDB 文件?]

... 延迟 2 个月后添加 ...

我在汇编代码的反汇编窗口中看到了这一点:
00480107 CC                   int         3  
00480108 CC                   int         3  
RTSAllocate11D_end:
00480109 8D A4 24 00 00 00 00 lea         esp,[esp]  
00480110 8D A4 24 00 00 00 00 lea         esp,[esp]  
00480117 8D A4 24 00 00 00 00 lea         esp,[esp]  
0048011E 8D A4 24 00 00 00 00 lea         esp,[esp]  
00480125 8D A4 24 00 00 00 00 lea         esp,[esp]  
0048012C 8D A4 24 00 00 00 00 lea         esp,[esp]  
00480133 8D A4 24 00 00 00 00 lea         esp,[esp]  
0048013A 8D 9B 00 00 00 00    lea         ebx,[ebx]  
allocate_2to1E_bytes:

这些是我的符号,因此它们显然正在进入调试器。我要求反汇编窗口显示行号......它什么也不做。所以不知何故,符号正在通过,但不是行号信息,也可能不是源文件位置。想法?

编辑:2019 年 10 月 9 日:问题已解决。 与 Microsoft 的长时间交互使他们同意这是调试器中的问题。我确认 VS 2015 Update 1 是最后一个运行正常的版本; VS 2015 Update 2 及更高版本、VS 2017 和 VS 2019 都遇到同样的问题。 MS 告诉我,他们已经确定了问题,并且将在 2019 年 12 月的 VS 2019 v16.4 公开版本中提供修复程序。

最佳答案

要获得调试信息(在 pdb 文件中)需要 2 个步骤:

  • 编译器必须将调试信息包含到 obj 文件中以用于 ml[64]
    编译器这是 /Zd选项
  • 链接器必须有 /DEBUG命令行中的选项。在这种情况下它
    获取调试信息(存储在 .debug$S obj/lib 文件的部分中)和
    创建 pdb 文件

  • 如果编译器和链接器的命令行都正确(有这个选项)需要按以下顺序检查:
  • 在任何文本/二进制查看器中查看 .obj 文件 - 是完整路径字符串
    文件中存在源代码 asm 文件名。只需搜索PARLANSE0.ASM (或您的源文件如何命名)在文件中(所有
    名称存储为 ansi 纯文本) - 是否找到此名称是路径
    是正确的 ?如果是 - 这意味着编译器(在我们的例子中为 ml 所有
    正确,我们可以继续前进)
  • 查看 pdb 文件 - 这里也存在这个字符串吗?
  • 查看 exe 文件 - 搜索 .pdb - 完整(且正确)的路径
    你的 pdb 存在于 exe 文件中吗?它再次存储为普通ansi
    正文
  • 尝试替代调试器使用 - 我建议 windbg - 他可以吗
    去源码。为了便于检查,您甚至可以制作特殊的临时
    build - 在转到汇编代码之前设置断点(或直接在某些汇编代码中
    过程)并在 exe 的最开始调用这个过程。即使
    这个逻辑上的“不正确” - 我们只需要检查 - 是调试器
    了解 pdb 格式并可以显示 asm 的源代码

  • 如果 windbg 可以转到 asm 源代码 - 这意味着集成的 vs2017 调试器存在一些问题。如果windbg不能 - 生成的pdb格式的一些问题

    关于winapi - 如何将 Win32 C + MASM "solution"从 Visual Studio 2015 升级到 VS 2017/2019,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44937125/

    相关文章:

    c - 为什么 GetOverlappedResult 需要文件句柄?

    c++ - Windows DLL 中的字符串表在哪里?

    java - 与Hibernate结合使用时,设置C3P0参数值的最佳方法是什么?

    php - 在 Symfony2 配置 TreeBuilder 中使用正则表达式验证?

    c++ - 如何在 ListView win32 api 中删除指针

    c++ - 在 UI 线程上运行代码

    visual-studio - 为解决方案生成代码图 - 无法连接到指定的数据库

    c++ - Visual Studio 2017 中的 Windows SDK 版本设置

    Grails:将 application.properties 中的应用程序配置注入(inject) Config.groovy

    installation - 从 Visual Studio 2015.3 和 2017 rc 更新 Visual Studio 2017