In these days I was working on tracking down a bug causing a service of ours to stop processing data. It didn't happen often, and was not simple to reproduce - it may take hours or days to appear, and was easir to see it on test/production machine than on my own development PC. Inspecting a system with SysInternals ProcessExplorer (after configuring it to download Windows symbols), showed in all processing threads a call stak like this:
kernel32.dll!Sleep+0xf DocMan.dll+0x6ccb DocMan.dll+0x737b
I knew that DocMan.dll is the only statitically linked DLL to the executable, didn't call Sleep() anywhere, but it was sharing the memory manager (FastMM 4.92) with the exe because it gets loaded first. FastMM does call Sleep() when a contention is detected accessing some internal data. I thought it could have been a deadlock, but have to demonstrate it, and I wish I could do it without installing the whole Delphi on a test machine (and never on a production machine!). Using the remote debugger proved not to be useful - attaching a stuck process blocked Delphi, and keeping the debugger attached all the time didn't trap any block.
ProcessExplorer can read debug symbols, but not the .rsm or .map file used by Delphi. Eventually, I found this utility map2dbg that converts a .map file to .dbg file ProcessExplorer (and WinDbg) can use. After copying the .dbg files to the program folder, the call stack became:
kernel32.dll!Sleep+0xf DocMan.dll!FastMM4.LockMediumBlocks+0x2f DocMan.dll!FastMM4.FreeMediumBlock+0x1b
Which is far more informative, and it confirmed the issue is in the locking mechanism of FastMM. Once debug symbols are available, one of the Windows debuggers (WinDbg, CDB and NTSD) too can be used to debug the application locally. It would be nice if Delphi could output .dbg or .pdb files directly - it would simplify tracking down bugs much easier.