I have looked into this again in a little more detail. What I think is happening is the following:
in delphi an exception is raised.
Delphi.Sytstem._RaiseExcept RaiseException RtlRaiseException RtlDispatchException RtlpExecuteHandlerForExecption Delphi.System._ExceptionHandler UnhandledExceptionFilter
EXCEPTION_DISPOSITION __cdecl Delphi.System.ExceptionHandler( struct _EXCEPTION_RECORD *ExceptionRecord, void * EstablisherFrame, struct _CONTEXT *ContextRecord, void * DispatcherContext );
Source code can be found here (search for _RaiseExcept, _ExceptionHandler): http://www.getunderstand.com/documents/sample_reports/udelphi_example_report...
what you can see in the code for _ExceptionHandler is 10680 LEA EAX,[ESP+4] 10681 PUSH EAX 10682 CALL UnhandledExceptionFilter
This is an unmodified esp, so esp points to the return address and esp+4 points to the function parameters so it's effectively doing something like
|EXCEPTION_POINTER ExceptionPointers; ||||ExceptionPointers||||.||ExceptionRecord| = ExceptionRecord;| ExceptionPointers||||.||||ContextRecord| = EstablisherFrame; UnhandledExceptionFilter(&|ExceptionPointers|);
It is done that way in multiple locations (line 9641, 9666 (push / esp+8), 10028, 10064, ...) so It's obviously done intentionally.