C++ PDB Symbols not loaded from same directory - c++

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.

Related

Dumping a stack trace from C++ (Windows) - fails to find symbols

I'm a developer of Windows desktop software, and from time to time our app crashes. In rare cases I'd like to get a customer to run a debug version of the app to send me a stack trace so I know where it crashed. I followed the instructions in here:
Windows C++ stack trace from a running app
...but while it works on my development machine, it doesn't work on any client machine or those of my colleagues, who don't have Visual Studio installed. So I presume that there's some .dll or something they need before it'll work. They're using the same .exe I'm using, i.e. the one I compiled in VC++ in debug mode.
After some painstaking "message window" debugging, I learnt it's failing in SymGetSymFromAddr64() - this returns FALSE. But when I walk the stack, this always returns FALSE or it returns garbage that doesn't make sense (random unrelated method names), as if it's the PC values which are invalid, not the mapping process. To reiterate, it's a debug mode .exe that produces a perfect symbolic stack trace on my development machine.
I did some research and found some mentions of "dbghelp.dll" and "imagehlp.dll" but I just ended up confused. "dbghelp.dll" ships with all versions of Windows, but with reduced functionality. There's some other things I could install, but it's a little scary to be installing some Windows "WDK" or "debug kits" which might overwrite important system .dll's or do god-knows-what to your computer.
So what I need to know is: "what's the simplest set of instructions I can give to these helper customers e.g. the minimum set of .dll's and where to stick them so that we can get proper symbolic information out of the stack traces when our program crashes?"
The most likely reason for failing to find the symbols is that the .pdb file cannot be found. Even if you generate a .exe in debug mode, the symbols are not in the .exe, they are in the .pdb file. Through a lot of empirical testing, it seems that the process has the pathname of the .pdb hardcoded in it, so if your clients don't have that file at that location, they won't necessarily find it. However, you can supply a "search path" to the SymInitialize() function - a folder or set of folders to use to search for the .pdb file.
In my configuration, I had an exe called "Edval.exe" and a .pdb called "DebugEdval.pdb". The process searches for "DebugEdval.pdb" in the search folders. This corresponds to what you've configured in "Properties > Linker > Debugging > Generate Program Database File".

Debug symbols are said to be not loaded for a document even though they are loaded for the dll

I have built a particular dll with debug information (compiler option /Zi and linker option /DEBUG). Through an interrupt statement in the main program, I launched the Visual Studio for debugging. In the list of modules shown as seen from Debug->Windows menu, I could see that the symbols have been loaded for the dll interested in. However when I open a C++ file from that dll and try to set a breakpoint, it says debug symbols are not available for the document. There is no question that this C++ file was compiled into that dll, and that it is the same source used to build the dll (I only did it). Why does this happen? Please help, before I shoot myself.
I don't have a definitive answer, only a few suggestions.
Sometimes mdm.exe (Machine Debug Manager) stops to work properly. Terminating the process and re-starting Visual Studio helps. If the problem persists between reboots however that probably isn't the cause.
Source-file-times (last modified) that are in the future can cause all kind of weird problems. To check file times, you can do a search for nothing (Windows XP) or "*" (Windows 7). That will list all files in the selected folder. Then sort the result by date to see the max/min file time. I have no idea where the incorrect file-times come from - I just know that it happens from time to time. Might be Visual Studio itself, might be some other tool I'm using.
You could try to start the application that uses your DLL from Visual Studio, with your DLL project already open. To do that, open the "Configuration Properties", select the "Debugging" page, and enter the .exe that should be started (+ arguments if you need any). Then start the debug session as you would for a .exe project.
A cure for many problems with Visual Studio is to "clean" the project manually, and do a full re-compile. Delete all files that are generated during a build process or that store solution or project "options". i.e. all .suo .ncb .user files plus everything in the "intermediate" and "output" folders. If you're using source control, just retrieve the whole project from your source control system into a clean directory, and re-build from scratch. (Getting everything "fresh" from source control also takes care of any potential file-time problems - at least with source control systems that don't preserve file-times)
Another possible reason would be, that VS loads the wrong .pdb file. A .pdb file with a matching name could be found in a symbol server/symbol directory configured for VS (or system wide through the _NT_SYMBOL_PATH variable), or in the VS symbol cache directory. How a .pdb file with a matching name came to be in such a place is a different story, but one can easily check if the wrong .pdb file is loaded: delete the .pdb file generated by the build, and start a debug session. If VS traces "symbols loaded" for the .exe/.dll in question, it must have found a .pdb file in some other location.
Sometimes VS seems to mess up breakpoint locations in some way. I don't exactly know when or how this happens, but one of the symptoms is, that if one deletes some breakpoints, they magically reappear when starting the next debug-session. I found that setting a new breakpoint, then deleting all break points by Debug/Delete All Breakpoints, and the re-setting the required ones helps.
1) Are you not able to hit the breakpoint at all ? Generally, it gets resolved once the code in the module or stack frame needs to be hit.
2) Check if your pdb is not source information stripped
Do a Build->Clean Solution, close visual studio and then restart it and do a fresh build. This happened to me once before, and that seemed to fix it, just some outdated pdb information, I suppose.
In my case, I had renamed the C++ project. The compiler was outputting newName.lib while my other projects were still referencing oldName.lib which of course would not be removed by a Build->Clean.
I found this out by following the advice to manually clean the build directory. The subsequent linker unresolved external reference gave away the situation.

