Для 64 бит тупо скопипастил.
Но недавно прослышал, что под x86-64 компилятор вежливо игнорирует все соглашения вызова. Встал вопрос: будет ли работать mov rax, [rbp + 8] ?
См.: используется при составлении сообщения об экранированной ошибке для отслеживания точки перехода между исполняемыми модулями. Ктулхуфтагн: экзешник вызывает функцию в DLL, которая вызывает функцию в экзешнике, внутри каждой функции экранируются исключения, чтобы потом поднять обратно после возврата из неё посредством AfterEfCheck. ExpExpAddress() парсит Dwarf2 блок и выдаёт имя файла и строки исходника.
- Код: Выделить всё
procedure AfterEfCheck; cdecl;
var
CallerAddr: pointer;
thread: TBackgroundThread = nil;
pes: PMotherSehState;
begin
asm
{$ifdef cpu64}
mov rax, [rbp + 8]
mov [CallerAddr], rax
{$else}
mov eax, [ebp + 4] //read the caller's EIP
mov [CallerAddr], eax
{$endif}
end;
pes:= GetExceptionState();
if pes^.IsModuleThread and Assigned(Module.ThreadManager) then begin
thread:= Module.ThreadManager.GetCurrentThread;
if not Assigned(thread) then begin
Mother^.State.StateTrashedRestartRequired:= true;
AddLog('Unable to identify the thread Id=%0 to pass exception to.'
+ #10#13' Putting the thread in an infinite loop.'#10#13' %1',
[pointer(GetCurrentThreadId()), StopDying()]);
repeat Sleep(1000) until false; //hang the thread;
end;
end;
if pes^.NowDying then
if pes^.DyingAfterTrueException
then Die(RuEn(
'Исключение коллбэк-функции модуля-матки'#10#13' принято шлюзом %0',
'The mother module callback function exception'#10#13' received at %0'),
[ExpExpAddress(CallerAddr)])
else begin
//re-raise silently
pes^.NowDying:= true;
raise exception.create('');
end;
end;