How do I use PDB files - debugging

I have heard using PDB files can help diagnose where a crash occurred.
My basic understanding is that you give Visual studio the source file, the pdb file and the crash information (from Dr Watson?)
Can someone please explain how it all works / what is involved?
(Thank you!)

PDB files map an assembly's MSIL to the original source lines. This means that if you put the PDB that was compiled with the assembly in the same directory as the assembly, your exception stack traces will have the names and lines of the positions in the original source files. Without the PDB file, you will only see the name of the class and method for each level of the stack trace.

PDB files are generated when you build your project. They contain information relating to the built binaries which Visual Studio can interpret.
When a program crashes and it generates a crash report, Visual Studio is able to take that report and link it back to the source code via the PDB file for the application. PDB files must be built from the same binary that generated the crash report!
There are some issues that we have encountered over time.
The machine that is debugging the crash report needs to have the source on the same path as the machine that built the binary.
Release builds often optimize to the extent where you cannot view the state of object member variables
If anyone knows how to defeat the former, I would be grateful for some input.

You should look into setting up a symbol server and indexing the PDB files to your source code control system. I just recently went through this process for our product and it works very well. You don't have to be concerned about making PDB files available with the binaries, nor how to get the appropriate source code when debugging dump files.
John Robbins' book: http://www.amazon.com/Debugging-Microsoft-NET-2-0-Applications/dp/0735622027/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1222366012&sr=8-1
Look here for some sample code for generating minidumps (which don't have to be restricted to post-crash analysis -- you can generate them at any point in your code without crashing): http://www.codeproject.com/KB/debug/postmortemdebug_standalone1.aspx

Related

LNK4099 errors for many individual object files, Visual Studio 2015

When building a large C++/Fortran app, I recently started getting LNK4099 errors for virtually every C++ object file. For example
Cfile.obj : warning LNK4099: PDB 'lnk{3FE844DB-7378-4485-9D93-6B1B48386536}.tmp' was not found with 'Cfile.obj' or at 'C:MyApp\x64\Debug\lnk{3FE844DB-7378-4485-9D93-6B1B48386536}.tmp'; linking object as if no debug info
Unlike a number of previous posts, this is not due to a library missing PDB info; the files with the errors are all my own source code, and freshly built.
This is Visual Studio 2015, building under 64-bit Windows 7. The problem occurs for both debug and release builds. The options for the debug build are C++: /Zi / Od; Linker: /DEBUG, Generate Full Program Database File.
The app is C++, using a Fortran library, created by Intel Fortran XE2017, and built with /debug:full. Linking to the Microsoft libraries (MFC, msimg32.lib, nafxcwd.lib, libcmtd.lib, etc) is static.
If I compile a single C++ source file AFile.cpp using F7 (Build/Compile) and then build the project, I get all the same errors EXCEPT there is none for AFile.obj. The debugging information for AFile is in the app's PDB (I can set breakpoints). Files that have the errors are missing debug info in the app's PDB (as the error message says), and I cannot set breakpoints.
What setting or configuration could be causing this mysterious behavior? I do not have this issue with smaller projects.
The LNK4099 documentation shows a DUMPBIN command that can be used to list the full path name of a .pdb file associated with an object file...
dumpbin /section:.debug$T /rawdata objectname.obj
It might be interesting to examine AFile.obj from your F7 experiment and another .obj file generated by the project build to see how the PDB file names differ (if they differ).
Assuming you're doing a build, not rebuild, of the project in your F7 experiment it might also be interesting to see what happens if you compile AFile.cpp with F7 and then do a full rebuild of the project. A full rebuild would recompile AFile.cpp where a regular build wouldn't.
Once you know what you should be looking for you can start trying to figure out if your build is: not creating the PDB files; creating them in the wrong place; creating them with the wrong name; or removing them after they're created.
UPDATE
I should have added the caveat that /PDBALTPATH can set the string shown by the DUMPBIN command above to a value different from the actual PDB file's pathname.
Per #Frank Boyne's suggestion, I found that
dumpbin /section:.debug$T /rawdata *.obj
lists the same result for all the object files, namely 0x1B byes of binary data, followed by the full path to App.pdb. Recompiling a single file shows the identical path, but slightly different binary data.
So, the answer is, the project's Program Database File Name property was set to $(TargetDir)$(TargetName).pdb, when it should have been $(IntDir)%(Filename).pdb. Following this change, .pdb files appeared with each object file (i e, separate file in the same directory), and the build completes without any LNK4099 errors.
This solves the original problem. I am wondering, though, if there is a way to have the PDB information added to a single output file, rather than producing a separate PDB file for each object file.

Which tool to use to open .pdb (symbol) files?

I have .pdb file, downloaded from MS symbols server. I need to fetch list of symbols (functions, arguments, anything it has). There is a tool on CodeProject, but it only reports modules. There is DbgHelp API, but it only could be attcahed to running process. How can I read .pdb file offline?
Good News for anyone still looking,
The information you seek is now open source!
https://github.com/Microsoft/microsoft-pdb
Some real interesting stuff there. Like this pdbdump.cpp file,
with its dumpPublics function or its main flow controls. Good documentation too
You can also use Visual Studio's Dia2Dump sample program to dump human-readable output from a PDB file, including its public symbols.
Be sure to build it as a 32-bit application though, or you might run into some problems with it. (See dia2dump: CoCreateInstance failed - HRESULT = 80040154)

PDB files do not include all .net source information

This may come down to my misunderstanding of PDB files and the build process, rather than any particular problem but I've struggled to find a good answer elsewhere.
We have recently been good little developers and started indexing and storing our pdb files on a central symbol server (all part of TFS). The problem is that our PDB files do not appear to include all the source information.
When trying to navigate to sources in Visual Studio, the pdb files of our assemblies are found, as shown by the output window:
PdbNavigator: Downloader: file://server/Symbols/my.assembly.pdb/1DB3F79EA3094EAAADFC6CDE6515FC871/my.assembly.pdb -> ok, 251 KB
PdbNavigator: No debugging information found on symbol servers for my.assembly, Version=1.0.1.1206, Culture=neutral, PublicKeyToken=4cd79aeab39b919b
But at the same time it says it found no sources. If I use some of the tools from the windows SDK I can see that the PDB file does not contain the information on about 30% of the source files in the project.
I think I read somewhere that PDB files only include the source for classes actually used within the project, but surely that creates a massive problem for any API type assemblies where multiple classes may have no function within the assembly, only when used from some other part of your project?
If anyone can shed light on this, please let me know.
Thanks.
A PDB (normally) doesn't store source code - it contains a list of "documents", which are the source code file names, and "method information", which maps source lines to offsets in the assembly or binary. A PDB matches when the signature and build date of the assembly matches the same in the PDB file. Chances are, the MyAssembly.pdb has the correct version, but the signature and/or build date don't match.
The signature is not exposed as far as I know, but you may find some code on the Internet that says how to read a PE signature and a PDB signature so you can do a comparison.

WinDbg Dr. Watson minidump - requires pdb/dll originally built for installed version?

I have a mindmp file from a target's application crash. Is it possible for me to rebuild the dll/pdb files for a version of software and have windbg load symbols correctly?
My problem is that our pdb files are only kept for major releases (unfortunately). This is a daily build, which I can rebuild myself, but I'm getting tripped up on errors.
With !sym noisy on:
"image header does not match memory image header."
DBGENG: C:\...\XXX.dll image header does not match memory image header.
DBGENG: XXX.dll - Partial symbol image load missing image info
DBGHELP: Module is not fully loaded into memory.
DBGHELP: Searching for symbols using debugger-provided data.
DBGHELP: C:\...\XXX.pdb - mismatched pdb
Note I've build the pdb with the dll, they are from the same RELEASE directory (should I be building debug?)
Theses are release builds (as release builds are installed on the target and crashing) should I be somehow using the debug build dlls to get more symbol information?
The ChkMatch utility is designed for this exact scenario.
As long as you have the original .EXE, you can recompile the sources (with the same compiler and compiler settings) and patch the new .PDB to match the old .EXE.
In this example, OriginalExecutable.exe is the executable that no longer has a .PDB file, and RebuiltPDB.pdb is one that has been produced by rebuilding the original source.
chkmatch -m OriginalExecutable.exe RebuiltPDB.pdb
Now, as long as the two files have their original names, The debugger should accept them as a matching pair.
In my experience probably not.
If you have the exact build directory and build with the exact same compiler settings then this might work. You definitely will not be able to load symbols from a debug build against a release crash dump.
You will need to turn on the 'load anything' options: .symopt+0x40 to get windbg to ignore the timestamp differences.
if you still have the exact source code the image was compiled from, then rebuild it producing a new pdb file and then instruct WinDbg to forcibly load this pdb when you open the crash dump - it worked once in my practice.
PDB files are tied to their EXE files by a GUID and an "age" (it's a sequence number). These are embedded in the EXE, and into the PDB. The GUID is regenerated on each complete build, and the "age" is changed on each incremental build.
The debugger uses these to ensure that it's looking at the correct PDB for the EXE file.
I didn't know about the "chkmatch" tool mentioned by SteveMan, but I suspect that it works by patching up the GUID/age so that they match.
This is too late to help Doug, but for the sake of anyone who comes across this question, another thread (Is it possible to load mismatched symbols in Visual Studio?) pointed out a way to get WinDbg to accept mismatched .PDB files
.symopt_0x40

Attaching to a foreign executable in Visual C++ 2003

I have an executable (compiled by someone else) that is hitting an assertion near my code. I work on the code in Visual C++ 2003, but I don't have a project file for this particular executable (the code is used to build many different tools). Is it possible to launch the binary in Visual C++'s debugger and just tell it where the sources are? I've done this before in GDB, so I know it ought to be possible.
Without the PDB symbols for that application you're going to have a tough time making heads or tails of what is going on and where. I think any source code information is going to be only in that PDB file that was created when whoever built that application.
This is assuming that the PDB file was EVER created for this application - which is not the default configuration for release mode VC++ projects I think. Since you're asserting, I guessing this is a debug configuration?
Short of any other answers, I would try attaching to the executable process in Visual Studio, setting a break point in your code and when you step into the process you don't have source to, it should ask for a source file.
Yes, it's possible. Just set up an empty project and specify the desired .exe file as debug target. I don't remember exactly how, but I know it's doable, because I used to set winamp.exe as debug target when I developed plug-ins for Winamp.
Since you don't have the source file it will only show the assembly code, but that might still be useful as you can also inspect memory, registers, etc.
Update
If you are debugging an assertion in your own program you should be able to see the source just fine, since the path to the source file is stored in the executable when you compile it with debug information.

Resources