Re: [DUG] DLL memory leaks

2011-08-07 Thread Ross Levis
I didn't know that was possible.  I'll investigate.

Thanks.

-Original Message-
From: delphi-boun...@delphi.org.nz [mailto:delphi-boun...@delphi.org.nz] On
Behalf Of Paul Heinz
Sent: Sunday, 7 August 2011 4:24 p.m.
To: NZ Borland Developers Group - Delphi List
Subject: Re: [DUG] DLL memory leaks

Ross asked:

 My app loads 3rd party DLL's.  There is a freeware 3rd party 
 DLL I distribute which has a memory leak in a rare situation. 
  The DLL source is not available.

 Unloading the DLL doesn't free the RAM.  I guess Windows 
 doesn't keep track of RAM allocations within DLL's.  Is there 
 any ability to determine the RAM allocated by the DLL and 
 force this to be released when the DLL is unloaded?  I'm 
 guessing not but thought I would ask.

I think you're right. I'm not aware that the Win32 heap and/or memory
management tracks the module doing the allocating. Memory management is
a whole address space kind of thing and DLL's live in your address
space, essentially by definition.

However, you could track that information yourself by patching the DLL's
import table to redirect all it's memory allocation activity through
your own shim routines which track the allocations and frees and
forwards them through to the usual imported routine. Then you would have
the information to be able to release the leaked memory on unload.

You'd need to examine the DLL's import table with an appropriate tool to
see which APIs it uses to allocate memory, eithe a run-time library DLL
or direct API calls like VirtualAlloc/HeapAlloc, etc. to determine
whether this is feasible.

Cheers,
  Paul.

___
NZ Borland Developers Group - Delphi mailing list
Post: delphi@delphi.org.nz
Admin: http://delphi.org.nz/mailman/listinfo/delphi
Unsubscribe: send an email to delphi-requ...@delphi.org.nz with Subject:
unsubscribe


___
NZ Borland Developers Group - Delphi mailing list
Post: delphi@delphi.org.nz
Admin: http://delphi.org.nz/mailman/listinfo/delphi
Unsubscribe: send an email to delphi-requ...@delphi.org.nz with Subject: 
unsubscribe


Re: [DUG] DLL memory leaks

2011-08-07 Thread Paul Heinz
Ross wrote: 

 I didn't know that was possible.  I'll investigate.

PE Explorer is probably one of the best tools for this. It's also
written in Delphi I believe.
You can download a fully functional 30-day trial version.
http://www.heaventools.com/download-pe-explorer.htm

Alternatively, if you want to point me at the DLL, I can have a look at
it's import table for you.

Import Address Table (or IAT) patching is a pretty standard albeit
'low-level' technique. 

If you look for sample code around the web, it's often more involved
that it needs to be since it's often written in the context of injecting
DLLs into other processes you don't control to patch their main import
table.

Since you'll be patching the import table of a DLL you've loaded into
your own process, it's much simpler.

Here's the routine I use. It's using HInstance rather than the module
handle for a loaded DLL since I used for patching the main executable's
import table. You'll want to pass the module handle of your DLL by
calling GetModuleHandle. It returns the current IAT entry so you can
easily forward chain.

There's a whole bunch of stanard PE table record type definitions this
code depends on which I've left out.

function InstallWin32Hook(const ModuleName, FuncName: string; HookFunc:
Pointer): Pointer;
var
  NTHeader: PImageNTHeaders;
  ImportDesc: PImageImportDescriptor;
  Thunk: PImageThunkData;
begin
  Result := GetProcAddress(GetModuleHandle(PChar(ModuleName)),
PChar(FuncName));
  if Result  nil then
begin
  NTHeader := PImageNTHeaders(DWord(HInstance) +
PImageDosHeader(HInstance).e_lfanew);
  ImportDesc := PImageImportDescriptor(DWord(HInstance) +
 
NTHeader.OptionalHeader.DataDirectory[ImageDirectoryEntryImport].Virtual
Address);

  while ImportDesc.Name  0 do begin
if StriComp(PAnsiChar(DWord(HInstance) + ImportDesc.Name),
PAnsiChar(AnsiString(ModuleName))) = 0 then
  begin
