core/win32/callback.c
/* common routine separate since used for let go and alternate let go */
common routine separate since used for let go and alternate let go
common routine separate since used for let go and alternate let go
static void
insert_let_go_cleanup(dcontext_t *dcontext, instrlist_t *ilist, instr_t *decision,
                      bool assume_xsp, bool assume_not_on_dstack,
                      after_intercept_action_t action_after)
{
    instr_t *first = NULL;
    if (action_after == AFTER_INTERCEPT_DYNAMIC_DECISION) {
        first = instrlist_last(ilist);
    }
    if (EXIT_DR_HOOK != NULL) {
        dr_insert_call((void *)dcontext, ilist, NULL, (void *)EXIT_DR_HOOK, 0);
    }
    APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_XAX)));
    preinsert_set_last_error(dcontext, ilist, NULL, REG_EAX);
    APP(ilist, INSTR_CREATE_mov_ld(dcontext, opnd_create_reg(REG_XAX),
                                   OPND_CREATE_MEMPTR(REG_XSP,
                                                      offsetof(dr_mcontext_t, xsp))));
    APP(ilist, INSTR_CREATE_mov_st(dcontext,
                                   OPND_CREATE_MEMPTR(REG_XSP,
                                                      sizeof(dr_mcontext_t)+XSP_SZ),
                                   opnd_create_reg(REG_XAX)));
    insert_pop_all_registers(dcontext, ilist, NULL, false);
    APP(ilist, INSTR_CREATE_RAW_popf(dcontext));
    APP(ilist, INSTR_CREATE_lea(dcontext, opnd_create_reg(REG_XSP), 
                                opnd_create_base_disp(REG_XSP, REG_NULL, 0,
                                                      XSP_SZ, OPSZ_lea)));
    if (action_after == AFTER_INTERCEPT_DYNAMIC_DECISION) {
        ASSERT(first != NULL);
        instr_set_target(decision, opnd_create_instr(instr_get_next(first)));
    }
    if (!assume_xsp) {
        instr_t *restore_initstack = INSTR_CREATE_label(dcontext);
        instr_t *done_restoring = INSTR_CREATE_label(dcontext);
        APP(ilist,
            INSTR_CREATE_mov_st(dcontext,
                                opnd_create_far_base_disp(SEG_TLS, REG_NULL, REG_NULL,
                                                          0, PID_TIB_OFFSET, OPSZ_PTR),
                                opnd_create_reg(REG_XCX)));
        APP(ilist,
            INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_XCX)));
        APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_XSP)));
        APP(ilist, INSTR_CREATE_jecxz(dcontext, opnd_create_instr(restore_initstack)));
        APP(ilist,
            INSTR_CREATE_jmp(dcontext, opnd_create_instr(done_restoring)));
        APP(ilist, restore_initstack);
#ifdef X64
        APP(ilist,
            INSTR_CREATE_mov_imm(dcontext, opnd_create_reg(REG_XCX),
                                 OPND_CREATE_INTPTR((ptr_uint_t)&initstack_mutex)));
#endif
        APP(ilist,
            INSTR_CREATE_mov_st(dcontext,
                                IF_X64_ELSE(OPND_CREATE_MEM32(REG_XCX, 0),
                                            OPND_CREATE_ABSMEM((void *)&initstack_mutex,
                                                               OPSZ_4)),
                                OPND_CREATE_INT32(0)));
        APP(ilist, done_restoring);
#ifdef X64
        APP(ilist,
            INSTR_CREATE_mov_imm(dcontext,
                                 opnd_create_reg(REG_XCX),
                                 OPND_CREATE_INTPTR((ptr_uint_t)win32_pid)));
        APP(ilist,
            INSTR_CREATE_xchg(dcontext,
                              opnd_create_far_base_disp(SEG_TLS, REG_NULL, REG_NULL,
                                                        0, PID_TIB_OFFSET, OPSZ_PTR),
                              opnd_create_reg(REG_XCX)));
#else
        APP(ilist,
            INSTR_CREATE_mov_ld(dcontext,
                                opnd_create_reg(REG_XCX),
                                opnd_create_far_base_disp(SEG_TLS, REG_NULL, REG_NULL,
                                                          0, PID_TIB_OFFSET, OPSZ_PTR)));
        APP(ilist,
            INSTR_CREATE_mov_st(dcontext,
                                opnd_create_far_base_disp(SEG_TLS, REG_NULL, REG_NULL,
                                                          0, PID_TIB_OFFSET, OPSZ_PTR),
                                OPND_CREATE_INTPTR(win32_pid)));
