This is the mail archive of the
gdb-prs@sourceware.org
mailing list for the GDB project.
[Bug server/15682] New: z/Z breakpoint reinsertions, dprintf-style gdb->agent
- From: "palves at redhat dot com" <sourceware-bugzilla at sourceware dot org>
- To: gdb-prs at sourceware dot org
- Date: Wed, 26 Jun 2013 15:47:43 +0000
- Subject: [Bug server/15682] New: z/Z breakpoint reinsertions, dprintf-style gdb->agent
- Auto-submitted: auto-generated
http://sourceware.org/bugzilla/show_bug.cgi?id=15682
Bug ID: 15682
Summary: z/Z breakpoint reinsertions, dprintf-style gdb->agent
Product: gdb
Version: HEAD
Status: NEW
Severity: normal
Priority: P2
Component: server
Assignee: unassigned at sourceware dot org
Reporter: palves at redhat dot com
I noticed this bit in gdbserver's server.c, where we handle z/Z packets:
if (insert && the_target->insert_point != NULL)
{
/* Insert the breakpoint. If it is already inserted, nothing
will take place. */
res = (*the_target->insert_point) (type, addr, len);
/* GDB may have sent us a list of *point parameters to be
evaluated on the target's side. Read such list here. If we
already have a list of parameters, GDB is telling us to drop
that list and use this one instead. */
if (!res && (type == '0' || type == '1'))
{
/* Remove previous conditions. */
clear_gdb_breakpoint_conditions (addr);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
process_point_options (addr, &dataptr);
}
}
That only clears previous conditions, but leaves other *point options behind.
That means that it leaves agent commands for dprintfs, if GDB flips
between dprintf-style gdb to agent (in always-inserted mode). That should
clear all print options, not just conditions.
I noticed that while reviewing Hui's "set dprintf-style agent" patch at
<http://sourceware.org/ml/gdb-patches/2013-04/msg00592.html>, and playing
with breakpoint always-inserted mode. But I only noticed it by inspection.
Trying to trigger the bug with:
set breakpoint always-inserted on
set displaced-stepping on (to minimize insert/removes)
dprintf 50, "hello"
b 51 (in a loop)
and then
(gdb) set dprintf-style agent
(gdb) c
*prints "hello" on the gdbserver console*
*stops at line 51*
(gdb) set dprintf-style gdb
(gdb) c
*prints "hello" on gdb's console ONLY*
*stops at line 51*
Looking deeper, what happens is that gdbserver always deletes the previous
breakpoint (the_target->insert_point ultimately will end up here):
int
set_gdb_breakpoint_at (CORE_ADDR where)
{
struct breakpoint *bp;
if (breakpoint_data == NULL)
return 1;
/* If we see GDB inserting a second breakpoint at the same address,
then the first breakpoint must have disappeared due to a shared
library unload. On targets where the shared libraries are
handled by userspace, like SVR4, for example, GDBserver can't
tell if a library was loaded or unloaded. Since we refcount
breakpoints, if we didn't do this, we'd just increase the
refcount of the previous breakpoint at this address, but the trap
was not planted in the inferior anymore, thus the breakpoint
would never be hit. */
bp = find_gdb_breakpoint_at (where);
if (bp != NULL)
{
delete_gdb_breakpoint_at (where);
/* Might as well validate all other breakpoints. */
validate_breakpoints ();
}
Now, if GDBserver does this, then the first reaction would be to just delete
the clear_gdb_breakpoint_conditions call. But, given non-stop, I think it's
wrong to be deleting the breakpoint like that even temporarily. Thread may
miss it. We either need to pause the whole inferior temporarily, or, I think
might be better, just rely on validate_breakpoints to detect the shared library
unload case.
--
You are receiving this mail because:
You are on the CC list for the bug.