/* Returns the reason for which gdbserver instrumentation is needed */ static VgVgdb VG_(gdbserver_instrumentation_needed) (const VexGuestExtents* vge) { GS_Address* g; int e; if (!gdbserver_called) return Vg_VgdbNo; if (valgrind_single_stepping()) { dlog(2, "gdbserver_instrumentation_needed due to single stepping\n"); return Vg_VgdbYes; } if (VG_(clo_vgdb) == Vg_VgdbYes && VG_(HT_count_nodes) (gs_addresses) == 0) return Vg_VgdbNo; /* We assume we do not have a huge nr of breakpoints. Otherwise, we need something more efficient e.g. a sorted list of breakpoints or associate extents to it or ... */ VG_(HT_ResetIter) (gs_addresses); while ((g = VG_(HT_Next) (gs_addresses))) { for (e = 0; e < vge->n_used; e++) { if (g->addr >= HT_addr(vge->base[e]) && g->addr < HT_addr(vge->base[e]) + vge->len[e]) { dlog(2, "gdbserver_instrumentation_needed %p %s reason %s\n", C2v(g->addr), sym(g->addr, /* is_code */ True), (g->kind == GS_jump ? "GS_jump" : "GS_break")); return Vg_VgdbYes; } } } if (VG_(clo_vgdb) == Vg_VgdbFull) { dlog(4, "gdbserver_instrumentation_needed" " due to VG_(clo_vgdb) == Vg_VgdbFull\n"); return Vg_VgdbFull; } return Vg_VgdbNo; }
void VG_(helperc_CallDebugger) ( HWord iaddr ) { GS_Address* g; // For Vg_VgdbFull, after a fork, we might have calls to this helper // while gdbserver is not yet initialized. if (!gdbserver_called) return; if (valgrind_single_stepping() || ((g = VG_(HT_lookup) (gs_addresses, (UWord)HT_addr(iaddr))) && (g->kind == GS_break))) { if (iaddr == HT_addr(ignore_this_break_once)) { dlog(1, "ignoring ignore_this_break_once %s\n", sym(ignore_this_break_once, /* is_code */ True)); ignore_this_break_once = 0; } else { call_gdbserver (VG_(get_running_tid)(), break_reason); } } }
static void add_gs_address (Addr addr, GS_Kind kind, const HChar* from) { GS_Address *p; p = VG_(arena_malloc)(VG_AR_CORE, from, sizeof(GS_Address)); p->addr = HT_addr (addr); p->kind = kind; VG_(HT_add_node)(gs_addresses, p); /* It should be sufficient to discard a range of 1. We use 2 to ensure the below is not sensitive to the presence of thumb bit in the range of addresses to discard. */ VG_(discard_translations) (addr, 2, from); }
static void add_gs_address (Addr addr, GS_Kind kind, const HChar* from) { GS_Address *p; p = VG_(malloc)(from, sizeof(GS_Address)); p->addr = HT_addr (addr); p->kind = kind; VG_(HT_add_node)(gs_addresses, p); /* It should be sufficient to discard a range of 1. We use 2 to ensure the below is not sensitive to the presence of thumb bit in the range of addresses to discard. No need to discard translations for Vg_VgdbFull as all instructions are in any case vgdb-instrumented. */ if (VG_(clo_vgdb) != Vg_VgdbFull) VG_(discard_translations) (addr, 2, from); }
static void invalidate_if_jump_not_yet_gdbserved (Addr addr, const HChar* from) { if (VG_(HT_lookup) (gs_addresses, (UWord)HT_addr(addr))) return; add_gs_address (addr, GS_jump, from); }