core/x86/mangle.c
/* returns false if failed to add sandboxing b/c of a problematic ilist --
 * invalid instrs, elided ctis, etc.
 */
returns false if failed to add sandboxing b/c of a problematic ilist
invalid instrs, elided ctis, etc.
returns false if failed to add sandboxing b / c of a problematic ilist invalid instrs elided ctis etc .
bool
insert_selfmod_sandbox(dcontext_t *dcontext, instrlist_t *ilist, uint flags,
                       app_pc start_pc, app_pc end_pc, 
                       bool record_translation, bool for_cache)
{
    instr_t *instr, *next;
    if (!INTERNAL_OPTION(cache_consistency))
        return true; 
    ASSERT((flags & FRAG_HAS_DIRECT_CTI) == 0);
    instr = instrlist_first_expanded(dcontext, ilist);
    instrlist_set_our_mangling(ilist, true); 
    if (record_translation) {
        instrlist_set_translation_target(ilist, instr_get_raw_bits(instr));
    }
    sandbox_top_of_bb(dcontext, ilist,
                      sandbox_top_of_bb_check_s2ro(dcontext, start_pc),
                      flags, start_pc, end_pc, for_cache,
                      NULL, NULL, NULL);
    if (INTERNAL_OPTION(sandbox_writes)) {
        for (; instr != NULL; instr = next) {
            int i, opcode;
            opnd_t op;
            opcode = instr_get_opcode(instr);
            if (!instr_valid(instr)) {
                if (record_translation)
                    instrlist_set_translation_target(ilist, NULL);
                instrlist_set_our_mangling(ilist, false); 
                return false;
            }
            next = instr_get_next_expanded(dcontext, ilist, instr);
            if (!instr_ok_to_mangle(instr))
                continue;
            if (instr_is_meta_may_fault(instr))
                continue;
            if (record_translation) {
                instrlist_set_translation_target(ilist, instr_get_raw_bits(instr));
            }
            if (opcode == OP_rep_ins || opcode == OP_rep_movs || opcode == OP_rep_stos) {
                sandbox_rep_instr(dcontext, ilist, instr, next, start_pc, end_pc);
                continue;
            }
            for (i=0; i<instr_num_dsts(instr); i++) {
                op = instr_get_dst(instr, i);
                if (opnd_is_memory_reference(op)) {
                    if (instr_is_call_indirect(instr)) {
                        ASSERT(next != NULL && !instr_raw_bits_valid(next));
                        ASSERT(TEST(INSTR_CALL_EXIT, instr_exit_branch_type(next)) || 
                               (DYNAMO_OPTION(IAT_convert) && 
                                TEST(INSTR_IND_CALL_DIRECT, instr->flags)));
                        LOG(THREAD, LOG_INTERP, 3, " ignoring CALL* at end of fragment\n");
                        continue;
                    }
                    sandbox_write(dcontext, ilist, instr, next, op, start_pc, end_pc);
                }
            }
        }
    }
    if (record_translation)
        instrlist_set_translation_target(ilist, NULL);
    instrlist_set_our_mangling(ilist, false); 
    return true;
}
bool insert_selfmod_sandbox ( dcontext_t * dcontext , instrlist_t * ilist , uint flags , app_pc start_pc , app_pc end_pc , bool record_translation , bool for_cache ) { instr_t * instr , * next ; if ( ! INTERNAL_OPTION ( cache_consistency ) ) return true ; ASSERT ( ( flags & FRAG_HAS_DIRECT_CTI ) == 0 ) ; instr = instrlist_first_expanded ( dcontext , ilist ) ; instrlist_set_our_mangling ( ilist , true ) ; if ( record_translation ) { instrlist_set_translation_target ( ilist , instr_get_raw_bits ( instr ) ) ; } sandbox_top_of_bb ( dcontext , ilist , sandbox_top_of_bb_check_s2ro ( dcontext , start_pc ) , flags , start_pc , end_pc , for_cache , NULL , NULL , NULL ) ; if ( INTERNAL_OPTION ( sandbox_writes ) ) { for ( ; instr != NULL ; instr = next ) { int i , opcode ; opnd_t op ; opcode = instr_get_opcode ( instr ) ; if ( ! instr_valid ( instr ) ) { if ( record_translation ) instrlist_set_translation_target ( ilist , NULL ) ; instrlist_set_our_mangling ( ilist , false ) ; return false ; } next = instr_get_next_expanded ( dcontext , ilist , instr ) ; if ( ! instr_ok_to_mangle ( instr ) ) continue ; if ( instr_is_meta_may_fault ( instr ) ) continue ; if ( record_translation ) { instrlist_set_translation_target ( ilist , instr_get_raw_bits ( instr ) ) ; } if ( opcode == OP_rep_ins || opcode == OP_rep_movs || opcode == OP_rep_stos ) { sandbox_rep_instr ( dcontext , ilist , instr , next , start_pc , end_pc ) ; continue ; } for ( i = 0 ; i < instr_num_dsts ( instr ) ; i ++ ) { op = instr_get_dst ( instr , i ) ; if ( opnd_is_memory_reference ( op ) ) { if ( instr_is_call_indirect ( instr ) ) { ASSERT ( next != NULL && ! instr_raw_bits_valid ( next ) ) ; ASSERT ( TEST ( INSTR_CALL_EXIT , instr_exit_branch_type ( next ) ) || ( DYNAMO_OPTION ( IAT_convert ) && TEST ( INSTR_IND_CALL_DIRECT , instr -> flags ) ) ) ; LOG ( THREAD , LOG_INTERP , 3 , " \n " ) ; continue ; } sandbox_write ( dcontext , ilist , instr , next , op , start_pc , end_pc ) ; } } } } if ( record_translation ) instrlist_set_translation_target ( ilist , NULL ) ; instrlist_set_our_mangling ( ilist , false ) ; return true ; }
returns false if failed to add sandboxing b/c of a problematic ilist
 invalid instrs, elided ctis, etc.
returns false if failed to add sandboxing b / c of a problematic ilist invalid instrs elided ctis etc .
/* end is open */ /* nothing to do */ /* this code assumes bb covers single, contiguous region */ /* store first instr so loop below will skip top check */ /* PR 267260 */ /* make sure inserted instrs translate to the proper original instr */ /* invalid instr -- best to truncate block here, easiest way
                 * to do that and get all flags right is to re-build it,
                 * but this time we'll use full decode so we'll avoid the discrepancy
                 * between fast and full decode on invalid instr detection.
                 */ /* PR 267260 */ /* don't mangle anything that mangle inserts! */ /* don't mangle "meta-instruction that can fault" (xref PR 472190) */ /* make sure inserted instrs translate to the proper original instr */ /* FIXME case 8165: optimize for multiple push/pop */ /* ignore CALL* since last anyways */ /* FIXME case 8165: why do we ever care about the last
                         * instruction modifying anything? 
                         */ /* conversion of IAT calls (but not elision)
                         * transforms this into a direct CALL,
                         * in that case 'next' is a direct jmp
                         * fall through, so has no exit flags
                         */ /* This test could be done outside of this loop on
                         * destinations, but since it is rare it is faster
                         * to do it here.  Using continue instead of break in case
                         * it gets moved out.
                         */ /* PR 267260 */