How does Very Sleepy find symbol files?

Has anyone figured out how the Very Sleepy profiler finds PDB files? It seems like it doesn't use the _NT_SYMBOL_PATH env variable.. I've had success by putting PDBs in the same directory as the executable and DLLs, but I'm trying to profile a program that uses a TON of DLLs and it's getting really painful. Isn't there some way to have it point to a symbol server?
The path to the original .pdb file is getting included in the DLL. Just don't move them.
The source code for Very Sleepy is readily available. It uses the DbgHelp API, symbolinfo.cpp source code file. The call to SymInitialize() allows a tool to specify the the search path for symbols, 2nd argument. It passes NULL, that's where the buck stops.

Breakpoint not hitting

I ported an application from VC6 to VS 2008. I rebuilt the application in release build. The Pdb file is available in the folder where exe is located. But when I loaded the application and put break point I am getting the following message
"The breakpoint will not currently be hit.No symbols have been loaded for this document"
What would be the cause of the issue?
The debugger could not find either the application or the PDBs.
When you start the program, exactly which binaries are loaded are shown in the Output window. Make sure the right files are being loaded. When everything loads properly, the output looks something like this:
'hacks_vs10.exe': Loaded
'C:\Users\john\Documents\Visual Studio
2010\Projects\hacks_vs10\x64\Debug\hacks_vs10.exe',
Symbols loaded.
When the PDB is not found, instead of saying "Symbols loaded" it says:
Cannot find or open the PDB file
Make sure that you are first running the correct version of your application (check the running path), and then make sure that the PDB is in that directory. You can change where the PDB is generated to by tweaking "Project>Properties...>Linker>Generate Program Database File"
The debugger could not find code associated with the source location you put the breakpoint at.
There can be a number of reasons for this. The one I've most often found was a section of code that was truly not compiled in. (either because of preprocessor conditionals or dead-code removal).
I imagine there can be other reasons too (e.g. inlining, though in theory, the compiler could generate the proper mapping for all the inlines. I don't know what VS2008 does here).
Are you sure you're putting the breakpoint in a code path that is supposed to be executed ?
The PDB file you mention is probably not related to the release build,
Debug information is normally absent in the release build (though you can enable it if you have to but should anticipate surprising effects due to compiler optimizations).
Therefore, you can only set breakpoints on known DLL entry points (possible via the Module List view - it has been a while since I used Visual Studio intensively) or directly on assembly instructions.
Note that you could perhaps compile part of your application with debug symbols.
I have just solved a similar problem
I re-referenced all my DLL's
went to (Tools->Options, "Projects and Solutions", "Build and Run") and set "On Run when projects are out of date" to 'Prompt to build'
I'm not sure which of these fixed the problem, but it did!

how do I specify the source code directory in VS when looking at the call stack of a memory dump?

I am analyzing a .dmp file that was created and I have a call stack which gives me a lot of info. But I'd like to double click on the call stack and have it bring me to the source code.
I can right click on the call stack and select symbol settings.. where I can put the location to the PDB. But there is no option for the source code directory.
The source code directory is unfortunately hard coded into the pdb's however if you know the folders required you can use windows concept of symbolic links, junctions.
I use the tool Junction Link Magic
Read this article about how to set up a Source Server (aka SrcSrv) integration at your site.
I took the time to follow these steps for our codebase, and now we are able to take a .dmp file from any build of our software in the past 6 months... get a stack trace with symbols... and view the exact source code lines in the debugger. Since the steps are integrated into our automated builds, there's very little overhead now.
I did need to write a custom indexer for ClearCase, but they have pre-existing ones for Perforce, TFS, and maybe others.
It is worth noting that the .dmp support in VS2005 is a little shaky.. it's quite a bit more stable in VS2008.
You'll also need to configure Visual Studio to grab the symbols for the MS products from here in addition to your own symbol server:
http://msdl.microsoft.com/download/symbols
That is described in a few places such as on the Debugging Tools for Windows site.
Windbg allows you to setup source paths same as PDB's paths.
After loading the PDB, manually navigate to the source file that matches the current execution location. A PDB contains the path and filename of the source files that built its associated binary, and I suspect the debugger is smart enough to hook things up when it notices that the filename being displayed and the filename associated with with current binary location, match.