[fpc-devel] Manual reload of a DLL snapshot (with relocations) causes multiple AV

Sven Barth pascaldragon at googlemail.com
Fri Jan 6 19:57:32 CET 2012

On 06.01.2012 19:10, Gennadiy Poryev wrote:
>>> First, I'd like to know why calling of DLL entry point anew does not
>>> re-initialize _all_ RTL internals regardless of what was remembered
>>> prior to taking the snapshot. Is it just assuming good behavior of
>>> system loader that carefully zeroes data segment while I don't?
>> The point is: why should a DLL that is used normally take special care of this?
>> The normal lifetime of a DLL is
>> * DLL is loaded by LoadLibrary
>> * Windows calls DLL entrypoint with PROCESS_ATTACH
>> * DLL is used
>> * DLL is unloaded by FreeLibrary
>> * Windows calls DLL entrypoint with PROCESS_DETACH
> Actually PROCESS_DETACH call happens before DLL is unloaded.

I used a unclear description. I meant more like "Unloading is triggered 
by call to FreeLibrary".

> But my point is that I take snapshot of the DLL image before all this happens, actually right after the call of its entry point with PROCESS_ATTACH.
> Therefore, for a DLL it appears as if PROCESS_ATTACH is called once again, only this time with different imagebase (i.e. hInstance) and relocs adjusted accordingly. And I don't see why it should not work this way.

I think this is exactly the problem. The RTL code relies on the fact 
that the entrypoint is only called once with PROCESS_ATTACH (maybe it 
relies not explicitely on that, but implicitly) during the lifetime of a 
DLL. If PROCESS_ATTACH is called again than the DLL should have been 
loaded freshly.

>> If now the process loads that DLL again after a PROCESS_DETACH it runs the
>> complete PROCESS_ATTACH again.
> I wish it was that easy. But there is no reasonable way to take snapshot image between PROCESS_DETACH and actual freeing of the memory.

It might not be the wisest to take a snapshot at that moment. 
Theoretically it would be the best if you take a snapshot BEFORE 
PROCESS_ATTACH is called or at least before any RTL startup code is run. 
I don't know how exactly you achive that snapshot taking, but you could 
modify the DLL entrypoint of FPC (located in 
%fpcdir%\rtl\win\syswin.inc) and e.g. raise an SEH exception that you 
catch, do the snapshot and continue. I have not tested whether raising 
an SEH exception inside DLL loading will abort the loading process or 
simply call the installed exception handlers, so this is just a theory...

>> Thinking about this a bit... it might be that there is still the TLS value set to a
>> value<>  Nil. Thus the RTL will reference the old values which are no longer
>> valid. I'd suggest you to take a look at %fpcdir%/rtl/win/systhrd.inc and there
>> SysRelocateThreadVar. It's just a guess though.
> If so, how can I make sure these values are properly initialized if I call dll entry point again?

AFAIK you'll need to modify the RTL. Additionally I don't know (perhaps 
noone really does) in which locations the RTL finalizes in a way that 
does not allow reinitialization.


More information about the fpc-devel mailing list