如何将Win32 C+MASM“解决方案”从Visual Studio 2015升级到VS 2017/2019

4

概述:一个具有混合C和汇编的VS2015解决方案,在升级到VS2017或VS2019后,在调试时无法显示汇编代码中的符号。

[2019年10月:问题已解决,详见末尾注释]。

详细信息:

我有一个由VS 2015编译器编译的32位C代码,并包含一个由自定义命令行汇编的32位大型汇编代码parlanse0.asm:

parlanse0.asm Property Pages

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文件支持VisualStudio标记查找,而不是对象位置到源行映射,因此我认为这是个错觉。 目录下哪里会生成对象位置到源行的映射? 连接器会这样做吗?]
[添加:根据评论中的建议查看另一个答案,我将/DEBUG选项更改为/DEBUG:FULL,但似乎对问题没有影响。]
[我在两个月后的延迟后发现这一点...] 我在我的汇编代码中的反汇编窗口中看到了这一点:
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日:问题已被解决。与微软的一次长时间交流使他们同意这是调试器中的问题。我验证了VS 2015 Update 1是最后一个正常工作的版本;VS 2015 Update 2及更高版本、VS 2017和VS 2019都存在相同的问题。微软告诉我,他们已经找出了问题并将在2019年12月发布的VS 2019 v16.4公共版本中提供修复。

1
“前往源代码”不是关于查找符号吗?2017年PDB的生成方式已经改变。请查看Hans的答案。 - Simon Mourier
@RbMm:在 ml 命令行中添加 /FR 选项,现在将生成 .sbr 文件。但是 .sbr 文件如何被链接命令处理(如果有的话)?请注意,该 .sbr 文件不位于所有 C .obj 和 .sbr 文件的同一目录中;过去从未这样做也没有问题。我还启用了 /Zd("行号"),但文档声称它们被"放入对象文件"中,但我不确定这是 .sbr 还是 .obj 文件。 - Ira Baxter
1
@IraBaxter - 我们根本不需要 .sbr 文件来进行调试信息。所有的调试信息都是由编译器在 .obj 文件中生成的。最后,链接器获取这些信息并将其放入 pdb 文件中。在 pdb 中可以存在源文件的路径,并将行 RVA 映射到 CV_DebugSLinesHeader_t - 你是否尝试在 windbg 中进行调试?也没有显示源代码吗?你是否尝试创建一个简单的测试项目 - 比如一个小的演示汇编文件?同时,你能否公开发送你的 pdb 文件?我可以分析它并准确地设置其中包含的信息。 - RbMm
1
@RbMM: 当然,正在处理这个问题… - Ira Baxter
1
你的pdb文件没问题,没有任何bug。你的masm设置也没问题。但是17/19 studio调试器存在bug,你自己无法修复。 - RbMm
显示剩余30条评论
2个回答

2
需要调试信息(在文件中),需要执行2个步骤:

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

如果编译器和链接器的命令行都正确(具有这些选项),则需要按以下顺序检查:

  1. 在任何文本/二进制查看器中查看 .obj 文件 - 是否存在源汇编文件名的完整路径字符串。只需按原样搜索文件中的 PARLANSE0.ASM(或您的源文件命名方式)(所有名称都存储为ansi纯文本)- 如果找到该名称并且路径正确吗?如果是,这意味着编译器(在我们的情况下为ml)全部正确,我们可以继续进行。
  2. 查看 pdb 文件 - 这些字符串是否也存在于此处?
  3. 查看 exe 文件 - 搜索 .pdb - 完整(且正确)路径 for your pdb 是否存在于 exe 文件中?再次存储为纯ansi文本
  4. 尝试使用替代调试器 - 我建议使用windbg - 它能够进入源代码。为了轻松检查,您甚至可以进行特殊的临时构建 - 在转到汇编代码之前设置断点(或直接在某个汇编过程中)并在 exe的非常开始调用此过程。即使这在逻辑上“不正确”,我们仅需要检查 - 调试器是否理解pdb格式并且可以显示汇编的源代码。
如果 windbg 可以进入汇编源代码,则意味着集成的 vs2017 调试器存在某些问题。如果 windbg 无法进入汇编源代码,则可能是生成的 pdb 格式存在问题。

我从未解决过这个问题。现在已经安装了VS 2019。行为完全相同。 - Ira Baxter
发现这个链接:https://developercommunity.visualstudio.com/content/problem/95867/fatal-error-lnk1103-debugging-information-corrupt.html。如果我没记错的话,你说我的PDB文件看起来很好...但是你的PDB文件解码器有一个bug。微软声称已经改变了obj文件格式。你的bug是否与文件格式的更改有关? - Ira Baxter
@IraBaxter - 已向您发送电子邮件。我不认为调试格式已更改(我的测试未确认此点)。我需要再次查找 parlanse0.objpdb(从使用此 parlanse0.obj 的 exe 或 dll 中),如果可以的话,需要两个版本 - 2019 年构建的版本无法调试源代码,而 2015 年的版本则可以。 - RbMm

1
将汇编文件名 P.asm 改为 parlanse0.asm 或者在你的自定义构建脚本开头添加 /Fo parlanse0.obj
你不能通过你的方式生成 parlanse0.obj 和调试相关文件(parlanse0.iobj, parlanse0.ipdb)。但是,由于这些文件已经编译过了,所以你可以无问题地进行构建。

感谢您指出这一点。很抱歉让您感到困惑。实际名称确实是parlanse0.asm;我将其更改为P.asm以简化我的问题,并且不一致,制造了一个误导。我已经更改了所有引用,以正确地说出parlanse0。... - Ira Baxter
忽略那个失误,".iobj"和".ipdb"文件是什么?我为什么需要它们?如何(不)通过你的方式生成它们?我一直在改变汇编代码,不能依赖于很久以前“编译过”的版本。 - Ira Baxter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接