2008-12-31 Pedro Alves PR breakpoints/9681: * exceptions.h (enum errors): New error type, MEMORY_ERROR. * corefile.c (memory_error): Rewrite to throw a MEMORY_ERROR. * breakpoint.c (fetch_watchpoint_value): Ignore MEMORY_ERRORs, but retrow all other exceptions. 2008-12-31 Pedro Alves PR breakpoints/9681: * gdb.base/watchpoint.exp: Add test regression. --- gdb/breakpoint.c | 24 ++++++++++++++++++++++-- gdb/corefile.c | 28 ++++++++++------------------ gdb/exceptions.h | 3 +++ gdb/testsuite/gdb.base/watchpoint.exp | 12 ++++++++++++ 4 files changed, 47 insertions(+), 20 deletions(-) Index: src/gdb/exceptions.h =================================================================== --- src.orig/gdb/exceptions.h 2008-12-31 17:59:21.000000000 +0000 +++ src/gdb/exceptions.h 2008-12-31 18:03:18.000000000 +0000 @@ -72,6 +72,9 @@ enum errors { /* Problem parsing an XML document. */ XML_PARSE_ERROR, + /* Error accessing memory. */ + MEMORY_ERROR, + /* Add more errors here. */ NR_ERRORS }; Index: src/gdb/corefile.c =================================================================== --- src.orig/gdb/corefile.c 2008-12-31 17:59:21.000000000 +0000 +++ src/gdb/corefile.c 2008-12-31 18:03:18.000000000 +0000 @@ -205,30 +205,22 @@ Use the \"file\" or \"exec-file\" comman } -/* Report a memory error with error(). */ +/* Report a memory error by throwing a MEMORY_ERROR error. */ void memory_error (int status, CORE_ADDR memaddr) { - struct ui_file *tmp_stream = mem_fileopen (); - make_cleanup_ui_file_delete (tmp_stream); - if (status == EIO) - { - /* Actually, address between memaddr and memaddr + len - was out of bounds. */ - fprintf_unfiltered (tmp_stream, "Cannot access memory at address "); - fputs_filtered (paddress (memaddr), tmp_stream); - } + /* Actually, address between memaddr and memaddr + len was out of + bounds. */ + throw_error (MEMORY_ERROR, + _("Cannot access memory at address %s"), + paddress (memaddr)); else - { - fprintf_filtered (tmp_stream, "Error accessing memory address "); - fputs_filtered (paddress (memaddr), tmp_stream); - fprintf_filtered (tmp_stream, ": %s.", - safe_strerror (status)); - } - - error_stream (tmp_stream); + throw_error (MEMORY_ERROR, + _("Error accessing memory address %s: %s."), + paddress (memaddr), + safe_strerror (status)); } /* Same as target_read_memory, but report an error if can't read. */ Index: src/gdb/breakpoint.c =================================================================== --- src.orig/gdb/breakpoint.c 2008-12-31 17:59:21.000000000 +0000 +++ src/gdb/breakpoint.c 2008-12-31 18:03:18.000000000 +0000 @@ -755,7 +755,7 @@ is_hardware_watchpoint (struct breakpoin in *VAL_CHAIN. RESULTP and VAL_CHAIN may be NULL if the caller does not need them. - If an error occurs while evaluating the expression, *RESULTP will + If a memory error occurs while evaluating the expression, *RESULTP will be set to NULL. *RESULTP may be a lazy value, if the result could not be read from memory. It is used to determine whether a value is user-specified (we should watch the whole value) or intermediate @@ -776,6 +776,7 @@ fetch_watchpoint_value (struct expressio struct value **resultp, struct value **val_chain) { struct value *mark, *new_mark, *result; + volatile struct gdb_exception ex; *valp = NULL; if (resultp) @@ -786,7 +787,26 @@ fetch_watchpoint_value (struct expressio /* Evaluate the expression. */ mark = value_mark (); result = NULL; - gdb_evaluate_expression (exp, &result); + + TRY_CATCH (ex, RETURN_MASK_ALL) + { + result = evaluate_expression (exp); + } + if (ex.reason < 0) + { + /* Ignore memory errors, we want watchpoints pointing at + inaccessible memory to still be created; otherwise, throw the + error to some higher catcher. */ + switch (ex.error) + { + case MEMORY_ERROR: + break; + default: + throw_exception (ex); + break; + } + } + new_mark = value_mark (); if (mark == new_mark) return; Index: src/gdb/testsuite/gdb.base/watchpoint.exp =================================================================== --- src.orig/gdb/testsuite/gdb.base/watchpoint.exp 2008-12-31 18:03:17.000000000 +0000 +++ src/gdb/testsuite/gdb.base/watchpoint.exp 2008-12-31 18:22:50.000000000 +0000 @@ -649,6 +649,18 @@ proc test_inaccessible_watchpoint {} { # valid) memory. if [runto func4] then { + # Make sure we only allow memory access errors. + set msg "watchpoint refused to insert on nonexistent struct member" + gdb_test_multiple "watch struct1.nosuchmember" "watchpoint in nonexisting struct member" { + -re ".*atchpoint \[0-9\]+: struct1.nosuchmember.*$gdb_prompt $" { + # PR breakpoints/9681 + fail $msg + } + -re "There is no member named nosuchmember\\..*$gdb_prompt $" { + pass $msg + } + } + gdb_test "watch *global_ptr" ".*atchpoint \[0-9\]+: \\*global_ptr" gdb_test "next" ".*global_ptr = buf.*" gdb_test_multiple "next" "next over ptr init" {