#include "captive/ldr_exports.h" /* for struct captive_ModuleList_patchpoint */
+int _abnormal_termination_orig(void);
+extern greg_t fs_KPCR_ExceptionList;
+
/**
- * _abnormal_termination:
+ * _abnormal_termination_wrap:
+ *
+ * This call can be also accessed as AbnormalTermination() or _abnormal_termination().
+ * It is a captive wrapper around _abnormal_termination() function.
*
- * This call can be also accessed as AbnormalTermination() or abnormal_termination().
+ * Returns whether some exception occured in the current #try block we are currently
+ * #finish -ing. Any functions called from current #finish block will be considered
+ * for returning zero back again. It is forbidden to call this function outside
+ * of #finish block, result of such call is undefined.
*
- * Returns whether some exception occured (FIXME: in what scope?).
* Exception handlers are registered from W32 binary in stack frames stored in "fs:[0x00000000]"
* value which gets mapped by libcaptive/ps/signal.c to #fs_KPCR_ExceptionList
* variable.
*
- * libcaptive currently does not raise any exceptions therefore this call always returns value %0.
- * See RtlpDispatchException().
+ * If no exception handler was registered yet this function returns zero.
*
- * Returns: non-zero if some exception is now registered and pending.
+ * See also RtlpDispatchException().
+ *
+ * Returns: non-zero if some exception is now being handled as pending.
*/
-int _abnormal_termination(void)
+int _abnormal_termination_wrap(void)
{
- return 0;
+ /* No handler registered yet? ntoskrnl _abnormal_termination() does not handle it
+ * and I do not want to bother with registering toplevel handler.
+ */
+ if (fs_KPCR_ExceptionList==(greg_t)-1)
+ return 0;
+
+ return _abnormal_termination_orig();
}
{
guint8 *reg_eip;
const void *reg_eip_aligned;
+static const void *reg_eip_aligned_last_valid=NULL; /* performance cache */
g_return_if_fail(signo==SIGSEGV);
g_return_if_fail(siginfo->si_signo==SIGSEGV);
*/
reg_eip_aligned=(const void *)(((char *)reg_eip)-(GPOINTER_TO_UINT(reg_eip)&(PAGE_SIZE-1)));
g_assert(reg_eip_aligned!=NULL);
- g_return_if_fail(!(captive_mmap_map_get(reg_eip_aligned)&PROT_EXEC));
+
+ /* We do not expect any pages can get un-PROT_EXEC-ed
+ * and therefore we never invalidate our cache 'reg_eip_aligned_last_valid'.
+ */
+ if (reg_eip_aligned_last_valid!=reg_eip_aligned) {
+ g_return_if_fail(!(captive_mmap_map_get(reg_eip_aligned)&PROT_EXEC));
+ reg_eip_aligned_last_valid=reg_eip_aligned;
+ }
/* all instruction notation comments are written in AT&T 'instr src,dest' syntax! */
if (*reg_eip==0x64) { /* prefix '%fs:' */