#endif
    } else {
        APP(ilist, INSTR_CREATE_lea(dcontext, opnd_create_reg(REG_XSP), 
                                    opnd_create_base_disp(REG_XSP, REG_NULL, 0,
                                                          XSP_SZ, OPSZ_0)));
        APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_XSP)));
    }
}
static void insert_let_go_cleanup ( dcontext_t * dcontext , instrlist_t * ilist , instr_t * decision , bool assume_xsp , bool assume_not_on_dstack , after_intercept_action_t action_after ) { instr_t * first = NULL ; if ( action_after == AFTER_INTERCEPT_DYNAMIC_DECISION ) { first = instrlist_last ( ilist ) ; } if ( EXIT_DR_HOOK != NULL ) { dr_insert_call ( ( void * ) dcontext , ilist , NULL , ( void * ) EXIT_DR_HOOK , 0 ) ; } APP ( ilist , INSTR_CREATE_pop ( dcontext , opnd_create_reg ( REG_XAX ) ) ) ; preinsert_set_last_error ( dcontext , ilist , NULL , REG_EAX ) ; APP ( ilist , INSTR_CREATE_mov_ld ( dcontext , opnd_create_reg ( REG_XAX ) , OPND_CREATE_MEMPTR ( REG_XSP , offsetof ( dr_mcontext_t , xsp ) ) ) ) ; APP ( ilist , INSTR_CREATE_mov_st ( dcontext , OPND_CREATE_MEMPTR ( REG_XSP , sizeof ( dr_mcontext_t ) + XSP_SZ ) , opnd_create_reg ( REG_XAX ) ) ) ; insert_pop_all_registers ( dcontext , ilist , NULL , false ) ; APP ( ilist , INSTR_CREATE_RAW_popf ( dcontext ) ) ; APP ( ilist , INSTR_CREATE_lea ( dcontext , opnd_create_reg ( REG_XSP ) , opnd_create_base_disp ( REG_XSP , REG_NULL , 0 , XSP_SZ , OPSZ_lea ) ) ) ; if ( action_after == AFTER_INTERCEPT_DYNAMIC_DECISION ) { ASSERT ( first != NULL ) ; instr_set_target ( decision , opnd_create_instr ( instr_get_next ( first ) ) ) ; } if ( ! assume_xsp ) { instr_t * restore_initstack = INSTR_CREATE_label ( dcontext ) ; instr_t * done_restoring = INSTR_CREATE_label ( dcontext ) ; APP ( ilist , INSTR_CREATE_mov_st ( dcontext , opnd_create_far_base_disp ( SEG_TLS , REG_NULL , REG_NULL , 0 , PID_TIB_OFFSET , OPSZ_PTR ) , opnd_create_reg ( REG_XCX ) ) ) ; APP ( ilist , INSTR_CREATE_pop ( dcontext , opnd_create_reg ( REG_XCX ) ) ) ; APP ( ilist , INSTR_CREATE_pop ( dcontext , opnd_create_reg ( REG_XSP ) ) ) ; APP ( ilist , INSTR_CREATE_jecxz ( dcontext , opnd_create_instr ( restore_initstack ) ) ) ; APP ( ilist , INSTR_CREATE_jmp ( dcontext , opnd_create_instr ( done_restoring ) ) ) ; APP ( ilist , restore_initstack ) ; #ifdef X64 APP ( ilist , INSTR_CREATE_mov_imm ( dcontext , opnd_create_reg ( REG_XCX ) , OPND_CREATE_INTPTR ( ( ptr_uint_t ) & initstack_mutex ) ) ) ; #endif APP ( ilist , INSTR_CREATE_mov_st ( dcontext , IF_X64_ELSE ( OPND_CREATE_MEM32 ( REG_XCX , 0 ) , OPND_CREATE_ABSMEM ( ( void * ) & initstack_mutex , OPSZ_4 ) ) , OPND_CREATE_INT32 ( 0 ) ) ) ; APP ( ilist , done_restoring ) ; #ifdef X64 APP ( ilist , INSTR_CREATE_mov_imm ( dcontext , opnd_create_reg ( REG_XCX ) , OPND_CREATE_INTPTR ( ( ptr_uint_t ) win32_pid ) ) ) ; APP ( ilist , INSTR_CREATE_xchg ( dcontext , opnd_create_far_base_disp ( SEG_TLS , REG_NULL , REG_NULL , 0 , PID_TIB_OFFSET , OPSZ_PTR ) , opnd_create_reg ( REG_XCX ) ) ) ; #else APP ( ilist , INSTR_CREATE_mov_ld ( dcontext , opnd_create_reg ( REG_XCX ) , opnd_create_far_base_disp ( SEG_TLS , REG_NULL , REG_NULL , 0 , PID_TIB_OFFSET , OPSZ_PTR ) ) ) ; APP ( ilist , INSTR_CREATE_mov_st ( dcontext , opnd_create_far_base_disp ( SEG_TLS , REG_NULL , REG_NULL , 0 , PID_TIB_OFFSET , OPSZ_PTR ) , OPND_CREATE_INTPTR ( win32_pid ) ) ) ; #endif } else { APP ( ilist , INSTR_CREATE_lea ( dcontext , opnd_create_reg ( REG_XSP ) , opnd_create_base_disp ( REG_XSP , REG_NULL , 0 , XSP_SZ , OPSZ_0 ) ) ) ; APP ( ilist , INSTR_CREATE_pop ( dcontext , opnd_create_reg ( REG_XSP ) ) ) ; } }
common routine separate since used for let go and alternate let go
common routine separate since used for let go and alternate let go
/* placeholder so can find 1st of this path */ /* make sure to use dr_insert_call() rather than a raw OP_call instr,
         * since x64 windows requires 32 bytes of stack space even w/ no args.
         */ /*append*/ /* must preserve the LastErrorCode (if call a Win32 API routine could
     * overwrite the app's error code) */ /* saved error code is currently on the top of the stack */ /* for x64, errno is still 32 bits */ /* the 4 bytes of x64 app_state_at_intercept_t padding are
     * handled by the 8-byte pop of eax */ /* Get the app xsp passed to the handler from the popa location and store
     * it in the app xsp cache; this is because the handler could have changed
     * the app xsp that was passed to it.  CAUTION: do this before the popa.
     */ /* now restore everything */ /*see push_all use*/ /* now that instrs are there, take 1st */ /* popa doesn't restore xsp; the handler might have changed it, so 
         * restore it from the app xsp cache, which is now the top of stack.
         */ /* use initstack to avoid any assumptions about app xsp */ /* we could perhaps assume the top 32 bits of win32_pid are zero, but
         * xchg works just as well */ /* popa doesn't restore xsp; the handler might have changed it, so 
         * restore it from the app xsp cache, which is now the top of stack.
         */