krait_signal_handler.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. #if defined(__ANDROID__)
  2. #include <signal.h>
  3. extern int __real_sigaction(int signum, const struct sigaction *action, struct sigaction *old_action);
  4. // Workaround a bug on Krait CPUs where a signal handler would not properly transition from thumb to non-thumb.
  5. // Note: The workaround has a flaw if multiple signal handlers are used, then the last sigaction call overwrites wrapped_signal_handlers value.
  6. // Since it's only needed for ARM 32 bit, don't perform this workaround on other architectures
  7. // Note: Previously this workaround (when used for all CPU architectures) caused a test failure in unity repo:
  8. // - Tests\Unity.IntegrationTests\Android\AndroidCrashHandler.cs
  9. // Since the test was using multiple signal handlers to validate that handlers are correcty invoked when registered before and after Unity runtime initialization
  10. #if defined(__arm__)
  11. #define SIGMAX 64
  12. static void (*wrapped_signal_handlers[SIGMAX]) (int, siginfo_t *, void *);
  13. static void signal_handler(int signum, siginfo_t* siginfo, void* sigcontext)
  14. {
  15. if (wrapped_signal_handlers[signum])
  16. wrapped_signal_handlers[signum](signum, siginfo, sigcontext);
  17. }
  18. __attribute__((used)) int __wrap_sigaction(int signum, const struct sigaction *action, struct sigaction *old_action)
  19. {
  20. struct sigaction wrapper_action_data;
  21. struct sigaction* wrapper_action = NULL;
  22. if (signum >= SIGMAX)
  23. return __real_sigaction(signum, action, old_action);
  24. // patch sig action with our thumb compiled dispatcher
  25. if (action)
  26. {
  27. wrapper_action = &wrapper_action_data;
  28. memcpy(wrapper_action, action, sizeof(*action));
  29. wrapper_action->sa_sigaction = signal_handler;
  30. }
  31. // install handler (abort on error)
  32. if (__real_sigaction(signum, wrapper_action, old_action) == -1)
  33. return -1;
  34. // hide any previously installed wrapper
  35. if (old_action && old_action->sa_sigaction == signal_handler)
  36. old_action->sa_sigaction = wrapped_signal_handlers[signum];
  37. // add action to dispatch table
  38. if (action)
  39. wrapped_signal_handlers[signum] = action->sa_sigaction;
  40. return 0;
  41. }
  42. #undef SIGMAX
  43. #else
  44. __attribute__((used)) int __wrap_sigaction(int signum, const struct sigaction *action, struct sigaction *old_action)
  45. {
  46. return __real_sigaction(signum, action, old_action);
  47. }
  48. #endif
  49. #endif /* __ANDROID__ */