static void check_duplicates (struct breakpoint *);
+static void breakpoint_adjustment_warning (CORE_ADDR, CORE_ADDR, int, int);
+
+static CORE_ADDR adjust_breakpoint_address (CORE_ADDR bpaddr);
+
static void describe_other_breakpoints (CORE_ADDR, asection *);
static void breakpoints_info (char *, int);
}
insertion_state_t;
-static int remove_breakpoint (struct breakpoint *, insertion_state_t);
+static int remove_breakpoint (struct bp_location *, insertion_state_t);
static enum print_stop_action print_it_typical (bpstat);
B ? (TMP=B->next, 1): 0; \
B = TMP)
+/* Similar iterators for the low-level breakpoints. */
+
+#define ALL_BP_LOCATIONS(B) for (B = bp_location_chain; B; B = B->next)
+
+#define ALL_BP_LOCATIONS_SAFE(B,TMP) \
+ for (B = bp_location_chain; \
+ B ? (TMP=B->next, 1): 0; \
+ B = TMP)
+
/* True if SHIFT_INST_REGS defined, false otherwise. */
int must_shift_inst_regs =
int show_breakpoint_hit_counts = 1;
-/* Chain of all breakpoints defined. */
+/* Chains of all breakpoints defined. */
struct breakpoint *breakpoint_chain;
+struct bp_location *bp_location_chain;
+
/* Number of last breakpoint made. */
int breakpoint_count;
static void
condition_command (char *arg, int from_tty)
{
- register struct breakpoint *b;
+ struct breakpoint *b;
char *p;
- register int bnum;
+ int bnum;
if (arg == 0)
error_no_arg ("breakpoint number");
/* I don't know if it matters whether this is the string the user
typed in or the decompiled expression. */
b->cond_string = savestring (arg, strlen (arg));
- b->cond = parse_exp_1 (&arg, block_for_pc (b->address), 0);
+ b->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
if (*arg)
error ("Junk at end of expression");
}
error ("No breakpoint number %d.", bnum);
}
-/* ARGSUSED */
static void
commands_command (char *arg, int from_tty)
{
- register struct breakpoint *b;
+ struct breakpoint *b;
char *p;
- register int bnum;
+ int bnum;
struct command_line *l;
/* If we allowed this, we would have problems with when to
read_memory_nobpt (CORE_ADDR memaddr, char *myaddr, unsigned len)
{
int status;
- struct breakpoint *b;
+ struct bp_location *b;
CORE_ADDR bp_addr = 0;
int bp_size = 0;
/* No breakpoints on this machine. */
return target_read_memory (memaddr, myaddr, len);
- ALL_BREAKPOINTS (b)
+ ALL_BP_LOCATIONS (b)
{
- if (b->type == bp_none)
- warning ("reading through apparently deleted breakpoint #%d?",
- b->number);
+ if (b->owner->type == bp_none)
+ warning ("reading through apparently deleted breakpoint #%d?",
+ b->owner->number);
- /* memory breakpoint? */
- if (b->type == bp_watchpoint
- || b->type == bp_hardware_watchpoint
- || b->type == bp_read_watchpoint
- || b->type == bp_access_watchpoint)
+ if (b->loc_type != bp_loc_software_breakpoint)
continue;
- /* bp in memory? */
if (!b->inserted)
continue;
/* Addresses and length of the part of the breakpoint that
return 0;
}
-/* insert_breakpoints is used when starting or continuing the program.
- remove_breakpoints is used when the program stops.
- Both return zero if successful,
- or an `errno' value if could not write the inferior. */
+/* Insert a low-level "breakpoint" of some type. BPT is the breakpoint.
+ Any error messages are printed to TMP_ERROR_STREAM; and DISABLED_BREAKS,
+ PROCESS_WARNING, and HW_BREAKPOINT_ERROR are used to report problems.
-int
-insert_breakpoints (void)
+ NOTE drow/2003-09-09: This routine could be broken down to an object-style
+ method for each breakpoint or catchpoint type. */
+static int
+insert_bp_location (struct bp_location *bpt,
+ struct ui_file *tmp_error_stream,
+ int *disabled_breaks, int *process_warning,
+ int *hw_breakpoint_error)
{
- register struct breakpoint *b, *temp;
- int return_val = 0; /* return success code. */
int val = 0;
- int disabled_breaks = 0;
- int hw_breakpoint_error = 0;
-#ifdef ONE_PROCESS_WRITETEXT
- int process_warning = 0;
-#endif
-
- struct ui_file *tmp_error_stream = mem_fileopen ();
- make_cleanup_ui_file_delete (tmp_error_stream);
- /* Explicitly mark the warning -- this will only be printed if
- there was an error. */
- fprintf_unfiltered (tmp_error_stream, "Warning:\n");
+ /* Permanent breakpoints cannot be inserted or removed. Disabled
+ breakpoints should not be inserted. */
+ if (bpt->owner->enable_state != bp_enabled)
+ return 0;
- ALL_BREAKPOINTS_SAFE (b, temp)
- {
- /* Permanent breakpoints cannot be inserted or removed. Disabled
- breakpoints should not be inserted. */
- if (b->enable_state != bp_enabled)
- continue;
+ if (bpt->inserted || bpt->duplicate)
+ return 0;
- if ((b->type == bp_watchpoint
- || b->type == bp_hardware_watchpoint
- || b->type == bp_read_watchpoint
- || b->type == bp_access_watchpoint) && (!b->val))
- {
- struct value *val;
- val = evaluate_expression (b->exp);
- release_value (val);
- if (VALUE_LAZY (val))
- value_fetch_lazy (val);
- b->val = val;
- }
- if (b->type != bp_watchpoint
- && b->type != bp_hardware_watchpoint
- && b->type != bp_read_watchpoint
- && b->type != bp_access_watchpoint
- && b->type != bp_catch_fork
- && b->type != bp_catch_vfork
- && b->type != bp_catch_exec
- && b->type != bp_catch_throw
- && b->type != bp_catch_catch
- && !b->inserted
- && !b->duplicate)
- {
- /* "Normal" instruction breakpoint: either the standard
- trap-instruction bp (bp_breakpoint), or a
- bp_hardware_breakpoint. */
-
- /* First check to see if we have to handle an overlay. */
- if (overlay_debugging == ovly_off
- || b->section == NULL
- || !(section_is_overlay (b->section)))
- {
- /* No overlay handling: just set the breakpoint. */
+ if (bpt->loc_type == bp_loc_software_breakpoint
+ || bpt->loc_type == bp_loc_hardware_breakpoint)
+ {
+ /* First check to see if we have to handle an overlay. */
+ if (overlay_debugging == ovly_off
+ || bpt->section == NULL
+ || !(section_is_overlay (bpt->section)))
+ {
+ /* No overlay handling: just set the breakpoint. */
- if (b->type == bp_hardware_breakpoint)
- val = target_insert_hw_breakpoint (b->address,
- b->shadow_contents);
- else
- val = target_insert_breakpoint (b->address, b->shadow_contents);
- }
- else
- {
- /* This breakpoint is in an overlay section.
- Shall we set a breakpoint at the LMA? */
- if (!overlay_events_enabled)
- {
- /* Yes -- overlay event support is not active,
- so we must try to set a breakpoint at the LMA.
- This will not work for a hardware breakpoint. */
- if (b->type == bp_hardware_breakpoint)
- warning ("hardware breakpoint %d not supported in overlay!\n",
- b->number);
- else
- {
- CORE_ADDR addr = overlay_unmapped_address (b->address,
- b->section);
- /* Set a software (trap) breakpoint at the LMA. */
- val = target_insert_breakpoint (addr, b->shadow_contents);
- if (val != 0)
- fprintf_unfiltered (tmp_error_stream,
- "Overlay breakpoint %d failed: in ROM?",
- b->number);
- }
- }
- /* Shall we set a breakpoint at the VMA? */
- if (section_is_mapped (b->section))
- {
- /* Yes. This overlay section is mapped into memory. */
- if (b->type == bp_hardware_breakpoint)
- val = target_insert_hw_breakpoint (b->address,
- b->shadow_contents);
- else
- val = target_insert_breakpoint (b->address,
- b->shadow_contents);
- }
- else
- {
- /* No. This breakpoint will not be inserted.
- No error, but do not mark the bp as 'inserted'. */
- continue;
- }
- }
+ if (bpt->loc_type == bp_loc_hardware_breakpoint)
+ val = target_insert_hw_breakpoint (bpt->address,
+ bpt->shadow_contents);
+ else
+ val = target_insert_breakpoint (bpt->address,
+ bpt->shadow_contents);
+ }
+ else
+ {
+ /* This breakpoint is in an overlay section.
+ Shall we set a breakpoint at the LMA? */
+ if (!overlay_events_enabled)
+ {
+ /* Yes -- overlay event support is not active,
+ so we must try to set a breakpoint at the LMA.
+ This will not work for a hardware breakpoint. */
+ if (bpt->loc_type == bp_loc_hardware_breakpoint)
+ warning ("hardware breakpoint %d not supported in overlay!\n",
+ bpt->owner->number);
+ else
+ {
+ CORE_ADDR addr = overlay_unmapped_address (bpt->address,
+ bpt->section);
+ /* Set a software (trap) breakpoint at the LMA. */
+ val = target_insert_breakpoint (addr, bpt->shadow_contents);
+ if (val != 0)
+ fprintf_unfiltered (tmp_error_stream,
+ "Overlay breakpoint %d failed: in ROM?",
+ bpt->owner->number);
+ }
+ }
+ /* Shall we set a breakpoint at the VMA? */
+ if (section_is_mapped (bpt->section))
+ {
+ /* Yes. This overlay section is mapped into memory. */
+ if (bpt->loc_type == bp_loc_hardware_breakpoint)
+ val = target_insert_hw_breakpoint (bpt->address,
+ bpt->shadow_contents);
+ else
+ val = target_insert_breakpoint (bpt->address,
+ bpt->shadow_contents);
+ }
+ else
+ {
+ /* No. This breakpoint will not be inserted.
+ No error, but do not mark the bp as 'inserted'. */
+ return 0;
+ }
+ }
- if (val)
- {
- /* Can't set the breakpoint. */
+ if (val)
+ {
+ /* Can't set the breakpoint. */
#if defined (DISABLE_UNSETTABLE_BREAK)
- if (DISABLE_UNSETTABLE_BREAK (b->address))
- {
- /* See also: disable_breakpoints_in_shlibs. */
- val = 0;
- b->enable_state = bp_shlib_disabled;
- if (!disabled_breaks)
- {
- fprintf_unfiltered (tmp_error_stream,
- "Cannot insert breakpoint %d.\n",
- b->number);
- fprintf_unfiltered (tmp_error_stream,
- "Temporarily disabling shared library breakpoints:\n");
- }
- disabled_breaks = 1;
- fprintf_unfiltered (tmp_error_stream,
- "breakpoint #%d\n", b->number);
- }
- else
+ if (DISABLE_UNSETTABLE_BREAK (bpt->address))
+ {
+ /* See also: disable_breakpoints_in_shlibs. */
+ val = 0;
+ bpt->owner->enable_state = bp_shlib_disabled;
+ if (!*disabled_breaks)
+ {
+ fprintf_unfiltered (tmp_error_stream,
+ "Cannot insert breakpoint %d.\n",
+ bpt->owner->number);
+ fprintf_unfiltered (tmp_error_stream,
+ "Temporarily disabling shared library breakpoints:\n");
+ }
+ *disabled_breaks = 1;
+ fprintf_unfiltered (tmp_error_stream,
+ "breakpoint #%d\n", bpt->owner->number);
+ }
+ else
#endif
- {
+ {
#ifdef ONE_PROCESS_WRITETEXT
- process_warning = 1;
+ *process_warning = 1;
#endif
- if (b->type == bp_hardware_breakpoint)
- {
- hw_breakpoint_error = 1;
- fprintf_unfiltered (tmp_error_stream,
- "Cannot insert hardware breakpoint %d.\n",
- b->number);
- }
- else
- {
- fprintf_unfiltered (tmp_error_stream,
- "Cannot insert breakpoint %d.\n",
- b->number);
- fprintf_filtered (tmp_error_stream,
- "Error accessing memory address ");
- print_address_numeric (b->address, 1, tmp_error_stream);
- fprintf_filtered (tmp_error_stream, ": %s.\n",
- safe_strerror (val));
- }
+ if (bpt->loc_type == bp_loc_hardware_breakpoint)
+ {
+ *hw_breakpoint_error = 1;
+ fprintf_unfiltered (tmp_error_stream,
+ "Cannot insert hardware breakpoint %d.\n",
+ bpt->owner->number);
+ }
+ else
+ {
+ fprintf_unfiltered (tmp_error_stream,
+ "Cannot insert breakpoint %d.\n",
+ bpt->owner->number);
+ fprintf_filtered (tmp_error_stream,
+ "Error accessing memory address ");
+ print_address_numeric (bpt->address, 1, tmp_error_stream);
+ fprintf_filtered (tmp_error_stream, ": %s.\n",
+ safe_strerror (val));
+ }
- }
- }
- else
- b->inserted = 1;
+ }
+ }
+ else
+ bpt->inserted = 1;
- if (val)
- return_val = val; /* remember failure */
- }
- else if (ep_is_exception_catchpoint (b)
- && !b->inserted
- && !b->duplicate)
+ return val;
+ }
- {
- /* 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 (b->address, b->shadow_contents);
- if (val)
- {
- /* Couldn't set breakpoint for some reason */
- fprintf_unfiltered (tmp_error_stream,
- "Cannot insert catchpoint %d; disabling it.\n",
- b->number);
- fprintf_filtered (tmp_error_stream,
- "Error accessing memory address ");
- print_address_numeric (b->address, 1, tmp_error_stream);
- fprintf_filtered (tmp_error_stream, ": %s.\n",
- safe_strerror (val));
- b->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",
- b->number);
- struct cleanup *cleanups = make_cleanup (xfree, message);
- int val;
- args_for_catchpoint_enable args;
- args.kind = b->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)
- {
- b->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",
- b->number);
- b->enable_state = bp_disabled;
- }
- }
+ else if (bpt->loc_type == bp_loc_hardware_watchpoint
+ /* NOTE drow/2003-09-08: This state only exists for removing
+ watchpoints. It's not clear that it's necessary... */
+ && bpt->owner->disposition != disp_del_at_next_stop)
+ {
+ /* 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. */
- if (val)
- return_val = val; /* remember failure */
- }
+ struct frame_info *saved_frame;
+ int saved_level, within_current_scope;
+ struct value *mark = value_mark ();
+ struct value *v;
- else if ((b->type == bp_hardware_watchpoint ||
- b->type == bp_read_watchpoint ||
- b->type == bp_access_watchpoint)
- && b->disposition != disp_del_at_next_stop
- && !b->inserted
- && !b->duplicate)
- {
- struct frame_info *saved_frame;
- int saved_level, within_current_scope;
- struct value *mark = value_mark ();
- struct value *v;
+ /* Save the current frame and level 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 = deprecated_selected_frame;
+ saved_level = frame_relative_level (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);
+ }
- /* Save the current frame and level so we can restore it after
- evaluating the watchpoint expression on its own frame. */
- saved_frame = deprecated_selected_frame;
- saved_level = frame_relative_level (deprecated_selected_frame);
+ if (within_current_scope)
+ {
+ /* Evaluate the expression and cut the chain of values
+ produced off from the value chain.
- /* Determine if the watchpoint is within scope. */
- if (b->exp_valid_block == NULL)
- within_current_scope = 1;
- else
- {
- struct frame_info *fi;
- fi = frame_find_by_id (b->watchpoint_frame);
- within_current_scope = (fi != NULL);
- if (within_current_scope)
- select_frame (fi);
- }
+ 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);
- if (within_current_scope)
- {
- /* Evaluate the expression and cut the chain of values
- produced off from the value chain.
+ bpt->owner->val_chain = v;
+ bpt->inserted = 1;
- 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 (b->exp);
- VALUE_CONTENTS(v);
- value_release_to_mark (mark);
+ /* Look at each value on the value chain. */
+ for (; v; v = v->next)
+ {
+ /* 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 ", bpt->owner->number);
+ printf_filtered ("because the program has left the block \n");
+ printf_filtered ("in which its expression is valid.\n");
+ if (bpt->owner->related_breakpoint)
+ bpt->owner->related_breakpoint->disposition = disp_del_at_next_stop;
+ bpt->owner->disposition = disp_del_at_next_stop;
+ }
- b->val_chain = v;
- b->inserted = 1;
+ /* Restore the frame and level. */
+ if (saved_frame != deprecated_selected_frame
+ || saved_level != frame_relative_level (deprecated_selected_frame))
+ select_frame (saved_frame);
- /* Look at each value on the value chain. */
- for (; v; v = v->next)
- {
- /* 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 == b->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 (b->type == bp_read_watchpoint)
- type = hw_read;
- else if (b->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. */
- b->inserted = 0;
- }
- val = 0;
- }
- }
- }
- /* Failure to insert a watchpoint on any memory value in the
- value chain brings us here. */
- if (!b->inserted)
- {
- remove_breakpoint (b, mark_uninserted);
- hw_breakpoint_error = 1;
- fprintf_unfiltered (tmp_error_stream,
- "Could not insert hardware watchpoint %d.\n",
- b->number);
- val = -1;
- }
- }
- else
- {
- printf_filtered ("Hardware watchpoint %d deleted ", b->number);
- printf_filtered ("because the program has left the block \n");
- printf_filtered ("in which its expression is valid.\n");
- if (b->related_breakpoint)
- b->related_breakpoint->disposition = disp_del_at_next_stop;
- b->disposition = disp_del_at_next_stop;
- }
+ return val;
+ }
- /* Restore the frame and level. */
- if ((saved_frame != deprecated_selected_frame) ||
- (saved_level != frame_relative_level (deprecated_selected_frame)))
- select_frame (saved_frame);
+ 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 (val)
- return_val = val; /* remember failure */
- }
- else if ((b->type == bp_catch_fork
- || b->type == bp_catch_vfork
- || b->type == bp_catch_exec)
- && !b->inserted
- && !b->duplicate)
- {
- char *prefix = xstrprintf ("warning: inserting catchpoint %d: ",
- b->number);
- struct cleanup *cleanups = make_cleanup (xfree, prefix);
- val = catch_exceptions (uiout, insert_catchpoint, b, prefix,
- RETURN_MASK_ERROR);
- do_cleanups (cleanups);
- if (val < 0)
- b->enable_state = bp_disabled;
- else
- b->inserted = 1;
- }
- }
-
- if (return_val)
+ /* 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 ");
+ 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;
+ }
+
+ else if (bpt->owner->type == bp_catch_fork
+ || bpt->owner->type == bp_catch_vfork
+ || bpt->owner->type == bp_catch_exec)
+ {
+ char *prefix = xstrprintf ("warning: inserting catchpoint %d: ",
+ bpt->owner->number);
+ struct cleanup *cleanups = make_cleanup (xfree, prefix);
+ val = catch_exceptions (uiout, insert_catchpoint, bpt->owner, prefix,
+ RETURN_MASK_ERROR);
+ do_cleanups (cleanups);
+ if (val < 0)
+ bpt->owner->enable_state = bp_disabled;
+ else
+ bpt->inserted = 1;
+ return val;
+ }
+
+ return 0;
+}
+
+/* insert_breakpoints is used when starting or continuing the program.
+ remove_breakpoints is used when the program stops.
+ Both return zero if successful,
+ or an `errno' value if could not write the inferior. */
+
+int
+insert_breakpoints (void)
+{
+ struct bp_location *b, *temp;
+ int return_val = 0; /* return success code. */
+ int val = 0;
+ int disabled_breaks = 0;
+ int hw_breakpoint_error = 0;
+ int process_warning = 0;
+
+ struct ui_file *tmp_error_stream = mem_fileopen ();
+ make_cleanup_ui_file_delete (tmp_error_stream);
+
+ /* Explicitly mark the warning -- this will only be printed if
+ there was an error. */
+ fprintf_unfiltered (tmp_error_stream, "Warning:\n");
+
+ ALL_BP_LOCATIONS_SAFE (b, temp)
+ {
+ /* Permanent breakpoints cannot be inserted or removed. Disabled
+ breakpoints should not be inserted. */
+ if (b->owner->enable_state != bp_enabled)
+ continue;
+
+ /* FIXME drow/2003-10-07: This code should be pushed elsewhere when
+ hardware watchpoints are split into multiple loc breakpoints. */
+ if ((b->loc_type == bp_loc_hardware_watchpoint
+ || b->owner->type == bp_watchpoint) && !b->owner->val)
+ {
+ struct value *val;
+ val = evaluate_expression (b->owner->exp);
+ release_value (val);
+ if (VALUE_LAZY (val))
+ value_fetch_lazy (val);
+ b->owner->val = val;
+ }
+
+ val = insert_bp_location (b, tmp_error_stream,
+ &disabled_breaks, &process_warning,
+ &hw_breakpoint_error);
+ if (val)
+ return_val = val;
+ }
+
+ if (return_val)
{
/* If a hardware breakpoint or watchpoint was inserted, add a
message about possibly exhausted resources. */
- if (hw_breakpoint_error)
+ if (hw_breakpoint_error)
{
fprintf_unfiltered (tmp_error_stream,
"Could not insert hardware breakpoints:\n\
int
remove_breakpoints (void)
{
- register struct breakpoint *b;
+ struct bp_location *b;
int val;
- ALL_BREAKPOINTS (b)
+ ALL_BP_LOCATIONS (b)
{
if (b->inserted)
{
int
remove_hw_watchpoints (void)
{
- register struct breakpoint *b;
+ struct bp_location *b;
int val;
- ALL_BREAKPOINTS (b)
+ ALL_BP_LOCATIONS (b)
{
- if (b->inserted
- && (b->type == bp_hardware_watchpoint
- || b->type == bp_read_watchpoint
- || b->type == bp_access_watchpoint))
+ if (b->inserted && b->loc_type == bp_loc_hardware_watchpoint)
{
val = remove_breakpoint (b, mark_uninserted);
if (val != 0)
int
reattach_breakpoints (int pid)
{
- register struct breakpoint *b;
+ struct bp_location *b;
int val;
struct cleanup *old_chain = save_inferior_ptid ();
/* Set inferior_ptid; remove_breakpoint uses this global. */
inferior_ptid = pid_to_ptid (pid);
- ALL_BREAKPOINTS (b)
+ ALL_BP_LOCATIONS (b)
{
if (b->inserted)
{
remove_breakpoint (b, mark_inserted);
- if (b->type == bp_hardware_breakpoint)
+ if (b->loc_type == bp_loc_hardware_breakpoint)
val = target_insert_hw_breakpoint (b->address, b->shadow_contents);
else
val = target_insert_breakpoint (b->address, b->shadow_contents);
+ /* FIXME drow/2003-10-07: This doesn't handle any other kinds of
+ breakpoints. It's wrong for watchpoints, for example. */
if (val != 0)
{
do_cleanups (old_chain);
automagically. Certainly on HP-UX that's true.
Jim Blandy <jimb@redhat.com>: Actually, zero is a perfectly
- valid code address on some platforms (like the OBSOLETE mn10200
- and mn10300 simulators). We shouldn't assign any special
- interpretation to a breakpoint with a zero address. And in
- fact, GDB doesn't --- I can't see what that comment above is
- talking about. As far as I can tell, setting the address of a
+ valid code address on some platforms (like the mn10300
+ simulators). We shouldn't assign any special interpretation to
+ a breakpoint with a zero address. And in fact, GDB doesn't ---
+ I can't see what that comment above is talking about. As far
+ as I can tell, setting the address of a
bp_catch_exec/bp_catch_vfork/bp_catch_fork breakpoint to zero
is meaningless, since those are implemented with HP-UX kernel
hackery, not by storing breakpoint instructions somewhere. */
(b->type == bp_catch_vfork) ||
(b->type == bp_catch_fork))
{
- b->address = (CORE_ADDR) NULL;
+ b->loc->address = (CORE_ADDR) NULL;
continue;
}
unnecessary. A call to breakpoint_re_set_one always recomputes
the breakpoint's address from scratch, or deletes it if it can't.
So I think this assignment could be deleted without effect. */
- b->address = (CORE_ADDR) NULL;
+ b->loc->address = (CORE_ADDR) NULL;
}
/* FIXME what about longjmp breakpoints? Re-create them here? */
create_overlay_event_breakpoint ("_ovly_debug_event");
int
detach_breakpoints (int pid)
{
- register struct breakpoint *b;
+ struct bp_location *b;
int val;
struct cleanup *old_chain = save_inferior_ptid ();
/* Set inferior_ptid; remove_breakpoint uses this global. */
inferior_ptid = pid_to_ptid (pid);
- ALL_BREAKPOINTS (b)
+ ALL_BP_LOCATIONS (b)
{
if (b->inserted)
{
}
static int
-remove_breakpoint (struct breakpoint *b, insertion_state_t is)
+remove_breakpoint (struct bp_location *b, insertion_state_t is)
{
int val;
- if (b->enable_state == bp_permanent)
+ if (b->owner->enable_state == bp_permanent)
/* Permanent breakpoints cannot be inserted or removed. */
return 0;
- if (b->type == bp_none)
+ if (b->owner->type == bp_none)
warning ("attempted to remove apparently deleted breakpoint #%d?",
- b->number);
-
- if (b->type != bp_watchpoint
- && b->type != bp_hardware_watchpoint
- && b->type != bp_read_watchpoint
- && b->type != bp_access_watchpoint
- && b->type != bp_catch_fork
- && b->type != bp_catch_vfork
- && b->type != bp_catch_exec
- && b->type != bp_catch_catch
- && b->type != bp_catch_throw)
+ b->owner->number);
+
+ if (b->loc_type == bp_loc_software_breakpoint
+ || b->loc_type == bp_loc_hardware_breakpoint)
{
/* "Normal" instruction breakpoint: either the standard
trap-instruction bp (bp_breakpoint), or a
{
/* No overlay handling: just remove the breakpoint. */
- if (b->type == bp_hardware_breakpoint)
+ if (b->loc_type == bp_loc_hardware_breakpoint)
val = target_remove_hw_breakpoint (b->address,
b->shadow_contents);
else
b->section);
/* Ignore any failures: if the LMA is in ROM, we will
have already warned when we failed to insert it. */
- if (b->type != bp_hardware_breakpoint)
+ if (b->loc_type == bp_loc_hardware_breakpoint)
target_remove_hw_breakpoint (addr, b->shadow_contents);
else
target_remove_breakpoint (addr, b->shadow_contents);
remove the breakpoint if the section had been
unmapped, but let's not rely on that being safe. We
don't know what the overlay manager might do. */
- if (b->type == bp_hardware_breakpoint)
+ if (b->loc_type == bp_loc_hardware_breakpoint)
val = target_remove_hw_breakpoint (b->address,
b->shadow_contents);
else
return val;
b->inserted = (is == mark_inserted);
}
- else if ((b->type == bp_hardware_watchpoint ||
- b->type == bp_read_watchpoint ||
- b->type == bp_access_watchpoint)
- && b->enable_state == bp_enabled
+ else if (b->loc_type == bp_loc_hardware_watchpoint
+ && b->owner->enable_state == bp_enabled
&& !b->duplicate)
{
struct value *v;
b->inserted = (is == mark_inserted);
/* Walk down the saved value chain. */
- for (v = b->val_chain; v; v = v->next)
+ for (v = b->owner->val_chain; v; v = v->next)
{
/* For each memory reference remove the watchpoint
at that address. */
{
struct type *vtype = check_typedef (VALUE_TYPE (v));
- if (v == b->val_chain
+ if (v == b->owner->val_chain
|| (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
&& TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
{
addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
len = TYPE_LENGTH (VALUE_TYPE (v));
type = hw_write;
- if (b->type == bp_read_watchpoint)
+ if (b->owner->type == bp_read_watchpoint)
type = hw_read;
- else if (b->type == bp_access_watchpoint)
+ else if (b->owner->type == bp_access_watchpoint)
type = hw_access;
val = target_remove_watchpoint (addr, len, type);
/* Failure to remove any of the hardware watchpoints comes here. */
if ((is == mark_uninserted) && (b->inserted))
warning ("Could not remove hardware watchpoint %d.",
- b->number);
+ b->owner->number);
/* Free the saved value chain. We will construct a new one
the next time the watchpoint is inserted. */
- for (v = b->val_chain; v; v = n)
+ for (v = b->owner->val_chain; v; v = n)
{
n = v->next;
value_free (v);
}
- b->val_chain = NULL;
+ b->owner->val_chain = NULL;
}
- else if ((b->type == bp_catch_fork ||
- b->type == bp_catch_vfork ||
- b->type == bp_catch_exec)
- && b->enable_state == bp_enabled
+ else if ((b->owner->type == bp_catch_fork ||
+ b->owner->type == bp_catch_vfork ||
+ b->owner->type == bp_catch_exec)
+ && b->owner->enable_state == bp_enabled
&& !b->duplicate)
{
val = -1;
- switch (b->type)
+ switch (b->owner->type)
{
case bp_catch_fork:
val = target_remove_fork_catchpoint (PIDGET (inferior_ptid));
return val;
b->inserted = (is == mark_inserted);
}
- else if ((b->type == bp_catch_catch ||
- b->type == bp_catch_throw)
- && b->enable_state == bp_enabled
+ else if ((b->owner->type == bp_catch_catch ||
+ b->owner->type == bp_catch_throw)
+ && b->owner->enable_state == bp_enabled
&& !b->duplicate)
{
return val;
b->inserted = (is == mark_inserted);
}
- else if (ep_is_exception_catchpoint (b)
+ else if (ep_is_exception_catchpoint (b->owner)
&& b->inserted /* sometimes previous insert doesn't happen */
- && b->enable_state == bp_enabled
+ && b->owner->enable_state == bp_enabled
&& !b->duplicate)
{
void
mark_breakpoints_out (void)
{
- register struct breakpoint *b;
+ struct bp_location *bpt;
- ALL_BREAKPOINTS (b)
- b->inserted = 0;
+ ALL_BP_LOCATIONS (bpt)
+ bpt->inserted = 0;
}
/* Clear the "inserted" flag in all breakpoints and delete any
void
breakpoint_init_inferior (enum inf_context context)
{
- register struct breakpoint *b, *temp;
+ struct breakpoint *b, *temp;
+ struct bp_location *bpt;
static int warning_needed = 0;
+ ALL_BP_LOCATIONS (bpt)
+ bpt->inserted = 0;
+
ALL_BREAKPOINTS_SAFE (b, temp)
{
- b->inserted = 0;
-
switch (b->type)
{
case bp_call_dummy:
enum breakpoint_here
breakpoint_here_p (CORE_ADDR pc)
{
- register struct breakpoint *b;
+ struct bp_location *bpt;
int any_breakpoint_here = 0;
- ALL_BREAKPOINTS (b)
- if ((b->enable_state == bp_enabled
- || b->enable_state == bp_permanent)
- && b->address == pc) /* bp is enabled and matches pc */
- {
- if (overlay_debugging
- && section_is_overlay (b->section)
- && !section_is_mapped (b->section))
- continue; /* unmapped overlay -- can't be a match */
- else if (b->enable_state == bp_permanent)
- return permanent_breakpoint_here;
- else
- any_breakpoint_here = 1;
- }
+ ALL_BP_LOCATIONS (bpt)
+ {
+ if (bpt->loc_type != bp_loc_software_breakpoint
+ && bpt->loc_type != bp_loc_hardware_breakpoint)
+ continue;
+
+ if ((bpt->owner->enable_state == bp_enabled
+ || bpt->owner->enable_state == bp_permanent)
+ && bpt->address == pc) /* bp is enabled and matches pc */
+ {
+ if (overlay_debugging
+ && section_is_overlay (bpt->section)
+ && !section_is_mapped (bpt->section))
+ continue; /* unmapped overlay -- can't be a match */
+ else if (bpt->owner->enable_state == bp_permanent)
+ return permanent_breakpoint_here;
+ else
+ any_breakpoint_here = 1;
+ }
+ }
return any_breakpoint_here ? ordinary_breakpoint_here : 0;
}
int
breakpoint_inserted_here_p (CORE_ADDR pc)
{
- register struct breakpoint *b;
+ struct bp_location *bpt;
- ALL_BREAKPOINTS (b)
- if (b->inserted
- && b->address == pc) /* bp is inserted and matches pc */
+ ALL_BP_LOCATIONS (bpt)
{
- if (overlay_debugging
- && section_is_overlay (b->section)
- && !section_is_mapped (b->section))
- continue; /* unmapped overlay -- can't be a match */
- else
- return 1;
+ if (bpt->loc_type != bp_loc_software_breakpoint
+ && bpt->loc_type != bp_loc_hardware_breakpoint)
+ continue;
+
+ if (bpt->inserted
+ && bpt->address == pc) /* bp is inserted and matches pc */
+ {
+ if (overlay_debugging
+ && section_is_overlay (bpt->section)
+ && !section_is_mapped (bpt->section))
+ continue; /* unmapped overlay -- can't be a match */
+ else
+ return 1;
+ }
}
return 0;
/* We need to check the PC as well as the frame on the sparc,
for signals.exp in the testsuite. */
&& (get_frame_pc (frame)
- >= (b->address
+ >= (b->loc->address
- DEPRECATED_SIZEOF_CALL_DUMMY_WORDS / sizeof (LONGEST) * DEPRECATED_REGISTER_SIZE))
- && get_frame_pc (frame) <= b->address)
+ && get_frame_pc (frame) <= b->loc->address)
return 1;
}
return 0;
}
-/* breakpoint_thread_match (PC, PID) returns true if the breakpoint at
- PC is valid for process/thread PID. */
+/* breakpoint_thread_match (PC, PTID) returns true if the breakpoint at
+ PC is valid for process/thread PTID. */
int
breakpoint_thread_match (CORE_ADDR pc, ptid_t ptid)
{
- struct breakpoint *b;
+ struct bp_location *bpt;
int thread;
thread = pid_to_thread_id (ptid);
- ALL_BREAKPOINTS (b)
- if (b->enable_state != bp_disabled
- && b->enable_state != bp_shlib_disabled
- && b->enable_state != bp_call_disabled
- && b->address == pc
- && (b->thread == -1 || b->thread == thread))
- {
- if (overlay_debugging
- && section_is_overlay (b->section)
- && !section_is_mapped (b->section))
- continue; /* unmapped overlay -- can't be a match */
- else
- return 1;
+ ALL_BP_LOCATIONS (bpt)
+ {
+ if (bpt->loc_type != bp_loc_software_breakpoint
+ && bpt->loc_type != bp_loc_hardware_breakpoint)
+ continue;
+
+ if ((bpt->owner->enable_state == bp_enabled
+ || bpt->owner->enable_state == bp_permanent)
+ && bpt->address == pc
+ && (bpt->owner->thread == -1 || bpt->owner->thread == thread))
+ {
+ if (overlay_debugging
+ && section_is_overlay (bpt->section)
+ && !section_is_mapped (bpt->section))
+ continue; /* unmapped overlay -- can't be a match */
+ else
+ return 1;
+ }
}
return 0;
}
/* Stub for cleaning up our state if we error-out of a breakpoint command */
-/* ARGSUSED */
static void
cleanup_executing_breakpoints (void *ignore)
{
{
case bp_breakpoint:
case bp_hardware_breakpoint:
+ if (bs->breakpoint_at->loc->address != bs->breakpoint_at->loc->requested_address)
+ breakpoint_adjustment_warning (bs->breakpoint_at->loc->requested_address,
+ bs->breakpoint_at->loc->address,
+ bs->breakpoint_at->number, 1);
annotate_breakpoint (bs->breakpoint_at->number);
ui_out_text (uiout, "\nBreakpoint ");
if (ui_out_is_mi_like_p (uiout))
the frame chain (so we can determine if we're in scope). */
reinit_frame_cache ();
fr = frame_find_by_id (b->watchpoint_frame);
-#if 0
- current_frame_id = get_frame_id (get_current_frame ());
- within_current_scope = frame_id_eq (current_frame_id, b->watchpoint_frame)
- || frame_id_inner (current_frame_id,
- b->watchpoint_frame);
-#else
within_current_scope = (fr != NULL);
-#endif
/* in_function_epilogue_p() returns a non-zero value if we're still
in the function but the stack frame has already been invalidated.
Since we can't rely on the values of local variables after the
stack has been destroyed, we are treating the watchpoint in that
- state as `not changed' without further checking. */
-#if 0
- if (within_current_scope && (!fr || fr == get_current_frame ())
-#else
+ state as `not changed' without further checking.
+
+ vinschen/2003-09-04: The former implementation left out the case
+ that the watchpoint frame couldn't be found by frame_find_by_id()
+ because the current PC is currently in an epilogue. Calling
+ gdbarch_in_function_epilogue_p() also when fr == NULL fixes that. */
if ((!within_current_scope || fr == get_current_frame ())
-#endif
&& gdbarch_in_function_epilogue_p (current_gdbarch, read_pc ()))
return WP_VALUE_NOT_CHANGED;
if (fr && within_current_scope)
bpstat
bpstat_stop_status (CORE_ADDR *pc, int not_a_sw_breakpoint)
{
- register struct breakpoint *b, *temp;
+ struct breakpoint *b, *temp;
CORE_ADDR bp_addr;
/* True if we've hit a breakpoint (as opposed to a watchpoint). */
int real_breakpoint = 0;
&& b->type != bp_catch_catch
&& b->type != bp_catch_throw) /* a non-watchpoint bp */
{
- if (b->address != bp_addr) /* address doesn't match */
+ if (b->loc->address != bp_addr) /* address doesn't match */
continue;
if (overlay_debugging /* unmapped overlay section */
- && section_is_overlay (b->section)
- && !section_is_mapped (b->section))
+ && section_is_overlay (b->loc->section)
+ && !section_is_mapped (b->loc->section))
continue;
}
if (b->type == bp_hardware_breakpoint)
{
- if (b->address != (*pc - DECR_PC_AFTER_HW_BREAK))
+ if (b->loc->address != (*pc - DECR_PC_AFTER_HW_BREAK))
continue;
if (overlay_debugging /* unmapped overlay section */
- && section_is_overlay (b->section)
- && !section_is_mapped (b->section))
+ && section_is_overlay (b->loc->section)
+ && !section_is_mapped (b->loc->section))
continue;
}
int
bpstat_have_active_hw_watchpoints (void)
{
- struct breakpoint *b;
- ALL_BREAKPOINTS (b)
- if ((b->enable_state == bp_enabled) &&
- (b->inserted) &&
- ((b->type == bp_hardware_watchpoint) ||
- (b->type == bp_read_watchpoint) ||
- (b->type == bp_access_watchpoint)))
+ struct bp_location *bpt;
+ ALL_BP_LOCATIONS (bpt)
+ if ((bpt->owner->enable_state == bp_enabled)
+ && bpt->inserted
+ && bpt->loc_type == bp_loc_hardware_watchpoint)
return 1;
return 0;
}
print_one_breakpoint (struct breakpoint *b,
CORE_ADDR *last_addr)
{
- register struct command_line *l;
- register struct symbol *sym;
+ struct command_line *l;
+ struct symbol *sym;
struct ep_type_description
{
enum bptype type;
if (addressprint)
{
annotate_field (4);
- ui_out_field_core_addr (uiout, "addr", b->address);
+ ui_out_field_core_addr (uiout, "addr", b->loc->address);
}
annotate_field (5);
- *last_addr = b->address;
+ *last_addr = b->loc->address;
if (b->source_file)
{
- sym = find_pc_sect_function (b->address, b->section);
+ sym = find_pc_sect_function (b->loc->address, b->loc->section);
if (sym)
{
ui_out_text (uiout, "in ");
}
else
{
- print_address_symbolic (b->address, stb->stream, demangle, "");
+ print_address_symbolic (b->loc->address, stb->stream, demangle, "");
ui_out_field_stream (uiout, "at", stb);
}
break;
do_captured_breakpoint_query (struct ui_out *uiout, void *data)
{
struct captured_breakpoint_query_args *args = data;
- register struct breakpoint *b;
+ struct breakpoint *b;
CORE_ADDR dummy_addr = 0;
ALL_BREAKPOINTS (b)
{
static void
breakpoint_1 (int bnum, int allflag)
{
- register struct breakpoint *b;
+ struct breakpoint *b;
CORE_ADDR last_addr = (CORE_ADDR) -1;
int nr_printable_breakpoints;
struct cleanup *bkpttbl_chain;
annotate_breakpoints_table_end ();
}
-/* ARGSUSED */
static void
breakpoints_info (char *bnum_exp, int from_tty)
{
breakpoint_1 (bnum, 0);
}
-/* ARGSUSED */
static void
maintenance_info_breakpoints (char *bnum_exp, int from_tty)
{
static void
describe_other_breakpoints (CORE_ADDR pc, asection *section)
{
- register int others = 0;
- register struct breakpoint *b;
+ int others = 0;
+ struct breakpoint *b;
ALL_BREAKPOINTS (b)
- if (b->address == pc) /* address match / overlay match */
- if (!overlay_debugging || b->section == section)
+ if (b->loc->address == pc) /* address match / overlay match */
+ if (!overlay_debugging || b->loc->section == section)
others++;
if (others > 0)
{
printf_filtered ("Note: breakpoint%s ", (others > 1) ? "s" : "");
ALL_BREAKPOINTS (b)
- if (b->address == pc) /* address match / overlay match */
- if (!overlay_debugging || b->section == section)
+ if (b->loc->address == pc) /* address match / overlay match */
+ if (!overlay_debugging || b->loc->section == section)
{
others--;
printf_filtered ("%d%s%s ",
static void
check_duplicates (struct breakpoint *bpt)
{
- register struct breakpoint *b;
- register int count = 0;
- struct breakpoint *perm_bp = 0;
- CORE_ADDR address = bpt->address;
- asection *section = bpt->section;
+ struct bp_location *b;
+ int count = 0;
+ struct bp_location *perm_bp = 0;
+ CORE_ADDR address = bpt->loc->address;
+ asection *section = bpt->loc->section;
if (! breakpoint_address_is_meaningful (bpt))
return;
- ALL_BREAKPOINTS (b)
- if (b->enable_state != bp_disabled
- && b->enable_state != bp_shlib_disabled
- && b->enable_state != bp_call_disabled
+ ALL_BP_LOCATIONS (b)
+ if (b->owner->enable_state != bp_disabled
+ && b->owner->enable_state != bp_shlib_disabled
+ && b->owner->enable_state != bp_call_disabled
&& b->address == address /* address / overlay match */
&& (!overlay_debugging || b->section == section)
- && breakpoint_address_is_meaningful (b))
+ && breakpoint_address_is_meaningful (b->owner))
{
/* Have we found a permanent breakpoint? */
- if (b->enable_state == bp_permanent)
+ if (b->owner->enable_state == bp_permanent)
{
perm_bp = b;
break;
"allegedly permanent breakpoint is not "
"actually inserted");
- ALL_BREAKPOINTS (b)
+ ALL_BP_LOCATIONS (b)
if (b != perm_bp)
{
- if (b->inserted)
- internal_error (__FILE__, __LINE__,
- "another breakpoint was inserted on top of "
- "a permanent breakpoint");
-
- if (b->enable_state != bp_disabled
- && b->enable_state != bp_shlib_disabled
- && b->enable_state != bp_call_disabled
+ if (b->owner->enable_state != bp_disabled
+ && b->owner->enable_state != bp_shlib_disabled
+ && b->owner->enable_state != bp_call_disabled
&& b->address == address /* address / overlay match */
&& (!overlay_debugging || b->section == section)
- && breakpoint_address_is_meaningful (b))
- b->duplicate = 1;
+ && breakpoint_address_is_meaningful (b->owner))
+ {
+ if (b->inserted)
+ internal_error (__FILE__, __LINE__,
+ "another breakpoint was inserted on top of "
+ "a permanent breakpoint");
+
+ b->duplicate = 1;
+ }
}
}
}
+static void
+breakpoint_adjustment_warning (CORE_ADDR from_addr, CORE_ADDR to_addr,
+ int bnum, int have_bnum)
+{
+ char astr1[40];
+ char astr2[40];
+
+ strcpy (astr1, local_hex_string_custom ((unsigned long) from_addr, "08l"));
+ strcpy (astr2, local_hex_string_custom ((unsigned long) to_addr, "08l"));
+ if (have_bnum)
+ warning ("Breakpoint %d address previously adjusted from %s to %s.",
+ bnum, astr1, astr2);
+ else
+ warning ("Breakpoint address adjusted from %s to %s.", astr1, astr2);
+}
+
+/* Adjust a breakpoint's address to account for architectural constraints
+ on breakpoint placement. Return the adjusted address. Note: Very
+ few targets require this kind of adjustment. For most targets,
+ this function is simply the identity function. */
+
+static CORE_ADDR
+adjust_breakpoint_address (CORE_ADDR bpaddr)
+{
+ if (!gdbarch_adjust_breakpoint_address_p (current_gdbarch))
+ {
+ /* Very few targets need any kind of breakpoint adjustment. */
+ return bpaddr;
+ }
+ else
+ {
+ CORE_ADDR adjusted_bpaddr;
+
+ /* Some targets have architectural constraints on the placement
+ of breakpoint instructions. Obtain the adjusted address. */
+ adjusted_bpaddr = gdbarch_adjust_breakpoint_address (current_gdbarch,
+ bpaddr);
+
+ /* An adjusted breakpoint address can significantly alter
+ a user's expectations. Print a warning if an adjustment
+ is required. */
+ if (adjusted_bpaddr != bpaddr)
+ breakpoint_adjustment_warning (bpaddr, adjusted_bpaddr, 0, 0);
+
+ return adjusted_bpaddr;
+ }
+}
+
+/* Allocate a struct bp_location. */
+
+static struct bp_location *
+allocate_bp_location (struct breakpoint *bpt, enum bptype bp_type)
+{
+ struct bp_location *loc, *loc_p;
+
+ loc = xmalloc (sizeof (struct bp_location));
+ memset (loc, 0, sizeof (*loc));
+
+ loc->owner = bpt;
+
+ switch (bp_type)
+ {
+ case bp_breakpoint:
+ case bp_until:
+ case bp_finish:
+ case bp_longjmp:
+ case bp_longjmp_resume:
+ case bp_step_resume:
+ case bp_through_sigtramp:
+ case bp_watchpoint_scope:
+ case bp_call_dummy:
+ case bp_shlib_event:
+ case bp_thread_event:
+ case bp_overlay_event:
+ case bp_catch_load:
+ case bp_catch_unload:
+ loc->loc_type = bp_loc_software_breakpoint;
+ break;
+ case bp_hardware_breakpoint:
+ loc->loc_type = bp_loc_hardware_breakpoint;
+ break;
+ case bp_hardware_watchpoint:
+ case bp_read_watchpoint:
+ case bp_access_watchpoint:
+ loc->loc_type = bp_loc_hardware_watchpoint;
+ break;
+ case bp_watchpoint:
+ case bp_catch_fork:
+ case bp_catch_vfork:
+ case bp_catch_exec:
+ case bp_catch_catch:
+ case bp_catch_throw:
+ loc->loc_type = bp_loc_other;
+ break;
+ default:
+ internal_error (__FILE__, __LINE__, "unknown breakpoint type");
+ }
+
+ /* Add this breakpoint to the end of the chain. */
+
+ loc_p = bp_location_chain;
+ if (loc_p == 0)
+ bp_location_chain = loc;
+ else
+ {
+ while (loc_p->next)
+ loc_p = loc_p->next;
+ loc_p->next = loc;
+ }
+
+ return loc;
+}
+
/* set_raw_breakpoint() is a low level routine for allocating and
partially initializing a breakpoint of type BPTYPE. The newly
created breakpoint's address, section, source file name, and line
struct breakpoint *
set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype)
{
- register struct breakpoint *b, *b1;
+ struct breakpoint *b, *b1;
b = (struct breakpoint *) xmalloc (sizeof (struct breakpoint));
memset (b, 0, sizeof (*b));
- b->address = sal.pc;
+ b->loc = allocate_bp_location (b, bptype);
+ b->loc->requested_address = sal.pc;
+ b->loc->address = adjust_breakpoint_address (b->loc->requested_address);
if (sal.symtab == NULL)
b->source_file = NULL;
else
b->source_file = savestring (sal.symtab->filename,
strlen (sal.symtab->filename));
- b->section = sal.section;
+ b->loc->section = sal.section;
b->type = bptype;
b->language = current_language->la_language;
b->input_radix = input_radix;
b->enable_state = bp_permanent;
/* By definition, permanent breakpoints are already present in the code. */
- b->inserted = 1;
+ b->loc->inserted = 1;
}
static struct breakpoint *
b = create_internal_breakpoint (0, bp_longjmp_resume);
else
{
- if ((m = lookup_minimal_symbol_text (func_name, NULL, NULL)) == NULL)
+ if ((m = lookup_minimal_symbol_text (func_name, NULL)) == NULL)
return;
b = create_internal_breakpoint (SYMBOL_VALUE_ADDRESS (m), bp_longjmp);
void
enable_longjmp_breakpoint (void)
{
- register struct breakpoint *b;
+ struct breakpoint *b;
ALL_BREAKPOINTS (b)
if (b->type == bp_longjmp)
void
disable_longjmp_breakpoint (void)
{
- register struct breakpoint *b;
+ struct breakpoint *b;
ALL_BREAKPOINTS (b)
if (b->type == bp_longjmp
struct breakpoint *b;
struct minimal_symbol *m;
- if ((m = lookup_minimal_symbol_text (func_name, NULL, NULL)) == NULL)
+ if ((m = lookup_minimal_symbol_text (func_name, NULL)) == NULL)
return;
b = create_internal_breakpoint (SYMBOL_VALUE_ADDRESS (m),
void
enable_overlay_breakpoints (void)
{
- register struct breakpoint *b;
+ struct breakpoint *b;
ALL_BREAKPOINTS (b)
if (b->type == bp_overlay_event)
void
disable_overlay_breakpoints (void)
{
- register struct breakpoint *b;
+ struct breakpoint *b;
ALL_BREAKPOINTS (b)
if (b->type == bp_overlay_event)
b->enable_state = bp_enabled;
/* addr_string has to be used or breakpoint_re_set will delete me. */
- xasprintf (&b->addr_string, "*0x%s", paddr (b->address));
+ xasprintf (&b->addr_string, "*0x%s", paddr (b->loc->address));
return b;
}
void
remove_solib_event_breakpoints (void)
{
- register struct breakpoint *b, *temp;
+ struct breakpoint *b, *temp;
ALL_BREAKPOINTS_SAFE (b, temp)
if (b->type == bp_shlib_event)
if (((b->type == bp_breakpoint) ||
(b->type == bp_hardware_breakpoint)) &&
b->enable_state == bp_enabled &&
- !b->duplicate &&
- PC_SOLIB (b->address))
+ !b->loc->duplicate &&
+ PC_SOLIB (b->loc->address))
{
b->enable_state = bp_shlib_disabled;
if (!silent)
/* Do not reenable the breakpoint if the shared library
is still not mapped in. */
- if (target_read_memory (b->address, buf, 1) == 0)
+ if (target_read_memory (b->loc->address, buf, 1) == 0)
b->enable_state = bp_enabled;
}
}
static int
hw_breakpoint_used_count (void)
{
- register struct breakpoint *b;
+ struct breakpoint *b;
int i = 0;
ALL_BREAKPOINTS (b)
static int
hw_watchpoint_used_count (enum bptype type, int *other_type_used)
{
- register struct breakpoint *b;
+ struct breakpoint *b;
int i = 0;
*other_type_used = 0;
void
set_longjmp_resume_breakpoint (CORE_ADDR pc, struct frame_id frame_id)
{
- register struct breakpoint *b;
+ struct breakpoint *b;
ALL_BREAKPOINTS (b)
if (b->type == bp_longjmp_resume)
{
- b->address = pc;
+ b->loc->requested_address = pc;
+ b->loc->address = adjust_breakpoint_address (b->loc->requested_address);
b->enable_state = bp_enabled;
b->frame_id = frame_id;
check_duplicates (b);
set_momentary_breakpoint (struct symtab_and_line sal, struct frame_id frame_id,
enum bptype type)
{
- register struct breakpoint *b;
+ struct breakpoint *b;
b = set_raw_breakpoint (sal, type);
b->enable_state = bp_enabled;
b->disposition = disp_donttouch;
if (addressprint || b->source_file == NULL)
{
printf_filtered (" at ");
- print_address_numeric (b->address, 1, gdb_stdout);
+ print_address_numeric (b->loc->address, 1, gdb_stdout);
}
if (b->source_file)
printf_filtered (": file %s, line %d.",
else
/* addr_string has to be used or breakpoint_re_set will delete
me. */
- xasprintf (&b->addr_string, "*0x%s", paddr (b->address));
+ xasprintf (&b->addr_string, "*0x%s", paddr (b->loc->address));
b->cond_string = cond_string[i];
b->ignore_count = ignore_count;
b->enable_state = bp_enabled;
{
int tempflag, hardwareflag;
struct symtabs_and_lines sals;
- register struct expression **cond = 0;
+ struct expression **cond = 0;
/* Pointers in arg to the start, and one past the end, of the
condition. */
char **cond_string = (char **) NULL;
{
struct captured_breakpoint_args *args = data;
struct symtabs_and_lines sals;
- register struct expression **cond;
+ struct expression **cond;
struct cleanup *old_chain;
struct cleanup *breakpoint_chain = NULL;
int i;
break_command_1 (arg, 0, from_tty);
}
-/* ARGSUSED */
/* accessflag: hw_write: watch write,
hw_read: watch read,
hw_access: watch access (read or write) */
scope_breakpoint->frame_id = get_frame_id (prev_frame);
/* Set the address at which we will stop. */
- scope_breakpoint->address = get_frame_pc (prev_frame);
+ scope_breakpoint->loc->requested_address
+ = get_frame_pc (prev_frame);
+ scope_breakpoint->loc->address
+ = adjust_breakpoint_address (scope_breakpoint->loc->requested_address);
/* The scope breakpoint is related to the watchpoint. We
will need to act on them together. */
do_exec_cleanups (cleanups);
}
-/* ARGSUSED */
void
until_break_command (char *arg, int from_tty, int anywhere)
{
if (addressprint)
{
annotate_field (4);
- ui_out_field_core_addr (uiout, "addr", b->address);
+ ui_out_field_core_addr (uiout, "addr", b->loc->address);
}
annotate_field (5);
- *last_addr = b->address;
+ *last_addr = b->loc->address;
if (strstr (b->addr_string, "throw") != NULL)
ui_out_field_string (uiout, "what", "exception throw");
else
&& b->type != bp_read_watchpoint
&& b->type != bp_access_watchpoint
/* Not if b is a watchpoint of any sort... */
- && (((sal.pc && (b->address == sal.pc))
- && (!section_is_overlay (b->section)
- || b->section == sal.section))
+ && (((sal.pc && (b->loc->address == sal.pc))
+ && (!section_is_overlay (b->loc->section)
+ || b->loc->section == sal.section))
/* Yes, if sal.pc matches b (modulo overlays). */
|| ((default_match || (0 == sal.pc))
&& b->source_file != NULL
void
delete_breakpoint (struct breakpoint *bpt)
{
- register struct breakpoint *b;
- register bpstat bs;
+ struct breakpoint *b;
+ bpstat bs;
+ struct bp_location *loc;
if (bpt == NULL)
error ("Internal error (attempted to delete a NULL breakpoint)");
delete_breakpoint_hook (bpt);
breakpoint_delete_event (bpt->number);
- if (bpt->inserted)
- remove_breakpoint (bpt, mark_inserted);
+ if (bpt->loc->inserted)
+ remove_breakpoint (bpt->loc, mark_inserted);
if (breakpoint_chain == bpt)
breakpoint_chain = bpt->next;
+ if (bp_location_chain == bpt->loc)
+ bp_location_chain = bpt->loc->next;
+
/* If we have callback-style exception catchpoints, don't go through
the adjustments to the C++ runtime library etc. if the inferior
isn't actually running. target_enable_exception_callback for a
break;
}
+ ALL_BP_LOCATIONS (loc)
+ if (loc->next == bpt->loc)
+ {
+ loc->next = bpt->loc->next;
+ break;
+ }
+
check_duplicates (bpt);
/* If this breakpoint was inserted, and there is another breakpoint
at the same address, we need to insert the other breakpoint. */
- if (bpt->inserted
+ if (bpt->loc->inserted
&& bpt->type != bp_hardware_watchpoint
&& bpt->type != bp_read_watchpoint
&& bpt->type != bp_access_watchpoint
&& bpt->type != bp_catch_exec)
{
ALL_BREAKPOINTS (b)
- if (b->address == bpt->address
- && b->section == bpt->section
- && !b->duplicate
+ if (b->loc->address == bpt->loc->address
+ && b->loc->section == bpt->loc->section
+ && !b->loc->duplicate
&& b->enable_state != bp_disabled
&& b->enable_state != bp_shlib_disabled
&& b->enable_state != bp_call_disabled)
"a permanent breakpoint");
if (b->type == bp_hardware_breakpoint)
- val = target_insert_hw_breakpoint (b->address, b->shadow_contents);
+ val = target_insert_hw_breakpoint (b->loc->address, b->loc->shadow_contents);
else
- val = target_insert_breakpoint (b->address, b->shadow_contents);
+ val = target_insert_breakpoint (b->loc->address, b->loc->shadow_contents);
/* If there was an error in the insert, print a message, then stop execution. */
if (val != 0)
{
fprintf_unfiltered (tmp_error_stream, "Cannot insert breakpoint %d.\n", b->number);
fprintf_filtered (tmp_error_stream, "Error accessing memory address ");
- print_address_numeric (b->address, 1, tmp_error_stream);
+ print_address_numeric (b->loc->address, 1, tmp_error_stream);
fprintf_filtered (tmp_error_stream, ": %s.\n",
safe_strerror (val));
}
error_stream(tmp_error_stream);
}
else
- b->inserted = 1;
+ b->loc->inserted = 1;
}
}
bp, we mark it as deleted before freeing its storage. */
bpt->type = bp_none;
+ xfree (bpt->loc);
xfree (bpt);
}
}
/* We need to re-set the breakpoint if the address changes... */
- if (b->address != sals.sals[i].pc
+ if (b->loc->address != sals.sals[i].pc
/* ...or new and old breakpoints both have source files, and
the source file name or the line number changes... */
|| (b->source_file != NULL
savestring (sals.sals[i].symtab->filename,
strlen (sals.sals[i].symtab->filename));
b->line_number = sals.sals[i].line;
- b->address = sals.sals[i].pc;
+ b->loc->requested_address = sals.sals[i].pc;
+ b->loc->address
+ = adjust_breakpoint_address (b->loc->requested_address);
/* Used to check for duplicates here, but that can
cause trouble, as it doesn't check for disabled
rather than once for every breakpoint. */
breakpoints_changed ();
}
- b->section = sals.sals[i].section;
+ b->loc->section = sals.sals[i].section;
b->enable_state = save_enable; /* Restore it, this worked. */
void
set_ignore_count (int bptnum, int count, int from_tty)
{
- register struct breakpoint *b;
+ struct breakpoint *b;
if (count < 0)
count = 0;
ignore_command (char *args, int from_tty)
{
char *p = args;
- register int num;
+ int num;
if (p == 0)
error_no_arg ("a breakpoint number");
static void
map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *))
{
- register char *p = args;
+ char *p = args;
char *p1;
- register int num;
- register struct breakpoint *b, *tmp;
+ int num;
+ struct breakpoint *b, *tmp;
int match;
if (p == 0)
breakpoint_modify_event (bpt->number);
}
-/* ARGSUSED */
static void
disable_command (char *args, int from_tty)
{
- register struct breakpoint *bpt;
+ struct breakpoint *bpt;
if (args == 0)
ALL_BREAKPOINTS (bpt)
switch (bpt->type)
breakpoints) so they once again become (or continue to be) effective
in stopping the inferior. */
-/* ARGSUSED */
static void
enable_command (char *args, int from_tty)
{
- register struct breakpoint *bpt;
+ struct breakpoint *bpt;
if (args == 0)
ALL_BREAKPOINTS (bpt)
switch (bpt->type)
do_enable_breakpoint (bpt, disp_disable);
}
-/* ARGSUSED */
static void
enable_once_command (char *args, int from_tty)
{
do_enable_breakpoint (bpt, disp_del);
}
-/* ARGSUSED */
static void
enable_delete_command (char *args, int from_tty)
{