/* Initializes a dcontext with the supplied state and calls dispatch */ void dynamo_start(priv_mcontext_t *mc) { priv_mcontext_t *mcontext; dcontext_t *dcontext = get_thread_private_dcontext(); ASSERT(dcontext != NULL); thread_starting(dcontext); /* Signal other threads for take over. */ dynamorio_take_over_threads(dcontext); /* Set return address */ mc->pc = canonicalize_pc_target(dcontext, mc->pc); dcontext->next_tag = mc->pc; ASSERT(dcontext->next_tag != NULL); /* transfer exec state to mcontext */ mcontext = get_mcontext(dcontext); *mcontext = *mc; /* clear pc */ mcontext->pc = 0; DOLOG(2, LOG_TOP, { byte *cur_esp; GET_STACK_PTR(cur_esp); LOG(THREAD, LOG_TOP, 2, "%s: next_tag="PFX", cur xsp="PFX", mc->xsp="PFX"\n", __FUNCTION__, dcontext->next_tag, cur_esp, mc->xsp); });
bool instr_is_cti_short_rewrite(instr_t *instr, byte *pc) { /* We assume all app's cbz/cbnz have been mangled. * See comments in x86/'s version of this routine. */ dcontext_t *dcontext; dr_isa_mode_t old_mode; if (pc == NULL) { if (instr == NULL || !instr_has_allocated_bits(instr) || instr->length != CTI_SHORT_REWRITE_LENGTH) return false; pc = instr_get_raw_bits(instr); } if (instr != NULL && instr_opcode_valid(instr)) { int opc = instr_get_opcode(instr); if (opc != OP_cbz && opc != OP_cbnz) return false; } if ((*(pc+1) != CBNZ_BYTE_A && *(pc+1) != CBZ_BYTE_A) || /* Further verify by checking for a disp of 1 */ (*pc & 0xf8) != 0x08) return false; /* XXX: this would be easier if decode_raw_is_jmp took in isa_mode */ dcontext = get_thread_private_dcontext(); if (instr != NULL) dr_set_isa_mode(dcontext, instr_get_isa_mode(instr), &old_mode); if (!decode_raw_is_jmp(dcontext, pc + CTI_SHORT_REWRITE_B_OFFS)) return false; if (instr != NULL) dr_set_isa_mode(dcontext, old_mode, NULL); return true; }
static void nudge_terminate_on_dstack(dcontext_t *dcontext) { ASSERT(dcontext == get_thread_private_dcontext()); if (dcontext->nudge_terminate_process) { os_terminate_with_code(dcontext, TERMINATE_PROCESS|TERMINATE_CLEANUP, dcontext->nudge_exit_code); } else os_terminate(dcontext, TERMINATE_THREAD|TERMINATE_CLEANUP); ASSERT_NOT_REACHED(); }
bool redirect_heap_call(HANDLE heap) { ASSERT(!dynamo_initialized || dynamo_exited || standalone_library || get_thread_private_dcontext() == NULL /*thread exiting*/ || !os_using_app_state(get_thread_private_dcontext())); #ifdef CLIENT_INTERFACE if (!INTERNAL_OPTION(privlib_privheap)) return false; #endif /* either default heap, or one whose creation we intercepted */ return ( #ifdef CLIENT_INTERFACE /* check both current and private: should be same, but * handle case where didn't swap */ heap == get_private_peb()->ProcessHeap || #endif heap == get_peb(NT_CURRENT_PROCESS)->ProcessHeap || is_dynamo_address((byte*)heap)); }
static void annotation_unmanage_code_area(void *start, size_t size) { dcontext_t *dcontext = get_thread_private_dcontext(); if (!is_jit_managed_area(start)) return; LOG(GLOBAL, LOG_ANNOTATIONS, 2, "Remove code area "PFX"-"PFX" from JIT managed regions\n", start, (app_pc) start + size); mutex_lock(&thread_initexit_lock); flush_fragments_and_remove_region(dcontext, start, size, true/*own initexit_lock*/, false/*keep futures*/); mutex_unlock(&thread_initexit_lock); jitopt_clear_span(start, (app_pc) start + size); }
/* Initializes a dcontext with the supplied state and calls dispatch */ void dynamo_start(priv_mcontext_t *mc) { priv_mcontext_t *mcontext; dcontext_t *dcontext = get_thread_private_dcontext(); ASSERT(dcontext != NULL); thread_starting(dcontext); /* Signal other threads for take over. */ dynamorio_take_over_threads(dcontext); /* Set return address */ dcontext->next_tag = mc->pc; ASSERT(dcontext->next_tag != NULL); /* transfer exec state to mcontext */ mcontext = get_mcontext(dcontext); *mcontext = *mc; /* clear pc */ mcontext->pc = 0; /* Swap stacks so dispatch is invoked outside the application. * We begin interpretation at the application return point, * and thus we need to look like DR returned -- adjust the app * stack to account for the return address. */ mcontext->xsp += XSP_SZ; call_switch_stack(dcontext, dcontext->dstack, dispatch, false/*not on initstack*/, true/*return on error*/); /* In release builds, this will simply return and continue native * execution. That's better than calling unexpected_return() which * goes into an infinite loop. */ ASSERT_NOT_REACHED(); }
/* This is the actual nudge handler * Notes: This function returns a boolean mainly to fix case 5130; it is not * really necessary. */ bool generic_nudge_handler(nudge_arg_t *arg_dont_use) { dcontext_t *dcontext = get_thread_private_dcontext(); nudge_arg_t safe_arg = {0}; uint nudge_action_mask = 0; #ifdef WINDOWS /* this routine is run natively via leave_call_native() so there's no * cxt switch that swapped for us */ if (dcontext != NULL) swap_peb_pointer(dcontext, true/*to priv*/); #endif /* To be extra safe we use safe_read() to access the nudge argument, though once * we get past the checks below we are trusting its content. */ ASSERT(arg_dont_use != NULL && "invalid nudge argument"); if (!safe_read(arg_dont_use, sizeof(nudge_arg_t), &safe_arg)) { ASSERT(false && "invalid nudge argument"); goto nudge_finished; } nudge_action_mask = safe_arg.nudge_action_mask; /* if needed tell thread exit to free the application stack */ if (!TEST(NUDGE_NUDGER_FREE_STACK, safe_arg.flags)) { dcontext->free_app_stack = true; } else { ASSERT_NOT_TESTED(); } /* FIXME - would be nice to inform nudge creator if we need to nop the nudge. */ /* Fix for case 5702. If a nudge thread comes in during process exit, * don't process it, i.e., nop it. FIXME - this leaks the app stack and nudge arg * if the nudge was supposed to free them. */ if (dynamo_exited) goto nudge_finished; /* Node manager will not be able to nudge before reading the drmarker and * the dr_marker isn't available before callback_interception_init(). * Since after callback_interception_init() new threads won't be allowed * to progress till dynamo_initialized is set, by the time a nudge thread * reaches here dynamo_initialized should be set. */ ASSERT(dynamo_initialized); if (!dynamo_initialized) goto nudge_finished; /* We should always have a dcontext. */ ASSERT(dcontext != NULL); if (dcontext == NULL) goto nudge_finished; ENTERING_DR(); /* Xref case 552, the nudge_target value provides a reasonable measure * of security against an attacker leveraging this routine. */ if (dcontext->nudge_target != (void *)generic_nudge_target) { /* FIXME - should we report this likely attempt to attack us? need * a unit test for this (though will then have to tone this down). */ ASSERT(false && "unauthorized thread tried to nudge"); /* If we really are under attack we should terminate immediately and * proceed no further. Note we are leaking the app stack and nudge arg if we * were supposed to free them. */ os_terminate(dcontext, TERMINATE_THREAD); ASSERT_NOT_REACHED(); } /* Free the arg if requested. */ if (TEST(NUDGE_FREE_ARG, safe_arg.flags)) { ASSERT_NOT_TESTED(); nt_free_virtual_memory(arg_dont_use); } handle_nudge(dcontext, &safe_arg); nudge_finished: return nudge_thread_cleanup(dcontext, false/*just thread*/, 0/*unused*/); }