/*********************************************************************** * break_add_break_from_lvalue * * Add a breakpoint. */ BOOL break_add_break_from_lvalue(const struct dbg_lvalue* lvalue, BOOL swbp) { ADDRESS64 addr; types_extract_as_address(lvalue, &addr); if (!break_add_break(&addr, TRUE, swbp)) { if (!DBG_IVAR(CanDeferOnBPByAddr)) { dbg_printf("Invalid address, can't set breakpoint\n" "You can turn on deferring bp by address by setting $CanDeferOnBPByAddr to 1\n"); return FALSE; } dbg_printf("Unable to add breakpoint, will check again any time a new DLL is loaded\n"); dbg_curr_process->delayed_bp = dbg_heap_realloc(dbg_curr_process->delayed_bp, sizeof(struct dbg_delayed_bp) * ++dbg_curr_process->num_delayed_bp); dbg_curr_process->delayed_bp[dbg_curr_process->num_delayed_bp - 1].is_symbol = FALSE; dbg_curr_process->delayed_bp[dbg_curr_process->num_delayed_bp - 1].software_bp = swbp; dbg_curr_process->delayed_bp[dbg_curr_process->num_delayed_bp - 1].u.addr = addr; return TRUE; } return FALSE; }
/*********************************************************************** * break_add_break_from_id * * Add a breakpoint from a function name (and eventually a line #) */ void break_add_break_from_id(const char *name, int lineno, BOOL swbp) { struct dbg_lvalue lvalue; int i; switch (symbol_get_lvalue(name, lineno, &lvalue, TRUE)) { case sglv_found: break_add_break(&lvalue.addr, TRUE, swbp); return; case sglv_unknown: break; case sglv_aborted: /* user aborted symbol lookup */ return; } dbg_printf("Unable to add breakpoint, will check again when a new DLL is loaded\n"); for (i = 0; i < dbg_curr_process->num_delayed_bp; i++) { if (dbg_curr_process->delayed_bp[i].is_symbol && !strcmp(name, dbg_curr_process->delayed_bp[i].u.symbol.name) && lineno == dbg_curr_process->delayed_bp[i].u.symbol.lineno) return; } dbg_curr_process->delayed_bp = dbg_heap_realloc(dbg_curr_process->delayed_bp, sizeof(struct dbg_delayed_bp) * ++dbg_curr_process->num_delayed_bp); dbg_curr_process->delayed_bp[dbg_curr_process->num_delayed_bp - 1].is_symbol = TRUE; dbg_curr_process->delayed_bp[dbg_curr_process->num_delayed_bp - 1].software_bp = swbp; dbg_curr_process->delayed_bp[dbg_curr_process->num_delayed_bp - 1].u.symbol.name = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(name) + 1), name); dbg_curr_process->delayed_bp[dbg_curr_process->num_delayed_bp - 1].u.symbol.lineno = lineno; }
/****************************************************************** * stack_fetch_frames * * Do a backtrace on the current thread */ unsigned stack_fetch_frames(const CONTEXT* _ctx) { STACKFRAME64 sf; unsigned nf = 0; /* as native stackwalk can modify the context passed to it, simply copy * it to avoid any damage */ CONTEXT ctx = *_ctx, prevctx = ctx; HeapFree(GetProcessHeap(), 0, dbg_curr_thread->frames); dbg_curr_thread->frames = NULL; memset(&sf, 0, sizeof(sf)); be_cpu->get_addr(dbg_curr_thread->handle, &ctx, be_cpu_addr_frame, &sf.AddrFrame); be_cpu->get_addr(dbg_curr_thread->handle, &ctx, be_cpu_addr_pc, &sf.AddrPC); be_cpu->get_addr(dbg_curr_thread->handle, &ctx, be_cpu_addr_stack, &sf.AddrStack); /* don't confuse StackWalk by passing in inconsistent addresses */ if ((sf.AddrPC.Mode == AddrModeFlat) && (sf.AddrFrame.Mode != AddrModeFlat)) { sf.AddrFrame.Offset = (ULONG_PTR)memory_to_linear_addr(&sf.AddrFrame); sf.AddrFrame.Mode = AddrModeFlat; } while (StackWalk64(be_cpu->machine, dbg_curr_process->handle, dbg_curr_thread->handle, &sf, &ctx, stack_read_mem, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) { dbg_curr_thread->frames = dbg_heap_realloc(dbg_curr_thread->frames, (nf + 1) * sizeof(dbg_curr_thread->frames[0])); dbg_curr_thread->frames[nf].addr_pc = sf.AddrPC; dbg_curr_thread->frames[nf].linear_pc = (DWORD_PTR)memory_to_linear_addr(&sf.AddrPC); dbg_curr_thread->frames[nf].addr_frame = sf.AddrFrame; dbg_curr_thread->frames[nf].linear_frame = (DWORD_PTR)memory_to_linear_addr(&sf.AddrFrame); dbg_curr_thread->frames[nf].addr_stack = sf.AddrStack; dbg_curr_thread->frames[nf].linear_stack = (DWORD_PTR)memory_to_linear_addr(&sf.AddrStack); dbg_curr_thread->frames[nf].context = prevctx; /* FIXME: can this heuristic be improved: we declare first context always valid, and next ones * if it has been modified by the call to StackWalk... */ dbg_curr_thread->frames[nf].is_ctx_valid = (nf == 0 || (dbg_curr_thread->frames[nf - 1].is_ctx_valid && memcmp(&dbg_curr_thread->frames[nf - 1].context, &ctx, sizeof(ctx)))); prevctx = ctx; nf++; /* we've probably gotten ourselves into an infinite loop so bail */ if (nf > 200) break; } dbg_curr_thread->curr_frame = -1; dbg_curr_thread->num_frames = nf; stack_set_frame_internal(0); return nf; }