- /* FIXME drow/2003-09-08: This code sets multiple hardware watchpoints
- based on the expression. Ideally this should happen at a higher level,
- and there should be one bp_location for each computed address we
- must watch. As soon as a many-to-one mapping is available I'll
- convert this. */
-
- int within_current_scope;
- struct value *mark = value_mark ();
- struct value *v;
- struct frame_id saved_frame_id;
-
- /* Save the current frame's ID so we can restore it after
- evaluating the watchpoint expression on its own frame. */
- /* FIXME drow/2003-09-09: It would be nice if evaluate_expression
- took a frame parameter, so that we didn't have to change the
- selected frame. */
- saved_frame_id = get_frame_id (deprecated_selected_frame);
-
- /* Determine if the watchpoint is within scope. */
- if (bpt->owner->exp_valid_block == NULL)
- within_current_scope = 1;
- else
- {
- struct frame_info *fi;
- fi = frame_find_by_id (bpt->owner->watchpoint_frame);
- within_current_scope = (fi != NULL);
- if (within_current_scope)
- select_frame (fi);
- }
-
- if (within_current_scope)
- {
- free_valchain (bpt);
-
- /* Evaluate the expression and cut the chain of values
- produced off from the value chain.
-
- Make sure the value returned isn't lazy; we use
- laziness to determine what memory GDB actually needed
- in order to compute the value of the expression. */
- v = evaluate_expression (bpt->owner->exp);
- value_contents (v);
- value_release_to_mark (mark);
-
- bpt->owner->val_chain = v;
- bpt->inserted = 1;
-
- /* Look at each value on the value chain. */
- for (; v; v = value_next (v))
- {
- /* If it's a memory location, and GDB actually needed
- its contents to evaluate the expression, then we
- must watch it. */
- if (VALUE_LVAL (v) == lval_memory
- && ! value_lazy (v))
- {
- struct type *vtype = check_typedef (value_type (v));
-
- /* We only watch structs and arrays if user asked
- for it explicitly, never if they just happen to
- appear in the middle of some value chain. */
- if (v == bpt->owner->val_chain
- || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
- && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
- {
- CORE_ADDR addr;
- int len, type;
-
- addr = VALUE_ADDRESS (v) + value_offset (v);
- len = TYPE_LENGTH (value_type (v));
- type = hw_write;
- if (bpt->owner->type == bp_read_watchpoint)
- type = hw_read;
- else if (bpt->owner->type == bp_access_watchpoint)
- type = hw_access;
-
- val = target_insert_watchpoint (addr, len, type);
- if (val == -1)
- {
- /* Don't exit the loop, try to insert
- every value on the value chain. That's
- because we will be removing all the
- watches below, and removing a
- watchpoint we didn't insert could have
- adverse effects. */
- bpt->inserted = 0;
- }
- val = 0;
- }
- }
- }
- /* Failure to insert a watchpoint on any memory value in the
- value chain brings us here. */
- if (!bpt->inserted)
- {
- remove_breakpoint (bpt, mark_uninserted);
- *hw_breakpoint_error = 1;
- fprintf_unfiltered (tmp_error_stream,
- "Could not insert hardware watchpoint %d.\n",
- bpt->owner->number);
- val = -1;
- }
- }
- else
- {
- printf_filtered (_("\
-Hardware watchpoint %d deleted because the program has left the block \n\
-in which its expression is valid.\n"),
- bpt->owner->number);
- if (bpt->owner->related_breakpoint)
- bpt->owner->related_breakpoint->disposition = disp_del_at_next_stop;
- bpt->owner->disposition = disp_del_at_next_stop;
- }
-
- /* Restore the selected frame. */
- select_frame (frame_find_by_id (saved_frame_id));
-
- return val;
- }
-
- else if (ep_is_exception_catchpoint (bpt->owner))
- {
- /* FIXME drow/2003-09-09: This code sets both a catchpoint and a
- breakpoint. Once again, it would be better if this was represented
- as two bp_locations. */
-
- /* If we get here, we must have a callback mechanism for exception
- events -- with g++ style embedded label support, we insert
- ordinary breakpoints and not catchpoints. */
- val = target_insert_breakpoint (bpt->address, bpt->shadow_contents);
- if (val)
- {
- /* Couldn't set breakpoint for some reason */
- fprintf_unfiltered (tmp_error_stream,
- "Cannot insert catchpoint %d; disabling it.\n",
- bpt->owner->number);
- fprintf_filtered (tmp_error_stream,
- "Error accessing memory address ");
- deprecated_print_address_numeric (bpt->address, 1, tmp_error_stream);
- fprintf_filtered (tmp_error_stream, ": %s.\n",
- safe_strerror (val));
- bpt->owner->enable_state = bp_disabled;
- }
- else
- {
- /* Bp set, now make sure callbacks are enabled */
- /* Format possible error msg */
- char *message = xstrprintf ("Error inserting catchpoint %d:\n",
- bpt->owner->number);
- struct cleanup *cleanups = make_cleanup (xfree, message);
- int val;
- args_for_catchpoint_enable args;
- args.kind = bpt->owner->type == bp_catch_catch ?
- EX_EVENT_CATCH : EX_EVENT_THROW;
- args.enable_p = 1;
- val = catch_errors (cover_target_enable_exception_callback,
- &args, message, RETURN_MASK_ALL);
- do_cleanups (cleanups);
- if (val != 0 && val != -1)
- bpt->inserted = 1;
-
- /* Check if something went wrong; val == 0 can be ignored */
- if (val == -1)
- {
- /* something went wrong */
- fprintf_unfiltered (tmp_error_stream,
- "Cannot insert catchpoint %d; disabling it.\n",
- bpt->owner->number);
- bpt->owner->enable_state = bp_disabled;
- }
- }
-
- return val;