Application base address?

I'm trying to track down some exceptions in a large Delphi 3 application. When I get an exception it gives me the memory address of the exception. In order to use my link map to find out where the problem is, I need to subtract the memory address that my program is loaded at. My question is, how do I find out the starting address that my program is currently loaded at in memory?

You were asking about the application base address, it is in fact what I already told you. However, there are more addresses, e.g. the application code base address and the application data base address.

Since Win32 uses a flat memory model, the base address usually stays the same. You can define it in the project options, linker tab. Note that apparently some code in SysUtils already does some address math on exceptions.

P.P.S: Don't you know the "Find runtime error" function? Look in your Delphi menu. It works like this:

(1) Set a breakpoint to the first line of your project file.
(2) Start your exe inside of the IDE, until it stops at the breakpoint.
(3) Use the menu item "search/find" -> "runtime error", give in the exception address (with a leading "$").

Delphi will now show you the line where the exception occured. Well, in fact, Delphi shows you the line after the exception location...

First. I am not doing this from within the IDE. The exceptions have never been seen
in testing. There are about 1000 users of this application, and the exceptions are so
rare that no one even complains about them. The only way that I know about them is
the fact that my application creates an exception log file whenever an exception is
raised.

I have a menu item that I use to raise an exception at a specific line of code.
I use this feature to test if the exception log file contains the correct relative
address of the exception.

The only solution that I have been able to get to work is to raise an exception at a
know line in my program, and subtract the relative address of that line of code
(as listed in the link map). Then I store this as my base address. When I get an
actual exception, I subtract this base address and I get the correct relative address,
which I log. This works, but I have to hardcode in the address from the link map each
time that I rebuild my application. In addition, since I only save this base address
once, when the program starts, I can't handle the situation of when my application is
moved to another location in memory (which I assume can happen).

So, I am looking for a better solution.

To test the proposed solutions:

I raised an exception at line 3607 in unit main.pas. According to the link map this
statement is at the relative address of 154948 within my application. Once I take the
exception address returned by ExceptAddr, and subtract the application base
address, I except to get 154948.

You were asking about the application base address, it is in fact what I already told you. However, there are more addresses, e.g. the application code base address and the application data base address. For your problem you need the application code base address:

In 32bit Windows each process has a flat memory/address area from $00000000 - $7FFFFFFF. Each module (exe or dll) is simply mapped to a specific address inside this whole area (via file mapping, see CreateFileMapping). The address at which the module image is loaded is used as the module handle. So by using "pointer(moduleHandle)" you get the pointer to the complete module image (= file content) in the memory area of the current process. Each 32bit module has a PE header. The function posted above takes a module handle, converts it into a pointer (which will point to a valid PE header), then uses one element of the PE header structure, which tells us at which offset the code of this PE module begins. Usually for Delphi modules this is $1000. The map file address neither contains this code offset, nor does it contain the image base address (= module handle) of the module. Thus you have to sub both from your exception address to get a relative address, which fits to your map file.

If you didn't understand any part of this text, or if something is missing for you to understand, please feel free to ask... :-)

Regards, Madshi.

0

Featured Post

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

A lot of questions regard threads in Delphi.
One of the more specific questions is how to show progress of the thread.
Updating a progressbar from inside a thread is a mistake.
A solution to this would be to send a synchronized message to the…

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech.
SAPI Installation
First you need to install the SAPI type library, th…

You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes.
Assigning simple products to configurable: We assigned simple products…