Thunk := PImageThunkData(DWord(HInstance) +
DWord(ImportDesc.FirstThunk));
while Thunk.Funct  nil do begin
  if Thunk.Funct = Result then
Thunk.Funct := HookFunc;
  Inc(Thunk)
  end
end;
Inc(ImportDesc)
  end
end
end;

And here's how its used with a sample shim:

var
  OldRaiseException: procedure (dwExceptionCode, dwExceptionFlags,
nNumberOfArguments: DWord;
const lpArguments: DWord); stdcall;

OldRaiseException := InstallWin32Hook(Kernel32, 'RaiseException',
@HookRaiseException);

procedure HookRaiseException(dwExceptionCode, dwExceptionFlags,
nNumberOfArguments: DWord;
  const lpArguments: DWord); stdcall;
begin
  {
If this is a real Delphi exception and has the arguments as we
expect from
System._RaiseExcept then we can crack the argument structure and
determine
if we need to take a stack trace. Note that this may change from
version to
version of Delphi.
  }
  if (dwExceptionCode = cDelphiException) and (lpArguments  0) and
(nNumberOfArguments = 7) and
  not InHookRaise then
with PDelphiExceptionArguments(lpArguments)^ do
  try
InHookRaise := True;
if not IgnoreException(ExceptObject) then
  HookStackTrace(ExceptAddress, EBP, ESP, False);
  finally
InHookRaise := False;
  end;

  if Assigned(OldRaiseException) then
OldRaiseException(dwExceptionCode, dwExceptionFlags,
nNumberOfArguments, lpArguments);
end;

Cheers,
  Paul.

___
NZ Borland Developers Group - Delphi mailing list
Post: delphi@delphi.org.nz
Admin: http://delphi.org.nz/mailman/listinfo/delphi
Unsubscribe: send an email to delphi-requ...@delphi.org.nz with Subject: 
unsubscribe


[DUG] DLL memory leaks

2011-08-06 Thread Ross Levis
My app loads 3rd party DLL's.  There is a freeware 3rd party DLL I
distribute which has a memory leak in a rare situation.  The DLL source is
not available.

 

Unloading the DLL doesn't free the RAM.  I guess Windows doesn't keep track
of RAM allocations within DLL's.  Is there any ability to determine the RAM
allocated by the DLL and force this to be released when the DLL is unloaded?
I'm guessing not but thought I would ask.

 

Cheers,

Ross.

___
NZ Borland Developers Group - Delphi mailing list
Post: delphi@delphi.org.nz
Admin: http://delphi.org.nz/mailman/listinfo/delphi
Unsubscribe: send an email to delphi-requ...@delphi.org.nz with Subject: 
unsubscribe

Re: [DUG] DLL memory leaks

2011-08-06 Thread Paul Heinz
Ross asked:

 My app loads 3rd party DLL's.  There is a freeware 3rd party 
 DLL I distribute which has a memory leak in a rare situation. 
  The DLL source is not available.

 Unloading the DLL doesn't free the RAM.  I guess Windows 
 doesn't keep track of RAM allocations within DLL's.  Is there 
 any ability to determine the RAM allocated by the DLL and 
 force this to be released when the DLL is unloaded?  I'm 
 guessing not but thought I would ask.

I think you're right. I'm not aware that the Win32 heap and/or memory
management tracks the module doing the allocating. Memory management is
a whole address space kind of thing and DLL's live in your address
space, essentially by definition.

However, you could track that information yourself by patching the DLL's
import table to redirect all it's memory allocation activity through
your own shim routines which track the allocations and frees and
forwards them through to the usual imported routine. Then you would have
the information to be able to release the leaked memory on unload.

You'd need to examine the DLL's import table with an appropriate tool to
see which APIs it uses to allocate memory, eithe a run-time library DLL
or direct API calls like VirtualAlloc/HeapAlloc, etc. to determine
whether this is feasible.

Cheers,
  Paul.

___
NZ Borland Developers Group - Delphi mailing list
Post: delphi@delphi.org.nz
Admin: http://delphi.org.nz/mailman/listinfo/delphi
Unsubscribe: send an email to delphi-requ...@delphi.org.nz with Subject: 
unsubscribe