From b554e4bd5309b7a5bdfd36ab20c4c8f3edcb88d5 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Tue, 8 Sep 2009 17:39:22 +0000 Subject: [PATCH] gdb/ Fix ia64 shadowing of breakpoints in multiple slots of a single bundle. * ia64-tdep.c (ia64_memory_insert_breakpoint): New call of make_show_memory_breakpoints_cleanup with parameter 0. Move the reading of SHADOW_CONTENTS to this memory state point of code. Update comment for the memory re-read. gdb/testsuite/ * gdb.base/breakpoint-shadow.exp (Second breakpoint placed): Initialize $bpt2address. (Second breakpoint address is valid on ia64) (Third breakpoint on ia64 in the Second breakpoint's bundle): New. --- gdb/ChangeLog | 8 +++++ gdb/ia64-tdep.c | 34 +++++++++++++------- gdb/testsuite/ChangeLog | 7 ++++ gdb/testsuite/gdb.base/breakpoint-shadow.exp | 24 +++++++++++++- 4 files changed, 61 insertions(+), 12 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 94cfea7f035..d84702d5e74 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2009-09-08 Jan Kratochvil + + Fix ia64 shadowing of breakpoints in multiple slots of a single bundle. + * ia64-tdep.c (ia64_memory_insert_breakpoint): New call + of make_show_memory_breakpoints_cleanup with parameter 0. Move the + reading of SHADOW_CONTENTS to this memory state point of code. Update + comment for the memory re-read. + 2009-09-07 Michael Snyder * record.c: Minor comment and white space fix-ups. diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c index 8b93db415de..29601bde2d5 100644 --- a/gdb/ia64-tdep.c +++ b/gdb/ia64-tdep.c @@ -622,27 +622,37 @@ ia64_memory_insert_breakpoint (struct gdbarch *gdbarch, addr &= ~0x0f; - /* Disable the automatic memory restoration from breakpoints while - we read our instruction bundle. Otherwise, the general restoration - mechanism kicks in and we would possibly remove parts of the adjacent + /* Enable the automatic memory restoration from breakpoints while + we read our instruction bundle for the purpose of SHADOW_CONTENTS. + Otherwise, we could possibly store into the shadow parts of the adjacent placed breakpoints. It is due to our SHADOW_CONTENTS overlapping the real breakpoint instruction bits region. */ - cleanup = make_show_memory_breakpoints_cleanup (1); + cleanup = make_show_memory_breakpoints_cleanup (0); val = target_read_memory (addr, bundle, BUNDLE_LEN); - /* Check for L type instruction in slot 1, if present then bump up the slot - number to the slot 2. */ - template = extract_bit_field (bundle, 0, 5); - if (slotnum == 1 && template_encoding_table[template][slotnum] == L) - slotnum = 2; - /* Slot number 2 may skip at most 2 bytes at the beginning. */ - bp_tgt->placed_size = bp_tgt->shadow_len = BUNDLE_LEN - 2; + bp_tgt->shadow_len = BUNDLE_LEN - 2; /* Store the whole bundle, except for the initial skipped bytes by the slot number interpreted as bytes offset in PLACED_ADDRESS. */ memcpy (bp_tgt->shadow_contents, bundle + slotnum, bp_tgt->shadow_len); + /* Re-read the same bundle as above except that, this time, read it in order + to compute the new bundle inside which we will be inserting the + breakpoint. Therefore, disable the automatic memory restoration from + breakpoints while we read our instruction bundle. Otherwise, the general + restoration mechanism kicks in and we would possibly remove parts of the + adjacent placed breakpoints. It is due to our SHADOW_CONTENTS overlapping + the real breakpoint instruction bits region. */ + make_show_memory_breakpoints_cleanup (1); + val |= target_read_memory (addr, bundle, BUNDLE_LEN); + + /* Check for L type instruction in slot 1, if present then bump up the slot + number to the slot 2. */ + template = extract_bit_field (bundle, 0, 5); + if (slotnum == 1 && template_encoding_table[template][slotnum] == L) + slotnum = 2; + /* Breakpoints already present in the code will get deteacted and not get reinserted by bp_loc_is_permanent. Multiple breakpoints at the same location cannot induce the internal error as they are optimized into @@ -654,6 +664,8 @@ ia64_memory_insert_breakpoint (struct gdbarch *gdbarch, paddress (gdbarch, bp_tgt->placed_address)); replace_slotN_contents (bundle, IA64_BREAKPOINT, slotnum); + bp_tgt->placed_size = bp_tgt->shadow_len; + if (val == 0) val = target_write_memory (addr + slotnum, bundle + slotnum, bp_tgt->shadow_len); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 824dfb77990..f6ffeb9d2f8 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2009-09-08 Jan Kratochvil + + * gdb.base/breakpoint-shadow.exp (Second breakpoint placed): Initialize + $bpt2address. + (Second breakpoint address is valid on ia64) + (Third breakpoint on ia64 in the Second breakpoint's bundle): New. + 2009-09-03 Joseph Myers * gdb.base/ending-run.exp: Restrict regular expression matching diff --git a/gdb/testsuite/gdb.base/breakpoint-shadow.exp b/gdb/testsuite/gdb.base/breakpoint-shadow.exp index fcc50dd4730..7da032f3aa9 100644 --- a/gdb/testsuite/gdb.base/breakpoint-shadow.exp +++ b/gdb/testsuite/gdb.base/breakpoint-shadow.exp @@ -48,7 +48,29 @@ gdb_test_multiple "disass main" $test { } gdb_test "b [gdb_get_line_number "break-first"]" "Breakpoint \[0-9\] at .*" "First breakpoint placed" -gdb_test "b [gdb_get_line_number "break-second"]" "Breakpoint \[0-9\] at .*" "Second breakpoint placed" +set test "Second breakpoint placed" +gdb_test_multiple "b [gdb_get_line_number "break-second"]" $test { + -re "Breakpoint \[0-9\] at (0x\[0-9a-f\]*):.*" { + pass $test + set bpt2address $expect_out(1,string) + } +} + +if [istarget "ia64-*-*"] then { + # Unoptimized code should not use the 3rd slot for the first instruction of + # a source line. This is important for our test, because we want both + # breakpoints ("Second breakpoint" and the following one) to be in the same + # bundle. + + set test "Second breakpoint address is valid on ia64" + if [string match "*\[01\]" $bpt2address] { + pass $test + + gdb_test "b *($bpt2address + 1)" "Breakpoint \[0-9\] at .*" "Third breakpoint on ia64 in the Second breakpoint's bundle" + } else { + unresolved $test + } +} set test "disassembly with breakpoints" gdb_test_multiple "disass main" $test { -- 2.30.2