i386-signal.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // i386-signal.h - Catch runtime signals and turn them into exceptions
  2. // on an i386 based Linux system.
  3. /* Copyright (C) 1998, 1999, 2001, 2002, 2006, 2007, 2011
  4. Free Software Foundation
  5. This file is part of libgcj.
  6. This software is copyrighted work licensed under the terms of the
  7. Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
  8. details. */
  9. #ifdef __i386__
  10. #ifndef JAVA_SIGNAL_H
  11. #define JAVA_SIGNAL_H 1
  12. #include <signal.h>
  13. #include <sys/syscall.h>
  14. #define HANDLE_SEGV 1
  15. #define HANDLE_FPE 1
  16. #define SIGNAL_HANDLER(_name) \
  17. static void _Jv_##_name (int, siginfo_t *, \
  18. void *_p __attribute__ ((__unused__)))
  19. #define HANDLE_DIVIDE_OVERFLOW \
  20. do \
  21. { \
  22. struct ucontext *_uc = (struct ucontext *)_p; \
  23. gregset_t &_gregs = _uc->uc_mcontext.gregs; \
  24. unsigned char *_eip = (unsigned char *)_gregs[REG_EIP]; \
  25. \
  26. /* According to the JVM spec, "if the dividend is the negative \
  27. * integer of largest possible magnitude for the type and the \
  28. * divisor is -1, then overflow occurs and the result is equal to \
  29. * the dividend. Despite the overflow, no exception occurs". \
  30. \
  31. * We handle this by inspecting the instruction which generated the \
  32. * signal and advancing ip to point to the following instruction. \
  33. * As the instructions are variable length it is necessary to do a \
  34. * little calculation to figure out where the following instruction \
  35. * actually is. \
  36. \
  37. */ \
  38. \
  39. /* Detect a signed division of Integer.MIN_VALUE. */ \
  40. if (_eip[0] == 0xf7) \
  41. { \
  42. bool _min_value_dividend = false; \
  43. unsigned char _modrm = _eip[1]; \
  44. \
  45. if (((_modrm >> 3) & 7) == 7) /* Signed divide */ \
  46. { \
  47. _min_value_dividend = \
  48. _gregs[REG_EAX] == (greg_t)0x80000000UL; \
  49. } \
  50. \
  51. if (_min_value_dividend) \
  52. { \
  53. unsigned char _rm = _modrm & 7; \
  54. _gregs[REG_EDX] = 0; /* the remainder is zero */ \
  55. switch (_modrm >> 6) \
  56. { \
  57. case 0: /* register indirect */ \
  58. if (_rm == 5) /* 32-bit displacement */ \
  59. _eip += 4; \
  60. if (_rm == 4) /* A SIB byte follows the ModR/M byte */ \
  61. _eip += 1; \
  62. break; \
  63. case 1: /* register indirect + 8-bit displacement */ \
  64. _eip += 1; \
  65. if (_rm == 4) /* A SIB byte follows the ModR/M byte */ \
  66. _eip += 1; \
  67. break; \
  68. case 2: /* register indirect + 32-bit displacement */ \
  69. _eip += 4; \
  70. if (_rm == 4) /* A SIB byte follows the ModR/M byte */ \
  71. _eip += 1; \
  72. break; \
  73. case 3: \
  74. break; \
  75. } \
  76. _eip += 2; \
  77. _gregs[REG_EIP] = (greg_t)_eip; \
  78. return; \
  79. } \
  80. } \
  81. } \
  82. while (0)
  83. /* We use kernel_sigaction here because we're calling the kernel
  84. directly rather than via glibc. The sigaction structure that the
  85. syscall uses is a different shape from the one in userland and not
  86. visible to us in a header file so we define it here. */
  87. extern "C"
  88. {
  89. struct kernel_sigaction
  90. {
  91. void (*k_sa_sigaction)(int,siginfo_t *,void *);
  92. unsigned long k_sa_flags;
  93. void (*k_sa_restorer) (void);
  94. sigset_t k_sa_mask;
  95. };
  96. }
  97. #define MAKE_THROW_FRAME(_exception)
  98. #define RESTORE(name, syscall) RESTORE2 (name, syscall)
  99. #define RESTORE2(name, syscall) \
  100. asm \
  101. ( \
  102. ".text\n" \
  103. ".byte 0 # Yes, this really is necessary\n" \
  104. " .align 16\n" \
  105. "__" #name ":\n" \
  106. " movl $" #syscall ", %eax\n" \
  107. " int $0x80" \
  108. );
  109. /* The return code for realtime-signals. */
  110. RESTORE (restore_rt, __NR_rt_sigreturn)
  111. void restore_rt (void) asm ("__restore_rt")
  112. __attribute__ ((visibility ("hidden")));
  113. #define INIT_SEGV \
  114. do \
  115. { \
  116. struct kernel_sigaction act; \
  117. act.k_sa_sigaction = _Jv_catch_segv; \
  118. sigemptyset (&act.k_sa_mask); \
  119. act.k_sa_flags = SA_SIGINFO|0x4000000; \
  120. act.k_sa_restorer = restore_rt; \
  121. syscall (SYS_rt_sigaction, SIGSEGV, &act, NULL, _NSIG / 8); \
  122. } \
  123. while (0)
  124. #define INIT_FPE \
  125. do \
  126. { \
  127. struct kernel_sigaction act; \
  128. act.k_sa_sigaction = _Jv_catch_fpe; \
  129. sigemptyset (&act.k_sa_mask); \
  130. act.k_sa_flags = SA_SIGINFO|0x4000000; \
  131. act.k_sa_restorer = restore_rt; \
  132. syscall (SYS_rt_sigaction, SIGFPE, &act, NULL, _NSIG / 8); \
  133. } \
  134. while (0)
  135. /* You might wonder why we use syscall(SYS_sigaction) in INIT_FPE
  136. * instead of the standard sigaction(). This is necessary because of
  137. * the shenanigans above where we increment the PC saved in the
  138. * context and then return. This trick will only work when we are
  139. * called _directly_ by the kernel, because linuxthreads wraps signal
  140. * handlers and its wrappers do not copy the sigcontext struct back
  141. * when returning from a signal handler. If we return from our divide
  142. * handler to a linuxthreads wrapper, we will lose the PC adjustment
  143. * we made and return to the faulting instruction again. Using
  144. * syscall(SYS_sigaction) causes our handler to be called directly
  145. * by the kernel, bypassing any wrappers.
  146. * Also, there may not be any unwind info in the linuxthreads
  147. * library's signal handlers and so we can't unwind through them
  148. * anyway. */
  149. #endif /* JAVA_SIGNAL_H */
  150. #else /* __i386__ */
  151. /* This is for the 64-bit subsystem on i386. */
  152. #define sigcontext_struct sigcontext
  153. #include <java-signal-aux.h>
  154. #endif /* __i386__ */