VS中调试时不能关联源代码问题

时间:2022-06-14 13:06:16

转自: http://blog.csdn.net/hydream/article/details/7241439


/*****************************************************************/
/**  本人原创文章,转摘请保留本段内容,万分感谢!
/**  microdreamsoft(Lin Shaohua):
/**  由于本人水平有限,欢迎各位高手指正。
/**  本人所有原创文章将发布在以下blog:
/**   http://blog.csdn.net/hydream
/**   http://websoso.bokee.com
/**   http://89727175.qzone.qq.com
/**   http://hi.baidu.com/microdreamsoft
/**   http://751728871.qzone.qq.com
/*****************************************************************/ 

一、问题提出:

         我们有时候调试程序的时候,会碰到一种问题,例如通过myclass.cs编译后的程序,我们在调试的时候,却发现即使我们有myclass.cs源文件,Visual Studio却不能自动关联,当你在堆栈窗口双击打开时候,会出现类似以下的界面:

        VS中调试时不能关联源代码问题

                          (图1)

 

提示没有源代码,有时候还会弹出对话框,让你选择源文件。尤其是在调试第三方代码,或者是调试在其他机子上编译的程序时候,会出现这种情况,那么问题在哪里呢?

 

二、VS中是怎样查找源文件的?

         要弄清楚这个问题,首先要理解pdb文件的作用,关于这个文件的知识,请见文后的《pdb文件知识》。

         源文件和可执行模块(exe or dll)是通过pdb文件进行关联的。如下图所示:

        VS中调试时不能关联源代码问题

 

可执行模块中保存有pdb文件的信息,pdb文件中保存有源文件的信息。

 VS中调试时不能关联源代码问题



VS查找源文件的流程是这样的:

 

1、根据可执行模块中保存的pdb文件信息(guid,pdb文件名,age)查找加载pdb文件。

2、根据pdb中的源文件路径查找源文件。如果源文件在路径中不存在,则在“图1”中的“Browse to find source”可以使用,点击后会弹出文件打开对话框。如果pdb是public pdb文件,则没有包含源文件信息,这时“图1”中的“Browse to find source”变成灰色,不可使用。

 

 

三、解决问题的思路方法

有了这个流程概念后,我们就可以知道,如果无法关联源文件或者无法关联正确的文件的话,出的问题一定在pdb上。

 

那么我们怎么来查找问题呢?

 

1、首先确定vs是能找到pdb文件,这个可以在vs的模块列表窗口和堆栈窗口中看到。选中相应的模块,然后点击右键,在弹出的菜单中选择“Symbol Load Information”,可以看到pdb文件的加载信息。例如:

E:\temp\WindowsFormsApplication2\WindowsFormsApplication2\bin\Debug\WindowsFormsApplication2.pdb:Symbols loaded.

 

在“模块列表窗口”中可以看到最终加载的符号文件信息。

VS中调试时不能关联源代码问题


其中Symbol Status是符号文件加载状态。Symbol File是加载的符号文件的全路径信息。

 

2、如果vs不能加载正确的pdb文件,则“堆栈窗口”中的对应模块会变成灰色。如果是不能正确加载pdb文件,则有两种情况。

1)pdb文件不在vs搜索的路径之内。

这种情况发生在pdb文件丢失,或者pdb文件拷贝到其它目录了。这个可以通过“Symbol Load Information”窗口看到。

 

2)pdb文件不匹配。

这种情况就比较难发现一点,因为很多人以为pdb文件的关联是通过文件名的。例如明明在可执行模块的同目录下,有同文件名的pdb文件,却没有加载,这是怎么回事呢?

这个就要看看这个pdb文件的签名是否和exe或者dll中保存的pdb文件一直。

我们可以通过dumpbin /headers命令查看可执行模块中保存的pdb文件信息。例如:

Microsoft (R) COFF/PE DumperVersion 10.00.40219.01

Copyright (C) MicrosoftCorporation.  All rights reserved.

 

 

Dump of fileSystem.Windows.Forms.dll

 

PE signature found

 

File Type: DLL

 

FILE HEADER VALUES

             14C machine (x86)

               3 number of sections

        4D8C1991 time date stamp Fri Mar 2512:26:57 2011

               0 file pointer to symbol table

               0 number of symbols

              E0 size of optional header

            210E characteristics

                   Executable

                   Line numbers stripped

                   Symbols stripped

                   32 bit word machine

                   DLL

 

