Skip to content

Instantly share code, notes, and snippets.

@kekyo
Last active November 13, 2018 10:52
Show Gist options
  • Save kekyo/cc9bace942b8c2aa2484431e047d267d to your computer and use it in GitHub Desktop.
Save kekyo/cc9bace942b8c2aa2484431e047d267d to your computer and use it in GitHub Desktop.
How to unwind the signal handler using the longjmp on Windows environment.
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
jmp_buf jb;
// Run in windows, this handler called from SEH filter context from "_seh_filter_exe()".
// The SEH __try - __except() block contains at "__scrt_common_main_seh(),"
// the callgraph is:
// __scrt_common_main_seh() --> __try --> main() --> [SEGV] --> __except() --> _seh_filter_exe() --> handler()
// But the "__except(...)" expression has correct only EBP register except ESP register (!!)
// Therefore the "_seh_filter_exe()" called before NO any unroll stacks,
// the "handler()" function at deeper stack than "main(),"
// We can use the longjmp() and unwinding without any stack corruption.
// (CAUTION: These descriptions doesn't contain breaking context for async race calls.)
// Just before called main (__scrt_common_main_seh() __try block)
// EAX = 0012A57C EBX = 006EE000 ECX = 005E0000 EDX = 0012A57C ESI = 0012132A EDI = 0012132A
// EIP = 00121D72 ESP = 005DFE38 EBP = 005DFE8C EFL = 00000246
// Just enter __except() expression code
// EAX = 00000000 EBX = 00000000 ECX = 00121DC3 EDX = 00000000 ESI = 00000000 EDI = 00000000
// EIP = 00121DC3 ESP = 005DF708 EBP = 005DFE8C EFL = 00000246 (ESP deeper but EBP adjusted at __try block)
void handler(int sig) {
longjmp(jb, 1);
}
int main()
{
signal(SIGSEGV, handler);
// This variable will corrupt if the handler() calls after stack unrolls by SEH __except() handling.
volatile int v = 123;
if (setjmp(jb) == 0)
{
char*p = nullptr;
char a = *p;
}
printf("%d\n", v);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment