专用符号加载,但显示没有行号?行号、符号、加载

2023-09-04 03:14:42 作者:叼着棒棒糖勇闯天下

我使用的Windbg加载从管理code崩溃转储(C#,专为任何CPU的控制台应用程序),以及崩溃转储在x64平台上创建的。我调试的x64平台。

I am using Windbg to load a crash dump from managed code (C#, a console application built for Any CPU), and crash dump is created on x64 platform. I am debugging on x64 platform.

我已经尝试使用下面的命令来加载我的应用程序的专用符号。下面是我使用的WinDbg中什么命令。

I have using the following command to load private symbol of my application. Here are what the commands I am using in Windbg.

(set symbol path and copy FooService.pdb pdb file to local symbol path D:\Debug)

0:016> .reload /f
.*** WARNING: Unable to verify checksum for FooService.exe
DBGHELP: FooService.pdb- private symbols & lines 
         D:\Debug\FooService.pdb

0:016> lm
start             end                 module name
00000000`00400000 00000000`0041c000   FooService C (private pdb symbols)  D:\Debug\FooService.pdb

我的困惑是,使用下面的命令时,没有行号信息显示,堆栈跟踪。任何想法有什么不好?我是否需要设置源路径?

My confusion is, when using the following command, no line number information is showed in stack trace. Any ideas what is wrong? Do I need to set source path?

0:016> ~6 e!clrstack

编辑1:!,我会见了使用PE和U寻找到抛出异常堆栈跟踪的一些问题

EDIT 1: I met with some issues with using !pe and !U to find stack trace where the exception is thrown.

下面是我的调试过程。起初,我用!PE打印堆栈跟踪异常对象,当我用!U给diassemble的code。我觉得这个问题是!U将diassemble FooService.ProcessOrders()的所有函数code,我要找到确切的地方,在功能上FooService.ProcessOrders崩溃发生。我还发现了diassembled注明IL code仅包含函数调用我做了(对于非函数调用C#code,例如A = A * 2,只有汇编语言显示),不完全是IL映射到每个对C#code线,(1)是正确的预期的行为? (2)如何解决或进一步建议,找到确切的失败的C#code,从我的分析贴在这里?

Here is my debug process. At first I use !pe to print stack trace for the exception object, when I use !U to diassemble the code. The issue I find is !U will diassemble all function code of FooService.ProcessOrders(), and I want to find the exact place where in function FooService.ProcessOrders the crash happens. I also find the diassembled annotated IL code only contains function calls I made (for non-function call C# code, for example a=a*2, only assembly language is shown), not exactly IL mapped to each line of C# code, (1) is that the correct expected behavior? (2) what is the solution or further suggestion to find the exact failed C# code from my analysis posted here?

!pe 0000064280155325

StackTrace (generated):
    SP               IP               Function

    000000001A56DA70 00000642B74E3B7A System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(System.Data.Common.DbAsyncResult, System.String, Boolean)
    000000001A56DB10 00000642B74E3FCC System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
    000000001A56DB90 0000064280155325 FooService.ProcessOrders()
    000000001A56F3E0 0000064280153A21 FooService.RountineJob()

!U 0000064280155325

感谢提前, 乔治

推荐答案

WinDbg中/ SOS没有行号映射到输出!clrstack 。所以只要流明告诉你,你有你自己的程序集的私人PDB符号,你的设置是正确的。 Unfortuntately的WinDbg / SOS的当前版本不支持源代码级调试到同一延长为本地code。

WinDbg/SOS doesn't map line numbers to the output of !clrstack. So as long as lm tells you that you have private pdb symbols for your own assemblies you setup is correct. Unfortuntately the current versions of WinDbg/SOS doesn't support source level debugging to the same extend as for native code.

编辑:关于异常。当你做了!PE ,它会告诉你调用堆栈以及偏移到相关的方法。如果您的的IP列取地址!PE 输出,并做了!U 上,你会看到即时编译$ C $下的相关方法。该IP栏将是生成异常的code中的最后一个地址(所以你必须做一些计算来找到正确的指令)。

Regarding exceptions. When you do a !pe, it will tell you the call stack as well as offsets into the relevant methods. If you take the address from the IP column of the !pe output and do a !U on that, you will see the JITTED code for the relevant method. The IP column will be the last address of the code that generated the exception (so you have to do a little counting to find the correct instruction).

在拆卸输出都标注有.NET调用所以它是没有硬映射这个针对IL或源$ C ​​$ C。这将帮助你确定到底是哪扔你要找的声明。

The disassembled output is annotated with .NET calls so it is no hard to map this against the IL or source code. That should help you identify exactly which throw statement you're looking for.

话虽这么说,你会做调试方便很多,如果你把方法细分成若干更小的方法。如果你这样做,方法名通常是足以查明异常的位置。我认识到,并不总是一个选择,但它是值得考虑的。

That being said, you will make debugging a lot easier if you split methods into a number of smaller methods. If you do that, the method name is usually enough to pinpoint the location of the exception. I realize that is not always an option, but it is worth considering.