[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.
Regards,
Sven
More information about the fpc-devel
mailing list