views:

347

answers:

1

Hello everyone,

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.

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

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

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

thank in advance, George

+2  A: 

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.

EDIT: 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).

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.

Brian Rasmussen
Thanks! If I have a crash dump with full source codes (C# managed code) of my application, what is the easiest way to find the source crashes/breaks from which line of managed code using Windbg? If Windbg cannot achieve this goal, what other tools may be helpful?
George2
By crash I reckon you're talking about an unhandled exception. If that is the case, you can find the exception on the appropriate thread. Use the !threads command to display all managed threads as well as any exceptions on these. The !pe command will list the exception object in detail. For further info please see this excellent blog http://blogs.msdn.com/tess/
Brian Rasmussen
Yes, Brain, I am talking about unhandled exceptions. I have tried to use !pe and !threads, they provide some information, but since the exception (SqlException) may be thrown from a couple of different lines (scenarios) from a specific function of my code. And using !pe and !threads can tell me which function the exception is from, but if the function could throw the exception in different locations/scenarios, how to tell where the exception is thrown?
George2
BTW: I read the blog, and it is talking about memory leak, is it related to my question?
George2
Thanks Brain, I have followed your advice and tried your solution of using !pe and !U. Please refer to the EDIT 1 section of my updated post. The issue I find is, !U will diassemble all the function, not exact the place where it crashes. Any solutions?
George2
From you edit it looks like you're disassembling the method ProcessOrders, but your exception is thrown in InternalExecuteNonQuery according to the stack dump from !pe. So if you want to find the line where the exception is trown you should disassemble InternalExecuteNonQuery. Doesn't the exception object give you any hints about what is wrong here?
Brian Rasmussen
I am confused Brain, since InternalExecuteNonQuery is .Net Framework code. I think it does not has bug. It should be my code bug, which triggers .Net SqlException. so, I think I should diassemble my own application code (in class FooService), but why do you think I should debug .Net Framework code InternalExecuteNonQuery?
George2
You are probably right asserting that the bug is in your code. However, since InternalExecuteNonQuery throws an exception you could be calling it with wrong parameters or the like. What does the exception say? If you can't figure out the source of the exception from looking at the exception itself, you could look at the implementation of InternalExecuteNonQuery to see if you can spot the problem. From there you can work your way back to the calling code.
Brian Rasmussen
Cool, Brain, question answered. I have a related question posted here, appreciate if you could take a look, http://stackoverflow.com/questions/1558221/diassemble-managed-code-issue
George2