Solved

Application base address?

Posted on 2001-06-09
13
480 Views
Last Modified: 2010-05-18
Hi,

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?

Regards,

Bill
0
Comment
Question by:wipnav
  • 5
  • 3
  • 2
  • +2
13 Comments
 
LVL 3

Expert Comment

by:f15iaf
ID: 6171277
addr(application);
0
 
LVL 3

Expert Comment

by:f15iaf
ID: 6171338
use getcurrentprocessid and openprocess and then
try to use readprocessmemory api function
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6171368
GetModuleHandle(nil) gives you the handle of your process. You can simply convert this handle into a pointer, which is then the base address of your process.

var baseAddress : pointer;
begin
  baseAddress := pointer(GetModuleHandle(nil));

Usually for applications it's $400000.

Regards, Madshi.

P.S: Sad, that you're still using Delphi3, otherwise I would have pointed you to my exception handling package. But well, in case you're upgrading to D4/5/6 somewhen, here is the link:

http://help.madshi.net/Data/madExcept.htm
0
 
LVL 14

Expert Comment

by:AvonWyss
ID: 6171370
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.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6171374
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...
0
 
LVL 14

Expert Comment

by:AvonWyss
ID: 6171376
Instead of setting a breakpoint on the first code line, you can also start the project with F7 - it's even shorter. But the goal is the same.

Strange enough, in Delphi 2 and older compilers (r.g. BP7 etc.), one could also search for an error address when the debugger was not running.
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 5

Expert Comment

by:Gwena
ID: 6171688
Listening :-)
0
 
LVL 1

Author Comment

by:wipnav
ID: 6177721
Thank you for your comments and suggestions.

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.

Suggestion 1:

  "addr(application);"

  Im my exception handling method I placed the following code:

  var
    BaseOffset, ExceptionAddress: Integer;
  begin
    BaseOffset := Integer(Pointer(Addr(Application)));
    ExceptionAddress := Integer(ExceptAddr) - BaseOffset;

  Output:
    BaseOffset was 5756F8
    ExceptionAddress was FFFE0266

  This is not what I would except.

Suggestion 2:

  "use getcurrentprocessid and openprocess and then
  try to use readprocessmemory api function"

  Please provide a more specific code sample.

Suggestion 3:

  "GetModuleHandle(nil) gives you the handle of your process.
  You can simply convert this handle into a pointer, which is
  then the base address of your process.

  var baseAddress : pointer;
  begin
    baseAddress := pointer(GetModuleHandle(nil));"

  Im my exception handling method I placed the following code:

  var
    BaseOffset, ExceptionAddress: Integer;
  begin
    BaseOffset := Integer(Pointer(GetModuleHandle(nil)));
    ExceptionAddress := Integer(ExceptAddr) - BaseOffset;

  Output:
    BaseOffset was 400000
    ExceptionAddress was 15595E

  This is close, but I expect to get 154948.
0
 
LVL 14

Expert Comment

by:AvonWyss
ID: 6178690
For testing, you could try this (anywhere in your code):

        raise Exception.Create('Test') at nil;

and look at the exception address you get. If should obviouly be 0, if it isn't, something else is messing around in your address calculation.
0
 
LVL 20

Accepted Solution

by:
Madshi earned 200 total points
ID: 6180052
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:

function GetCodeBase(module: dword) : pointer;
const CENEWHDR = $003C; // offset of new EXE header
      CEMAGIC  = $5A4D; // old EXE magic id:  'MZ'
      CPEMAGIC = $4550; // NT portable executable
var ih : PImageNtHeaders;
begin
  result := nil;
  try
    if word(pointer(module)^) = CEMAGIC then begin
      dword(ih) := module + word(pointer(module + CENEWHDR)^);
      if ih^.signature = CPEMAGIC then
        dword(result) := module + ih^.OptionalHeader.BaseOfCode;
    end;
  except end;
end;

Give in HInstance as the module handle of the current module, or (if you are in a dll and want to know the module handle of the exe) give in "GetModuleHandle(nil)".

Regards, Madshi.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6180056
P.S: The exception address is not the beginning of the instruction where the exception was raised, it's the beginning of the next asm instruction.
0
 
LVL 1

Author Comment

by:wipnav
ID: 6182481
Madshi,

Thank you. I don't understand how it works, but it works, and that is all I need.

Regards,

Bill
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6182796
>> I don't understand how it works

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

Better Security Awareness With Threat Intelligence

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.

Join & Write a Comment

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…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…
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…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now