void recover_from_breakpoint (LPDBGPROCESS process, LPDBGTHREAD thread, BOOL resume) { CONTEXT context; LPDEBUG_POINT breakpoint; BOOL status; context.ContextFlags = CONTEXT_CONTROL; status = get_thread_context(process, thread, &context); thread->NeedsBreakpointReplacement = FALSE; breakpoint = thread->BreakpointToReplace; drop_breakpoint(process, breakpoint); // In order to recover from the breakpoint, we will have put the // processor into single-step mode. We now need to take it // out of single-step mode UNLESS the thread was being // single-stepped anyway! if (!(thread->SingleStepping)) { context.EFlags = context.EFlags & 0xFFFFFEFF; /* dylan_debugger_message("Resuming all threads for breakpoint recovery %=", thread->ThreadHandle, 0); if (resume) resume_all_except(process, thread); */ } status = SetThreadContext(thread->ThreadHandle, &context); }
void bedrock::event_move(core_window_t* wd, int x, int y) { if (wd) { arg_move arg; arg.window_handle = reinterpret_cast<window>(wd); arg.x = x; arg.y = y; if (emit(event_code::move, wd, arg, false, get_thread_context())) wd_manager.update(wd, false, true); } }
bool bedrock::event_msleave(core_window_t* hovered) { if (wd_manager.available(hovered) && hovered->flags.enabled) { hovered->flags.action = mouse_action::normal; arg_mouse arg; arg.evt_code = event_code::mouse_leave; arg.window_handle = reinterpret_cast<window>(hovered); arg.pos.x = arg.pos.y = 0; arg.left_button = arg.right_button = arg.mid_button = false; arg.ctrl = arg.shift = false; emit(event_code::mouse_leave, hovered, arg, true, get_thread_context()); return true; } return false; }
static ptr eval(ptr x) { if (Spairp(x)) { switch (Schar_value(Scar(x))) { case '+': return S_add(First(x), Second(x)); case '-': return S_sub(First(x), Second(x)); case '*': return S_mul(First(x), Second(x)); case '/': return S_div(First(x), Second(x)); case 'q': return S_trunc(First(x), Second(x)); case 'r': return S_rem(First(x), Second(x)); case 'g': return S_gcd(First(x), Second(x)); case '=': { ptr x1 = First(x), x2 = Second(x); if (Sfixnump(x1) && Sfixnump(x2)) return Sboolean(x1 == x2); else if (Sbignump(x1) && Sbignump(x2)) return Sboolean(S_big_eq(x1, x2)); else return Sfalse; } case '<': { ptr x1 = First(x), x2 = Second(x); if (Sfixnump(x1)) if (Sfixnump(x2)) return Sboolean(x1 < x2); else return Sboolean(!BIGSIGN(x2)); else if (Sfixnump(x2)) return Sboolean(BIGSIGN(x1)); else return Sboolean(S_big_lt(x1, x2)); } case 'f': return Sflonum(S_floatify(First(x))); case 'c': S_gc(get_thread_context(), UNFIX(First(x)),UNFIX(Second(x))); return Svoid; case 'd': return S_decode_float(Sflonum_value(First(x))); default: S_prin1(x); putchar('\n'); printf("unrecognized operator, returning zero\n"); return FIX(0); } } else return x; }
void get_debug_event() { PCONTEXT ctx; debug_event = DEBUG_EVENT(); ctn_status = DBG_CONTINUE; if (WaitForDebugEvent(&debug_event, INFINITE)) { h_thread = open_thread(debug_event.dwThreadId); ctx = get_thread_context(h_thread, NULL); std::cout << "[E] Event Code : " << debug_event.dwDebugEventCode << " Thread ID : " << debug_event.dwThreadId << std::endl; if (debug_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) { exception = debug_event.u.Exception.ExceptionRecord.ExceptionCode; exception_address = debug_event.u.Exception.ExceptionRecord.ExceptionAddress; switch (exception) { case EXCEPTION_ACCESS_VIOLATION: std::cout << "[EXCEPTION] ACCESS VIOLATION." << std::endl; break; case EXCEPTION_BREAKPOINT: ctn_status = exception_handler_breakpoint(); break; case EXCEPTION_GUARD_PAGE: std::cout << "[EXCEPTION] Guard Page Access Detected." << std::endl; break; case EXCEPTION_SINGLE_STEP: std::cout << "[EXCEPTION] Single Stepping." << std::endl; break; default: break; } ContinueDebugEvent(debug_event.dwProcessId, debug_event.dwThreadId, ctn_status); } } ContinueDebugEvent(debug_event.dwProcessId, debug_event.dwThreadId, ctn_status); }
void bedrock::update_cursor(core_window_t * wd) { internal_scope_guard isg; if (wd_manager.available(wd)) { auto * thrd = get_thread_context(wd->thread_id); if (nullptr == thrd) return; auto pos = native_interface::cursor_position(); auto native_handle = native_interface::find_window(pos.x, pos.y); if (!native_handle) return; native_interface::calc_window_point(native_handle, pos); if (wd != wd_manager.find_window(native_handle, pos.x, pos.y)) return; set_cursor(wd, wd->predef_cursor, thrd); } }
void bedrock::event_expose(core_window_t * wd, bool exposed) { if (nullptr == wd) return; wd->visible = exposed; arg_expose arg; arg.exposed = exposed; arg.window_handle = reinterpret_cast<window>(wd); if (emit(event_code::expose, wd, arg, false, get_thread_context())) { const core_window_t * caret_wd = (wd->together.caret ? wd : wd->child_caret()); if (caret_wd) { if (exposed) { if (wd->root_widget->other.attribute.root->focus == caret_wd) caret_wd->together.caret->visible(true); } else caret_wd->together.caret->visible(false); } if (!exposed) { if (category::flags::root != wd->other.category) { //find an ancestor until it is not a lite_widget wd = wd->seek_non_lite_widget_ancestor(); } else if (category::flags::frame == wd->other.category) wd = wd_manager.find_window(wd->root, wd->pos_root.x, wd->pos_root.y); } wd_manager.refresh_tree(wd); wd_manager.map(wd, false); } }
static void main_init() { ptr tc = get_thread_context(); ptr p; INT i; /* force thread inline allocation to go through find_room until ready */ AP(tc) = (ptr)0; EAP(tc) = (ptr)0; REAL_EAP(tc) = (ptr)0; /* set up dummy CP so locking in read/write/Scall won't choke */ CP(tc) = Svoid; CODERANGESTOFLUSH(tc) = Snil; if (S_boot_time) S_G.protect_next = 0; S_segment_init(); S_alloc_init(); S_thread_init(); S_intern_init(); S_gc_init(); S_number_init(); S_schsig_init(); S_new_io_init(); S_print_init(); S_stats_init(); S_foreign_init(); S_prim_init(); S_prim5_init(); S_fasl_init(); S_machine_init(); S_flushcache_init(); /* must come after S_machine_init(); */ #ifdef FEATURE_EXPEDITOR S_expeditor_init(); #endif /* FEATURE_EXPEDITOR */ if (!S_boot_time) return; FXLENGTHBV(tc) = p = S_bytevector(256); for (i = 0; i < 256; i += 1) { BVIT(p, i) = (iptr)FIX(i & 0x80 ? 8 : i & 0x40 ? 7 : i & 0x20 ? 6 : i & 0x10 ? 5 : i & 0x08 ? 4 : i & 0x04 ? 3 : i & 0x02 ? 2 : i & 0x01 ? 1 : 0); } FXFIRSTBITSETBV(tc) = p = S_bytevector(256); for (i = 0; i < 256; i += 1) { BVIT(p, i) = (iptr)FIX(i & 0x01 ? 0 : i & 0x02 ? 1 : i & 0x04 ? 2 : i & 0x08 ? 3 : i & 0x10 ? 4 : i & 0x20 ? 5 : i & 0x40 ? 6 : i & 0x80 ? 7 : 0); } NULLIMMUTABLEVECTOR(tc) = S_null_immutable_vector(); NULLIMMUTABLEFXVECTOR(tc) = S_null_immutable_fxvector(); NULLIMMUTABLEBYTEVECTOR(tc) = S_null_immutable_bytevector(); NULLIMMUTABLESTRING(tc) = S_null_immutable_string(); PARAMETERS(tc) = S_G.null_vector; for (i = 0 ; i < virtual_register_count ; i += 1) { VIRTREG(tc, i) = FIX(0); } p = S_code(tc, type_code, size_rp_header); CODERELOC(p) = S_relocation_table(0); CODENAME(p) = Sfalse; CODEARITYMASK(p) = FIX(0); CODEFREE(p) = 0; CODEINFO(p) = Sfalse; CODEPINFOS(p) = Snil; RPHEADERFRAMESIZE(&CODEIT(p, 0)) = 0; RPHEADERLIVEMASK(&CODEIT(p, 0)) = 0; RPHEADERTOPLINK(&CODEIT(p, 0)) = (uptr)&RPHEADERTOPLINK(&CODEIT(p, 0)) - (uptr)p; S_protect(&S_G.dummy_code_object); S_G.dummy_code_object = p; S_protect(&S_G.error_invoke_code_object); S_G.error_invoke_code_object = Snil; S_protect(&S_G.invoke_code_object); S_G.invoke_code_object = Snil; S_protect(&S_G.active_threads_id); S_G.active_threads_id = S_intern((const unsigned char *)"$active-threads"); S_set_symbol_value(S_G.active_threads_id, FIX(0)); S_protect(&S_G.heap_reserve_ratio_id); S_G.heap_reserve_ratio_id = S_intern((const unsigned char *)"$heap-reserve-ratio"); SETSYMVAL(S_G.heap_reserve_ratio_id, Sflonum(default_heap_reserve_ratio)); S_protect(&S_G.scheme_version_id); S_G.scheme_version_id = S_intern((const unsigned char *)"$scheme-version"); S_protect(&S_G.make_load_binary_id); S_G.make_load_binary_id = S_intern((const unsigned char *)"$make-load-binary"); S_protect(&S_G.load_binary); S_G.load_binary = Sfalse; }
TARGET_ADDRESS nub_allocate_stack_space (NUB nub, NUBTHREAD nubthread, NUBINT byte_count) { LPDBGPROCESS process = (LPDBGPROCESS) nub; LPDBGTHREAD thread = (LPDBGTHREAD) nubthread; NUBINT code; DWORD count = (DWORD) byte_count; CONTEXT context; CONTEXT context_as_was; BOOL status_get_context, status_set_context, status_write, status_read; ALLOCATOR_INSTRUCTION_SEQUENCE instruction_sequence; ALLOCATOR_INSTRUCTION_SEQUENCE saved_stack_memory; DWORD SP; DWORD IP; DWORD instruction_position; DWORD bytes_written, bytes_read; DWORD expected_bp_address; BOOL spy_has_returned = FALSE; int second_chance_counter = 0; // Get the context for the thread. context.ContextFlags = CONTEXT_FULL; status_get_context = get_thread_context(process, thread, &context); dylan_debugger_message("nub_allocate_stack_space: Thread Context before: %= : %=", thread->ThreadHandle, status_get_context); dylan_debugger_message("Esp: %= Eip: %=", context.Esp, context.Eip); context_as_was = context; if (thread->NeedsBreakpointReplacement) context.EFlags = context.EFlags & 0xFFFFFEFF; // Fill in the instruction sequence SUB ESP, <count>; INT 3 instruction_sequence.Nop1 = 0x90; instruction_sequence.Nop2 = 0x90; instruction_sequence.SubInstruction = 0x81; instruction_sequence.SpecifyEsp = 0xEC; instruction_sequence.Immediate32 = count; instruction_sequence.BreakInstruction = 0xCC; SP = context.Esp; IP = context.Eip; // Write the instruction sequence onto the stack. The number of words we // are writing is small enough that this should work on both NT and // 95. //context.Esp -= sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE); instruction_position = context.Esp; context.Eip = instruction_position; // Save the data that was there originally. As a precaution, we will // re-write this back again if we have to abort the whole procedure. status_read = ReadProcessMemory (process->ProcessHandle, (LPCVOID) instruction_position, (LPVOID) &saved_stack_memory, sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE), &bytes_read); // Out with the old, in with the new... status_write = ValidatedWriteProcessMemory (process->ProcessHandle, (LPVOID) instruction_position, (LPVOID) &instruction_sequence, sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE), &bytes_written); // Flush the instruction cache because we have written a segment of // code. FlushInstructionCache(process->ProcessHandle, (LPCVOID) instruction_position, sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE)); // Set the context of the thread so that it will execute the SUB instruction // and then return control to the debugger. status_set_context = SetThreadContext(thread->ThreadHandle, &context); if (!status_set_context) { status_write = ValidatedWriteProcessMemory (process->ProcessHandle, (LPVOID) instruction_position, (LPVOID) &saved_stack_memory, sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE), &bytes_written); SetThreadContext(thread->ThreadHandle, &context_as_was); // Just in case return(NULL); } // Remember the address at which we expect the breakpoint. expected_bp_address = instruction_position + 8; // Let the thread execute the fragment of code. Hopefully, that will give // us space on the stack that Windows 95 won't crap all over. suspend_all(process); process->ThreadRunningSpy = thread; thread->AddressOfSpyBreakpoint = expected_bp_address; // Explicitly continue all threads to release frozen threads; // they are all suspended at this point so won't be put back // into execution nub_threads_continue(nub); // Now do what it takes to put this Spy running Thread alone into execution execute_thread(thread); wait_for_stop_reason_internal (process, TRUE, 30000, &code, STOP_REASON_WAIT_SPY); if (code == SPY_RETURN_DBG_EVENT) { // Resume the suspended threads. resume_all_except(process, thread); // Write back the stack data that we crapped all over. status_write = ValidatedWriteProcessMemory (process->ProcessHandle, (LPVOID) instruction_position, (LPVOID) &saved_stack_memory, sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE), &bytes_written); // Get the context again. This should have ESP correctly set. status_get_context = GetThreadContext(thread->ThreadHandle, &context); dylan_debugger_message("nub_allocate_stack_space: Thread Context after: %= : %=", thread->ThreadHandle, status_get_context); dylan_debugger_message("Esp: %= Eip: %=", context.Esp, context.Eip); return((TARGET_ADDRESS) (context.Esp)); } else { resume_all_except(process, thread); status_write = ValidatedWriteProcessMemory (process->ProcessHandle, (LPVOID) instruction_position, (LPVOID) &saved_stack_memory, sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE), &bytes_written); SetThreadContext(thread->ThreadHandle, &context_as_was); nub_debug_message("Error: Micro Spy call failed on Thread %=, code: %=", (TARGET_ADDRESS)thread->ThreadHandle, (TARGET_ADDRESS)code); return (NULL); } // Resume the suspended threads. resume_all_except(process, thread); // Write back the stack data that we crapped all over. status_write = ValidatedWriteProcessMemory (process->ProcessHandle, (LPVOID) instruction_position, (LPVOID) &saved_stack_memory, sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE), &bytes_written); // Get the context again. This should have ESP correctly set. status_get_context = GetThreadContext(thread->ThreadHandle, &context); return((TARGET_ADDRESS) (context.Esp)); }
TARGET_ADDRESS nub_setup_function_call (NUB nub, NUBTHREAD thread, TARGET_ADDRESS function, NUBINT arg_count, TARGET_ADDRESS *args, NUBHANDLE *context_cookie) { LPDBGPROCESS process = (LPDBGPROCESS) nub; LPDBGTHREAD threadC = (LPDBGTHREAD) thread; CONTEXT context; THREAD_MEMORY *saved_thread = (THREAD_MEMORY*) malloc (sizeof(THREAD_MEMORY)); BOOL status; DWORD stack_position; DWORD original_IP; DWORD i = 0; BOOL write_status; DWORD bytes_written; TARGET_ADDRESS address_to_break; // suspend_thread(threadC); // Now get context information. We need to know the return address // for our frame-to-be, and also the stack pointer + frame pointer // as is. context.ContextFlags = CONTEXT_FULL; status = get_thread_context(process, threadC, &context); dylan_debugger_message("nub_setup_function_call: Thread Context: %= : %=", threadC->ThreadHandle, status); dylan_debugger_message("Esp: %= Eip: %=", context.Esp, context.Eip); //print_context("Context pulled from thread state", &context); // Now remember everything about the debug state of this thread. saved_thread->ThreadState = threadC->ThreadState; saved_thread->WaitingForDebugger = threadC->WaitingForDebugger; saved_thread->SingleStepping = threadC->SingleStepping; saved_thread->NeedsBreakpointReplacement = threadC->NeedsBreakpointReplacement; saved_thread->BreakpointToReplace = threadC->BreakpointToReplace; saved_thread->StoppedState = threadC->StoppedState; saved_thread->LastReceivedEvent = threadC->LastReceivedEvent; saved_thread->NubCodeOfLastEvent = threadC->NubCodeOfLastEvent; saved_thread->ThreadContext = context; // Allocate enough space on the stack to hold the arguments to the // remote function, and the return address. stack_position = (DWORD) nub_allocate_stack_space (nub, thread, ((DWORD) (arg_count + 1)) * sizeof(DWORD)); if (stack_position == 0x0) { debugger_error("Serious Error: Failed to allocate stack in Spy call on Thread %=", (TARGET_ADDRESS)threadC->ThreadHandle, (TARGET_ADDRESS)NULL); // Internal error return(NULL); } // And get ready for the remote call. If the thread was stopped at a // breakpoint, we need to override that, because we are going to alter // the instruction pointer. if (saved_thread->NeedsBreakpointReplacement) { LPDEBUG_POINT breakpoint = saved_thread->BreakpointToReplace; drop_breakpoint(process, breakpoint); threadC->NeedsBreakpointReplacement = FALSE; if (!(saved_thread->SingleStepping)) { context.EFlags = context.EFlags & 0xFFFFFEFF; } // And resume those threads that will have been suspended. // resume_all_except(process, thread); } if (!status) { // Internal nub error. return (NULL); } //print_context("Context being saved", &(saved_thread->ThreadContext)); // Grab the return address so that the access path chappies can set a // breakpoint on it to clean up the stack. address_to_break = (TARGET_ADDRESS) context.Eip; original_IP = context.Eip; // DIY stack frame!!!! // We are using the C calling convention to bring about our remote // call. At the point of call, the new stack frame must have all the // arguments pushed, followed by the return address. context.Esp = stack_position; // And make the instruction pointer point to our function. context.Eip = (DWORD) function; // The stack should now be fooling this thread into thinking that // it has to execute our remote function, which it will go off and do // as soon as the application resumes. But we have to set the context. status = SetThreadContext (threadC->ThreadHandle, &context); if (!status) { // Internal nub error. return(NULL); } // print_context("Context set back to thread", &context); // Push the return address - ie, the next instruction that was going // to be executed, before we started messing about... write_status = ValidatedWriteProcessMemory (process->ProcessHandle, (LPVOID) stack_position, (LPVOID) &(original_IP), sizeof(TARGET_ADDRESS), &bytes_written); stack_position += sizeof(TARGET_ADDRESS); if ((!write_status) || (bytes_written != sizeof(TARGET_ADDRESS))) { // Internal nub error. return (NULL); } // Push the argument array. for (i = 0; i < (DWORD) arg_count; i++) { write_status = ValidatedWriteProcessMemory (process->ProcessHandle, (LPVOID) stack_position, (LPVOID) &(args[i]), sizeof(TARGET_ADDRESS), &bytes_written); if ((!write_status) || (bytes_written != sizeof(TARGET_ADDRESS))) { // Internal nub error. return (NULL); } else { //printf ("Wrote the argument %x at %x.\n", args[i], stack_position); } stack_position += sizeof(TARGET_ADDRESS); } //print_context("Context set back to thread", &context); (*context_cookie) = (NUBHANDLE) saved_thread; //resume_thread(threadC); return (address_to_break); }
void clear_application_breakpoint (LPDBGPROCESS process, DWORD address) { LPDEBUG_POINT this_debug_point, last_debug_point; LPDBGTHREAD this_thread; if (!process->ExitingProcess) { dylan_debugger_message("clear_application_breakpoint %=", address, 0); this_debug_point = process->DebugPointList; this_thread = process->ThreadList; last_debug_point = NULL; while (this_debug_point != NULL) { if ((this_debug_point->DebugPointType == DBG_POINT_BREAKPOINT) && (this_debug_point->u.Breakpoint.Type == APPLICATION_BREAKPOINT) && (this_debug_point->u.Breakpoint.Address == address)) { // Lift out the breakpoint. lift_breakpoint(process, this_debug_point); // One or more threads might actually be stopped at this breakpoint. // If so, they must be stopped from writing it back into the // process. this_thread = process->ThreadList; while (this_thread != NULL) { CONTEXT context; if (this_thread->NeedsBreakpointReplacement) { // This thread is waiting at a breakpoint. If that breakpoint // is the one we're removing now, we have to hack its state. if (this_thread->BreakpointToReplace == this_debug_point) { dylan_debugger_message("Thread no longer needs breakpoint replacement %= %=", this_thread->ThreadHandle, address); this_thread->NeedsBreakpointReplacement = FALSE; // The thread will have been put into single-step mode in order // to recover from the breakpoint. But it might also be in // single-step mode anyway! If it isn't, take it out of // single-step mode. if (!(this_thread->SingleStepping)) { context.ContextFlags = CONTEXT_CONTROL; get_thread_context(process, this_thread, &context); context.EFlags = context.EFlags & 0xFFFFFEFF; SetThreadContext(this_thread->ThreadHandle, &context); // resume_all_except(process, this_thread); } } } this_thread = this_thread->Next; } // Delete the descriptor from the list. if (last_debug_point == NULL) { // This shouldn't happen, but we might as well handle it. (process->DebugPointList) = this_debug_point->Next; free(this_debug_point); this_debug_point = (process->DebugPointList); } else { last_debug_point->Next = this_debug_point->Next; free(this_debug_point); this_debug_point = (last_debug_point->Next); } } else { last_debug_point = this_debug_point; this_debug_point = this_debug_point->Next; } } } }