Reading the PDB header in c++ - c++

I'm trying to read the header of a PDB file in order to know if it matches my EXE file.
Is there a nice way to read the signature of the PDB file (maybe using dbgHelp)?
I need to obtain the fields of the header in the PDB file that indicate in which build the PDB was created.
thanks :)

I don't believe either the Debug Help API nor the Debug Interface Access SDK provide access to any information that would solve your problem. About the only way to detect the build information using either of those would be to check the path of object files included during link time.
The PDB file does contain information about the options passed on the command line for both compiling object files and linking (libs, dll's, exe's) which is probably what you are looking for. Unfortunately I know of no documented way to access it. It may be buried deep in one of the tables available in the PDB file but I was unable to find any references for accessing it.
That said, if having the information you requested is an absolute necessity and you're willing to deal with some frustration have a look at the PDB Parser by Sven Boris Schreiber. It contains a lot of useful information although it may not support newer PDB versions

you can use the Pdb Inspector tool to view GUID and other basic details of you PDBs. This tool uses the Debug Interface Access (DIA)

Related

C++ PDB Symbols not loaded from same directory

I have a c++ application that uses the g3log library to provide stack trace information when a crash happens. My release configuration also builds full pdb file so that this is possible. My app.exe stores the full path to the pdb file, that is I am not using /PDBALTPATH:%_PDB%.
When I am running the .exe from any folder path, so long as the .pdb has not been moved, then if I force a crash, I get a meaningfull stack trace. Now if I move the .pdb file to be in the same directory with my .exe it is not loaded anymore. My guess is that is does not match the path in the .exe. I thought that a .pdb file with the same name as the .exe would be loaded, I guess I was wrong.
I have tested by specifying /PDBALTPATH:%_PDB% such that there is no path information but then the .pdb file is again never loaded.
For both cases if I attach a debugger all is good in the debugger but not in my stack trace.
Is there a way to get the "automatic loading" of the .pdb (not sure how to call it) from when it matches the full path to happen when the .pdb is in the same directory. That way I can get a meaningful call stack when needed.
In general, your use case seems pretty weird. Because unexpected exception usually means an undefined state, and there is no sense to continue. So you need probably to save a dump and investigate it later with your PDB files.
I'm not sure about the inner mechanics which gets the stack trace information in your dev environment. But usually, a debugger is looking for PDB files and trying to load it from different places. And when you place a PDB file with an EXE file, you make it possible to be found by a debugger.
For example, my build server saves PDB files while building to my local symbol server. And when I debug a crash dump with my debugger, it gets desired symbols correctly.
I have never tried to do things you are trying to do. In fact, it looks like debug build in production, which is not a good practice. So, I would consider an approach I described above.
You can set this path;
set _NT_SYMBOL_PATH=C:\MySymbols, where your pdb files are there.
Thats the simple way, if you cant set this path, then follow below procedure.
You mentioned:
When I am running the .exe from any folder path, so long as the .pdb has not been moved, then if I force a crash, I get a meaningfull stack trace. <<
So, always make sure your app runs from the directory where the .exe+.pdb files are there.
You can do that with GetModuleFileName+SetCurrentDirectory.
That means, your working directory is different.
I would suggest is, in you application, get "GetModuleFileName".
Then change the working directory to exe path using: SetCurrentDirectory.
It seems that #prasad-mk is half way correct. Setting the _NT_SYMBOL_PATH somehow forced my .pdb symbol to be loaded as in the case where the path matches.
Another option that I found is by using this utility
http://bytepointer.com/tools/index.htm#peupdate to update the path to wharever the location of my pdb is.

Will compiler generate different .pdb file for the same sources

I know that I should avoid it as long as possible but let's talk about urgent cases.
What's the chances that .pdb file generated from the same source code with the same libraries produces different result on every build?
Yes, I know that it will differ in GUID but I can change it manually.
Suppose that I don't have a corresponding .pdb file but I know which source code was used to compile the specified product's version.
What I know that you could find the mismatched information for different pdb files with the same source code like this blog except the GUID:
https://blogs.msdn.microsoft.com/junfeng/2007/11/05/mismatched-pdbs-why/
A thread also shared some information about the timestamp which should be match here:
Compiler PDB file and the Linker PDB file

Visual Studio - debugging with PDB but missing type info

I have a project built in VS 6.0, now I have to debug it remotely in VS 2010.
I am able to browse the source correctly, create a breakpoint and trace through lines, inspect simple types, but not complex data types. It looks as it didn't load them.
I had been able previously to debug with WinDbg, there I can read complex types, but have another (not really understand what) problem with inspection...
I have also tried to debug in VS 2013, where I can't even open PDB, it says that PDB can't match executable.
I must say that PDB is exact match of an EXE recently made, but in VS 6.0.
So I'm asking if someone have experience debugging with PDB, am I missing something? Is it possible that I'm using an old PDB which don't have type information?
Update:
When I open pdb file in Notepad, it looks that the symbols that debugger cannot find is really missing from pdb. So it happen that, from the same source file, some global variable names appear in pdb, and some not. Plus the debugger says that it cannot find symbol for complex type, even if it exists in pdb. The source code is not written in respect to new C++ standard, so it cannot be compiled in VS 2013, maybe that have effect.
The modules window (Ctrl-D, M) is a good place to understand whats going on.
Right-click the module/dll that you expect its pdb to be found for and select Symbol Load Information
It should look in the same directory as your dll to begin with and if it finds the pdb will either load it or tell you that the pdb file doesn't match the dll.
I hope it will help you solve your issue.

PDB corresponding to a binary

We have different versions of binary kept in SVN. We also keeps the pdb files corresponding to the binaries. Sometimes the developers check-in the wrong pdb files. This creates problems when an issue is reported by a client at a later point.
Is there any tools to check whether a pdb file corresponds to a binary?
Use this tool - ChkMatch. This both checks the match and also allows you to forcefully match(i.e. allow you to use wrong pdbs as long as they are not too different from the actual ones). Read through this page.

I am looking for a C++ library which processes debug symbols out of a .PDB document

Creating a module that will decode structures defined in a PDB document; can anyone provide me with a module that would extract the required debugging symbols from the PDB document? Thanks.
You want the Debug Interface Access (DIA) SDK. It's COM-based, but it's the most powerful and flexible way to deal with PDBs, and it abstracts away all of the version-to-version PDB format changes. It ships with Visual Studio, and the headers and libraries can be found under your VS installation directory.
MSDN also has a fairly complete example of dumping a PDB that includes dumping out type information.
The alternative to DIA is the Debug Help (DbgHelp) library. It has a simpler interface, but it exposes less functionality than DIA. For what you want, I imagine you'd use the SymGetTypeInfo method.