views:

444

answers:

1

We have a Delphi COM component being called from an ISAPI web app. The COM component is hanging the app because it is trying to display a MessageBox(). We have no MessageBox() call in our user code so it must be located in the Delphi runtime source, probably in exception handler code.

We have an IIS debug diagnostics report that shows our module name + an offset address as the offending code.

We have a .MAP file for our module and we also have produced a .dbg file using MAP2DBG.

Our question is how do we locate the source file line of code using the IIS debug diag hang report containing the offset address, using the .MAP or .DBG file?

We've tried to use WinDbg but have not been able to figure out what we need to do to locate the source line.

+3  A: 

Firstly you need to find the base address where the process loaded the COM module in to the IIS process - this may be evident by the IIS Debug log. Lets call this BASE.

Then you calculate the MAPoffset = offset - BASE - $1000 and you have an address that can be searched for in the Delphi MAP file.

In the MAP file (which should be detailed to get line number mapping) you will find a section for each source module which list records of "linenumber segment:offset". Then you check if MAPoffset is either equal to an offset or in between two of the line number offsets. This should give you a direction to which line is the offending line.

The segment is usually 1 - indicating a text segment with generated code - (there is a segment map in the top of the MAP file).

Hope this helps!

Christer Fahlgren
+1 Great answer. The map file is key to finding the bug, and understanding the map file is the secret to finding those pesky AV errors that pop up after deployment. I tend to keep the MAP files in source control tagged with the source to a release for just this reason.
skamradt
The IIS debug report against the dump file lists ModuleName+4974 as the offending address. Using WinDbg to load the dump file, the module start is 064F0000.So 064F4974 - 064F000 = 4974. 4974 - 1000 is 3974. I don't see anything in the .map file even close to that number. What am I missing?
Ken Byington
In your map file you should have a section very near the top called 'Detailed list of segments'. In this section the very first row looks like this in a map file of mine: 0001:00000000 00006B49 C=CODE S=.text G=(none) M=System ACBP=A9This is a segment of type 1 (.text) which starts at 0 and runs $6B49 bytes. If this was your map file it would tell me that your module is the 'System' module. Now, given that you have identified your module, there should be a section like this for that module : "Line numbers for System(GETMEM.INC) segment .text".
Christer Fahlgren
And in this line numbers section I would find a "record" that says this: 9292 0001:00003974 - this means line 9292 in system.pas starts at $3974.Then you would go to system.pas - line 9292 to find the line.
Christer Fahlgren
Thanks so much for the additional help. We now know exactly where the exception is being raised. Unfortunately it is deep inside the RTL where the COM dll is being initialized, in assembly language procedures. There's a check for IsConsole in the exception handler that gets invoked so that the MessageBox() dialog is not displayed. IsConsole is set to True when the {$APPTYPE CONSOLE} compiler directive is used. In spite of the help which states that {$APPTYPE CONSOLE} has no meaning in a library, we will try using it to suppress the MessageBox() dialog.
Ken Byington
{$APPTYPE CONSOLE} has no effect in a COM component .dll.IsConsole has a value of False.
Ken Byington
IIS Debug Diagnostics and a detailed map file make it possible to track down exactly where the exception occurs. Thanks again for the help. IIS Debug Diagnostics lists [ModuleName] + offset in the debug dump report. Just subtract $1000 and you can search the map file for the exact line of code.
Ken Byington