2011-10-27 Pedro Alves gdb/gdbserver/ * mem-break.c (check_mem_write): Split updating shadows and filling the write buffer into two passes. Don't clobber the breakpoints' shadows with fast tracepoint jumps. --- gdb/gdbserver/mem-break.c | 68 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 7 deletions(-) Index: src/gdb/gdbserver/mem-break.c =================================================================== --- src.orig/gdb/gdbserver/mem-break.c 2011-10-27 15:40:38.195141376 +0100 +++ src/gdb/gdbserver/mem-break.c 2011-10-27 16:31:25.865141831 +0100 @@ -1032,14 +1032,15 @@ void check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len) { struct process_info *proc = current_process (); - struct raw_breakpoint *bp = proc->raw_breakpoints; - struct fast_tracepoint_jump *jp = proc->fast_tracepoint_jumps; - CORE_ADDR mem_end = mem_addr + mem_len; + struct raw_breakpoint *bp; + struct fast_tracepoint_jump *jp; + const CORE_ADDR mem_end = mem_addr + mem_len; int disabled_one = 0; - /* First fast tracepoint jumps, then breakpoint traps on top. */ + /* First update the shadows of breakpoints and fast tracepoint jumps + with the contents of BUF. */ - for (; jp != NULL; jp = jp->next) + for (jp = proc->fast_tracepoint_jumps; jp != NULL; jp = jp->next) { CORE_ADDR jp_end = jp->pc + jp->length; CORE_ADDR start, end; @@ -1064,12 +1065,66 @@ check_mem_write (CORE_ADDR mem_addr, uns memcpy (fast_tracepoint_jump_shadow (jp) + copy_offset, buf + buf_offset, copy_len); + } + + for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next) + { + CORE_ADDR bp_end = bp->pc + breakpoint_len; + CORE_ADDR start, end; + int copy_offset, copy_len, buf_offset; + + if (mem_addr >= bp_end) + continue; + if (bp->pc >= mem_end) + continue; + + start = bp->pc; + if (mem_addr > start) + start = mem_addr; + + end = bp_end; + if (end > mem_end) + end = mem_end; + + copy_len = end - start; + copy_offset = start - bp->pc; + buf_offset = start - mem_addr; + + memcpy (bp->old_data + copy_offset, buf + buf_offset, copy_len); + } + + /* Then fill in BUF with what we really want to write to memory. + First fast tracepoint jumps, then breakpoint traps on top. */ + + for (jp = proc->fast_tracepoint_jumps; jp != NULL; jp = jp->next) + { + CORE_ADDR jp_end = jp->pc + jp->length; + CORE_ADDR start, end; + int copy_offset, copy_len, buf_offset; + + if (mem_addr >= jp_end) + continue; + if (jp->pc >= mem_end) + continue; + + start = jp->pc; + if (mem_addr > start) + start = mem_addr; + + end = jp_end; + if (end > mem_end) + end = mem_end; + + copy_len = end - start; + copy_offset = start - jp->pc; + buf_offset = start - mem_addr; + if (jp->inserted) memcpy (buf + buf_offset, fast_tracepoint_jump_insn (jp) + copy_offset, copy_len); } - for (; bp != NULL; bp = bp->next) + for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next) { CORE_ADDR bp_end = bp->pc + breakpoint_len; CORE_ADDR start, end; @@ -1092,7 +1147,6 @@ check_mem_write (CORE_ADDR mem_addr, uns copy_offset = start - bp->pc; buf_offset = start - mem_addr; - memcpy (bp->old_data + copy_offset, buf + buf_offset, copy_len); if (bp->inserted) { if (validate_inserted_breakpoint (bp))