LNK4099 errors for many individual object files, Visual Studio 2015 - visual-studio

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.

Related

Debugging crash dump: binary and symbol files from same build event do not match according to VS2010

I have received a crash dump file from a customer, and I am attempting to debug the dump file using VS2010. I have retrieved the source code we used for the build along with the generated symbol files, and I've provided VS with the path to the directory that contains them; everything seems to be in place. When I attempt to debug, however, VS reports that there is "no matching binary" for the .exe or any of the .dll's contained in that directory. I've used chkmatch to compare a few of the binaries and symbol files, and it reports that they match, time stamp and signature and all. I've searched around online and no one seems to have had as much trouble with this as I am encountering, and all the solutions I've found are things that I've already done.
Hopefully I'm overlooking something simple.
What am I missing? How can I ensure that VS matches the binaries to the symbol files?
You can use WinDbg
Download the tool (http://msdn.microsoft.com/en-us/windows/hardware/gg463016, you can use version 6.11.1.404 in order to avoid downloading the whole SDK) and install it.
start WinDbg and load the dump file (File > Open crash Dump).
specify the location of the symbols (File > Symbol File Path).
activate traces on symbols loading (!sym noisy at the command prompt)
unload all symbols (.reload /u at the command prompt).
load symbols for a module you have problem with (ld at the command prompt).
the engine will tell you where it loads symbols and why it doesn't match.
you can also have detailed informations on the module contained in the dump file (lm vm ), cinluding the timestamp of the module.
Hope this helps.
Another thing to check: I had problems if binaries and symbols for other build versions of the same product were in the symbol path.
VS (I'm using 2015) doesn't seem to search all the paths and choose the right files - I had to add symbol paths specific to the crash dump I'm debugging and move these "up" in the symbol path list for them to be found first and used.

Embed .pdb debug symbol information into an .exe file in Visual Studio

I am experimenting an analysis tool that can analyze executable files with embedded debug symbol information in Windows. While trying this tool on several open source projects, I realize that most of the builds do not keep symbolic information in executable files. I am able to compile the source code with VS (2008), but the build normally keeps the debug information in a separated .pdb file, not in the .exe file (unfortunately I only want to read debug information from .exe file and not .pdb file :-().
Does anybody know a way to embed symbol debug information into a single .exe file using Visual Studio?
I know this is a pretty old issue but this feature has recently been merged into Roslyn: https://github.com/dotnet/roslyn/issues/12390
The MSDN says that it isn't possible.
It is not possible to create an .exe or .dll that contains debug information. Debug information is always placed in a .pdb file.
i don't know, yet, how to do it - but there's article on MSDN that talks about it.
A portable executable (i.e .exe or .dll) can have a flag present in the header: (archive)
IMAGE_FILE_DEBUG_STRIPPED
Debugging information was removed and stored separately in stored separately in a .dbg file.
This implies that debugging information can be in the executable, and has the option of being removed and stored in a separate .dbg file.
From MSDN article DBG Files: (archive)
DBG files are portable executable (PE) format files that contain debug information in Codeview format for the Visual Studio debugger (and possibly other formats, depending on how the DBG was created). When you do not have source for certain code, such as libraries or Windows APIs, DBG files permit debugging. DBG files also permit you to do OLE RPC debugging.
DBG files have been superseded by PDB files, which are now more commonly used for debugging.
You can use the REBASE.EXE utility to strip debug information from a PE-format executable and store it in a DBG file. The file characteristic field IMAGE_FILE_DEBUG_STRIPPED in the PE file header tells the debugger that Codeview information has been stripped to a separate DBG file.
A knowledge base article describing the COFF format mentions the dumpbin utility, and it's /SYMBOLS option:
/SYMBOLS Setting this option causes DUMPBIN to display the COFF symbol
table. Symbol tables exist in all object files. A COFF symbol
table appears in an image file only if it is linked with
/DEBUG /DEBUGTYPE:COFF
The next step, and the part that would answer our question is:
what format is the embedded debugging information?
where in the PE is the embedded debugging information stored? (resource?, data section?)
But the answer "it cannot be done" seems to be incorrect.
See also
IMAGE_FILE_HEADER structure (archive)
LOADED_IMAGE structure (archive)
DBG Files (archive)
Microsoft PE and COFF Specification (archive)
An In-Depth Look into the Win32 Portable Executable File Format (archive)
KB121460 - Common Object File Format (COFF) (archive)
There is no built-in support in Visual Studio for this type of operation (at least for managed languages). The .PDB and .EXE files are created at the same time and have no option for embedding. I'm not even sure the .EXE format supports embedding PDB symbols although I could be wrong on this point.
The only course I can see is embedding the PDB as a resource in th e .EXE. However that would have to be a post build step since the two are built at the same time. And there is the potential for invalidating parts of the PDB if you modify the EXE after it's been built.
Is there a particular reason you're trying to do this? I'm imagining it's going to end up causing you a lot of pain as 1) it's not supported AFAIK and 2) the tool chain is geared towards looking for PDB in the same directory not within the .EXE. Deploying 2 files is a bit annoying at first but it's how its done at this point.
I'm pretty sure PDBs were always stand-alone files. VC++ used to have a switch that would cause it to emit (limited compared to PDB) symbol information to a "CodeView" .DBG file that by default was embedded in the EXE. However, that switch appears to no longer be supported in the newer (post 6.x ?) versions of the compiler.

Visual C++: How to disable specific linker warnings?

I'm using a library from CGAL which during the linking stage of my code compilation produces a lot of linking warnings of this form:
warning LNK4099: PDB 'vc80.pdb' was not found with 'gmp-vc80-mt-sgd.lib' or at 'vc80.pdb'; linking object as if no debug info
How do I turn off this specific linker warning under Visual C++/Studio 2008?
Note that I do not have any control on the external (CGAL) library which I am using. I cannot/donot want to get into recompiling the external library. Hence, the need to fix the messages at my end.
Add the following as a additional linker option:
/ignore:4099
This is in Properties->Linker->Command Line
Update 2018-10-16
Reportedly, as of VS 2013, this warning can be disabled. See the comment by #Mark Ransom.
Original Answer
You can't disable that specific warning.
According to Geoff Chappell the 4099 warning is treated as though it's too important to ignore, even by using in conjunction with /wx (which would treat warnings as errors and ignore the specified warning in other situations)
Here is the relevant text from the link:
Not Quite Unignorable Warnings
For some warning numbers, specification in a /ignore option is
accepted but not necessarily acted upon. Should the warning occur
while the /wx option is not active, then the warning message is still
displayed, but if the /wx option is active, then the warning is
ignored. It is as if the warning is thought important enough to
override an attempt at ignoring it, but not if the user has put too
high a price on unignored warnings.
The following warning numbers are affected:
4200, 4203, 4204, 4205, 4206, 4207, 4208, 4209, 4219, 4231 and 4237
(For the record and before the thread disappears on the msdn forums)
You can't disable the warning (at least under VS2010) because it is on the list of the warnings that can't be disabled (so /wd4099 will not work), but what you can do instead is patch link.exe (usually C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe) to remove it from said list . Sounds like a jackhammer, i know. It works though.
For instance, if you want to remove the warning for 4099, open link.exe with an hex editor, goto line 15A0 which reads 03 10 (little endian for 4099) and replace it with FF 00 (which does not exist.)
For the benefit of others, I though I'd include what I did.
Since you cannot get Visual Studio (2010 in my case) to ignore the LNK4204 warnings, my approach was to give it what it wanted: the pdb files. As I was using open source libraries in my case, I have the code building the pdb files already.
BUT, the default is to name all of the PDF files the same thing: vc100.pdb in my case.
As you need a .pdb for each and every .lib, this creates a problem, especially if you are using something like ImageMagik, which creates about 20 static .lib files. You cannot have 20 lib files in one directory (which your application's linker references to link in the libraries from) and have all the 20 .pdb files called the same thing.
My solution was to go and rebuild my static library files, and configure VS2010 to name the .pdb file with respect to the PROJECT. This way, each .lib gets a similarly named .pdb, and you can put all of the LIBs and PDBs in one directory for your project to use.
So for the "Debug" configuraton, I edited:
Properties->Configuration Properties -> C/C++ -> Output Files -> Program Database File Name from
$(IntDir)vc$(PlatformToolsetVersion).pdb
to be the following value:
$(OutDir)vc$(PlatformToolsetVersion)D$(ProjectName).pdb
Now rather than somewhere in the intermediate directory, the .pdb files are written to the output directory, where the .lib files are also being written, AND most importantly, they are named with a suffix of D+project name. This means each library project produduces a project .lib and a project specific .pdb.
I'm now able to copy all of my release .lib files, my debug .lib files and the debug .pdb files into one place on my development system, and the project that uses that 3rd party library in debug mode, has the pdb files it needs in debug mode.
I suspect /ignore is a VC6 link.exe option.
for VS2005 and VS2008's linker there's no documented /ignore option available, but the linker looks just ignore the "/ignore:XXX" option, no error and no effect.
The PDB file is typically used to store debug information. This warning is caused probably because the file vc80.pdb is not found when linking the target object file. Read the MSDN entry on LNK4099 here.
Alternatively, you can turn off debug information generation from the Project Properties > Linker > Debugging > Generate Debug Info field.
EDIT: don't use vc80 / Visual Studio 2005, but Visual Studio 2008 / vc90 versions of the CGAL library (maybe from here).
Linker Tools Warning LNK4099:
You could also compile with /Z7, so
the pdb doesn't need to be used, or
remove the /DEBUG linker option if you
do not have .pdb files for the objects
you are linking.
You cannot disable linker warning 4099, as said #John Weldon.
You should rebuild library with some project configuration changes. You have several options:
Save PDB file with debug information is same folder where you save .lib file. Set value "$(OutDir)$(TargetName).pdb" to Properties->C/C++->Output Files-Program Database File Name
Save debug information in .lib file. Set value "C7 compatible (/Z7)" to Properties->C/C++->General->Debug Information Format
Disable generation debug information for this library. Remove value from Properties->C/C++->General->Debug Information Format
In case anyone is looking to add the /ignore to a property sheet rather than modify many projects individually, you can add it as follows:
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Link>
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
</Link>

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

How do I use PDB files

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

Resources