core/win32/callback.c
/* The interp.c -process_SEH_push -borland_SEH_rct processing covers 99.9% of
 * the Borland SEH rct problems I've seen.  See notes there for more general
 * explanation of the Borland SEH constructs.  However, I've seen (at least
 * in one spot in one dll) an optimization that isn't covered by watching the
 * frame pushes (you'd think with all the clever, and problematic for us,
 * optimization done, they'd do something about screwing up the rsb predictor
 * on the hot [fall through] path of try finally blocks, oh well).  In what
 * looks like part of the exception handler itself, there appears to be an
 * optimization that rather than pop then push an SEH frame, it modifies the
 * SEH frame directly on the stack (I've only seen it do the top frame, but
 * perhaps it sometimes needs to do a deeper frame in which case this would
 * make more sense).  The x: y: pattern (see interp.c) still holds so we can
 * match on that (even though isn't too much to match on) and use
 * seen_Borland_SEH to limit when we open this hole. (Note that I saw this
 * exemption in spybot, but only with the case 8123 bug, hopefully not missing
 * any other rarely hit corner cases)
 */
The interp.c -process_SEH_push -borland_SEH_rct processing covers 99.9% of
the Borland SEH rct problems I've seen.  See notes there for more general
explanation of the Borland SEH constructs.  However, I've seen (at least
in one spot in one dll) an optimization that isn't covered by watching the
frame pushes (you'd think with all the clever, and problematic for us,
optimization done, they'd do something about screwing up the rsb predictor
on the hot [fall through] path of try finally blocks, oh well).  In what
looks like part of the exception handler itself, there appears to be an
optimization that rather than pop then push an SEH frame, it modifies the
SEH frame directly on the stack (I've only seen it do the top frame, but
perhaps it sometimes needs to do a deeper frame in which case this would
make more sense).  The x: y: pattern  still holds so we can
match on that (even though isn't too much to match on) and use
seen_Borland_SEH to limit when we open this hole. (Note that I saw this
exemption in spybot, but only with the case 8123 bug, hopefully not missing
any other rarely hit corner cases)
The interp . c - process_SEH_push - borland_SEH_rct processing covers 99 . 9% of the Borland SEH rct problems I ' ve seen . See notes there for more general explanation of the Borland SEH constructs . However I ' ve seen ( at least in one spot in one dll ) an optimization that isn ' t covered by watching the frame pushes ( you ' d think with all the clever and problematic for us optimization done they ' d do something about screwing up the rsb predictor on the hot [ fall through ] path of try finally blocks oh well ) . In what looks like part of the exception handler itself there appears to be an optimization that rather than pop then push an SEH frame it modifies the SEH frame directly on the stack ( I ' ve only seen it do the top frame but perhaps it sometimes needs to do a deeper frame in which case this would make more sense ) . The x : y : pattern still holds so we can match on that ( even though isn ' t too much to match on ) and use seen_Borland_SEH to limit when we open this hole . ( Note that I saw this exemption in spybot but only with the case 8123 bug hopefully not missing any other rarely hit corner cases )
static bool
at_Borland_SEH_rct_exemption(dcontext_t *dcontext, app_pc target_pc)
{
    app_pc base, jmp_target, jmp_loc = target_pc - JMP_LONG_LENGTH;
    byte buf[JMP_LONG_LENGTH];
    if (!seen_Borland_SEH || 
        (DYNAMO_OPTION(rct_ind_jump) == OPTION_DISABLED &&
         DYNAMO_OPTION(rct_ind_call) == OPTION_DISABLED)) {
        return false;
    }
    base = get_module_base(target_pc);
    if (base != NULL && 
        rct_ind_branch_target_lookup(dcontext, jmp_loc) != NULL &&
        is_in_code_section(base, target_pc, NULL, NULL) &&
        safe_read(jmp_loc, sizeof(buf), &buf) &&
        is_jmp_rel32(buf, jmp_loc, &jmp_target) &&
        get_allocation_base(jmp_target) == base &&
        is_in_code_section(base, jmp_target, NULL, NULL)) {
        return true;
    }
    return false;
}
static bool at_Borland_SEH_rct_exemption ( dcontext_t * dcontext , app_pc target_pc ) { app_pc base , jmp_target , jmp_loc = target_pc - JMP_LONG_LENGTH ; byte buf [ JMP_LONG_LENGTH ] ; if ( ! seen_Borland_SEH || ( DYNAMO_OPTION ( rct_ind_jump ) == OPTION_DISABLED && DYNAMO_OPTION ( rct_ind_call ) == OPTION_DISABLED ) ) { return false ; } base = get_module_base ( target_pc ) ; if ( base != NULL && rct_ind_branch_target_lookup ( dcontext , jmp_loc ) != NULL && is_in_code_section ( base , target_pc , NULL , NULL ) && safe_read ( jmp_loc , sizeof ( buf ) , & buf ) && is_jmp_rel32 ( buf , jmp_loc , & jmp_target ) && get_allocation_base ( jmp_target ) == base && is_in_code_section ( base , jmp_target , NULL , NULL ) ) { return true ; } return false ; }
The interp.c -process_SEH_push -borland_SEH_rct processing covers 99.9% of
 the Borland SEH rct problems I've seen.
The interp . c - process_SEH_push - borland_SEH_rct processing covers 99 . 9% of the Borland SEH rct problems I ' ve seen .
/* See pattern in interp.c -borland_SEH_rct (try except ind branch to y).
     * If we've seen_Borland_SEH already and target_pc is in a module code
     * section and target_pc - JMP_LONG_LENGTH is on the .E/.F table already
     * and is a jmp rel32 whose target is in a code section of the same module
     * then allow.  FIXME - if we can reliably recreate the src cti could also
     * check that it is in a code section of the same module.  FIXME - if we
     * give up the seen_Borland_SEH flag restriction this could cover all try
     * except Borland SEH rct violations (if we feel the above checks are
     * strong enough standalone), however we can't cover the try finally
     * exemptions here unless we can accurately recreate the src cti to have a
     * starting point for pattern matching.  There are some impediments in our
     * system to being able to accurately get the src cti at this point, though
     * if we do that may be preferable to the process_SEH code in interp.c
     * (lazy  rather then upfront processing and less impact to non-Borland
     * apps).  Is also not clear how we could reactively cover the call to a:
     * case in the try finally construct as there is very little to match there
     * (target follows a push imm of an in module addr).  Still I've never
     * actually triggered a call to a (though I've seen it compute the address.
     * FIXME revist handling the Borland SEH execmptions reactively
     * instead of in interp.
     */ /* see above this routine is only for a certain .E/.F violation */ /* even without rct_analyze_at_load should have processed this
         * module by now (before we hit the exemption code) */ /* perf opt, we use get_allocation_base instead of get_module_base
         * since already checking if matches a known module base (base) */ /* we have a match */