From 218d2fc6506ec89b6ee03af89b4f23199f9fc8e9 Mon Sep 17 00:00:00 2001 From: Thiago Jung Bauermann Date: Wed, 30 Dec 2009 17:33:35 +0000 Subject: [PATCH] gdb/ * valarith.c (value_equal_contents): New function. * value.h (value_equal_contents): Declare. * breakpoint.c (watchpoint_check): Use value_equal_contents instead of value_equal. gdb/testsuite/ * gdb.base/watchpoint.exp (test_watchpoint_in_big_blob): New function. (top level): Call test_watchpoint_in_big_blob. * gdb.base/watchpoint.c (buf): Change size to value too big for hardware watchpoints. (func3): Write to buf. --- gdb/ChangeLog | 7 +++++++ gdb/breakpoint.c | 8 ++++++-- gdb/testsuite/ChangeLog | 8 ++++++++ gdb/testsuite/gdb.base/watchpoint.c | 3 ++- gdb/testsuite/gdb.base/watchpoint.exp | 9 +++++++++ gdb/valarith.c | 18 ++++++++++++++++++ gdb/value.h | 2 ++ 7 files changed, 52 insertions(+), 3 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5c9586be699..b6a5034e2fd 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2009-12-30 Thiago Jung Bauermann + + * valarith.c (value_equal_contents): New function. + * value.h (value_equal_contents): Declare. + * breakpoint.c (watchpoint_check): Use value_equal_contents + instead of value_equal. + 2009-12-30 Stan Shebs Add default-collect variable. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index f041e647c0d..5c605422a5f 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -3174,7 +3174,7 @@ watchpoints_triggered (struct target_waitstatus *ws) #define BP_TEMPFLAG 1 #define BP_HARDWAREFLAG 2 -/* Check watchpoint condition. */ +/* Evaluate watchpoint condition expression and check if its value changed. */ static int watchpoint_check (void *p) @@ -3245,8 +3245,12 @@ watchpoint_check (void *p) struct value *new_val; fetch_watchpoint_value (b->exp, &new_val, NULL, NULL); + + /* We use value_equal_contents instead of value_equal because the latter + coerces an array to a pointer, thus comparing just the address of the + array instead of its contents. This is not what we want. */ if ((b->val != NULL) != (new_val != NULL) - || (b->val != NULL && !value_equal (b->val, new_val))) + || (b->val != NULL && !value_equal_contents (b->val, new_val))) { if (new_val != NULL) { diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 13da3d3136a..33aee0831c3 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2009-12-30 Thiago Jung Bauermann + + * gdb.base/watchpoint.exp (test_watchpoint_in_big_blob): New function. + (top level): Call test_watchpoint_in_big_blob. + * gdb.base/watchpoint.c (buf): Change size to value too big for hardware + watchpoints. + (func3): Write to buf. + 2009-12-29 Stan Shebs * gdb.trace/actions.exp: Test default-collect. diff --git a/gdb/testsuite/gdb.base/watchpoint.c b/gdb/testsuite/gdb.base/watchpoint.c index bba97fad99d..9275d88d929 100644 --- a/gdb/testsuite/gdb.base/watchpoint.c +++ b/gdb/testsuite/gdb.base/watchpoint.c @@ -30,7 +30,7 @@ int ival2 = -1; int ival3 = -1; int ival4 = -1; int ival5 = -1; -char buf[10]; +char buf[30] = "testtesttesttesttesttesttestte"; struct foo { int val; @@ -95,6 +95,7 @@ func3 () x = 1; /* second x assignment */ y = 1; y = 2; + buf[26] = 3; } int diff --git a/gdb/testsuite/gdb.base/watchpoint.exp b/gdb/testsuite/gdb.base/watchpoint.exp index 9fee73b6c38..ff11a4f7eda 100644 --- a/gdb/testsuite/gdb.base/watchpoint.exp +++ b/gdb/testsuite/gdb.base/watchpoint.exp @@ -678,6 +678,13 @@ proc test_inaccessible_watchpoint {} { } } +proc test_watchpoint_in_big_blob {} { + global gdb_prompt + + gdb_test "watch buf" ".*atchpoint \[0-9\]+: buf" + gdb_test "cont" "Continuing.*atchpoint \[0-9\]+: buf\r\n\r\nOld value = .*testte\".*" "watchpoint on buf hit" +} + # Start with a fresh gdb. gdb_exit @@ -842,6 +849,8 @@ if [initialize] then { } test_watchpoint_and_breakpoint + + test_watchpoint_in_big_blob } # Restore old timeout diff --git a/gdb/valarith.c b/gdb/valarith.c index a9c875d907a..2b5d116e493 100644 --- a/gdb/valarith.c +++ b/gdb/valarith.c @@ -1397,6 +1397,24 @@ value_equal (struct value *arg1, struct value *arg2) } } +/* Compare values based on their raw contents. Useful for arrays since + value_equal coerces them to pointers, thus comparing just the address + of the array instead of its contents. */ + +int +value_equal_contents (struct value *arg1, struct value *arg2) +{ + struct type *type1, *type2; + + type1 = check_typedef (value_type (arg1)); + type2 = check_typedef (value_type (arg2)); + + return (TYPE_CODE (type1) == TYPE_CODE (type2) + && TYPE_LENGTH (type1) == TYPE_LENGTH (type2) + && memcmp (value_contents (arg1), value_contents (arg2), + TYPE_LENGTH (type1)) == 0); +} + /* Simulate the C operator < by returning 1 iff ARG1's contents are less than ARG2's. */ diff --git a/gdb/value.h b/gdb/value.h index 993f05bd050..c0acccd2232 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -563,6 +563,8 @@ extern struct internalvar *lookup_internalvar (const char *name); extern int value_equal (struct value *arg1, struct value *arg2); +extern int value_equal_contents (struct value *arg1, struct value *arg2); + extern int value_less (struct value *arg1, struct value *arg2); extern int value_logical_not (struct value *arg1); -- 2.30.2