I have a map file created by delphi compiler and I need to use it to analyze DMP file.
I converted the map file to dbg file, using Map2dbg.
The problem is that the process has a different signeture then the symbols.
I tried to use chkmatch to match the signeture, but I'm getting:
Error: Debug information not found in the executable
I guess this is because it is a delphi process.
Does anyone know how to match the signatures?
I made a minidumpreader some time ago:
https://asmprofiler.googlecode.com/svn/trunk/MiniDumpReader/ViewMinidump.exe (old link)
https://github.com/andremussche/asmprofiler/tree/master/Releases/ViewMinidump.exe (new link)
It is written in Delphi with jclDebug.pas so it supports all delphi debug symbols.
And because of this it has line number support (which map2dbg or tds2pdb don't have).
Note: I haven't made map2dbg or tds2pdb myself, just hosting it so other can easily find it
Related
I have a legacy Windows project using the legacy 32 Bit C++ compiler. For various reasons I need to use the Windows 8+ function PathCchCanonicalizeEx. C++Builder seems to provide the header and some module definition file for that, but I can't find any library to link against:
[ilink32 Error] Error: Unresolved external 'PathCchCanonicalizeEx' referenced from C:\[...]\WIN32\DEBUG\TMP\FILE.OBJ
How am I supposed to fix this? Do I need to add a Windows 8.1 SDK? Is the necessary lib simply named differently and I can't find it? Something completely different?
According my tests, one has two options:
IMPLIB/MKEXP
I'm developing/testing a some Windows 10 21H2, which provides an implementation for PathCchCanonicalizeEx in some DLL already. So if that source DLL is known, one can use IMPLIB or MKEXP to create an import library manually. I did that and after adding the created library from IMPLIB to my project, the linker errors were instantly gone.
Though, it's not that easy to know where PathCchCanonicalizeEx is placed in. One pretty easily finds the api-ms-win-core-path-l1-1-0.dll, but that thing is NOT an actual file on the disk and therefore can't be used by IMPLIB or MKEXP. That name is only a virtual concept for the library loader to address the same named API set of modern Windows, the extension .dll doesn't mean it's a file at all.
You can use an API set name in the context of a loader operation such as LoadLibrary or P/Invoke instead of a DLL module name to ensure a correct route to the implementation no matter where the API is actually implemented on the current device. However, when you do this you must append the string .dll at the end of the contract name. This is a requirement of the loader to function properly, and is not considered actually a part of the contract name. Although contract names appear similar to DLL names in this context, they are fundamentally different from DLL module names and do not directly refer to a file on disk.
https://learn.microsoft.com/en-us/windows/win32/apiindex/windows-apisets#api-set-contract-names
What you really need to work with is KernelBase.dll, which is even documented by MS.
implib "KernelBase x86.lib" C:\Windows\SysWOW64\KernelBase.dll
implib "KernelBase x86-64.lib" C:\Windows\System32\KernelBase.dll
Module Definition File
The downside of manually creating LIB files is that one needs to maintain those with the project. Things depend on if the target is 32 or 64 Bit, DEBUG or RELEASE, so paths might become a bit complex, one might need to create relative paths for libraries in the project settings using placeholders for the target and stuff like that.
It seems that all of this can be avoided with Module Definition Files, which's purpose is to provide IMPORT and EXPORT statements to either consume exported functions by other DLLs or make that possible for others with own functions. I've successfully resolved my linker problems by simply creating a file named like my app using the extension .def alongside my other project files. That file needs to be added to the project, though.
dbxml.cbproj
dbxml.cbproj.local
dbxml.cpp
dbxml.def
dbxml.res
[...]
The following content made the app use the correct function from the correct DLL. Though, what didn't work was using the API set name, which resulted in an error message by the linker.
IMPORTS
KernelBase.PathCchCanonicalizeEx
IMPORTS
api-ms-win-core-path-l1-1-0.PathCchCanonicalizeEx
[ilink32 Error] Invalid command line switch for "ilink32". Parameter "ItemSpec" cannot be null.
[ilink32 Error] Fatal: Error processing .DEF file
The latter is after restarting C++Builder, so I guess the format of the file is simply wrong because of the API set name.
I'd like to add the map file as resource, then extract the file every time that execute the system, to ensure that the map file is always right, and make the life of support easier. In Delphi 7 I can compile the project, with the map file as resource, but the map is wrong, because when an exception is raised the call stack is wrong. In Delphi Seattle, I can't even compile, because it tries to add the resource before generate the map. I know that I can add the file in a post-compile thask, but is there any way to do it in compiling/building time?
Sorry if I'm not very specific, that's my first question here. Thanks.
UPDATE
After I read some answers, I did some research. I was already using JEDI exception unit in my project, but I did not know the JEDI Debug expert. It does exactly what I want and more.
JEDI Debug expert convert a .map file to .jdbg file, wich is an encrypted file of map (map is just a text file). Also, the jdbg file is about 12% smaller then the map. It also has the options to insert the jdbg into binary (exe). To do that, I enabled the options:
Project -> JCL Debug expert -> Generate .jdbg files -> Enabled for this project
Project -> JCL Debug expert -> Insert jdbg data into binary -> Enabled for this project
Project -> JCL Debug expert -> Delete map files after conversion -> Enabled for this project (if you want to delete the file, of course)
To use this tool outside the IDE, with Jenkins for example, I had to build the project available in JEDI\jcl\examples\windows\debug\tools\MakeJclDbg.dpr. After build, it will generate the exe file in the bin directory of jcl. How to use:
MakeJclDbg -J -E -M map_filename
J - Create .JDBG files
E - Insert debug data into executable files
M - Delete MAP file after conversion
Executable files must be in the same directory as the MAP files. This will create the jdbg file (based in the map file), insert into the exe and delete the map. With this (and with the exception unit of JEDI), when an exception is raised, It's available to me the stack trace, the versions of all dll's used by the system, operation system info, and more, and also send all this to an email.
I realised that Embarcadero also have jdbg files of theirs bpl, so I think they use JCL tool as well.
No, the map file is generated after the program output is linked. It is impossible to incorporate a, not-yet generated, map file as a resource into the project.
You're missing the point.
The MAP files are generated as a separate file to avoid increasing the size of your executable. Trying to embed that file back into the executable as a resource simply defeats the purpose.
You haven't mentioned what debug framework you're using. But there are other ways to provide debug information, and I suggest you refer to the documentation of the debug framework you using for the specifics. I'll just offer some general concepts applicable to most of the frameworks I've tried.
If you're happy with increased EXE size and want debug information included within your executable: Don't use the map file option. Simply enable the linking option to include debug information. (And ensure your debug framework will use it.)
Most debug frameworks recommend compiling with stack frames turned on. This is very important because it makes it easier for the debug framework to deduce the call stack.
Some debugging frameworks have a feature that allows guessing missing call stack information. If enabled, you will need to manually ignore any stack entries that don't actually make sense.
Of course, don't forget that any units compiled without debug information won't have debug information to include in the final executable.
The Question
There are plenty of manual ways to make WinDBG find mscordacwks.dll without a symbol store (putting the file in the path somewhere, putting it in the same folder as windbg.exe, putting it in my Framework\v folder, specifying the path in WinDBG using .cordll -lp c:\dacFolder, etc.), but they all only fix it for me. I need to fix it more generally for everyone who uses my symbol store.
The possible solutions I can imagine are:
WinDBG be made to check the symbol store using mscordacwks.dll's subfolder name instead of mscorwks.dll's folder name.
SymStore.exe be made to add mscordacwks.dll under mscorwks.dll's subfolder name so WinDBG finds it when it looks there.
Q: Are either of these things possible, or is there another way that I'm not thinking of to solve the problem?
The Background
When analyzing a .NET process, I encountered the (apparently common) problem that psscor2 (and sosex) could not find the appropriate mscordacwks.dll on my machine. The error in WinDBG is:
Failed to load data access DLL, 0x80004005
Verify that 1) you have a recent build of the debugger (6.2.14 or newer)
2) the file mscordacwks.dll that matches your version of mscorwks.dll is
in the version directory
3) or, if you are debugging a dump file, verify that the file
mscordacwks_<arch>_<arch>_<version>.dll is on your symbol path.
4) you are debugging on the same architecture as the dump file.
For example, an IA64 dump file must be debugged on an IA64
machine.
You can also run the debugger command .cordll to control the debugger's
load of mscordacwks.dll. .cordll -ve -u -l will do a verbose reload.
If that succeeds, the SOS command should work on retry.
If you are debugging a minidump, you need to make sure that your executable
path is pointing to mscorwks.dll as well.
There are plenty of SO questions on this and plenty of good answers, practically all of which ultimately reference Doug Stewart's outstanding blog post, What is mscordacwks.dll?.
Thanks to that, I got my situation all straightened out by obtaining the correct mscordacwks.dll and placing it here:
"C:\Symbols\mscordacwks_AMD64_AMD64_2.0.50727.4216.dll\4E1545829a3000\mscordacwks_AMD64_AMD64_2.0.50727.4216.dll"
where I knew WinDBG would look because I had previously tried it with !sym noisy.
So I'm all set now, but I had to put it in that path physically rather than adding it to my symbol server through the normal symstore.exe mechanism. Since my symbol store is used by more than just me, I need to do it the right way for everyone else using the store.
And that's the problem. When I add using symstore.exe instead of going into the above path, it goes into:
"C:\Symbols\mscordacwks_AMD64_AMD64_2.0.50727.4216.dll\4E1545CB1bd000\mscordacwks_AMD64_AMD64_2.0.50727.4216.dll"
The only difference being that the subfolder name is 4E1545CB1bd000 here instead of the 4E1545829a3000 that WinDBG is looking for.
The reason for this is that when adding a binary to the symbol store, symstore.exe uses the PE of the binary to get the image timestamp and the image size. In the case of this particular .dll, dumpbin.exe /headers mscordacwks.dll reveals these to be:
image timestamp: 0x4E1545CB (Thu Jul 07 01:36:11 2011)
image size: 0x1BD000
Hence, the subfolder name 4E1545CB1BD000.
What WinDBG is looking for, on the other hand, is a subfolder based on the image timestamp and image size of mscorwks.dll, not mscordacwks.dll, because the former is loaded into the process, not the latter. WinDBG can't know the timestamp and size of the DAC module because that module is not in the process dump.
As further verification of this explanation, dumpbin.exe /headers mscorwks.dll reveals:
image timestamp: 0x4E154582 (Thu Jul 07 01:34:58 2011)
image size: 0x9A3000
which you can see add up to subfolder name 4E1545829A3000.
Knowing this, now it makes a lot more sense why all these many versions of the mscordacwks.dll that people keep running into seem to be missing from Microsoft's symbol servers. I'm sure they're there, it's just that WinDBG and psscor2 can't find them because they're picking the wrong subfolder name. Why it even bothers searching the symbols path is beyond me since it's guaranteed never to find it!
So that's my challenge. Can I somehow force symstore.exe to add mscordacwks.dll using the PE info of mscorwks.dll? If not, am I missing something about WinDBG and psscor2, might there be a way for them to know the correct timestamp and size of mscordacwks.dll even though it's not loaded (and a way for them to actually use those instead of mscorwks.dll)?
Since no other solution has appeared and my workaround seems to handle everything nicely, I'm just going to keep on with that, and I would recommend anyone else who never wants to see the annoying Failed to load data access DLL, 0x80004005 error again do the same.
So to make this work for you (and everyone who uses your symbol store, so I really wish Microsoft would do this to save us all a lot of trouble) simply place the compressed DAC file (mscordacwks.dl_) by hand into the correct path within your local SYM store.
Here are the steps I follow to accomplish this:
In WinDBG do a !sym noisy
In WinDBG do a .cordll -ve -u -l
In WinDBG do another !CLRStack or other psscor2 command if necessary to force it to load symbols again
The symbol search logging will reveal the dll it’s looking for and where it’s looking in your symbol store by showing lines like this: C:\Symbols\mscordacwks_AMD64_AMD64_2.0.50727.4216.dll\4E1545829a3000\mscordacwks_AMD64_AMD64_2.0.50727.4216.dll which indicates two things:
you need the 64-bit mscordacwks.dll of version 2.0.50727.4216; see https://stackoverflow.com/a/12024171/1910619 for ways to get it
it needs to go in a subfolder called 4E1545829a3000 under a folder called mscordacwks_AMD64_AMD64_2.0.50727.4216.dll in your symbol store
Once you obtain the file, rename it according to the name WinDBG is looking for, e.g. "mscordacwks_AMD64_AMD64_2.0.50727.4216.dll"
Manually compress this file using makecab.exe like this: makecab /D CompressionType=LZX /D CompressionMemory=21 mscordacwks_AMD64_AMD64_2.0.50727.4216.dll mscordacwks_AMD64_AMD64_2.0.50727.4216.dl_
Copy that compressed file to the expected place in the symbol store. (That you found in step 4 above, so C:\Symbols\mscordacwks_AMD64_AMD64_2.0.50727.4216.dll\4E1545829a3000\mscordacwks_AMD64_AMD64_2.0.50727.4216.dl_ in our running example here.)
You have to put the CLR dll and the associated mscordacwks dll in the same folder and register the CLR dll with symstore.
In that case symstore will add the clr and the mscordacwks dll on the symbol store.
More importantly, it will use the timestamp and file size of the clr dll to create the mscordacwks subfolder, so windbg can find the mscordacwks dll when debugging a dump.
The mscordacwks name must follow the mscordacwks_ARCH_ARCH_fileversion pattern, otherwise symstore won't add it to the symbol store.
I didn't find any documentation on that feature so it may be removed in the future.
Here is the command and the symstore output:
symstore.exe add /o /f 4.6.1076.00\clr.dll /t clr.dll /s \\mystore\microsoft
SYMSTORE MESSAGE: 0 alternate indexers registered
SYMSTORE MESSAGE: LastId.txt reported id 0
SYMSTORE MESSAGE: History.txt reported id 58228
SYMSTORE MESSAGE: Final id is 0000058228
SYMSTORE MESSAGE: Copying C:\Users\build.robot\symstore\4.6.1076.00\clr.dll to \\mystore\microsoft\clr.dll\56D79ED4990000\clr.dll [Force: T, Compress: F]
SYMSTORE MESSAGE: Copying 4.6.1076.00\mscordacwks_AMD64_AMD64_4.6.1076.00.dll to \\mystore\microsoft\mscordacwks_AMD64_AMD64_4.6.1076.00.dll\56D79ED4990000\mscordacwks_AMD64_AMD64_4.6.1076.00.dll [Force: T, Compress: F]
SYMSTORE: Number of files stored = 2
SYMSTORE: Number of errors = 0
SYMSTORE: Number of files ignored = 0
Okey, this is not a core programming question; it is more of a question regarding cgns (CFD general notational system) API.
I've exported a grid/mesh file from ANSYS Fluent (which was first created in Gambit 2.46), and I wrote a very simple Fortran program to open and close it (doing nothing else). To check the file is not corrupt I plotted it in Tecplot.
So, when I compiled using gfortran with the mentioned cgns and ran the program I got this error (as part of cg_error_exit_f())
ADF_Database_Open:File does not exist or is not a HDF5 file
Here is the program
program cavity
include "/usr/include/cgnslib_f.h"
call cg_open_f("Cavity.cgns",CG_MODE_READ,index_file,ier)
!check for error if so exit
if (ier .ne. CG_OK) then
call cg_error_exit_f()
end if
write(*,*)"I kind of opened the file?"
call cg_close_f(index_file,ier)
stop
end program cavity
I'm able to write both structured and unstructured grids in cgns format, without any problem.
I suspect the cgns library I'm using(version 2.5.5 packaged in Fedora 15 and Scientific linux 6.1) is built to support only HDF5, while the exported grid file is written in ADF format.
Any ideas to circumvent this or perhaps adding ADF? Which by the way is not packaged in both the distributions. Any other grid generator which is compatible with cgns version 2.5.5?
I hope I was clear. Any further info required, I would provide.
There is so much that could've gone wrong in here, and I'm afraid you didn't exactly narrow the problem down.
You said you exported a file from Fluent (what kind of a file is it? Be sure!). cg_error_exit_f() gave you an error listed. I'm assuming you have the source of the mentioned routines? In the program you include a cgnslib_f.h file - what's in it? I'm assumming the program compiled without errors of any kind, making this a file format question, not a fortran question.
Again, verify what kind of file Fluent produced.
When I ran into this situation, I discovered the following tools:
hdf2adf
adf2hdf
They are in the cgns-convert package on Ubuntu and are probably available for your distribution as well.
I'm currently porting a rather big project from C++ Builder 5 to the newest version, C++ Builder XE. It's my first experience with C++ Builder. I'm stuck with an error in a file, but I don't want to include this file anyway (it's code of a component not required anymore). I was not able to find out where and how this file is included, however. The compiler error does not give any hint at all apart from the error itself. How do you usually find out where a file is included?
The preprocessor is perfect for this. Right click on the cpp file which gives you the error in the project manager then choose "preprocess"
The output from this tells you every file and line number in the order they are processed. You can then search for the file in question, and the line above it is the file that included it.
This could conceivably be another header file as well, so it could be a long chain, but you can determine exactly where it comes from.
In the Project Options, enable the compiler's general messages. When the compiler encounters an error, you will be able to see the chain of includes that lead to the erroneous code.
If the files in question are rather sizable, a tool like Doxygen can be helpful in showing you the include dependencies (as well as call paths, etc.).
If it's just once or twice you'll have to do this, David Dean's suggestion of the preprocessor is golden.