OPTIONAL HEADER VALUES

             10B magic # (PE32)

            8.00 linker version

          47B000 size of code

           4F000 size of initialized data

               0 size of uninitialized data

          47C17E entry point (7B44C17E)

            2000 base of code

          47E000 base of data

        7AFD0000 image base (7AFD0000 to7B49DFFF)

            2000 section alignment

            1000 file alignment

            4.00 operating system version

            0.00 image version

            4.00 subsystem version

               0 Win32 version

          4CE000 size of image

            1000 size of headers

          4CBAAA checksum

               3 subsystem (Windows CUI)

             400 DLL characteristics

                   No structured exceptionhandler

          100000 size of stack reserve

            1000 size of stack commit

          100000 size of heap reserve

            1000 size of heap commit

               0 loader flags

              10 number of directories

               0 [       0] RVA [size] of Export Directory

          47C124 [      57] RVA [size] of Import Directory

          47E000 [   4D6E0] RVA [size] of Resource Directory

               0 [       0] RVA [size] of Exception Directory

               0 [       0] RVA [size] of Certificates Directory

          4CC000 [       C]RVA [size] of Base Relocation Directory

          47C0A8 [      1C] RVA [size] of Debug Directory

               0 [       0] RVA [size] of Architecture Directory

               0 [       0] RVA [size] of Global PointerDirectory

               0 [       0]RVA [size] of Thread Storage Directory

               0 [       0] RVA [size] of Load ConfigurationDirectory

               0 [       0] RVA [size] of Bound Import Directory

            2000 [       8] RVA [size] of Import Address TableDirectory

              0 [       0] RVA [size] of Delay Import Directory

            2008 [      48] RVA [size] of COM DescriptorDirectory

               0 [       0] RVA [size] of Reserved Directory

 

 

SECTION HEADER #1

  .text name

 47A184 virtual size

   2000 virtual address (7AFD2000 to 7B44C183)

 47B000 size of raw data

   1000 file pointer to raw data (00001000 to 0047BFFF)

       0 file pointer to relocation table

       0 file pointer to line numbers

       0 number of relocations

       0 number of line numbers

60000020 flags

         Code

         Execute Read

 

 Debug Directories

 

       Time Type       Size      RVA Pointer

   -------- ------ -------- -------- --------

   4D8C1991 cv           310047C0C4   47B0C4    Format: RSDS,{99F11F8D-84DA-4309-8DA9-2B4BE6DE8672}, 1, System.Windows.Forms.pdb

 

SECTION HEADER #2

  .rsrc name

  4D6E0 virtual size

 47E000 virtual address (7B44E000 to 7B49B6DF)

  4E000 size of raw data

 47C000 file pointer to raw data (0047C000 to 004C9FFF)

       0 file pointer to relocation table

       0 file pointer to line numbers

       0 number of relocations

       0 number of line numbers

40000040 flags

         Initialized Data

         Read Only

 

SECTION HEADER #3

 .reloc name

       C virtual size

 4CC000 virtual address (7B49C000 to 7B49C00B)

   1000 size of raw data

 4CA000 file pointer to raw data (004CA000 to 004CAFFF)

       0 file pointer to relocation table

       0 file pointer to line numbers

       0 number of relocations

       0 number of line numbers

42000040 flags

         Initialized Data

         Discardable

         Read Only

 

 Summary

 

        2000 .reloc

       4E000 .rsrc

      47C000 .text

 

注意上面的加粗信息。

Format: RSDS,{99F11F8D-84DA-4309-8DA9-2B4BE6DE8672}, 1, System.Windows.Forms.pdb

 

Format:RSDS:pdb文件的格式。

{99F11F8D-84DA-4309-8DA9-2B4BE6DE8672}:关联的pdb文件tag。

1:关联的pdb文件的age。

System.Windows.Forms.pdb :关联的pdb文件的文件名。

 

Vs加载pdb文件的时候会严格验证guid和age必须一直,即使文件名相同也不行。

所以如果我们碰到同名的pdb文件不能加载,我们可以再看看pdb文件的信息,看看是否一致。

 

 

3、如果能加载正确的pdb文件了,却不能自动关联对正确的源文件。这时候就可以看看pdb文件中对应的源文件信息是否正确。

 

查看pdb文件的工具,我们可以使用vs安装目录下的Microsoft Visual Studio 10.0\DIASDK\Samples\DIA2Dump中的DIA2Dump工具。这个有源代码,需要我们重新编译就可以使用了。

 

Dia2dump pdb文件名 >> 结果文件

 

打开结果文件,我们就可以看到里面包含的各种信息,例如源文件信息。

 VS中调试时不能关联源代码问题

 

Compiland就是编译的单元,我们可以看到全路径信息。然后到对应的路径下查看是否源代码文件是否存在。

 

四、注意

        另外值得提一下的是,在.net中,在编译的时候必须要采用/debug:full指令,而不是/debug:pdbonly,如果是后者,也是可以生成pdb文件,但是还是不能进行源代码级别的调试的,原因是/debug:pdbonly虽然和/debug:full一样生成同样的pdb文件,它们的唯一区别是后者会在assembly中加上:DebuggableAttribute。原因是.net是虚拟机执行的,这个标记的作用是告诉.net jit要保留调试信息,否则经过jit编译后的机器码就和pdb中的调试信息无法关联了。C/c++不存在这个问题。
       详细请参见:http://msdn.microsoft.com/en-us/library/8cw0bt21.aspx
 
 
<pdb文件知识>:
 
Pdb文件是program database的缩写,意思为程序数据库。它从编译器的角度描述了一个程序的组成,例如源代码,函数,变量,行号等信息。
 
具体可以参考以下资料:
1、《软件调试》(张银奎编著)
2、《How to Inspect the Content of a Program Database (PDB) File》http://www.codeproject.com/Articles/37456/How-To-Inspect-the-Content-of-a-Program-Database-P
3、《PDB Files: What Every Developer Must Know》http://www.wintellect.com/CS/blogs/jrobbins/archive/2009/05/11/pdb-files-what-every-developer-must-know.aspx
4、MSDN上的信息。