summaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorRalf Corsepius <ralf.corsepius@rtems.org>2008-09-17 14:34:15 +0000
committerRalf Corsepius <ralf.corsepius@rtems.org>2008-09-17 14:34:15 +0000
commitaa9a6dce1c3a7728ef2b4c8a5bc0020ef32d9d14 (patch)
tree73287bd67de75a2ce6aca0eb9a73f7be698691e7 /contrib
parentSwitch to gcc-core-4.3.2-rtems4.10-20080917.diff. (diff)
downloadrtems-aa9a6dce1c3a7728ef2b4c8a5bc0020ef32d9d14.tar.bz2
Add patch from http://sourceware.org/ml/gdb-patches/2008-02/msg00472.html
Diffstat (limited to 'contrib')
-rw-r--r--contrib/crossrpms/patches/gdb-6.8-rtems4.10-20080917.diff13354
1 files changed, 13354 insertions, 0 deletions
diff --git a/contrib/crossrpms/patches/gdb-6.8-rtems4.10-20080917.diff b/contrib/crossrpms/patches/gdb-6.8-rtems4.10-20080917.diff
new file mode 100644
index 0000000000..5b5243fa2e
--- /dev/null
+++ b/contrib/crossrpms/patches/gdb-6.8-rtems4.10-20080917.diff
@@ -0,0 +1,13354 @@
+diff -Naur gdb-6.8.orig/gdb/breakpoint.c gdb-6.8/gdb/breakpoint.c
+--- gdb-6.8.orig/gdb/breakpoint.c 2008-02-26 09:14:11.000000000 +0100
++++ gdb-6.8/gdb/breakpoint.c 2008-09-17 16:32:32.000000000 +0200
+@@ -55,6 +55,7 @@
+ #include "memattr.h"
+ #include "ada-lang.h"
+ #include "top.h"
++#include "wrapper.h"
+
+ #include "gdb-events.h"
+ #include "mi/mi-common.h"
+@@ -826,7 +827,65 @@
+ || bpt->type == bp_access_watchpoint);
+ }
+
+-/* Assuming that B is a hardware breakpoint:
++/* Find the current value of a watchpoint on EXP. Return the value in
++ *VALP and *RESULTP and the chain of intermediate and final values
++ 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
++ 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
++ (we should watch only the bit used to locate the final value).
++
++ If the final value, or any intermediate value, could not be read
++ from memory, *VALP will be set to NULL. *VAL_CHAIN will still be
++ set to any referenced values. *VALP will never be a lazy value.
++ This is the value which we store in struct breakpoint.
++
++ If VAL_CHAIN is non-NULL, *VAL_CHAIN will be released from the
++ value chain. The caller must free the values individually. If
++ VAL_CHAIN is NULL, all generated values will be left on the value
++ chain. */
++
++static void
++fetch_watchpoint_value (struct expression *exp, struct value **valp,
++ struct value **resultp, struct value **val_chain)
++{
++ struct value *mark, *new_mark, *result;
++
++ *valp = NULL;
++ if (resultp)
++ *resultp = NULL;
++ if (val_chain)
++ *val_chain = NULL;
++
++ /* Evaluate the expression. */
++ mark = value_mark ();
++ result = NULL;
++ gdb_evaluate_expression (exp, &result);
++ new_mark = value_mark ();
++ if (mark == new_mark)
++ return;
++ if (resultp)
++ *resultp = result;
++
++ /* Make sure it's not lazy, so that after the target stops again we
++ have a non-lazy previous value to compare with. */
++ if (result != NULL
++ && (!value_lazy (result) || gdb_value_fetch_lazy (result)))
++ *valp = result;
++
++ if (val_chain)
++ {
++ /* Return the chain of intermediate values. We use this to
++ decide which addresses to watch. */
++ *val_chain = new_mark;
++ value_release_to_mark (mark);
++ }
++}
++
++/* Assuming that B is a hardware watchpoint:
+ - Reparse watchpoint expression, is REPARSE is non-zero
+ - Evaluate expression and store the result in B->val
+ - Update the list of values that must be watched in B->loc.
+@@ -837,7 +896,6 @@
+ update_watchpoint (struct breakpoint *b, int reparse)
+ {
+ int within_current_scope;
+- struct value *mark = value_mark ();
+ struct frame_id saved_frame_id;
+ struct bp_location *loc;
+ bpstat bs;
+@@ -889,9 +947,9 @@
+ to the user when the old value and the new value may actually
+ be completely different objects. */
+ value_free (b->val);
+- b->val = NULL;
++ b->val = NULL;
++ b->val_valid = 0;
+ }
+-
+
+ /* If we failed to parse the expression, for example because
+ it refers to a global variable in a not-yet-loaded shared library,
+@@ -900,43 +958,37 @@
+ is different from out-of-scope watchpoint. */
+ if (within_current_scope && b->exp)
+ {
+- struct value *v, *next;
++ struct value *val_chain, *v, *result, *next;
++
++ fetch_watchpoint_value (b->exp, &v, &result, &val_chain);
+
+- /* Evaluate the expression and make sure it's not lazy, so that
+- after target stops again, we have a non-lazy previous value
+- to compare with. Also, making the value non-lazy will fetch
+- intermediate values as needed, which we use to decide which
+- addresses to watch.
+-
+- The value returned by evaluate_expression is stored in b->val.
+- In addition, we look at all values which were created
+- during evaluation, and set watchoints at addresses as needed.
+- Those values are explicitly deleted here. */
+- v = evaluate_expression (b->exp);
+ /* Avoid setting b->val if it's already set. The meaning of
+ b->val is 'the last value' user saw, and we should update
+ it only if we reported that last value to user. As it
+ happens, the code that reports it updates b->val directly. */
+- if (b->val == NULL)
+- b->val = v;
+- value_contents (v);
+- value_release_to_mark (mark);
++ if (!b->val_valid)
++ {
++ b->val = v;
++ b->val_valid = 1;
++ }
+
+ /* Look at each value on the value chain. */
+- for (; v; v = next)
++ for (v = val_chain; v; v = next)
+ {
+ /* If it's a memory location, and GDB actually needed
+ its contents to evaluate the expression, then we
+- must watch it. */
++ must watch it. If the first value returned is
++ still lazy, that means an error occurred reading it;
++ watch it anyway in case it becomes readable. */
+ if (VALUE_LVAL (v) == lval_memory
+- && ! value_lazy (v))
++ && (v == val_chain || ! 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
++ if (v == result
+ || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+ && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+ {
+@@ -1681,6 +1733,7 @@
+ if (b->val)
+ value_free (b->val);
+ b->val = NULL;
++ b->val_valid = 0;
+ }
+ break;
+ default:
+@@ -2103,6 +2156,17 @@
+ do_cleanups (old_chain);
+ }
+
++/* Print out the (old or new) value associated with a watchpoint. */
++
++static void
++watchpoint_value_print (struct value *val, struct ui_file *stream)
++{
++ if (val == NULL)
++ fprintf_unfiltered (stream, _("<unreadable>"));
++ else
++ value_print (val, stream, 0, Val_pretty_default);
++}
++
+ /* This is the normal print function for a bpstat. In the future,
+ much of this logic could (should?) be moved to bpstat_stop_status,
+ by having it set different print_it values.
+@@ -2221,26 +2285,21 @@
+
+ case bp_watchpoint:
+ case bp_hardware_watchpoint:
+- if (bs->old_val != NULL)
+- {
+- annotate_watchpoint (b->number);
+- if (ui_out_is_mi_like_p (uiout))
+- ui_out_field_string
+- (uiout, "reason",
+- async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
+- mention (b);
+- ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
+- ui_out_text (uiout, "\nOld value = ");
+- value_print (bs->old_val, stb->stream, 0, Val_pretty_default);
+- ui_out_field_stream (uiout, "old", stb);
+- ui_out_text (uiout, "\nNew value = ");
+- value_print (b->val, stb->stream, 0, Val_pretty_default);
+- ui_out_field_stream (uiout, "new", stb);
+- do_cleanups (ui_out_chain);
+- ui_out_text (uiout, "\n");
+- value_free (bs->old_val);
+- bs->old_val = NULL;
+- }
++ annotate_watchpoint (b->number);
++ if (ui_out_is_mi_like_p (uiout))
++ ui_out_field_string
++ (uiout, "reason",
++ async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
++ mention (b);
++ ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
++ ui_out_text (uiout, "\nOld value = ");
++ watchpoint_value_print (bs->old_val, stb->stream);
++ ui_out_field_stream (uiout, "old", stb);
++ ui_out_text (uiout, "\nNew value = ");
++ watchpoint_value_print (b->val, stb->stream);
++ ui_out_field_stream (uiout, "new", stb);
++ do_cleanups (ui_out_chain);
++ ui_out_text (uiout, "\n");
+ /* More than one watchpoint may have been triggered. */
+ return PRINT_UNKNOWN;
+ break;
+@@ -2253,7 +2312,7 @@
+ mention (b);
+ ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
+ ui_out_text (uiout, "\nValue = ");
+- value_print (b->val, stb->stream, 0, Val_pretty_default);
++ watchpoint_value_print (b->val, stb->stream);
+ ui_out_field_stream (uiout, "value", stb);
+ do_cleanups (ui_out_chain);
+ ui_out_text (uiout, "\n");
+@@ -2261,7 +2320,7 @@
+ break;
+
+ case bp_access_watchpoint:
+- if (bs->old_val != NULL)
++ if (bs->old_val != NULL)
+ {
+ annotate_watchpoint (b->number);
+ if (ui_out_is_mi_like_p (uiout))
+@@ -2271,10 +2330,8 @@
+ mention (b);
+ ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
+ ui_out_text (uiout, "\nOld value = ");
+- value_print (bs->old_val, stb->stream, 0, Val_pretty_default);
++ watchpoint_value_print (bs->old_val, stb->stream);
+ ui_out_field_stream (uiout, "old", stb);
+- value_free (bs->old_val);
+- bs->old_val = NULL;
+ ui_out_text (uiout, "\nNew value = ");
+ }
+ else
+@@ -2287,7 +2344,7 @@
+ ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
+ ui_out_text (uiout, "\nValue = ");
+ }
+- value_print (b->val, stb->stream, 0,Val_pretty_default);
++ watchpoint_value_print (b->val, stb->stream);
+ ui_out_field_stream (uiout, "new", stb);
+ do_cleanups (ui_out_chain);
+ ui_out_text (uiout, "\n");
+@@ -2574,13 +2631,20 @@
+ we might be in the middle of evaluating a function call. */
+
+ struct value *mark = value_mark ();
+- struct value *new_val = evaluate_expression (b->exp);
+- if (!value_equal (b->val, new_val))
++ struct value *new_val;
++
++ fetch_watchpoint_value (b->exp, &new_val, NULL, NULL);
++ if ((b->val != NULL) != (new_val != NULL)
++ || (b->val != NULL && !value_equal (b->val, new_val)))
+ {
+- release_value (new_val);
+- value_free_to_mark (mark);
++ if (new_val != NULL)
++ {
++ release_value (new_val);
++ value_free_to_mark (mark);
++ }
+ bs->old_val = b->val;
+ b->val = new_val;
++ b->val_valid = 1;
+ /* We will stop here */
+ return WP_VALUE_CHANGED;
+ }
+@@ -5722,10 +5786,9 @@
+ exp_end = arg;
+ exp_valid_block = innermost_block;
+ mark = value_mark ();
+- val = evaluate_expression (exp);
+- release_value (val);
+- if (value_lazy (val))
+- value_fetch_lazy (val);
++ fetch_watchpoint_value (exp, &val, NULL, NULL);
++ if (val != NULL)
++ release_value (val);
+
+ tok = arg;
+ while (*tok == ' ' || *tok == '\t')
+@@ -5814,6 +5877,7 @@
+ b->exp_valid_block = exp_valid_block;
+ b->exp_string = savestring (exp_start, exp_end - exp_start);
+ b->val = val;
++ b->val_valid = 1;
+ b->loc->cond = cond;
+ if (cond_start)
+ b->cond_string = savestring (cond_start, cond_end - cond_start);
+@@ -7697,11 +7761,11 @@
+ if (bpt->val)
+ value_free (bpt->val);
+ mark = value_mark ();
+- bpt->val = evaluate_expression (bpt->exp);
+- release_value (bpt->val);
+- if (value_lazy (bpt->val))
+- value_fetch_lazy (bpt->val);
+-
++ fetch_watchpoint_value (bpt->exp, &bpt->val, NULL, NULL);
++ if (bpt->val)
++ release_value (bpt->val);
++ bpt->val_valid = 1;
++
+ if (bpt->type == bp_hardware_watchpoint ||
+ bpt->type == bp_read_watchpoint ||
+ bpt->type == bp_access_watchpoint)
+diff -Naur gdb-6.8.orig/gdb/breakpoint.c.orig gdb-6.8/gdb/breakpoint.c.orig
+--- gdb-6.8.orig/gdb/breakpoint.c.orig 1970-01-01 01:00:00.000000000 +0100
++++ gdb-6.8/gdb/breakpoint.c.orig 2008-02-26 09:14:11.000000000 +0100
+@@ -0,0 +1,8357 @@
++/* Everything about breakpoints, for GDB.
++
++ Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
++ 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
++ 2008 Free Software Foundation, Inc.
++
++ This file is part of GDB.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 3 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program. If not, see <http://www.gnu.org/licenses/>. */
++
++#include "defs.h"
++#include <ctype.h>
++#include "hashtab.h"
++#include "symtab.h"
++#include "frame.h"
++#include "breakpoint.h"
++#include "gdbtypes.h"
++#include "expression.h"
++#include "gdbcore.h"
++#include "gdbcmd.h"
++#include "value.h"
++#include "command.h"
++#include "inferior.h"
++#include "gdbthread.h"
++#include "target.h"
++#include "language.h"
++#include "gdb_string.h"
++#include "demangle.h"
++#include "annotate.h"
++#include "symfile.h"
++#include "objfiles.h"
++#include "source.h"
++#include "linespec.h"
++#include "completer.h"
++#include "gdb.h"
++#include "ui-out.h"
++#include "cli/cli-script.h"
++#include "gdb_assert.h"
++#include "block.h"
++#include "solib.h"
++#include "solist.h"
++#include "observer.h"
++#include "exceptions.h"
++#include "memattr.h"
++#include "ada-lang.h"
++#include "top.h"
++
++#include "gdb-events.h"
++#include "mi/mi-common.h"
++
++/* Prototypes for local functions. */
++
++static void until_break_command_continuation (struct continuation_arg *arg);
++
++static void catch_command_1 (char *, int, int);
++
++static void enable_delete_command (char *, int);
++
++static void enable_delete_breakpoint (struct breakpoint *);
++
++static void enable_once_command (char *, int);
++
++static void enable_once_breakpoint (struct breakpoint *);
++
++static void disable_command (char *, int);
++
++static void enable_command (char *, int);
++
++static void map_breakpoint_numbers (char *, void (*)(struct breakpoint *));
++
++static void ignore_command (char *, int);
++
++static int breakpoint_re_set_one (void *);
++
++static void clear_command (char *, int);
++
++static void catch_command (char *, int);
++
++static void watch_command (char *, int);
++
++static int can_use_hardware_watchpoint (struct value *);
++
++static void break_command_1 (char *, int, int);
++
++static void mention (struct breakpoint *);
++
++struct breakpoint *set_raw_breakpoint (struct symtab_and_line, enum bptype);
++
++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,
++ enum bptype bptype);
++
++static void describe_other_breakpoints (CORE_ADDR, asection *, int);
++
++static void breakpoints_info (char *, int);
++
++static void breakpoint_1 (int, int);
++
++static bpstat bpstat_alloc (const struct bp_location *, bpstat);
++
++static int breakpoint_cond_eval (void *);
++
++static void cleanup_executing_breakpoints (void *);
++
++static void commands_command (char *, int);
++
++static void condition_command (char *, int);
++
++static int get_number_trailer (char **, int);
++
++void set_breakpoint_count (int);
++
++typedef enum
++ {
++ mark_inserted,
++ mark_uninserted
++ }
++insertion_state_t;
++
++static int remove_breakpoint (struct bp_location *, insertion_state_t);
++
++static enum print_stop_action print_it_typical (bpstat);
++
++static enum print_stop_action print_bp_stop_message (bpstat bs);
++
++typedef struct
++ {
++ enum exception_event_kind kind;
++ int enable_p;
++ }
++args_for_catchpoint_enable;
++
++static int watchpoint_check (void *);
++
++static void maintenance_info_breakpoints (char *, int);
++
++static void create_longjmp_breakpoint (char *);
++
++static void create_overlay_event_breakpoint (char *);
++
++static int hw_breakpoint_used_count (void);
++
++static int hw_watchpoint_used_count (enum bptype, int *);
++
++static void hbreak_command (char *, int);
++
++static void thbreak_command (char *, int);
++
++static void watch_command_1 (char *, int, int);
++
++static void rwatch_command (char *, int);
++
++static void awatch_command (char *, int);
++
++static void do_enable_breakpoint (struct breakpoint *, enum bpdisp);
++
++static void create_fork_vfork_event_catchpoint (int tempflag,
++ char *cond_string,
++ enum bptype bp_kind);
++
++static void stop_command (char *arg, int from_tty);
++
++static void stopin_command (char *arg, int from_tty);
++
++static void stopat_command (char *arg, int from_tty);
++
++static char *ep_find_event_name_end (char *arg);
++
++static char *ep_parse_optional_if_clause (char **arg);
++
++static char *ep_parse_optional_filename (char **arg);
++
++static void create_exception_catchpoint (int tempflag, char *cond_string,
++ enum exception_event_kind ex_event,
++ struct symtab_and_line *sal);
++
++static void catch_exception_command_1 (enum exception_event_kind ex_event,
++ char *arg, int tempflag, int from_tty);
++
++static void tcatch_command (char *arg, int from_tty);
++
++static void ep_skip_leading_whitespace (char **s);
++
++static int single_step_breakpoint_inserted_here_p (CORE_ADDR pc);
++
++static void free_bp_location (struct bp_location *loc);
++
++static void mark_breakpoints_out (void);
++
++static struct bp_location *
++allocate_bp_location (struct breakpoint *bpt, enum bptype bp_type);
++
++static void
++unlink_locations_from_global_list (struct breakpoint *bpt);
++
++static int
++is_hardware_watchpoint (struct breakpoint *bpt);
++
++/* Prototypes for exported functions. */
++
++/* If FALSE, gdb will not use hardware support for watchpoints, even
++ if such is available. */
++static int can_use_hw_watchpoints;
++
++static void
++show_can_use_hw_watchpoints (struct ui_file *file, int from_tty,
++ struct cmd_list_element *c,
++ const char *value)
++{
++ fprintf_filtered (file, _("\
++Debugger's willingness to use watchpoint hardware is %s.\n"),
++ value);
++}
++
++/* If AUTO_BOOLEAN_FALSE, gdb will not attempt to create pending breakpoints.
++ If AUTO_BOOLEAN_TRUE, gdb will automatically create pending breakpoints
++ for unrecognized breakpoint locations.
++ If AUTO_BOOLEAN_AUTO, gdb will query when breakpoints are unrecognized. */
++static enum auto_boolean pending_break_support;
++static void
++show_pending_break_support (struct ui_file *file, int from_tty,
++ struct cmd_list_element *c,
++ const char *value)
++{
++ fprintf_filtered (file, _("\
++Debugger's behavior regarding pending breakpoints is %s.\n"),
++ value);
++}
++
++/* If 1, gdb will automatically use hardware breakpoints for breakpoints
++ set with "break" but falling in read-only memory.
++ If 0, gdb will warn about such breakpoints, but won't automatically
++ use hardware breakpoints. */
++static int automatic_hardware_breakpoints;
++static void
++show_automatic_hardware_breakpoints (struct ui_file *file, int from_tty,
++ struct cmd_list_element *c,
++ const char *value)
++{
++ fprintf_filtered (file, _("\
++Automatic usage of hardware breakpoints is %s.\n"),
++ value);
++}
++
++
++void _initialize_breakpoint (void);
++
++extern int addressprint; /* Print machine addresses? */
++
++/* Are we executing breakpoint commands? */
++static int executing_breakpoint_commands;
++
++/* Are overlay event breakpoints enabled? */
++static int overlay_events_enabled;
++
++/* Walk the following statement or block through all breakpoints.
++ ALL_BREAKPOINTS_SAFE does so even if the statment deletes the current
++ breakpoint. */
++
++#define ALL_BREAKPOINTS(B) for (B = breakpoint_chain; B; B = B->next)
++
++#define ALL_BREAKPOINTS_SAFE(B,TMP) \
++ for (B = breakpoint_chain; \
++ 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->global_next)
++
++#define ALL_BP_LOCATIONS_SAFE(B,TMP) \
++ for (B = bp_location_chain; \
++ B ? (TMP=B->global_next, 1): 0; \
++ B = TMP)
++
++/* True if breakpoint hit counts should be displayed in breakpoint info. */
++
++int show_breakpoint_hit_counts = 1;
++
++/* Chains of all breakpoints defined. */
++
++struct breakpoint *breakpoint_chain;
++
++struct bp_location *bp_location_chain;
++
++/* Number of last breakpoint made. */
++
++int breakpoint_count;
++
++/* Pointer to current exception event record */
++static struct exception_event_record *current_exception_event;
++
++/* This function returns a pointer to the string representation of the
++ pathname of the dynamically-linked library that has just been
++ loaded.
++
++ This function must be used only when SOLIB_HAVE_LOAD_EVENT is TRUE,
++ or undefined results are guaranteed.
++
++ This string's contents are only valid immediately after the
++ inferior has stopped in the dynamic linker hook, and becomes
++ invalid as soon as the inferior is continued. Clients should make
++ a copy of this string if they wish to continue the inferior and
++ then access the string. */
++
++#ifndef SOLIB_LOADED_LIBRARY_PATHNAME
++#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) ""
++#endif
++
++/* This function returns a pointer to the string representation of the
++ pathname of the dynamically-linked library that has just been
++ unloaded.
++
++ This function must be used only when SOLIB_HAVE_UNLOAD_EVENT is
++ TRUE, or undefined results are guaranteed.
++
++ This string's contents are only valid immediately after the
++ inferior has stopped in the dynamic linker hook, and becomes
++ invalid as soon as the inferior is continued. Clients should make
++ a copy of this string if they wish to continue the inferior and
++ then access the string. */
++
++#ifndef SOLIB_UNLOADED_LIBRARY_PATHNAME
++#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) ""
++#endif
++
++/* This function is called by the "catch load" command. It allows the
++ debugger to be notified by the dynamic linker when a specified
++ library file (or any library file, if filename is NULL) is loaded. */
++
++#ifndef SOLIB_CREATE_CATCH_LOAD_HOOK
++#define SOLIB_CREATE_CATCH_LOAD_HOOK(pid,tempflag,filename,cond_string) \
++ error (_("catch of library loads not yet implemented on this platform"))
++#endif
++
++/* This function is called by the "catch unload" command. It allows
++ the debugger to be notified by the dynamic linker when a specified
++ library file (or any library file, if filename is NULL) is
++ unloaded. */
++
++#ifndef SOLIB_CREATE_CATCH_UNLOAD_HOOK
++#define SOLIB_CREATE_CATCH_UNLOAD_HOOK(pid, tempflag, filename, cond_string) \
++ error (_("catch of library unloads not yet implemented on this platform"))
++#endif
++
++/* Return whether a breakpoint is an active enabled breakpoint. */
++static int
++breakpoint_enabled (struct breakpoint *b)
++{
++ return (b->enable_state == bp_enabled);
++}
++
++/* Set breakpoint count to NUM. */
++
++void
++set_breakpoint_count (int num)
++{
++ breakpoint_count = num;
++ set_internalvar (lookup_internalvar ("bpnum"),
++ value_from_longest (builtin_type_int, (LONGEST) num));
++}
++
++/* Used in run_command to zero the hit count when a new run starts. */
++
++void
++clear_breakpoint_hit_counts (void)
++{
++ struct breakpoint *b;
++
++ ALL_BREAKPOINTS (b)
++ b->hit_count = 0;
++}
++
++/* Default address, symtab and line to put a breakpoint at
++ for "break" command with no arg.
++ if default_breakpoint_valid is zero, the other three are
++ not valid, and "break" with no arg is an error.
++
++ This set by print_stack_frame, which calls set_default_breakpoint. */
++
++int default_breakpoint_valid;
++CORE_ADDR default_breakpoint_address;
++struct symtab *default_breakpoint_symtab;
++int default_breakpoint_line;
++
++/* *PP is a string denoting a breakpoint. Get the number of the breakpoint.
++ Advance *PP after the string and any trailing whitespace.
++
++ Currently the string can either be a number or "$" followed by the name
++ of a convenience variable. Making it an expression wouldn't work well
++ for map_breakpoint_numbers (e.g. "4 + 5 + 6").
++
++ If the string is a NULL pointer, that denotes the last breakpoint.
++
++ TRAILER is a character which can be found after the number; most
++ commonly this is `-'. If you don't want a trailer, use \0. */
++static int
++get_number_trailer (char **pp, int trailer)
++{
++ int retval = 0; /* default */
++ char *p = *pp;
++
++ if (p == NULL)
++ /* Empty line means refer to the last breakpoint. */
++ return breakpoint_count;
++ else if (*p == '$')
++ {
++ /* Make a copy of the name, so we can null-terminate it
++ to pass to lookup_internalvar(). */
++ char *varname;
++ char *start = ++p;
++ struct value *val;
++
++ while (isalnum (*p) || *p == '_')
++ p++;
++ varname = (char *) alloca (p - start + 1);
++ strncpy (varname, start, p - start);
++ varname[p - start] = '\0';
++ val = value_of_internalvar (lookup_internalvar (varname));
++ if (TYPE_CODE (value_type (val)) == TYPE_CODE_INT)
++ retval = (int) value_as_long (val);
++ else
++ {
++ printf_filtered (_("Convenience variable must have integer value.\n"));
++ retval = 0;
++ }
++ }
++ else
++ {
++ if (*p == '-')
++ ++p;
++ while (*p >= '0' && *p <= '9')
++ ++p;
++ if (p == *pp)
++ /* There is no number here. (e.g. "cond a == b"). */
++ {
++ /* Skip non-numeric token */
++ while (*p && !isspace((int) *p))
++ ++p;
++ /* Return zero, which caller must interpret as error. */
++ retval = 0;
++ }
++ else
++ retval = atoi (*pp);
++ }
++ if (!(isspace (*p) || *p == '\0' || *p == trailer))
++ {
++ /* Trailing junk: return 0 and let caller print error msg. */
++ while (!(isspace (*p) || *p == '\0' || *p == trailer))
++ ++p;
++ retval = 0;
++ }
++ while (isspace (*p))
++ p++;
++ *pp = p;
++ return retval;
++}
++
++
++/* Like get_number_trailer, but don't allow a trailer. */
++int
++get_number (char **pp)
++{
++ return get_number_trailer (pp, '\0');
++}
++
++/* Parse a number or a range.
++ * A number will be of the form handled by get_number.
++ * A range will be of the form <number1> - <number2>, and
++ * will represent all the integers between number1 and number2,
++ * inclusive.
++ *
++ * While processing a range, this fuction is called iteratively;
++ * At each call it will return the next value in the range.
++ *
++ * At the beginning of parsing a range, the char pointer PP will
++ * be advanced past <number1> and left pointing at the '-' token.
++ * Subsequent calls will not advance the pointer until the range
++ * is completed. The call that completes the range will advance
++ * pointer PP past <number2>.
++ */
++
++int
++get_number_or_range (char **pp)
++{
++ static int last_retval, end_value;
++ static char *end_ptr;
++ static int in_range = 0;
++
++ if (**pp != '-')
++ {
++ /* Default case: pp is pointing either to a solo number,
++ or to the first number of a range. */
++ last_retval = get_number_trailer (pp, '-');
++ if (**pp == '-')
++ {
++ char **temp;
++
++ /* This is the start of a range (<number1> - <number2>).
++ Skip the '-', parse and remember the second number,
++ and also remember the end of the final token. */
++
++ temp = &end_ptr;
++ end_ptr = *pp + 1;
++ while (isspace ((int) *end_ptr))
++ end_ptr++; /* skip white space */
++ end_value = get_number (temp);
++ if (end_value < last_retval)
++ {
++ error (_("inverted range"));
++ }
++ else if (end_value == last_retval)
++ {
++ /* degenerate range (number1 == number2). Advance the
++ token pointer so that the range will be treated as a
++ single number. */
++ *pp = end_ptr;
++ }
++ else
++ in_range = 1;
++ }
++ }
++ else if (! in_range)
++ error (_("negative value"));
++ else
++ {
++ /* pp points to the '-' that betokens a range. All
++ number-parsing has already been done. Return the next
++ integer value (one greater than the saved previous value).
++ Do not advance the token pointer 'pp' until the end of range
++ is reached. */
++
++ if (++last_retval == end_value)
++ {
++ /* End of range reached; advance token pointer. */
++ *pp = end_ptr;
++ in_range = 0;
++ }
++ }
++ return last_retval;
++}
++
++
++
++/* condition N EXP -- set break condition of breakpoint N to EXP. */
++
++static void
++condition_command (char *arg, int from_tty)
++{
++ struct breakpoint *b;
++ char *p;
++ int bnum;
++
++ if (arg == 0)
++ error_no_arg (_("breakpoint number"));
++
++ p = arg;
++ bnum = get_number (&p);
++ if (bnum == 0)
++ error (_("Bad breakpoint argument: '%s'"), arg);
++
++ ALL_BREAKPOINTS (b)
++ if (b->number == bnum)
++ {
++ struct bp_location *loc = b->loc;
++ for (; loc; loc = loc->next)
++ {
++ if (loc->cond)
++ {
++ xfree (loc->cond);
++ loc->cond = 0;
++ }
++ }
++ if (b->cond_string != NULL)
++ xfree (b->cond_string);
++
++ if (*p == 0)
++ {
++ b->cond_string = NULL;
++ if (from_tty)
++ printf_filtered (_("Breakpoint %d now unconditional.\n"), bnum);
++ }
++ else
++ {
++ arg = p;
++ /* 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->condition_not_parsed = 0;
++ for (loc = b->loc; loc; loc = loc->next)
++ {
++ arg = p;
++ loc->cond = parse_exp_1 (&arg, block_for_pc (loc->address), 0);
++ if (*arg)
++ error (_("Junk at end of expression"));
++ }
++ }
++ breakpoints_changed ();
++ breakpoint_modify_event (b->number);
++ return;
++ }
++
++ error (_("No breakpoint number %d."), bnum);
++}
++
++static void
++commands_command (char *arg, int from_tty)
++{
++ struct breakpoint *b;
++ char *p;
++ int bnum;
++ struct command_line *l;
++
++ /* If we allowed this, we would have problems with when to
++ free the storage, if we change the commands currently
++ being read from. */
++
++ if (executing_breakpoint_commands)
++ error (_("Can't use the \"commands\" command among a breakpoint's commands."));
++
++ p = arg;
++ bnum = get_number (&p);
++
++ if (p && *p)
++ error (_("Unexpected extra arguments following breakpoint number."));
++
++ ALL_BREAKPOINTS (b)
++ if (b->number == bnum)
++ {
++ char *tmpbuf = xstrprintf ("Type commands for when breakpoint %d is hit, one per line.",
++ bnum);
++ struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
++ l = read_command_lines (tmpbuf, from_tty);
++ do_cleanups (cleanups);
++ free_command_lines (&b->commands);
++ b->commands = l;
++ breakpoints_changed ();
++ breakpoint_modify_event (b->number);
++ return;
++ }
++ error (_("No breakpoint number %d."), bnum);
++}
++
++/* Like commands_command, but instead of reading the commands from
++ input stream, takes them from an already parsed command structure.
++
++ This is used by cli-script.c to DTRT with breakpoint commands
++ that are part of if and while bodies. */
++enum command_control_type
++commands_from_control_command (char *arg, struct command_line *cmd)
++{
++ struct breakpoint *b;
++ char *p;
++ int bnum;
++
++ /* If we allowed this, we would have problems with when to
++ free the storage, if we change the commands currently
++ being read from. */
++
++ if (executing_breakpoint_commands)
++ error (_("Can't use the \"commands\" command among a breakpoint's commands."));
++
++ /* An empty string for the breakpoint number means the last
++ breakpoint, but get_number expects a NULL pointer. */
++ if (arg && !*arg)
++ p = NULL;
++ else
++ p = arg;
++ bnum = get_number (&p);
++
++ if (p && *p)
++ error (_("Unexpected extra arguments following breakpoint number."));
++
++ ALL_BREAKPOINTS (b)
++ if (b->number == bnum)
++ {
++ free_command_lines (&b->commands);
++ if (cmd->body_count != 1)
++ error (_("Invalid \"commands\" block structure."));
++ /* We need to copy the commands because if/while will free the
++ list after it finishes execution. */
++ b->commands = copy_command_lines (cmd->body_list[0]);
++ breakpoints_changed ();
++ breakpoint_modify_event (b->number);
++ return simple_control;
++ }
++ error (_("No breakpoint number %d."), bnum);
++}
++
++/* Like target_read_memory() but if breakpoints are inserted, return
++ the shadow contents instead of the breakpoints themselves.
++
++ Read "memory data" from whatever target or inferior we have.
++ Returns zero if successful, errno value if not. EIO is used
++ for address out of bounds. If breakpoints are inserted, returns
++ shadow contents, not the breakpoints themselves. From breakpoint.c. */
++
++int
++read_memory_nobpt (CORE_ADDR memaddr, gdb_byte *myaddr, unsigned len)
++{
++ int status;
++ const struct bp_location *b;
++ CORE_ADDR bp_addr = 0;
++ int bp_size = 0;
++
++ if (gdbarch_breakpoint_from_pc (current_gdbarch, &bp_addr, &bp_size) == NULL)
++ /* No breakpoints on this machine. */
++ return target_read_memory (memaddr, myaddr, len);
++
++ ALL_BP_LOCATIONS (b)
++ {
++ if (b->owner->type == bp_none)
++ warning (_("reading through apparently deleted breakpoint #%d?"),
++ b->owner->number);
++
++ if (b->loc_type != bp_loc_software_breakpoint)
++ continue;
++ if (!b->inserted)
++ continue;
++ /* Addresses and length of the part of the breakpoint that
++ we need to copy. */
++ bp_addr = b->target_info.placed_address;
++ bp_size = b->target_info.shadow_len;
++ if (bp_size == 0)
++ /* bp isn't valid, or doesn't shadow memory. */
++ continue;
++ if (bp_addr + bp_size <= memaddr)
++ /* The breakpoint is entirely before the chunk of memory we
++ are reading. */
++ continue;
++ if (bp_addr >= memaddr + len)
++ /* The breakpoint is entirely after the chunk of memory we are
++ reading. */
++ continue;
++ /* Copy the breakpoint from the shadow contents, and recurse for
++ the things before and after. */
++ {
++ /* Offset within shadow_contents. */
++ int bptoffset = 0;
++
++ if (bp_addr < memaddr)
++ {
++ /* Only copy the second part of the breakpoint. */
++ bp_size -= memaddr - bp_addr;
++ bptoffset = memaddr - bp_addr;
++ bp_addr = memaddr;
++ }
++
++ if (bp_addr + bp_size > memaddr + len)
++ {
++ /* Only copy the first part of the breakpoint. */
++ bp_size -= (bp_addr + bp_size) - (memaddr + len);
++ }
++
++ memcpy (myaddr + bp_addr - memaddr,
++ b->target_info.shadow_contents + bptoffset, bp_size);
++
++ if (bp_addr > memaddr)
++ {
++ /* Copy the section of memory before the breakpoint. */
++ status = read_memory_nobpt (memaddr, myaddr, bp_addr - memaddr);
++ if (status != 0)
++ return status;
++ }
++
++ if (bp_addr + bp_size < memaddr + len)
++ {
++ /* Copy the section of memory after the breakpoint. */
++ status = read_memory_nobpt (bp_addr + bp_size,
++ myaddr + bp_addr + bp_size - memaddr,
++ memaddr + len - (bp_addr + bp_size));
++ if (status != 0)
++ return status;
++ }
++ return 0;
++ }
++ }
++ /* Nothing overlaps. Just call read_memory_noerr. */
++ return target_read_memory (memaddr, myaddr, len);
++}
++
++
++/* A wrapper function for inserting catchpoints. */
++static void
++insert_catchpoint (struct ui_out *uo, void *args)
++{
++ struct breakpoint *b = (struct breakpoint *) args;
++ int val = -1;
++
++ switch (b->type)
++ {
++ case bp_catch_fork:
++ target_insert_fork_catchpoint (PIDGET (inferior_ptid));
++ break;
++ case bp_catch_vfork:
++ target_insert_vfork_catchpoint (PIDGET (inferior_ptid));
++ break;
++ case bp_catch_exec:
++ target_insert_exec_catchpoint (PIDGET (inferior_ptid));
++ break;
++ default:
++ internal_error (__FILE__, __LINE__, _("unknown breakpoint type"));
++ break;
++ }
++}
++
++static int
++is_hardware_watchpoint (struct breakpoint *bpt)
++{
++ return (bpt->type == bp_hardware_watchpoint
++ || bpt->type == bp_read_watchpoint
++ || bpt->type == bp_access_watchpoint);
++}
++
++/* Assuming that B is a hardware breakpoint:
++ - Reparse watchpoint expression, is REPARSE is non-zero
++ - Evaluate expression and store the result in B->val
++ - Update the list of values that must be watched in B->loc.
++
++ If the watchpoint is disabled, do nothing. If this is
++ local watchpoint that is out of scope, delete it. */
++static void
++update_watchpoint (struct breakpoint *b, int reparse)
++{
++ int within_current_scope;
++ struct value *mark = value_mark ();
++ struct frame_id saved_frame_id;
++ struct bp_location *loc;
++ bpstat bs;
++
++ unlink_locations_from_global_list (b);
++ for (loc = b->loc; loc;)
++ {
++ struct bp_location *loc_next = loc->next;
++ remove_breakpoint (loc, mark_uninserted);
++ xfree (loc);
++ loc = loc_next;
++ }
++ b->loc = NULL;
++
++ if (b->disposition == disp_del_at_next_stop)
++ return;
++
++ /* 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 (get_selected_frame (NULL));
++
++ /* 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);
++ }
++
++ if (within_current_scope && reparse)
++ {
++ char *s;
++ if (b->exp)
++ {
++ xfree (b->exp);
++ b->exp = NULL;
++ }
++ s = b->exp_string;
++ b->exp = parse_exp_1 (&s, b->exp_valid_block, 0);
++ /* If the meaning of expression itself changed, the old value is
++ no longer relevant. We don't want to report a watchpoint hit
++ to the user when the old value and the new value may actually
++ be completely different objects. */
++ value_free (b->val);
++ b->val = NULL;
++ }
++
++
++ /* If we failed to parse the expression, for example because
++ it refers to a global variable in a not-yet-loaded shared library,
++ don't try to insert watchpoint. We don't automatically delete
++ such watchpoint, though, since failure to parse expression
++ is different from out-of-scope watchpoint. */
++ if (within_current_scope && b->exp)
++ {
++ struct value *v, *next;
++
++ /* Evaluate the expression and make sure it's not lazy, so that
++ after target stops again, we have a non-lazy previous value
++ to compare with. Also, making the value non-lazy will fetch
++ intermediate values as needed, which we use to decide which
++ addresses to watch.
++
++ The value returned by evaluate_expression is stored in b->val.
++ In addition, we look at all values which were created
++ during evaluation, and set watchoints at addresses as needed.
++ Those values are explicitly deleted here. */
++ v = evaluate_expression (b->exp);
++ /* Avoid setting b->val if it's already set. The meaning of
++ b->val is 'the last value' user saw, and we should update
++ it only if we reported that last value to user. As it
++ happens, the code that reports it updates b->val directly. */
++ if (b->val == NULL)
++ b->val = v;
++ value_contents (v);
++ value_release_to_mark (mark);
++
++ /* Look at each value on the value chain. */
++ for (; 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
++ || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
++ && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
++ {
++ CORE_ADDR addr;
++ int len, type;
++ struct bp_location *loc, **tmp;
++
++ 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;
++
++ loc = allocate_bp_location (b, bp_hardware_watchpoint);
++ for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
++ ;
++ *tmp = loc;
++ loc->address = addr;
++ loc->length = len;
++ loc->watchpoint_type = type;
++ }
++ }
++
++ next = value_next (v);
++ if (v != b->val)
++ value_free (v);
++ }
++
++ if (reparse && b->cond_string != NULL)
++ {
++ char *s = b->cond_string;
++ if (b->loc->cond)
++ {
++ xfree (b->loc->cond);
++ b->loc->cond = NULL;
++ }
++ b->loc->cond = parse_exp_1 (&s, b->exp_valid_block, 0);
++ }
++ }
++ else if (!within_current_scope)
++ {
++ printf_filtered (_("\
++Hardware watchpoint %d deleted because the program has left the block \n\
++in which its expression is valid.\n"),
++ b->number);
++ if (b->related_breakpoint)
++ b->related_breakpoint->disposition = disp_del_at_next_stop;
++ b->disposition = disp_del_at_next_stop;
++ }
++
++ /* Restore the selected frame. */
++ select_frame (frame_find_by_id (saved_frame_id));
++}
++
++
++/* 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.
++
++ 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)
++{
++ int val = 0;
++
++ if (!breakpoint_enabled (bpt->owner))
++ return 0;
++
++ if (!bpt->enabled || bpt->shlib_disabled || bpt->inserted || bpt->duplicate)
++ return 0;
++
++ /* Initialize the target-specific information. */
++ memset (&bpt->target_info, 0, sizeof (bpt->target_info));
++ bpt->target_info.placed_address = bpt->address;
++
++ if (bpt->loc_type == bp_loc_software_breakpoint
++ || bpt->loc_type == bp_loc_hardware_breakpoint)
++ {
++ if (bpt->owner->type != bp_hardware_breakpoint)
++ {
++ /* If the explicitly specified breakpoint type
++ is not hardware breakpoint, check the memory map to see
++ if the breakpoint address is in read only memory or not.
++ Two important cases are:
++ - location type is not hardware breakpoint, memory
++ is readonly. We change the type of the location to
++ hardware breakpoint.
++ - location type is hardware breakpoint, memory is read-write.
++ This means we've previously made the location hardware one, but
++ then the memory map changed, so we undo.
++
++ When breakpoints are removed, remove_breakpoints will
++ use location types we've just set here, the only possible
++ problem is that memory map has changed during running program,
++ but it's not going to work anyway with current gdb. */
++ struct mem_region *mr
++ = lookup_mem_region (bpt->target_info.placed_address);
++
++ if (mr)
++ {
++ if (automatic_hardware_breakpoints)
++ {
++ int changed = 0;
++ enum bp_loc_type new_type;
++
++ if (mr->attrib.mode != MEM_RW)
++ new_type = bp_loc_hardware_breakpoint;
++ else
++ new_type = bp_loc_software_breakpoint;
++
++ if (new_type != bpt->loc_type)
++ {
++ static int said = 0;
++ bpt->loc_type = new_type;
++ if (!said)
++ {
++ fprintf_filtered (gdb_stdout, _("\
++Note: automatically using hardware breakpoints for read-only addresses.\n"));
++ said = 1;
++ }
++ }
++ }
++ else if (bpt->loc_type == bp_loc_software_breakpoint
++ && mr->attrib.mode != MEM_RW)
++ warning (_("cannot set software breakpoint at readonly address %s"),
++ paddr (bpt->address));
++ }
++ }
++
++ /* 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 (bpt->loc_type == bp_loc_hardware_breakpoint)
++ val = target_insert_hw_breakpoint (&bpt->target_info);
++ else
++ val = target_insert_breakpoint (&bpt->target_info);
++ }
++ 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!"),
++ bpt->owner->number);
++ else
++ {
++ CORE_ADDR addr = overlay_unmapped_address (bpt->address,
++ bpt->section);
++ /* Set a software (trap) breakpoint at the LMA. */
++ bpt->overlay_target_info = bpt->target_info;
++ bpt->overlay_target_info.placed_address = addr;
++ val = target_insert_breakpoint (&bpt->overlay_target_info);
++ 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->target_info);
++ else
++ val = target_insert_breakpoint (&bpt->target_info);
++ }
++ 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 (solib_address (bpt->address))
++ {
++ /* See also: disable_breakpoints_in_shlibs. */
++ val = 0;
++ bpt->shlib_disabled = 1;
++ 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
++ {
++#ifdef ONE_PROCESS_WRITETEXT
++ *process_warning = 1;
++#endif
++ 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 ");
++ fputs_filtered (paddress (bpt->address), tmp_error_stream);
++ fprintf_filtered (tmp_error_stream, ": %s.\n",
++ safe_strerror (val));
++ }
++
++ }
++ }
++ else
++ bpt->inserted = 1;
++
++ return val;
++ }
++
++ 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)
++ {
++ val = target_insert_watchpoint (bpt->address,
++ bpt->length,
++ bpt->watchpoint_type);
++ bpt->inserted = (val != -1);
++ }
++
++ else if (bpt->owner->type == bp_catch_fork
++ || bpt->owner->type == bp_catch_vfork
++ || bpt->owner->type == bp_catch_exec)
++ {
++ struct gdb_exception e = catch_exception (uiout, insert_catchpoint,
++ bpt->owner, RETURN_MASK_ERROR);
++ exception_fprintf (gdb_stderr, e, "warning: inserting catchpoint %d: ",
++ bpt->owner->number);
++ if (e.reason < 0)
++ bpt->owner->enable_state = bp_disabled;
++ else
++ bpt->inserted = 1;
++
++ /* We've already printed an error message if there was a problem
++ inserting this catchpoint, and we've disabled the catchpoint,
++ so just return success. */
++ return 0;
++ }
++
++ 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. */
++
++void
++insert_breakpoints (void)
++{
++ struct breakpoint *bpt;
++ struct bp_location *b, *temp;
++ int error = 0;
++ 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_BREAKPOINTS (bpt)
++ if (is_hardware_watchpoint (bpt))
++ update_watchpoint (bpt, 0 /* don't reparse */);
++
++ ALL_BP_LOCATIONS_SAFE (b, temp)
++ {
++ if (!breakpoint_enabled (b->owner))
++ continue;
++
++ /* There is no point inserting thread-specific breakpoints if the
++ thread no longer exists. */
++ if (b->owner->thread != -1
++ && !valid_thread_id (b->owner->thread))
++ continue;
++
++ val = insert_bp_location (b, tmp_error_stream,
++ &disabled_breaks, &process_warning,
++ &hw_breakpoint_error);
++ if (val)
++ error = val;
++ }
++
++ /* If we failed to insert all locations of a watchpoint,
++ remove them, as half-inserted watchpoint is of limited use. */
++ ALL_BREAKPOINTS (bpt)
++ {
++ int some_failed = 0;
++ struct bp_location *loc;
++
++ if (!is_hardware_watchpoint (bpt))
++ continue;
++
++ if (bpt->enable_state != bp_enabled)
++ continue;
++
++ for (loc = bpt->loc; loc; loc = loc->next)
++ if (!loc->inserted)
++ {
++ some_failed = 1;
++ break;
++ }
++ if (some_failed)
++ {
++ for (loc = bpt->loc; loc; loc = loc->next)
++ if (loc->inserted)
++ remove_breakpoint (loc, mark_uninserted);
++
++ hw_breakpoint_error = 1;
++ fprintf_unfiltered (tmp_error_stream,
++ "Could not insert hardware watchpoint %d.\n",
++ bpt->number);
++ error = -1;
++ }
++ }
++
++ if (error)
++ {
++ /* If a hardware breakpoint or watchpoint was inserted, add a
++ message about possibly exhausted resources. */
++ if (hw_breakpoint_error)
++ {
++ fprintf_unfiltered (tmp_error_stream,
++ "Could not insert hardware breakpoints:\n\
++You may have requested too many hardware breakpoints/watchpoints.\n");
++ }
++#ifdef ONE_PROCESS_WRITETEXT
++ if (process_warning)
++ fprintf_unfiltered (tmp_error_stream,
++ "The same program may be running in another process.");
++#endif
++ target_terminal_ours_for_output ();
++ error_stream (tmp_error_stream);
++ }
++}
++
++int
++remove_breakpoints (void)
++{
++ struct bp_location *b;
++ int val;
++
++ ALL_BP_LOCATIONS (b)
++ {
++ if (b->inserted)
++ {
++ val = remove_breakpoint (b, mark_uninserted);
++ if (val != 0)
++ return val;
++ }
++ }
++ return 0;
++}
++
++int
++remove_hw_watchpoints (void)
++{
++ struct bp_location *b;
++ int val;
++
++ ALL_BP_LOCATIONS (b)
++ {
++ if (b->inserted && b->loc_type == bp_loc_hardware_watchpoint)
++ {
++ val = remove_breakpoint (b, mark_uninserted);
++ if (val != 0)
++ return val;
++ }
++ }
++ return 0;
++}
++
++int
++reattach_breakpoints (int pid)
++{
++ struct bp_location *b;
++ int val;
++ struct cleanup *old_chain = save_inferior_ptid ();
++ struct ui_file *tmp_error_stream = mem_fileopen ();
++ int dummy1 = 0, dummy2 = 0, dummy3 = 0;
++
++ make_cleanup_ui_file_delete (tmp_error_stream);
++
++ inferior_ptid = pid_to_ptid (pid);
++ ALL_BP_LOCATIONS (b)
++ {
++ if (b->inserted)
++ {
++ b->inserted = 0;
++ val = insert_bp_location (b, tmp_error_stream,
++ &dummy1, &dummy2, &dummy3);
++ if (val != 0)
++ {
++ do_cleanups (old_chain);
++ return val;
++ }
++ }
++ }
++ do_cleanups (old_chain);
++ return 0;
++}
++
++void
++update_breakpoints_after_exec (void)
++{
++ struct breakpoint *b;
++ struct breakpoint *temp;
++
++ /* Doing this first prevents the badness of having delete_breakpoint()
++ write a breakpoint's current "shadow contents" to lift the bp. That
++ shadow is NOT valid after an exec()! */
++ mark_breakpoints_out ();
++
++ ALL_BREAKPOINTS_SAFE (b, temp)
++ {
++ /* Solib breakpoints must be explicitly reset after an exec(). */
++ if (b->type == bp_shlib_event)
++ {
++ delete_breakpoint (b);
++ continue;
++ }
++
++ /* Thread event breakpoints must be set anew after an exec(),
++ as must overlay event breakpoints. */
++ if (b->type == bp_thread_event || b->type == bp_overlay_event)
++ {
++ delete_breakpoint (b);
++ continue;
++ }
++
++ /* Step-resume breakpoints are meaningless after an exec(). */
++ if (b->type == bp_step_resume)
++ {
++ delete_breakpoint (b);
++ continue;
++ }
++
++ /* Don't delete an exec catchpoint, because else the inferior
++ won't stop when it ought!
++
++ Similarly, we probably ought to keep vfork catchpoints, 'cause
++ on this target, we may not be able to stop when the vfork is
++ seen, but only when the subsequent exec is seen. (And because
++ deleting fork catchpoints here but not vfork catchpoints will
++ seem mysterious to users, keep those too.) */
++ if ((b->type == bp_catch_exec) ||
++ (b->type == bp_catch_vfork) ||
++ (b->type == bp_catch_fork))
++ {
++ continue;
++ }
++
++ /* bp_finish is a special case. The only way we ought to be able
++ to see one of these when an exec() has happened, is if the user
++ caught a vfork, and then said "finish". Ordinarily a finish just
++ carries them to the call-site of the current callee, by setting
++ a temporary bp there and resuming. But in this case, the finish
++ will carry them entirely through the vfork & exec.
++
++ We don't want to allow a bp_finish to remain inserted now. But
++ we can't safely delete it, 'cause finish_command has a handle to
++ the bp on a bpstat, and will later want to delete it. There's a
++ chance (and I've seen it happen) that if we delete the bp_finish
++ here, that its storage will get reused by the time finish_command
++ gets 'round to deleting the "use to be a bp_finish" breakpoint.
++ We really must allow finish_command to delete a bp_finish.
++
++ In the absense of a general solution for the "how do we know
++ it's safe to delete something others may have handles to?"
++ problem, what we'll do here is just uninsert the bp_finish, and
++ let finish_command delete it.
++
++ (We know the bp_finish is "doomed" in the sense that it's
++ momentary, and will be deleted as soon as finish_command sees
++ the inferior stopped. So it doesn't matter that the bp's
++ address is probably bogus in the new a.out, unlike e.g., the
++ solib breakpoints.) */
++
++ if (b->type == bp_finish)
++ {
++ continue;
++ }
++
++ /* Without a symbolic address, we have little hope of the
++ pre-exec() address meaning the same thing in the post-exec()
++ a.out. */
++ if (b->addr_string == NULL)
++ {
++ delete_breakpoint (b);
++ continue;
++ }
++ }
++ /* FIXME what about longjmp breakpoints? Re-create them here? */
++ create_overlay_event_breakpoint ("_ovly_debug_event");
++}
++
++int
++detach_breakpoints (int pid)
++{
++ struct bp_location *b;
++ int val;
++ struct cleanup *old_chain = save_inferior_ptid ();
++
++ if (pid == PIDGET (inferior_ptid))
++ error (_("Cannot detach breakpoints of inferior_ptid"));
++
++ /* Set inferior_ptid; remove_breakpoint uses this global. */
++ inferior_ptid = pid_to_ptid (pid);
++ ALL_BP_LOCATIONS (b)
++ {
++ if (b->inserted)
++ {
++ val = remove_breakpoint (b, mark_inserted);
++ if (val != 0)
++ {
++ do_cleanups (old_chain);
++ return val;
++ }
++ }
++ }
++ do_cleanups (old_chain);
++ return 0;
++}
++
++static int
++remove_breakpoint (struct bp_location *b, insertion_state_t is)
++{
++ int val;
++
++ if (b->owner->enable_state == bp_permanent)
++ /* Permanent breakpoints cannot be inserted or removed. */
++ return 0;
++
++ if (b->owner->type == bp_none)
++ warning (_("attempted to remove apparently deleted breakpoint #%d?"),
++ 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
++ 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 remove the breakpoint. */
++
++ if (b->loc_type == bp_loc_hardware_breakpoint)
++ val = target_remove_hw_breakpoint (&b->target_info);
++ else
++ val = target_remove_breakpoint (&b->target_info);
++ }
++ else
++ {
++ /* This breakpoint is in an overlay section.
++ Did we set a breakpoint at the LMA? */
++ if (!overlay_events_enabled)
++ {
++ /* Yes -- overlay event support is not active, so we
++ should have set a breakpoint at the LMA. Remove it.
++ */
++ /* Ignore any failures: if the LMA is in ROM, we will
++ have already warned when we failed to insert it. */
++ if (b->loc_type == bp_loc_hardware_breakpoint)
++ target_remove_hw_breakpoint (&b->overlay_target_info);
++ else
++ target_remove_breakpoint (&b->overlay_target_info);
++ }
++ /* Did we set a breakpoint at the VMA?
++ If so, we will have marked the breakpoint 'inserted'. */
++ if (b->inserted)
++ {
++ /* Yes -- remove it. Previously we did not bother to
++ 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->loc_type == bp_loc_hardware_breakpoint)
++ val = target_remove_hw_breakpoint (&b->target_info);
++
++ /* However, we should remove *software* breakpoints only
++ if the section is still mapped, or else we overwrite
++ wrong code with the saved shadow contents. */
++ else if (section_is_mapped (b->section))
++ val = target_remove_breakpoint (&b->target_info);
++ else
++ val = 0;
++ }
++ else
++ {
++ /* No -- not inserted, so no need to remove. No error. */
++ val = 0;
++ }
++ }
++ if (val)
++ return val;
++ b->inserted = (is == mark_inserted);
++ }
++ else if (b->loc_type == bp_loc_hardware_watchpoint)
++ {
++ struct value *v;
++ struct value *n;
++
++ b->inserted = (is == mark_inserted);
++ val = target_remove_watchpoint (b->address, b->length,
++ b->watchpoint_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->owner->number);
++ }
++ else if ((b->owner->type == bp_catch_fork ||
++ b->owner->type == bp_catch_vfork ||
++ b->owner->type == bp_catch_exec)
++ && breakpoint_enabled (b->owner)
++ && !b->duplicate)
++ {
++ val = -1;
++ switch (b->owner->type)
++ {
++ case bp_catch_fork:
++ val = target_remove_fork_catchpoint (PIDGET (inferior_ptid));
++ break;
++ case bp_catch_vfork:
++ val = target_remove_vfork_catchpoint (PIDGET (inferior_ptid));
++ break;
++ case bp_catch_exec:
++ val = target_remove_exec_catchpoint (PIDGET (inferior_ptid));
++ break;
++ default:
++ warning (_("Internal error, %s line %d."), __FILE__, __LINE__);
++ break;
++ }
++ if (val)
++ return val;
++ b->inserted = (is == mark_inserted);
++ }
++
++ return 0;
++}
++
++/* Clear the "inserted" flag in all breakpoints. */
++
++static void
++mark_breakpoints_out (void)
++{
++ struct bp_location *bpt;
++
++ ALL_BP_LOCATIONS (bpt)
++ bpt->inserted = 0;
++}
++
++/* Clear the "inserted" flag in all breakpoints and delete any
++ breakpoints which should go away between runs of the program.
++
++ Plus other such housekeeping that has to be done for breakpoints
++ between runs.
++
++ Note: this function gets called at the end of a run (by
++ generic_mourn_inferior) and when a run begins (by
++ init_wait_for_inferior). */
++
++
++
++void
++breakpoint_init_inferior (enum inf_context context)
++{
++ struct breakpoint *b, *temp;
++ struct bp_location *bpt;
++
++ ALL_BP_LOCATIONS (bpt)
++ bpt->inserted = 0;
++
++ ALL_BREAKPOINTS_SAFE (b, temp)
++ {
++ switch (b->type)
++ {
++ case bp_call_dummy:
++ case bp_watchpoint_scope:
++
++ /* If the call dummy breakpoint is at the entry point it will
++ cause problems when the inferior is rerun, so we better
++ get rid of it.
++
++ Also get rid of scope breakpoints. */
++ delete_breakpoint (b);
++ break;
++
++ case bp_watchpoint:
++ case bp_hardware_watchpoint:
++ case bp_read_watchpoint:
++ case bp_access_watchpoint:
++
++ /* Likewise for watchpoints on local expressions. */
++ if (b->exp_valid_block != NULL)
++ delete_breakpoint (b);
++ else if (context == inf_starting)
++ {
++ /* Reset val field to force reread of starting value
++ in insert_breakpoints. */
++ if (b->val)
++ value_free (b->val);
++ b->val = NULL;
++ }
++ break;
++ default:
++ break;
++ }
++ }
++}
++
++/* breakpoint_here_p (PC) returns non-zero if an enabled breakpoint
++ exists at PC. It returns ordinary_breakpoint_here if it's an
++ ordinary breakpoint, or permanent_breakpoint_here if it's a
++ permanent breakpoint.
++ - When continuing from a location with an ordinary breakpoint, we
++ actually single step once before calling insert_breakpoints.
++ - When continuing from a localion with a permanent breakpoint, we
++ need to use the `SKIP_PERMANENT_BREAKPOINT' macro, provided by
++ the target, to advance the PC past the breakpoint. */
++
++enum breakpoint_here
++breakpoint_here_p (CORE_ADDR pc)
++{
++ const struct bp_location *bpt;
++ int any_breakpoint_here = 0;
++
++ ALL_BP_LOCATIONS (bpt)
++ {
++ if (bpt->loc_type != bp_loc_software_breakpoint
++ && bpt->loc_type != bp_loc_hardware_breakpoint)
++ continue;
++
++ if ((breakpoint_enabled (bpt->owner)
++ || 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;
++}
++
++
++/* Returns non-zero if there's a breakpoint inserted at PC, which is
++ inserted using regular breakpoint_chain/bp_location_chain mechanism.
++ This does not check for single-step breakpoints, which are
++ inserted and removed using direct target manipulation. */
++
++int
++regular_breakpoint_inserted_here_p (CORE_ADDR pc)
++{
++ const struct bp_location *bpt;
++
++ ALL_BP_LOCATIONS (bpt)
++ {
++ 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;
++}
++
++/* Returns non-zero iff there's either regular breakpoint
++ or a single step breakpoint inserted at PC. */
++
++int
++breakpoint_inserted_here_p (CORE_ADDR pc)
++{
++ if (regular_breakpoint_inserted_here_p (pc))
++ return 1;
++
++ if (single_step_breakpoint_inserted_here_p (pc))
++ return 1;
++
++ return 0;
++}
++
++/* This function returns non-zero iff there is a software breakpoint
++ inserted at PC. */
++
++int
++software_breakpoint_inserted_here_p (CORE_ADDR pc)
++{
++ const struct bp_location *bpt;
++ int any_breakpoint_here = 0;
++
++ ALL_BP_LOCATIONS (bpt)
++ {
++ if (bpt->loc_type != bp_loc_software_breakpoint)
++ continue;
++
++ if (bpt->inserted
++ && 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
++ return 1;
++ }
++ }
++
++ /* Also check for software single-step breakpoints. */
++ if (single_step_breakpoint_inserted_here_p (pc))
++ return 1;
++
++ return 0;
++}
++
++/* 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)
++{
++ const struct bp_location *bpt;
++ int thread;
++
++ thread = pid_to_thread_id (ptid);
++
++ ALL_BP_LOCATIONS (bpt)
++ {
++ if (bpt->loc_type != bp_loc_software_breakpoint
++ && bpt->loc_type != bp_loc_hardware_breakpoint)
++ continue;
++
++ if ((breakpoint_enabled (bpt->owner)
++ || 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;
++}
++
++
++/* bpstat stuff. External routines' interfaces are documented
++ in breakpoint.h. */
++
++int
++ep_is_catchpoint (struct breakpoint *ep)
++{
++ return
++ (ep->type == bp_catch_load)
++ || (ep->type == bp_catch_unload)
++ || (ep->type == bp_catch_fork)
++ || (ep->type == bp_catch_vfork)
++ || (ep->type == bp_catch_exec);
++
++ /* ??rehrauer: Add more kinds here, as are implemented... */
++}
++
++int
++ep_is_shlib_catchpoint (struct breakpoint *ep)
++{
++ return
++ (ep->type == bp_catch_load)
++ || (ep->type == bp_catch_unload);
++}
++
++void
++bpstat_free (bpstat bs)
++{
++ if (bs->old_val != NULL)
++ value_free (bs->old_val);
++ free_command_lines (&bs->commands);
++ xfree (bs);
++}
++
++/* Clear a bpstat so that it says we are not at any breakpoint.
++ Also free any storage that is part of a bpstat. */
++
++void
++bpstat_clear (bpstat *bsp)
++{
++ bpstat p;
++ bpstat q;
++
++ if (bsp == 0)
++ return;
++ p = *bsp;
++ while (p != NULL)
++ {
++ q = p->next;
++ bpstat_free (p);
++ p = q;
++ }
++ *bsp = NULL;
++}
++
++/* Return a copy of a bpstat. Like "bs1 = bs2" but all storage that
++ is part of the bpstat is copied as well. */
++
++bpstat
++bpstat_copy (bpstat bs)
++{
++ bpstat p = NULL;
++ bpstat tmp;
++ bpstat retval = NULL;
++
++ if (bs == NULL)
++ return bs;
++
++ for (; bs != NULL; bs = bs->next)
++ {
++ tmp = (bpstat) xmalloc (sizeof (*tmp));
++ memcpy (tmp, bs, sizeof (*tmp));
++ if (bs->commands != NULL)
++ tmp->commands = copy_command_lines (bs->commands);
++ if (bs->old_val != NULL)
++ tmp->old_val = value_copy (bs->old_val);
++
++ if (p == NULL)
++ /* This is the first thing in the chain. */
++ retval = tmp;
++ else
++ p->next = tmp;
++ p = tmp;
++ }
++ p->next = NULL;
++ return retval;
++}
++
++/* Find the bpstat associated with this breakpoint */
++
++bpstat
++bpstat_find_breakpoint (bpstat bsp, struct breakpoint *breakpoint)
++{
++ if (bsp == NULL)
++ return NULL;
++
++ for (; bsp != NULL; bsp = bsp->next)
++ {
++ if (bsp->breakpoint_at && bsp->breakpoint_at->owner == breakpoint)
++ return bsp;
++ }
++ return NULL;
++}
++
++/* Find a step_resume breakpoint associated with this bpstat.
++ (If there are multiple step_resume bp's on the list, this function
++ will arbitrarily pick one.)
++
++ It is an error to use this function if BPSTAT doesn't contain a
++ step_resume breakpoint.
++
++ See wait_for_inferior's use of this function. */
++struct breakpoint *
++bpstat_find_step_resume_breakpoint (bpstat bsp)
++{
++ int current_thread;
++
++ gdb_assert (bsp != NULL);
++
++ current_thread = pid_to_thread_id (inferior_ptid);
++
++ for (; bsp != NULL; bsp = bsp->next)
++ {
++ if ((bsp->breakpoint_at != NULL) &&
++ (bsp->breakpoint_at->owner->type == bp_step_resume) &&
++ (bsp->breakpoint_at->owner->thread == current_thread ||
++ bsp->breakpoint_at->owner->thread == -1))
++ return bsp->breakpoint_at->owner;
++ }
++
++ internal_error (__FILE__, __LINE__, _("No step_resume breakpoint found."));
++}
++
++
++/* Put in *NUM the breakpoint number of the first breakpoint we are stopped
++ at. *BSP upon return is a bpstat which points to the remaining
++ breakpoints stopped at (but which is not guaranteed to be good for
++ anything but further calls to bpstat_num).
++ Return 0 if passed a bpstat which does not indicate any breakpoints.
++ Return -1 if stopped at a breakpoint that has been deleted since
++ we set it.
++ Return 1 otherwise. */
++
++int
++bpstat_num (bpstat *bsp, int *num)
++{
++ struct breakpoint *b;
++
++ if ((*bsp) == NULL)
++ return 0; /* No more breakpoint values */
++
++ /* We assume we'll never have several bpstats that
++ correspond to a single breakpoint -- otherwise,
++ this function might return the same number more
++ than once and this will look ugly. */
++ b = (*bsp)->breakpoint_at ? (*bsp)->breakpoint_at->owner : NULL;
++ *bsp = (*bsp)->next;
++ if (b == NULL)
++ return -1; /* breakpoint that's been deleted since */
++
++ *num = b->number; /* We have its number */
++ return 1;
++}
++
++/* Modify BS so that the actions will not be performed. */
++
++void
++bpstat_clear_actions (bpstat bs)
++{
++ for (; bs != NULL; bs = bs->next)
++ {
++ free_command_lines (&bs->commands);
++ if (bs->old_val != NULL)
++ {
++ value_free (bs->old_val);
++ bs->old_val = NULL;
++ }
++ }
++}
++
++/* Stub for cleaning up our state if we error-out of a breakpoint command */
++static void
++cleanup_executing_breakpoints (void *ignore)
++{
++ executing_breakpoint_commands = 0;
++}
++
++/* Execute all the commands associated with all the breakpoints at this
++ location. Any of these commands could cause the process to proceed
++ beyond this point, etc. We look out for such changes by checking
++ the global "breakpoint_proceeded" after each command. */
++
++void
++bpstat_do_actions (bpstat *bsp)
++{
++ bpstat bs;
++ struct cleanup *old_chain;
++
++ /* Avoid endless recursion if a `source' command is contained
++ in bs->commands. */
++ if (executing_breakpoint_commands)
++ return;
++
++ executing_breakpoint_commands = 1;
++ old_chain = make_cleanup (cleanup_executing_breakpoints, 0);
++
++top:
++ /* Note that (as of this writing), our callers all appear to
++ be passing us the address of global stop_bpstat. And, if
++ our calls to execute_control_command cause the inferior to
++ proceed, that global (and hence, *bsp) will change.
++
++ We must be careful to not touch *bsp unless the inferior
++ has not proceeded. */
++
++ /* This pointer will iterate over the list of bpstat's. */
++ bs = *bsp;
++
++ breakpoint_proceeded = 0;
++ for (; bs != NULL; bs = bs->next)
++ {
++ struct command_line *cmd;
++ struct cleanup *this_cmd_tree_chain;
++
++ /* Take ownership of the BSP's command tree, if it has one.
++
++ The command tree could legitimately contain commands like
++ 'step' and 'next', which call clear_proceed_status, which
++ frees stop_bpstat's command tree. To make sure this doesn't
++ free the tree we're executing out from under us, we need to
++ take ownership of the tree ourselves. Since a given bpstat's
++ commands are only executed once, we don't need to copy it; we
++ can clear the pointer in the bpstat, and make sure we free
++ the tree when we're done. */
++ cmd = bs->commands;
++ bs->commands = 0;
++ this_cmd_tree_chain = make_cleanup_free_command_lines (&cmd);
++
++ while (cmd != NULL)
++ {
++ execute_control_command (cmd);
++
++ if (breakpoint_proceeded)
++ break;
++ else
++ cmd = cmd->next;
++ }
++
++ /* We can free this command tree now. */
++ do_cleanups (this_cmd_tree_chain);
++
++ if (breakpoint_proceeded)
++ /* The inferior is proceeded by the command; bomb out now.
++ The bpstat chain has been blown away by wait_for_inferior.
++ But since execution has stopped again, there is a new bpstat
++ to look at, so start over. */
++ goto top;
++ }
++ do_cleanups (old_chain);
++}
++
++/* This is the normal print function for a bpstat. In the future,
++ much of this logic could (should?) be moved to bpstat_stop_status,
++ by having it set different print_it values.
++
++ Current scheme: When we stop, bpstat_print() is called. It loops
++ through the bpstat list of things causing this stop, calling the
++ print_bp_stop_message function on each one. The behavior of the
++ print_bp_stop_message function depends on the print_it field of
++ bpstat. If such field so indicates, call this function here.
++
++ Return values from this routine (ultimately used by bpstat_print()
++ and normal_stop() to decide what to do):
++ PRINT_NOTHING: Means we already printed all we needed to print,
++ don't print anything else.
++ PRINT_SRC_ONLY: Means we printed something, and we do *not* desire
++ that something to be followed by a location.
++ PRINT_SCR_AND_LOC: Means we printed something, and we *do* desire
++ that something to be followed by a location.
++ PRINT_UNKNOWN: Means we printed nothing or we need to do some more
++ analysis. */
++
++static enum print_stop_action
++print_it_typical (bpstat bs)
++{
++ struct cleanup *old_chain, *ui_out_chain;
++ struct breakpoint *b;
++ const struct bp_location *bl;
++ struct ui_stream *stb;
++ stb = ui_out_stream_new (uiout);
++ old_chain = make_cleanup_ui_out_stream_delete (stb);
++ /* bs->breakpoint_at can be NULL if it was a momentary breakpoint
++ which has since been deleted. */
++ if (bs->breakpoint_at == NULL)
++ return PRINT_UNKNOWN;
++ bl = bs->breakpoint_at;
++ b = bl->owner;
++
++ switch (b->type)
++ {
++ case bp_breakpoint:
++ case bp_hardware_breakpoint:
++ if (bl->address != bl->requested_address)
++ breakpoint_adjustment_warning (bl->requested_address,
++ bl->address,
++ b->number, 1);
++ annotate_breakpoint (b->number);
++ ui_out_text (uiout, "\nBreakpoint ");
++ if (ui_out_is_mi_like_p (uiout))
++ ui_out_field_string (uiout, "reason",
++ async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
++ ui_out_field_int (uiout, "bkptno", b->number);
++ ui_out_text (uiout, ", ");
++ return PRINT_SRC_AND_LOC;
++ break;
++
++ case bp_shlib_event:
++ /* Did we stop because the user set the stop_on_solib_events
++ variable? (If so, we report this as a generic, "Stopped due
++ to shlib event" message.) */
++ printf_filtered (_("Stopped due to shared library event\n"));
++ return PRINT_NOTHING;
++ break;
++
++ case bp_thread_event:
++ /* Not sure how we will get here.
++ GDB should not stop for these breakpoints. */
++ printf_filtered (_("Thread Event Breakpoint: gdb should not stop!\n"));
++ return PRINT_NOTHING;
++ break;
++
++ case bp_overlay_event:
++ /* By analogy with the thread event, GDB should not stop for these. */
++ printf_filtered (_("Overlay Event Breakpoint: gdb should not stop!\n"));
++ return PRINT_NOTHING;
++ break;
++
++ case bp_catch_load:
++ annotate_catchpoint (b->number);
++ printf_filtered (_("\nCatchpoint %d (loaded %s), "),
++ b->number,
++ b->triggered_dll_pathname);
++ return PRINT_SRC_AND_LOC;
++ break;
++
++ case bp_catch_unload:
++ annotate_catchpoint (b->number);
++ printf_filtered (_("\nCatchpoint %d (unloaded %s), "),
++ b->number,
++ b->triggered_dll_pathname);
++ return PRINT_SRC_AND_LOC;
++ break;
++
++ case bp_catch_fork:
++ annotate_catchpoint (b->number);
++ printf_filtered (_("\nCatchpoint %d (forked process %d), "),
++ b->number,
++ b->forked_inferior_pid);
++ return PRINT_SRC_AND_LOC;
++ break;
++
++ case bp_catch_vfork:
++ annotate_catchpoint (b->number);
++ printf_filtered (_("\nCatchpoint %d (vforked process %d), "),
++ b->number,
++ b->forked_inferior_pid);
++ return PRINT_SRC_AND_LOC;
++ break;
++
++ case bp_catch_exec:
++ annotate_catchpoint (b->number);
++ printf_filtered (_("\nCatchpoint %d (exec'd %s), "),
++ b->number,
++ b->exec_pathname);
++ return PRINT_SRC_AND_LOC;
++ break;
++
++ case bp_watchpoint:
++ case bp_hardware_watchpoint:
++ if (bs->old_val != NULL)
++ {
++ annotate_watchpoint (b->number);
++ if (ui_out_is_mi_like_p (uiout))
++ ui_out_field_string
++ (uiout, "reason",
++ async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
++ mention (b);
++ ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
++ ui_out_text (uiout, "\nOld value = ");
++ value_print (bs->old_val, stb->stream, 0, Val_pretty_default);
++ ui_out_field_stream (uiout, "old", stb);
++ ui_out_text (uiout, "\nNew value = ");
++ value_print (b->val, stb->stream, 0, Val_pretty_default);
++ ui_out_field_stream (uiout, "new", stb);
++ do_cleanups (ui_out_chain);
++ ui_out_text (uiout, "\n");
++ value_free (bs->old_val);
++ bs->old_val = NULL;
++ }
++ /* More than one watchpoint may have been triggered. */
++ return PRINT_UNKNOWN;
++ break;
++
++ case bp_read_watchpoint:
++ if (ui_out_is_mi_like_p (uiout))
++ ui_out_field_string
++ (uiout, "reason",
++ async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER));
++ mention (b);
++ ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
++ ui_out_text (uiout, "\nValue = ");
++ value_print (b->val, stb->stream, 0, Val_pretty_default);
++ ui_out_field_stream (uiout, "value", stb);
++ do_cleanups (ui_out_chain);
++ ui_out_text (uiout, "\n");
++ return PRINT_UNKNOWN;
++ break;
++
++ case bp_access_watchpoint:
++ if (bs->old_val != NULL)
++ {
++ annotate_watchpoint (b->number);
++ if (ui_out_is_mi_like_p (uiout))
++ ui_out_field_string
++ (uiout, "reason",
++ async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
++ mention (b);
++ ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
++ ui_out_text (uiout, "\nOld value = ");
++ value_print (bs->old_val, stb->stream, 0, Val_pretty_default);
++ ui_out_field_stream (uiout, "old", stb);
++ value_free (bs->old_val);
++ bs->old_val = NULL;
++ ui_out_text (uiout, "\nNew value = ");
++ }
++ else
++ {
++ mention (b);
++ if (ui_out_is_mi_like_p (uiout))
++ ui_out_field_string
++ (uiout, "reason",
++ async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
++ ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
++ ui_out_text (uiout, "\nValue = ");
++ }
++ value_print (b->val, stb->stream, 0,Val_pretty_default);
++ ui_out_field_stream (uiout, "new", stb);
++ do_cleanups (ui_out_chain);
++ ui_out_text (uiout, "\n");
++ return PRINT_UNKNOWN;
++ break;
++
++ /* Fall through, we don't deal with these types of breakpoints
++ here. */
++
++ case bp_finish:
++ if (ui_out_is_mi_like_p (uiout))
++ ui_out_field_string
++ (uiout, "reason",
++ async_reason_lookup (EXEC_ASYNC_FUNCTION_FINISHED));
++ return PRINT_UNKNOWN;
++ break;
++
++ case bp_until:
++ if (ui_out_is_mi_like_p (uiout))
++ ui_out_field_string
++ (uiout, "reason",
++ async_reason_lookup (EXEC_ASYNC_LOCATION_REACHED));
++ return PRINT_UNKNOWN;
++ break;
++
++ case bp_none:
++ case bp_longjmp:
++ case bp_longjmp_resume:
++ case bp_step_resume:
++ case bp_watchpoint_scope:
++ case bp_call_dummy:
++ default:
++ return PRINT_UNKNOWN;
++ }
++}
++
++/* Generic routine for printing messages indicating why we
++ stopped. The behavior of this function depends on the value
++ 'print_it' in the bpstat structure. Under some circumstances we
++ may decide not to print anything here and delegate the task to
++ normal_stop(). */
++
++static enum print_stop_action
++print_bp_stop_message (bpstat bs)
++{
++ switch (bs->print_it)
++ {
++ case print_it_noop:
++ /* Nothing should be printed for this bpstat entry. */
++ return PRINT_UNKNOWN;
++ break;
++
++ case print_it_done:
++ /* We still want to print the frame, but we already printed the
++ relevant messages. */
++ return PRINT_SRC_AND_LOC;
++ break;
++
++ case print_it_normal:
++ {
++ const struct bp_location *bl = bs->breakpoint_at;
++ struct breakpoint *b = bl ? bl->owner : NULL;
++
++ /* Normal case. Call the breakpoint's print_it method, or
++ print_it_typical. */
++ /* FIXME: how breakpoint can ever be NULL here? */
++ if (b != NULL && b->ops != NULL && b->ops->print_it != NULL)
++ return b->ops->print_it (b);
++ else
++ return print_it_typical (bs);
++ }
++ break;
++
++ default:
++ internal_error (__FILE__, __LINE__,
++ _("print_bp_stop_message: unrecognized enum value"));
++ break;
++ }
++}
++
++/* Print a message indicating what happened. This is called from
++ normal_stop(). The input to this routine is the head of the bpstat
++ list - a list of the eventpoints that caused this stop. This
++ routine calls the generic print routine for printing a message
++ about reasons for stopping. This will print (for example) the
++ "Breakpoint n," part of the output. The return value of this
++ routine is one of:
++
++ PRINT_UNKNOWN: Means we printed nothing
++ PRINT_SRC_AND_LOC: Means we printed something, and expect subsequent
++ code to print the location. An example is
++ "Breakpoint 1, " which should be followed by
++ the location.
++ PRINT_SRC_ONLY: Means we printed something, but there is no need
++ to also print the location part of the message.
++ An example is the catch/throw messages, which
++ don't require a location appended to the end.
++ PRINT_NOTHING: We have done some printing and we don't need any
++ further info to be printed.*/
++
++enum print_stop_action
++bpstat_print (bpstat bs)
++{
++ int val;
++
++ /* Maybe another breakpoint in the chain caused us to stop.
++ (Currently all watchpoints go on the bpstat whether hit or not.
++ That probably could (should) be changed, provided care is taken
++ with respect to bpstat_explains_signal). */
++ for (; bs; bs = bs->next)
++ {
++ val = print_bp_stop_message (bs);
++ if (val == PRINT_SRC_ONLY
++ || val == PRINT_SRC_AND_LOC
++ || val == PRINT_NOTHING)
++ return val;
++ }
++
++ /* We reached the end of the chain, or we got a null BS to start
++ with and nothing was printed. */
++ return PRINT_UNKNOWN;
++}
++
++/* Evaluate the expression EXP and return 1 if value is zero.
++ This is used inside a catch_errors to evaluate the breakpoint condition.
++ The argument is a "struct expression *" that has been cast to char * to
++ make it pass through catch_errors. */
++
++static int
++breakpoint_cond_eval (void *exp)
++{
++ struct value *mark = value_mark ();
++ int i = !value_true (evaluate_expression ((struct expression *) exp));
++ value_free_to_mark (mark);
++ return i;
++}
++
++/* Allocate a new bpstat and chain it to the current one. */
++
++static bpstat
++bpstat_alloc (const struct bp_location *bl, bpstat cbs /* Current "bs" value */ )
++{
++ bpstat bs;
++
++ bs = (bpstat) xmalloc (sizeof (*bs));
++ cbs->next = bs;
++ bs->breakpoint_at = bl;
++ /* If the condition is false, etc., don't do the commands. */
++ bs->commands = NULL;
++ bs->old_val = NULL;
++ bs->print_it = print_it_normal;
++ return bs;
++}
++
++/* The target has stopped with waitstatus WS. Check if any hardware
++ watchpoints have triggered, according to the target. */
++
++int
++watchpoints_triggered (struct target_waitstatus *ws)
++{
++ int stopped_by_watchpoint = STOPPED_BY_WATCHPOINT (*ws);
++ CORE_ADDR addr;
++ struct breakpoint *b;
++
++ if (!stopped_by_watchpoint)
++ {
++ /* We were not stopped by a watchpoint. Mark all watchpoints
++ as not triggered. */
++ ALL_BREAKPOINTS (b)
++ if (b->type == bp_hardware_watchpoint
++ || b->type == bp_read_watchpoint
++ || b->type == bp_access_watchpoint)
++ b->watchpoint_triggered = watch_triggered_no;
++
++ return 0;
++ }
++
++ if (!target_stopped_data_address (&current_target, &addr))
++ {
++ /* We were stopped by a watchpoint, but we don't know where.
++ Mark all watchpoints as unknown. */
++ ALL_BREAKPOINTS (b)
++ if (b->type == bp_hardware_watchpoint
++ || b->type == bp_read_watchpoint
++ || b->type == bp_access_watchpoint)
++ b->watchpoint_triggered = watch_triggered_unknown;
++
++ return stopped_by_watchpoint;
++ }
++
++ /* The target could report the data address. Mark watchpoints
++ affected by this data address as triggered, and all others as not
++ triggered. */
++
++ ALL_BREAKPOINTS (b)
++ if (b->type == bp_hardware_watchpoint
++ || b->type == bp_read_watchpoint
++ || b->type == bp_access_watchpoint)
++ {
++ struct bp_location *loc;
++ struct value *v;
++
++ b->watchpoint_triggered = watch_triggered_no;
++ for (loc = b->loc; loc; loc = loc->next)
++ /* Exact match not required. Within range is
++ sufficient. */
++ if (addr >= loc->address
++ && addr < loc->address + loc->length)
++ {
++ b->watchpoint_triggered = watch_triggered_yes;
++ break;
++ }
++ }
++
++ return 1;
++}
++
++/* Possible return values for watchpoint_check (this can't be an enum
++ because of check_errors). */
++/* The watchpoint has been deleted. */
++#define WP_DELETED 1
++/* The value has changed. */
++#define WP_VALUE_CHANGED 2
++/* The value has not changed. */
++#define WP_VALUE_NOT_CHANGED 3
++
++#define BP_TEMPFLAG 1
++#define BP_HARDWAREFLAG 2
++
++/* Check watchpoint condition. */
++
++static int
++watchpoint_check (void *p)
++{
++ bpstat bs = (bpstat) p;
++ struct breakpoint *b;
++ struct frame_info *fr;
++ int within_current_scope;
++
++ b = bs->breakpoint_at->owner;
++
++ if (b->exp_valid_block == NULL)
++ within_current_scope = 1;
++ else
++ {
++ /* There is no current frame at this moment. If we're going to have
++ any chance of handling watchpoints on local variables, we'll need
++ the frame chain (so we can determine if we're in scope). */
++ reinit_frame_cache ();
++ fr = frame_find_by_id (b->watchpoint_frame);
++ within_current_scope = (fr != NULL);
++
++ /* If we've gotten confused in the unwinder, we might have
++ returned a frame that can't describe this variable. */
++ if (within_current_scope
++ && block_function (b->exp_valid_block) != get_frame_function (fr))
++ within_current_scope = 0;
++
++ /* 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.
++
++ 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 ())
++ && gdbarch_in_function_epilogue_p (current_gdbarch, read_pc ()))
++ return WP_VALUE_NOT_CHANGED;
++ if (fr && within_current_scope)
++ /* If we end up stopping, the current frame will get selected
++ in normal_stop. So this call to select_frame won't affect
++ the user. */
++ select_frame (fr);
++ }
++
++ if (within_current_scope)
++ {
++ /* We use value_{,free_to_}mark because it could be a
++ *long* time before we return to the command level and
++ call free_all_values. We can't call free_all_values because
++ we might be in the middle of evaluating a function call. */
++
++ struct value *mark = value_mark ();
++ struct value *new_val = evaluate_expression (b->exp);
++ if (!value_equal (b->val, new_val))
++ {
++ release_value (new_val);
++ value_free_to_mark (mark);
++ bs->old_val = b->val;
++ b->val = new_val;
++ /* We will stop here */
++ return WP_VALUE_CHANGED;
++ }
++ else
++ {
++ /* Nothing changed, don't do anything. */
++ value_free_to_mark (mark);
++ /* We won't stop here */
++ return WP_VALUE_NOT_CHANGED;
++ }
++ }
++ else
++ {
++ /* This seems like the only logical thing to do because
++ if we temporarily ignored the watchpoint, then when
++ we reenter the block in which it is valid it contains
++ garbage (in the case of a function, it may have two
++ garbage values, one before and one after the prologue).
++ So we can't even detect the first assignment to it and
++ watch after that (since the garbage may or may not equal
++ the first value assigned). */
++ /* We print all the stop information in print_it_typical(), but
++ in this case, by the time we call print_it_typical() this bp
++ will be deleted already. So we have no choice but print the
++ information here. */
++ if (ui_out_is_mi_like_p (uiout))
++ ui_out_field_string
++ (uiout, "reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_SCOPE));
++ ui_out_text (uiout, "\nWatchpoint ");
++ ui_out_field_int (uiout, "wpnum", b->number);
++ ui_out_text (uiout, " deleted because the program has left the block in\n\
++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 WP_DELETED;
++ }
++}
++
++/* Get a bpstat associated with having just stopped at address
++ BP_ADDR in thread PTID.
++
++ Determine whether we stopped at a breakpoint, etc, or whether we
++ don't understand this stop. Result is a chain of bpstat's such that:
++
++ if we don't understand the stop, the result is a null pointer.
++
++ if we understand why we stopped, the result is not null.
++
++ Each element of the chain refers to a particular breakpoint or
++ watchpoint at which we have stopped. (We may have stopped for
++ several reasons concurrently.)
++
++ Each element of the chain has valid next, breakpoint_at,
++ commands, FIXME??? fields. */
++
++bpstat
++bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid)
++{
++ struct breakpoint *b = NULL;
++ const struct bp_location *bl;
++ /* Root of the chain of bpstat's */
++ struct bpstats root_bs[1];
++ /* Pointer to the last thing in the chain currently. */
++ bpstat bs = root_bs;
++ int thread_id = pid_to_thread_id (ptid);
++
++ ALL_BP_LOCATIONS (bl)
++ {
++ b = bl->owner;
++ gdb_assert (b);
++ if (!breakpoint_enabled (b) && b->enable_state != bp_permanent)
++ continue;
++
++ if (b->type != bp_watchpoint
++ && b->type != bp_hardware_watchpoint
++ && b->type != bp_read_watchpoint
++ && b->type != bp_access_watchpoint
++ && b->type != bp_hardware_breakpoint
++ && b->type != bp_catch_fork
++ && b->type != bp_catch_vfork
++ && b->type != bp_catch_exec) /* a non-watchpoint bp */
++ {
++ if (bl->address != bp_addr) /* address doesn't match */
++ continue;
++ if (overlay_debugging /* unmapped overlay section */
++ && section_is_overlay (bl->section)
++ && !section_is_mapped (bl->section))
++ continue;
++ }
++
++ /* Continuable hardware watchpoints are treated as non-existent if the
++ reason we stopped wasn't a hardware watchpoint (we didn't stop on
++ some data address). Otherwise gdb won't stop on a break instruction
++ in the code (not from a breakpoint) when a hardware watchpoint has
++ been defined. Also skip watchpoints which we know did not trigger
++ (did not match the data address). */
++
++ if ((b->type == bp_hardware_watchpoint
++ || b->type == bp_read_watchpoint
++ || b->type == bp_access_watchpoint)
++ && b->watchpoint_triggered == watch_triggered_no)
++ continue;
++
++ if (b->type == bp_hardware_breakpoint)
++ {
++ if (bl->address != bp_addr)
++ continue;
++ if (overlay_debugging /* unmapped overlay section */
++ && section_is_overlay (bl->section)
++ && !section_is_mapped (bl->section))
++ continue;
++ }
++
++ /* Is this a catchpoint of a load or unload? If so, did we
++ get a load or unload of the specified library? If not,
++ ignore it. */
++ if ((b->type == bp_catch_load)
++#if defined(SOLIB_HAVE_LOAD_EVENT)
++ && (!SOLIB_HAVE_LOAD_EVENT (PIDGET (inferior_ptid))
++ || ((b->dll_pathname != NULL)
++ && (strcmp (b->dll_pathname,
++ SOLIB_LOADED_LIBRARY_PATHNAME (
++ PIDGET (inferior_ptid)))
++ != 0)))
++#endif
++ )
++ continue;
++
++ if ((b->type == bp_catch_unload)
++#if defined(SOLIB_HAVE_UNLOAD_EVENT)
++ && (!SOLIB_HAVE_UNLOAD_EVENT (PIDGET (inferior_ptid))
++ || ((b->dll_pathname != NULL)
++ && (strcmp (b->dll_pathname,
++ SOLIB_UNLOADED_LIBRARY_PATHNAME (
++ PIDGET (inferior_ptid)))
++ != 0)))
++#endif
++ )
++ continue;
++
++ if ((b->type == bp_catch_fork)
++ && !inferior_has_forked (PIDGET (inferior_ptid),
++ &b->forked_inferior_pid))
++ continue;
++
++ if ((b->type == bp_catch_vfork)
++ && !inferior_has_vforked (PIDGET (inferior_ptid),
++ &b->forked_inferior_pid))
++ continue;
++
++ if ((b->type == bp_catch_exec)
++ && !inferior_has_execd (PIDGET (inferior_ptid), &b->exec_pathname))
++ continue;
++
++ /* For hardware watchpoints, we look only at the first location.
++ The watchpoint_check function will work on entire expression,
++ not the individual locations. For read watchopints, the
++ watchpoints_triggered function have checked all locations
++ alrea
++ */
++ if (b->type == bp_hardware_watchpoint && bl != b->loc)
++ continue;
++
++ /* Come here if it's a watchpoint, or if the break address matches */
++
++ bs = bpstat_alloc (bl, bs); /* Alloc a bpstat to explain stop */
++
++ /* Watchpoints may change this, if not found to have triggered. */
++ bs->stop = 1;
++ bs->print = 1;
++
++ if (b->type == bp_watchpoint
++ || b->type == bp_read_watchpoint
++ || b->type == bp_access_watchpoint
++ || b->type == bp_hardware_watchpoint)
++ {
++ CORE_ADDR addr;
++ struct value *v;
++ int must_check_value = 0;
++
++ if (b->type == bp_watchpoint)
++ /* For a software watchpoint, we must always check the
++ watched value. */
++ must_check_value = 1;
++ else if (b->watchpoint_triggered == watch_triggered_yes)
++ /* We have a hardware watchpoint (read, write, or access)
++ and the target earlier reported an address watched by
++ this watchpoint. */
++ must_check_value = 1;
++ else if (b->watchpoint_triggered == watch_triggered_unknown
++ && b->type == bp_hardware_watchpoint)
++ /* We were stopped by a hardware watchpoint, but the target could
++ not report the data address. We must check the watchpoint's
++ value. Access and read watchpoints are out of luck; without
++ a data address, we can't figure it out. */
++ must_check_value = 1;
++
++ if (must_check_value)
++ {
++ char *message = xstrprintf ("Error evaluating expression for watchpoint %d\n",
++ b->number);
++ struct cleanup *cleanups = make_cleanup (xfree, message);
++ int e = catch_errors (watchpoint_check, bs, message,
++ RETURN_MASK_ALL);
++ do_cleanups (cleanups);
++ switch (e)
++ {
++ case WP_DELETED:
++ /* We've already printed what needs to be printed. */
++ bs->print_it = print_it_done;
++ /* Stop. */
++ break;
++ case WP_VALUE_CHANGED:
++ if (b->type == bp_read_watchpoint)
++ {
++ /* Don't stop: read watchpoints shouldn't fire if
++ the value has changed. This is for targets
++ which cannot set read-only watchpoints. */
++ bs->print_it = print_it_noop;
++ bs->stop = 0;
++ continue;
++ }
++ ++(b->hit_count);
++ break;
++ case WP_VALUE_NOT_CHANGED:
++ if (b->type == bp_hardware_watchpoint
++ || b->type == bp_watchpoint)
++ {
++ /* Don't stop: write watchpoints shouldn't fire if
++ the value hasn't changed. */
++ bs->print_it = print_it_noop;
++ bs->stop = 0;
++ continue;
++ }
++ /* Stop. */
++ ++(b->hit_count);
++ break;
++ default:
++ /* Can't happen. */
++ case 0:
++ /* Error from catch_errors. */
++ printf_filtered (_("Watchpoint %d deleted.\n"), b->number);
++ if (b->related_breakpoint)
++ b->related_breakpoint->disposition = disp_del_at_next_stop;
++ b->disposition = disp_del_at_next_stop;
++ /* We've already printed what needs to be printed. */
++ bs->print_it = print_it_done;
++ break;
++ }
++ }
++ else /* must_check_value == 0 */
++ {
++ /* This is a case where some watchpoint(s) triggered, but
++ not at the address of this watchpoint, or else no
++ watchpoint triggered after all. So don't print
++ anything for this watchpoint. */
++ bs->print_it = print_it_noop;
++ bs->stop = 0;
++ continue;
++ }
++ }
++ else
++ {
++ /* By definition, an encountered breakpoint is a triggered
++ breakpoint. */
++ ++(b->hit_count);
++ }
++
++ if (frame_id_p (b->frame_id)
++ && !frame_id_eq (b->frame_id, get_frame_id (get_current_frame ())))
++ bs->stop = 0;
++ else
++ {
++ int value_is_zero = 0;
++
++ /* If this is a scope breakpoint, mark the associated
++ watchpoint as triggered so that we will handle the
++ out-of-scope event. We'll get to the watchpoint next
++ iteration. */
++ if (b->type == bp_watchpoint_scope)
++ b->related_breakpoint->watchpoint_triggered = watch_triggered_yes;
++
++ if (bl->cond && bl->owner->disposition != disp_del_at_next_stop)
++ {
++ /* Need to select the frame, with all that implies
++ so that the conditions will have the right context. */
++ select_frame (get_current_frame ());
++ value_is_zero
++ = catch_errors (breakpoint_cond_eval, (bl->cond),
++ "Error in testing breakpoint condition:\n",
++ RETURN_MASK_ALL);
++ /* FIXME-someday, should give breakpoint # */
++ free_all_values ();
++ }
++ if (bl->cond && value_is_zero)
++ {
++ bs->stop = 0;
++ /* Don't consider this a hit. */
++ --(b->hit_count);
++ }
++ else if (b->thread != -1 && b->thread != thread_id)
++ {
++ bs->stop = 0;
++ /* Don't consider this a hit. */
++ --(b->hit_count);
++ }
++ else if (b->ignore_count > 0)
++ {
++ b->ignore_count--;
++ annotate_ignore_count_change ();
++ bs->stop = 0;
++ }
++ else if (b->type == bp_thread_event || b->type == bp_overlay_event)
++ /* We do not stop for these. */
++ bs->stop = 0;
++ else
++ {
++ /* We will stop here */
++ if (b->disposition == disp_disable)
++ b->enable_state = bp_disabled;
++ if (b->silent)
++ bs->print = 0;
++ bs->commands = b->commands;
++ if (bs->commands &&
++ (strcmp ("silent", bs->commands->line) == 0
++ || (xdb_commands && strcmp ("Q", bs->commands->line) == 0)))
++ {
++ bs->commands = bs->commands->next;
++ bs->print = 0;
++ }
++ bs->commands = copy_command_lines (bs->commands);
++ }
++ }
++ /* Print nothing for this entry if we dont stop or if we dont print. */
++ if (bs->stop == 0 || bs->print == 0)
++ bs->print_it = print_it_noop;
++ }
++
++ bs->next = NULL; /* Terminate the chain */
++ bs = root_bs->next; /* Re-grab the head of the chain */
++
++ /* If we aren't stopping, the value of some hardware watchpoint may
++ not have changed, but the intermediate memory locations we are
++ watching may have. Don't bother if we're stopping; this will get
++ done later. */
++ for (bs = root_bs->next; bs != NULL; bs = bs->next)
++ if (bs->stop)
++ break;
++
++ if (bs == NULL)
++ for (bs = root_bs->next; bs != NULL; bs = bs->next)
++ if (!bs->stop
++ && (bs->breakpoint_at->owner->type == bp_hardware_watchpoint
++ || bs->breakpoint_at->owner->type == bp_read_watchpoint
++ || bs->breakpoint_at->owner->type == bp_access_watchpoint))
++ {
++ /* remove/insert can invalidate bs->breakpoint_at, if this
++ location is no longer used by the watchpoint. Prevent
++ further code from trying to use it. */
++ bs->breakpoint_at = NULL;
++ remove_breakpoints ();
++ insert_breakpoints ();
++ break;
++ }
++
++ return root_bs->next;
++}
++
++/* Tell what to do about this bpstat. */
++struct bpstat_what
++bpstat_what (bpstat bs)
++{
++ /* Classify each bpstat as one of the following. */
++ enum class
++ {
++ /* This bpstat element has no effect on the main_action. */
++ no_effect = 0,
++
++ /* There was a watchpoint, stop but don't print. */
++ wp_silent,
++
++ /* There was a watchpoint, stop and print. */
++ wp_noisy,
++
++ /* There was a breakpoint but we're not stopping. */
++ bp_nostop,
++
++ /* There was a breakpoint, stop but don't print. */
++ bp_silent,
++
++ /* There was a breakpoint, stop and print. */
++ bp_noisy,
++
++ /* We hit the longjmp breakpoint. */
++ long_jump,
++
++ /* We hit the longjmp_resume breakpoint. */
++ long_resume,
++
++ /* We hit the step_resume breakpoint. */
++ step_resume,
++
++ /* We hit the shared library event breakpoint. */
++ shlib_event,
++
++ /* We caught a shared library event. */
++ catch_shlib_event,
++
++ /* This is just used to count how many enums there are. */
++ class_last
++ };
++
++ /* Here is the table which drives this routine. So that we can
++ format it pretty, we define some abbreviations for the
++ enum bpstat_what codes. */
++#define kc BPSTAT_WHAT_KEEP_CHECKING
++#define ss BPSTAT_WHAT_STOP_SILENT
++#define sn BPSTAT_WHAT_STOP_NOISY
++#define sgl BPSTAT_WHAT_SINGLE
++#define slr BPSTAT_WHAT_SET_LONGJMP_RESUME
++#define clr BPSTAT_WHAT_CLEAR_LONGJMP_RESUME
++#define clrs BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE
++#define sr BPSTAT_WHAT_STEP_RESUME
++#define shl BPSTAT_WHAT_CHECK_SHLIBS
++#define shlr BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK
++
++/* "Can't happen." Might want to print an error message.
++ abort() is not out of the question, but chances are GDB is just
++ a bit confused, not unusable. */
++#define err BPSTAT_WHAT_STOP_NOISY
++
++ /* Given an old action and a class, come up with a new action. */
++ /* One interesting property of this table is that wp_silent is the same
++ as bp_silent and wp_noisy is the same as bp_noisy. That is because
++ after stopping, the check for whether to step over a breakpoint
++ (BPSTAT_WHAT_SINGLE type stuff) is handled in proceed() without
++ reference to how we stopped. We retain separate wp_silent and
++ bp_silent codes in case we want to change that someday.
++
++ Another possibly interesting property of this table is that
++ there's a partial ordering, priority-like, of the actions. Once
++ you've decided that some action is appropriate, you'll never go
++ back and decide something of a lower priority is better. The
++ ordering is:
++
++ kc < clr sgl shl shlr slr sn sr ss
++ sgl < clrs shl shlr slr sn sr ss
++ slr < err shl shlr sn sr ss
++ clr < clrs err shl shlr sn sr ss
++ clrs < err shl shlr sn sr ss
++ ss < shl shlr sn sr
++ sn < shl shlr sr
++ shl < shlr sr
++ shlr < sr
++ sr <
++
++ What I think this means is that we don't need a damned table
++ here. If you just put the rows and columns in the right order,
++ it'd look awfully regular. We could simply walk the bpstat list
++ and choose the highest priority action we find, with a little
++ logic to handle the 'err' cases, and the CLEAR_LONGJMP_RESUME/
++ CLEAR_LONGJMP_RESUME_SINGLE distinction (which breakpoint.h says
++ is messy anyway). */
++
++ /* step_resume entries: a step resume breakpoint overrides another
++ breakpoint of signal handling (see comment in wait_for_inferior
++ at where we set the step_resume breakpoint). */
++
++ static const enum bpstat_what_main_action
++ table[(int) class_last][(int) BPSTAT_WHAT_LAST] =
++ {
++ /* old action */
++ /* kc ss sn sgl slr clr clrs sr shl shlr
++ */
++/*no_effect */
++ {kc, ss, sn, sgl, slr, clr, clrs, sr, shl, shlr},
++/*wp_silent */
++ {ss, ss, sn, ss, ss, ss, ss, sr, shl, shlr},
++/*wp_noisy */
++ {sn, sn, sn, sn, sn, sn, sn, sr, shl, shlr},
++/*bp_nostop */
++ {sgl, ss, sn, sgl, slr, clrs, clrs, sr, shl, shlr},
++/*bp_silent */
++ {ss, ss, sn, ss, ss, ss, ss, sr, shl, shlr},
++/*bp_noisy */
++ {sn, sn, sn, sn, sn, sn, sn, sr, shl, shlr},
++/*long_jump */
++ {slr, ss, sn, slr, slr, err, err, sr, shl, shlr},
++/*long_resume */
++ {clr, ss, sn, clrs, err, err, err, sr, shl, shlr},
++/*step_resume */
++ {sr, sr, sr, sr, sr, sr, sr, sr, sr, sr},
++/*shlib */
++ {shl, shl, shl, shl, shl, shl, shl, sr, shl, shlr},
++/*catch_shlib */
++ {shlr, shlr, shlr, shlr, shlr, shlr, shlr, sr, shlr, shlr}
++ };
++
++#undef kc
++#undef ss
++#undef sn
++#undef sgl
++#undef slr
++#undef clr
++#undef clrs
++#undef err
++#undef sr
++#undef ts
++#undef shl
++#undef shlr
++ enum bpstat_what_main_action current_action = BPSTAT_WHAT_KEEP_CHECKING;
++ struct bpstat_what retval;
++
++ retval.call_dummy = 0;
++ for (; bs != NULL; bs = bs->next)
++ {
++ enum class bs_class = no_effect;
++ if (bs->breakpoint_at == NULL)
++ /* I suspect this can happen if it was a momentary breakpoint
++ which has since been deleted. */
++ continue;
++ switch (bs->breakpoint_at->owner->type)
++ {
++ case bp_none:
++ continue;
++
++ case bp_breakpoint:
++ case bp_hardware_breakpoint:
++ case bp_until:
++ case bp_finish:
++ if (bs->stop)
++ {
++ if (bs->print)
++ bs_class = bp_noisy;
++ else
++ bs_class = bp_silent;
++ }
++ else
++ bs_class = bp_nostop;
++ break;
++ case bp_watchpoint:
++ case bp_hardware_watchpoint:
++ case bp_read_watchpoint:
++ case bp_access_watchpoint:
++ if (bs->stop)
++ {
++ if (bs->print)
++ bs_class = wp_noisy;
++ else
++ bs_class = wp_silent;
++ }
++ else
++ /* There was a watchpoint, but we're not stopping.
++ This requires no further action. */
++ bs_class = no_effect;
++ break;
++ case bp_longjmp:
++ bs_class = long_jump;
++ break;
++ case bp_longjmp_resume:
++ bs_class = long_resume;
++ break;
++ case bp_step_resume:
++ if (bs->stop)
++ {
++ bs_class = step_resume;
++ }
++ else
++ /* It is for the wrong frame. */
++ bs_class = bp_nostop;
++ break;
++ case bp_watchpoint_scope:
++ bs_class = bp_nostop;
++ break;
++ case bp_shlib_event:
++ bs_class = shlib_event;
++ break;
++ case bp_thread_event:
++ case bp_overlay_event:
++ bs_class = bp_nostop;
++ break;
++ case bp_catch_load:
++ case bp_catch_unload:
++ /* Only if this catchpoint triggered should we cause the
++ step-out-of-dld behaviour. Otherwise, we ignore this
++ catchpoint. */
++ if (bs->stop)
++ bs_class = catch_shlib_event;
++ else
++ bs_class = no_effect;
++ break;
++ case bp_catch_fork:
++ case bp_catch_vfork:
++ case bp_catch_exec:
++ if (bs->stop)
++ {
++ if (bs->print)
++ bs_class = bp_noisy;
++ else
++ bs_class = bp_silent;
++ }
++ else
++ /* There was a catchpoint, but we're not stopping.
++ This requires no further action. */
++ bs_class = no_effect;
++ break;
++ case bp_call_dummy:
++ /* Make sure the action is stop (silent or noisy),
++ so infrun.c pops the dummy frame. */
++ bs_class = bp_silent;
++ retval.call_dummy = 1;
++ break;
++ }
++ current_action = table[(int) bs_class][(int) current_action];
++ }
++ retval.main_action = current_action;
++ return retval;
++}
++
++/* Nonzero if we should step constantly (e.g. watchpoints on machines
++ without hardware support). This isn't related to a specific bpstat,
++ just to things like whether watchpoints are set. */
++
++int
++bpstat_should_step (void)
++{
++ struct breakpoint *b;
++ ALL_BREAKPOINTS (b)
++ if (breakpoint_enabled (b) && b->type == bp_watchpoint)
++ return 1;
++ return 0;
++}
++
++
++
++/* Given a bpstat that records zero or more triggered eventpoints, this
++ function returns another bpstat which contains only the catchpoints
++ on that first list, if any. */
++void
++bpstat_get_triggered_catchpoints (bpstat ep_list, bpstat *cp_list)
++{
++ struct bpstats root_bs[1];
++ bpstat bs = root_bs;
++ struct breakpoint *ep;
++ char *dll_pathname;
++
++ bpstat_clear (cp_list);
++ root_bs->next = NULL;
++
++ for (; ep_list != NULL; ep_list = ep_list->next)
++ {
++ /* Is this eventpoint a catchpoint? If not, ignore it. */
++ ep = ep_list->breakpoint_at->owner;
++ if (ep == NULL)
++ break;
++ if ((ep->type != bp_catch_load) &&
++ (ep->type != bp_catch_unload))
++ /* pai: (temp) ADD fork/vfork here!! */
++ continue;
++
++ /* Yes; add it to the list. */
++ bs = bpstat_alloc (ep_list->breakpoint_at, bs);
++ *bs = *ep_list;
++ bs->next = NULL;
++ bs = root_bs->next;
++
++#if defined(SOLIB_ADD)
++ /* Also, for each triggered catchpoint, tag it with the name of
++ the library that caused this trigger. (We copy the name now,
++ because it's only guaranteed to be available NOW, when the
++ catchpoint triggers. Clients who may wish to know the name
++ later must get it from the catchpoint itself.) */
++ if (ep->triggered_dll_pathname != NULL)
++ xfree (ep->triggered_dll_pathname);
++ if (ep->type == bp_catch_load)
++ dll_pathname = SOLIB_LOADED_LIBRARY_PATHNAME (
++ PIDGET (inferior_ptid));
++ else
++ dll_pathname = SOLIB_UNLOADED_LIBRARY_PATHNAME (
++ PIDGET (inferior_ptid));
++#else
++ dll_pathname = NULL;
++#endif
++ if (dll_pathname)
++ {
++ ep->triggered_dll_pathname = (char *)
++ xmalloc (strlen (dll_pathname) + 1);
++ strcpy (ep->triggered_dll_pathname, dll_pathname);
++ }
++ else
++ ep->triggered_dll_pathname = NULL;
++ }
++
++ *cp_list = bs;
++}
++
++static void print_breakpoint_location (struct breakpoint *b,
++ struct bp_location *loc,
++ char *wrap_indent,
++ struct ui_stream *stb)
++{
++ if (b->source_file)
++ {
++ struct symbol *sym
++ = find_pc_sect_function (loc->address, loc->section);
++ if (sym)
++ {
++ ui_out_text (uiout, "in ");
++ ui_out_field_string (uiout, "func",
++ SYMBOL_PRINT_NAME (sym));
++ ui_out_wrap_hint (uiout, wrap_indent);
++ ui_out_text (uiout, " at ");
++ }
++ ui_out_field_string (uiout, "file", b->source_file);
++ ui_out_text (uiout, ":");
++
++ if (ui_out_is_mi_like_p (uiout))
++ {
++ struct symtab_and_line sal = find_pc_line (loc->address, 0);
++ char *fullname = symtab_to_fullname (sal.symtab);
++
++ if (fullname)
++ ui_out_field_string (uiout, "fullname", fullname);
++ }
++
++ ui_out_field_int (uiout, "line", b->line_number);
++ }
++ else if (!b->loc)
++ {
++ ui_out_field_string (uiout, "pending", b->addr_string);
++ }
++ else
++ {
++ print_address_symbolic (loc->address, stb->stream, demangle, "");
++ ui_out_field_stream (uiout, "at", stb);
++ }
++}
++
++/* Print B to gdb_stdout. */
++static void
++print_one_breakpoint_location (struct breakpoint *b,
++ struct bp_location *loc,
++ int loc_number,
++ CORE_ADDR *last_addr)
++{
++ struct command_line *l;
++ struct symbol *sym;
++ struct ep_type_description
++ {
++ enum bptype type;
++ char *description;
++ };
++ static struct ep_type_description bptypes[] =
++ {
++ {bp_none, "?deleted?"},
++ {bp_breakpoint, "breakpoint"},
++ {bp_hardware_breakpoint, "hw breakpoint"},
++ {bp_until, "until"},
++ {bp_finish, "finish"},
++ {bp_watchpoint, "watchpoint"},
++ {bp_hardware_watchpoint, "hw watchpoint"},
++ {bp_read_watchpoint, "read watchpoint"},
++ {bp_access_watchpoint, "acc watchpoint"},
++ {bp_longjmp, "longjmp"},
++ {bp_longjmp_resume, "longjmp resume"},
++ {bp_step_resume, "step resume"},
++ {bp_watchpoint_scope, "watchpoint scope"},
++ {bp_call_dummy, "call dummy"},
++ {bp_shlib_event, "shlib events"},
++ {bp_thread_event, "thread events"},
++ {bp_overlay_event, "overlay events"},
++ {bp_catch_load, "catch load"},
++ {bp_catch_unload, "catch unload"},
++ {bp_catch_fork, "catch fork"},
++ {bp_catch_vfork, "catch vfork"},
++ {bp_catch_exec, "catch exec"}
++ };
++
++ static char *bpdisps[] =
++ {"del", "dstp", "dis", "keep"};
++ static char bpenables[] = "nynny";
++ char wrap_indent[80];
++ struct ui_stream *stb = ui_out_stream_new (uiout);
++ struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb);
++ struct cleanup *bkpt_chain;
++
++ int header_of_multiple = 0;
++ int part_of_multiple = (loc != NULL);
++
++ gdb_assert (!loc || loc_number != 0);
++ /* See comment in print_one_breakpoint concerning
++ treatment of breakpoints with single disabled
++ location. */
++ if (loc == NULL
++ && (b->loc != NULL
++ && (b->loc->next != NULL || !b->loc->enabled)))
++ header_of_multiple = 1;
++ if (loc == NULL)
++ loc = b->loc;
++
++ annotate_record ();
++ bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "bkpt");
++
++ /* 1 */
++ annotate_field (0);
++ if (part_of_multiple)
++ {
++ char *formatted;
++ formatted = xstrprintf ("%d.%d", b->number, loc_number);
++ ui_out_field_string (uiout, "number", formatted);
++ xfree (formatted);
++ }
++ else
++ {
++ ui_out_field_int (uiout, "number", b->number);
++ }
++
++ /* 2 */
++ annotate_field (1);
++ if (part_of_multiple)
++ ui_out_field_skip (uiout, "type");
++ else
++ {
++ if (((int) b->type >= (sizeof (bptypes) / sizeof (bptypes[0])))
++ || ((int) b->type != bptypes[(int) b->type].type))
++ internal_error (__FILE__, __LINE__,
++ _("bptypes table does not describe type #%d."),
++ (int) b->type);
++ ui_out_field_string (uiout, "type", bptypes[(int) b->type].description);
++ }
++
++ /* 3 */
++ annotate_field (2);
++ if (part_of_multiple)
++ ui_out_field_skip (uiout, "disp");
++ else
++ ui_out_field_string (uiout, "disp", bpdisps[(int) b->disposition]);
++
++
++ /* 4 */
++ annotate_field (3);
++ if (part_of_multiple)
++ ui_out_field_string (uiout, "enabled", loc->enabled ? "y" : "n");
++ else
++ ui_out_field_fmt (uiout, "enabled", "%c",
++ bpenables[(int) b->enable_state]);
++ ui_out_spaces (uiout, 2);
++
++
++ /* 5 and 6 */
++ strcpy (wrap_indent, " ");
++ if (addressprint)
++ {
++ if (gdbarch_addr_bit (current_gdbarch) <= 32)
++ strcat (wrap_indent, " ");
++ else
++ strcat (wrap_indent, " ");
++ }
++
++ if (b->ops != NULL && b->ops->print_one != NULL)
++ {
++ /* Although the print_one can possibly print
++ all locations, calling it here is not likely
++ to get any nice result. So, make sure there's
++ just one location. */
++ gdb_assert (b->loc == NULL || b->loc->next == NULL);
++ b->ops->print_one (b, last_addr);
++ }
++ else
++ switch (b->type)
++ {
++ case bp_none:
++ internal_error (__FILE__, __LINE__,
++ _("print_one_breakpoint: bp_none encountered\n"));
++ break;
++
++ case bp_watchpoint:
++ case bp_hardware_watchpoint:
++ case bp_read_watchpoint:
++ case bp_access_watchpoint:
++ /* Field 4, the address, is omitted (which makes the columns
++ not line up too nicely with the headers, but the effect
++ is relatively readable). */
++ if (addressprint)
++ ui_out_field_skip (uiout, "addr");
++ annotate_field (5);
++ print_expression (b->exp, stb->stream);
++ ui_out_field_stream (uiout, "what", stb);
++ break;
++
++ case bp_catch_load:
++ case bp_catch_unload:
++ /* Field 4, the address, is omitted (which makes the columns
++ not line up too nicely with the headers, but the effect
++ is relatively readable). */
++ if (addressprint)
++ ui_out_field_skip (uiout, "addr");
++ annotate_field (5);
++ if (b->dll_pathname == NULL)
++ {
++ ui_out_field_string (uiout, "what", "<any library>");
++ ui_out_spaces (uiout, 1);
++ }
++ else
++ {
++ ui_out_text (uiout, "library \"");
++ ui_out_field_string (uiout, "what", b->dll_pathname);
++ ui_out_text (uiout, "\" ");
++ }
++ break;
++
++ case bp_catch_fork:
++ case bp_catch_vfork:
++ /* Field 4, the address, is omitted (which makes the columns
++ not line up too nicely with the headers, but the effect
++ is relatively readable). */
++ if (addressprint)
++ ui_out_field_skip (uiout, "addr");
++ annotate_field (5);
++ if (b->forked_inferior_pid != 0)
++ {
++ ui_out_text (uiout, "process ");
++ ui_out_field_int (uiout, "what", b->forked_inferior_pid);
++ ui_out_spaces (uiout, 1);
++ }
++ break;
++
++ case bp_catch_exec:
++ /* Field 4, the address, is omitted (which makes the columns
++ not line up too nicely with the headers, but the effect
++ is relatively readable). */
++ if (addressprint)
++ ui_out_field_skip (uiout, "addr");
++ annotate_field (5);
++ if (b->exec_pathname != NULL)
++ {
++ ui_out_text (uiout, "program \"");
++ ui_out_field_string (uiout, "what", b->exec_pathname);
++ ui_out_text (uiout, "\" ");
++ }
++ break;
++
++ case bp_breakpoint:
++ case bp_hardware_breakpoint:
++ case bp_until:
++ case bp_finish:
++ case bp_longjmp:
++ case bp_longjmp_resume:
++ case bp_step_resume:
++ case bp_watchpoint_scope:
++ case bp_call_dummy:
++ case bp_shlib_event:
++ case bp_thread_event:
++ case bp_overlay_event:
++ if (addressprint)
++ {
++ annotate_field (4);
++ if (header_of_multiple)
++ ui_out_field_string (uiout, "addr", "<MULTIPLE>");
++ if (b->loc == NULL || loc->shlib_disabled)
++ ui_out_field_string (uiout, "addr", "<PENDING>");
++ else
++ ui_out_field_core_addr (uiout, "addr", loc->address);
++ }
++ annotate_field (5);
++ if (!header_of_multiple)
++ print_breakpoint_location (b, loc, wrap_indent, stb);
++ if (b->loc)
++ *last_addr = b->loc->address;
++ break;
++ }
++
++ if (!part_of_multiple && b->thread != -1)
++ {
++ /* FIXME: This seems to be redundant and lost here; see the
++ "stop only in" line a little further down. */
++ ui_out_text (uiout, " thread ");
++ ui_out_field_int (uiout, "thread", b->thread);
++ }
++
++ ui_out_text (uiout, "\n");
++
++ if (part_of_multiple && frame_id_p (b->frame_id))
++ {
++ annotate_field (6);
++ ui_out_text (uiout, "\tstop only in stack frame at ");
++ /* FIXME: cagney/2002-12-01: Shouldn't be poeking around inside
++ the frame ID. */
++ ui_out_field_core_addr (uiout, "frame", b->frame_id.stack_addr);
++ ui_out_text (uiout, "\n");
++ }
++
++ if (!part_of_multiple && b->cond_string && !ada_exception_catchpoint_p (b))
++ {
++ /* We do not print the condition for Ada exception catchpoints
++ because the condition is an internal implementation detail
++ that we do not want to expose to the user. */
++ annotate_field (7);
++ ui_out_text (uiout, "\tstop only if ");
++ ui_out_field_string (uiout, "cond", b->cond_string);
++ ui_out_text (uiout, "\n");
++ }
++
++ if (!part_of_multiple && b->thread != -1)
++ {
++ /* FIXME should make an annotation for this */
++ ui_out_text (uiout, "\tstop only in thread ");
++ ui_out_field_int (uiout, "thread", b->thread);
++ ui_out_text (uiout, "\n");
++ }
++
++ if (!part_of_multiple && show_breakpoint_hit_counts && b->hit_count)
++ {
++ /* FIXME should make an annotation for this */
++ if (ep_is_catchpoint (b))
++ ui_out_text (uiout, "\tcatchpoint");
++ else
++ ui_out_text (uiout, "\tbreakpoint");
++ ui_out_text (uiout, " already hit ");
++ ui_out_field_int (uiout, "times", b->hit_count);
++ if (b->hit_count == 1)
++ ui_out_text (uiout, " time\n");
++ else
++ ui_out_text (uiout, " times\n");
++ }
++
++ /* Output the count also if it is zero, but only if this is
++ mi. FIXME: Should have a better test for this. */
++ if (ui_out_is_mi_like_p (uiout))
++ if (!part_of_multiple && show_breakpoint_hit_counts && b->hit_count == 0)
++ ui_out_field_int (uiout, "times", b->hit_count);
++
++ if (!part_of_multiple && b->ignore_count)
++ {
++ annotate_field (8);
++ ui_out_text (uiout, "\tignore next ");
++ ui_out_field_int (uiout, "ignore", b->ignore_count);
++ ui_out_text (uiout, " hits\n");
++ }
++
++ if (!part_of_multiple && (l = b->commands))
++ {
++ struct cleanup *script_chain;
++
++ annotate_field (9);
++ script_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "script");
++ print_command_lines (uiout, l, 4);
++ do_cleanups (script_chain);
++ }
++ do_cleanups (bkpt_chain);
++ do_cleanups (old_chain);
++}
++
++static void
++print_one_breakpoint (struct breakpoint *b,
++ CORE_ADDR *last_addr)
++{
++ print_one_breakpoint_location (b, NULL, 0, last_addr);
++
++ /* If this breakpoint has custom print function,
++ it's already printed. Otherwise, print individual
++ locations, if any. */
++ if (b->ops == NULL || b->ops->print_one == NULL)
++ {
++ /* If breakpoint has a single location that is
++ disabled, we print it as if it had
++ several locations, since otherwise it's hard to
++ represent "breakpoint enabled, location disabled"
++ situation.
++ Note that while hardware watchpoints have
++ several locations internally, that's no a property
++ exposed to user. */
++ if (b->loc
++ && !is_hardware_watchpoint (b)
++ && (b->loc->next || !b->loc->enabled)
++ && !ui_out_is_mi_like_p (uiout))
++ {
++ struct bp_location *loc;
++ int n = 1;
++ for (loc = b->loc; loc; loc = loc->next, ++n)
++ print_one_breakpoint_location (b, loc, n, last_addr);
++ }
++ }
++}
++
++
++struct captured_breakpoint_query_args
++ {
++ int bnum;
++ };
++
++static int
++do_captured_breakpoint_query (struct ui_out *uiout, void *data)
++{
++ struct captured_breakpoint_query_args *args = data;
++ struct breakpoint *b;
++ CORE_ADDR dummy_addr = 0;
++ ALL_BREAKPOINTS (b)
++ {
++ if (args->bnum == b->number)
++ {
++ print_one_breakpoint (b, &dummy_addr);
++ return GDB_RC_OK;
++ }
++ }
++ return GDB_RC_NONE;
++}
++
++enum gdb_rc
++gdb_breakpoint_query (struct ui_out *uiout, int bnum, char **error_message)
++{
++ struct captured_breakpoint_query_args args;
++ args.bnum = bnum;
++ /* For the moment we don't trust print_one_breakpoint() to not throw
++ an error. */
++ if (catch_exceptions_with_msg (uiout, do_captured_breakpoint_query, &args,
++ error_message, RETURN_MASK_ALL) < 0)
++ return GDB_RC_FAIL;
++ else
++ return GDB_RC_OK;
++}
++
++/* Return non-zero if B is user settable (breakpoints, watchpoints,
++ catchpoints, et.al.). */
++
++static int
++user_settable_breakpoint (const struct breakpoint *b)
++{
++ return (b->type == bp_breakpoint
++ || b->type == bp_catch_load
++ || b->type == bp_catch_unload
++ || b->type == bp_catch_fork
++ || b->type == bp_catch_vfork
++ || b->type == bp_catch_exec
++ || b->type == bp_hardware_breakpoint
++ || b->type == bp_watchpoint
++ || b->type == bp_read_watchpoint
++ || b->type == bp_access_watchpoint
++ || b->type == bp_hardware_watchpoint);
++}
++
++/* Print information on user settable breakpoint (watchpoint, etc)
++ number BNUM. If BNUM is -1 print all user settable breakpoints.
++ If ALLFLAG is non-zero, include non- user settable breakpoints. */
++
++static void
++breakpoint_1 (int bnum, int allflag)
++{
++ struct breakpoint *b;
++ CORE_ADDR last_addr = (CORE_ADDR) -1;
++ int nr_printable_breakpoints;
++ struct cleanup *bkpttbl_chain;
++
++ /* Compute the number of rows in the table. */
++ nr_printable_breakpoints = 0;
++ ALL_BREAKPOINTS (b)
++ if (bnum == -1
++ || bnum == b->number)
++ {
++ if (allflag || user_settable_breakpoint (b))
++ nr_printable_breakpoints++;
++ }
++
++ if (addressprint)
++ bkpttbl_chain
++ = make_cleanup_ui_out_table_begin_end (uiout, 6, nr_printable_breakpoints,
++ "BreakpointTable");
++ else
++ bkpttbl_chain
++ = make_cleanup_ui_out_table_begin_end (uiout, 5, nr_printable_breakpoints,
++ "BreakpointTable");
++
++ if (nr_printable_breakpoints > 0)
++ annotate_breakpoints_headers ();
++ if (nr_printable_breakpoints > 0)
++ annotate_field (0);
++ ui_out_table_header (uiout, 7, ui_left, "number", "Num"); /* 1 */
++ if (nr_printable_breakpoints > 0)
++ annotate_field (1);
++ ui_out_table_header (uiout, 14, ui_left, "type", "Type"); /* 2 */
++ if (nr_printable_breakpoints > 0)
++ annotate_field (2);
++ ui_out_table_header (uiout, 4, ui_left, "disp", "Disp"); /* 3 */
++ if (nr_printable_breakpoints > 0)
++ annotate_field (3);
++ ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb"); /* 4 */
++ if (addressprint)
++ {
++ if (nr_printable_breakpoints > 0)
++ annotate_field (4);
++ if (gdbarch_addr_bit (current_gdbarch) <= 32)
++ ui_out_table_header (uiout, 10, ui_left, "addr", "Address");/* 5 */
++ else
++ ui_out_table_header (uiout, 18, ui_left, "addr", "Address");/* 5 */
++ }
++ if (nr_printable_breakpoints > 0)
++ annotate_field (5);
++ ui_out_table_header (uiout, 40, ui_noalign, "what", "What"); /* 6 */
++ ui_out_table_body (uiout);
++ if (nr_printable_breakpoints > 0)
++ annotate_breakpoints_table ();
++
++ ALL_BREAKPOINTS (b)
++ if (bnum == -1
++ || bnum == b->number)
++ {
++ /* We only print out user settable breakpoints unless the
++ allflag is set. */
++ if (allflag || user_settable_breakpoint (b))
++ print_one_breakpoint (b, &last_addr);
++ }
++
++ do_cleanups (bkpttbl_chain);
++
++ if (nr_printable_breakpoints == 0)
++ {
++ if (bnum == -1)
++ ui_out_message (uiout, 0, "No breakpoints or watchpoints.\n");
++ else
++ ui_out_message (uiout, 0, "No breakpoint or watchpoint number %d.\n",
++ bnum);
++ }
++ else
++ {
++ /* Compare against (CORE_ADDR)-1 in case some compiler decides
++ that a comparison of an unsigned with -1 is always false. */
++ if (last_addr != (CORE_ADDR) -1 && !server_command)
++ set_next_address (last_addr);
++ }
++
++ /* FIXME? Should this be moved up so that it is only called when
++ there have been breakpoints? */
++ annotate_breakpoints_table_end ();
++}
++
++static void
++breakpoints_info (char *bnum_exp, int from_tty)
++{
++ int bnum = -1;
++
++ if (bnum_exp)
++ bnum = parse_and_eval_long (bnum_exp);
++
++ breakpoint_1 (bnum, 0);
++}
++
++static void
++maintenance_info_breakpoints (char *bnum_exp, int from_tty)
++{
++ int bnum = -1;
++
++ if (bnum_exp)
++ bnum = parse_and_eval_long (bnum_exp);
++
++ breakpoint_1 (bnum, 1);
++}
++
++static int
++breakpoint_has_pc (struct breakpoint *b, CORE_ADDR pc, asection *section)
++{
++ struct bp_location *bl = b->loc;
++ for (; bl; bl = bl->next)
++ {
++ if (bl->address == pc
++ && (!overlay_debugging || bl->section == section))
++ return 1;
++ }
++ return 0;
++}
++
++/* Print a message describing any breakpoints set at PC. */
++
++static void
++describe_other_breakpoints (CORE_ADDR pc, asection *section, int thread)
++{
++ int others = 0;
++ struct breakpoint *b;
++
++ ALL_BREAKPOINTS (b)
++ others += breakpoint_has_pc (b, pc, section);
++ if (others > 0)
++ {
++ if (others == 1)
++ printf_filtered (_("Note: breakpoint "));
++ else /* if (others == ???) */
++ printf_filtered (_("Note: breakpoints "));
++ ALL_BREAKPOINTS (b)
++ if (breakpoint_has_pc (b, pc, section))
++ {
++ others--;
++ printf_filtered ("%d", b->number);
++ if (b->thread == -1 && thread != -1)
++ printf_filtered (" (all threads)");
++ else if (b->thread != -1)
++ printf_filtered (" (thread %d)", b->thread);
++ printf_filtered ("%s%s ",
++ ((b->enable_state == bp_disabled ||
++ b->enable_state == bp_call_disabled)
++ ? " (disabled)"
++ : b->enable_state == bp_permanent
++ ? " (permanent)"
++ : ""),
++ (others > 1) ? ","
++ : ((others == 1) ? " and" : ""));
++ }
++ printf_filtered (_("also set at pc "));
++ fputs_filtered (paddress (pc), gdb_stdout);
++ printf_filtered (".\n");
++ }
++}
++
++/* Set the default place to put a breakpoint
++ for the `break' command with no arguments. */
++
++void
++set_default_breakpoint (int valid, CORE_ADDR addr, struct symtab *symtab,
++ int line)
++{
++ default_breakpoint_valid = valid;
++ default_breakpoint_address = addr;
++ default_breakpoint_symtab = symtab;
++ default_breakpoint_line = line;
++}
++
++/* Return true iff it is meaningful to use the address member of
++ BPT. For some breakpoint types, the address member is irrelevant
++ and it makes no sense to attempt to compare it to other addresses
++ (or use it for any other purpose either).
++
++ More specifically, each of the following breakpoint types will always
++ have a zero valued address and we don't want check_duplicates() to mark
++ breakpoints of any of these types to be a duplicate of an actual
++ breakpoint at address zero:
++
++ bp_watchpoint
++ bp_hardware_watchpoint
++ bp_read_watchpoint
++ bp_access_watchpoint
++ bp_catch_exec
++ bp_longjmp_resume
++ bp_catch_fork
++ bp_catch_vork */
++
++static int
++breakpoint_address_is_meaningful (struct breakpoint *bpt)
++{
++ enum bptype type = bpt->type;
++
++ return (type != bp_watchpoint
++ && type != bp_hardware_watchpoint
++ && type != bp_read_watchpoint
++ && type != bp_access_watchpoint
++ && type != bp_catch_exec
++ && type != bp_longjmp_resume
++ && type != bp_catch_fork
++ && type != bp_catch_vfork);
++}
++
++/* Rescan breakpoints at the same address and section as BPT,
++ marking the first one as "first" and any others as "duplicates".
++ This is so that the bpt instruction is only inserted once.
++ If we have a permanent breakpoint at the same place as BPT, make
++ that one the official one, and the rest as duplicates. */
++
++static void
++check_duplicates_for (CORE_ADDR address, asection *section)
++{
++ struct bp_location *b;
++ int count = 0;
++ struct bp_location *perm_bp = 0;
++
++ ALL_BP_LOCATIONS (b)
++ if (b->owner->enable_state != bp_disabled
++ && b->owner->enable_state != bp_call_disabled
++ && b->enabled
++ && !b->shlib_disabled
++ && b->address == address /* address / overlay match */
++ && (!overlay_debugging || b->section == section)
++ && breakpoint_address_is_meaningful (b->owner))
++ {
++ /* Have we found a permanent breakpoint? */
++ if (b->owner->enable_state == bp_permanent)
++ {
++ perm_bp = b;
++ break;
++ }
++
++ count++;
++ b->duplicate = count > 1;
++ }
++
++ /* If we found a permanent breakpoint at this address, go over the
++ list again and declare all the other breakpoints there to be the
++ duplicates. */
++ if (perm_bp)
++ {
++ perm_bp->duplicate = 0;
++
++ /* Permanent breakpoint should always be inserted. */
++ if (! perm_bp->inserted)
++ internal_error (__FILE__, __LINE__,
++ _("allegedly permanent breakpoint is not "
++ "actually inserted"));
++
++ ALL_BP_LOCATIONS (b)
++ if (b != perm_bp)
++ {
++ if (b->owner->enable_state != bp_disabled
++ && b->owner->enable_state != bp_call_disabled
++ && b->enabled && !b->shlib_disabled
++ && b->address == address /* address / overlay match */
++ && (!overlay_debugging || b->section == section)
++ && 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
++check_duplicates (struct breakpoint *bpt)
++{
++ struct bp_location *bl = bpt->loc;
++
++ if (! breakpoint_address_is_meaningful (bpt))
++ return;
++
++ for (; bl; bl = bl->next)
++ check_duplicates_for (bl->address, bl->section);
++}
++
++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, hex_string_custom ((unsigned long) from_addr, 8));
++ strcpy (astr2, hex_string_custom ((unsigned long) to_addr, 8));
++ 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, enum bptype bptype)
++{
++ if (!gdbarch_adjust_breakpoint_address_p (current_gdbarch))
++ {
++ /* Very few targets need any kind of breakpoint adjustment. */
++ return bpaddr;
++ }
++ else if (bptype == bp_watchpoint
++ || bptype == bp_hardware_watchpoint
++ || bptype == bp_read_watchpoint
++ || bptype == bp_access_watchpoint
++ || bptype == bp_catch_fork
++ || bptype == bp_catch_vfork
++ || bptype == bp_catch_exec)
++ {
++ /* Watchpoints and the various bp_catch_* eventpoints should not
++ have their addresses modified. */
++ 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;
++ loc->cond = NULL;
++ loc->shlib_disabled = 0;
++ loc->enabled = 1;
++
++ 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_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:
++ 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->global_next)
++ loc_p = loc_p->global_next;
++ loc_p->global_next = loc;
++ }
++
++ return loc;
++}
++
++static void free_bp_location (struct bp_location *loc)
++{
++ if (loc->cond)
++ xfree (loc->cond);
++ xfree (loc);
++}
++
++/* Helper to set_raw_breakpoint below. Creates a breakpoint
++ that has type BPTYPE and has no locations as yet. */
++
++static struct breakpoint *
++set_raw_breakpoint_without_location (enum bptype bptype)
++{
++ struct breakpoint *b, *b1;
++
++ b = (struct breakpoint *) xmalloc (sizeof (struct breakpoint));
++ memset (b, 0, sizeof (*b));
++
++ b->type = bptype;
++ b->language = current_language->la_language;
++ b->input_radix = input_radix;
++ b->thread = -1;
++ b->enable_state = bp_enabled;
++ b->next = 0;
++ b->silent = 0;
++ b->ignore_count = 0;
++ b->commands = NULL;
++ b->frame_id = null_frame_id;
++ b->dll_pathname = NULL;
++ b->triggered_dll_pathname = NULL;
++ b->forked_inferior_pid = 0;
++ b->exec_pathname = NULL;
++ b->ops = NULL;
++ b->condition_not_parsed = 0;
++
++ /* Add this breakpoint to the end of the chain
++ so that a list of breakpoints will come out in order
++ of increasing numbers. */
++
++ b1 = breakpoint_chain;
++ if (b1 == 0)
++ breakpoint_chain = b;
++ else
++ {
++ while (b1->next)
++ b1 = b1->next;
++ b1->next = b;
++ }
++ return b;
++}
++
++/* Initialize loc->function_name. */
++static void
++set_breakpoint_location_function (struct bp_location *loc)
++{
++ if (loc->owner->type == bp_breakpoint
++ || loc->owner->type == bp_hardware_breakpoint)
++ {
++ find_pc_partial_function (loc->address, &(loc->function_name),
++ NULL, NULL);
++ if (loc->function_name)
++ loc->function_name = xstrdup (loc->function_name);
++ }
++}
++
++/* 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
++ number are provided by SAL. The newly created and partially
++ initialized breakpoint is added to the breakpoint chain and
++ is also returned as the value of this function.
++
++ It is expected that the caller will complete the initialization of
++ the newly created breakpoint struct as well as output any status
++ information regarding the creation of a new breakpoint. In
++ particular, set_raw_breakpoint does NOT set the breakpoint
++ number! Care should be taken to not allow an error to occur
++ prior to completing the initialization of the breakpoint. If this
++ should happen, a bogus breakpoint will be left on the chain. */
++
++struct breakpoint *
++set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype)
++{
++ struct breakpoint *b = set_raw_breakpoint_without_location (bptype);
++ CORE_ADDR adjusted_address;
++
++ /* Adjust the breakpoint's address prior to allocating a location.
++ Once we call allocate_bp_location(), that mostly uninitialized
++ location will be placed on the location chain. Adjustment of the
++ breakpoint may cause read_memory_nobpt() to be called and we do
++ not want its scan of the location chain to find a breakpoint and
++ location that's only been partially initialized. */
++ adjusted_address = adjust_breakpoint_address (sal.pc, bptype);
++
++ b->loc = allocate_bp_location (b, bptype);
++ b->loc->requested_address = sal.pc;
++ b->loc->address = adjusted_address;
++
++ if (sal.symtab == NULL)
++ b->source_file = NULL;
++ else
++ b->source_file = savestring (sal.symtab->filename,
++ strlen (sal.symtab->filename));
++ b->loc->section = sal.section;
++ b->line_number = sal.line;
++
++ set_breakpoint_location_function (b->loc);
++
++ check_duplicates (b);
++ breakpoints_changed ();
++
++ return b;
++}
++
++
++/* Note that the breakpoint object B describes a permanent breakpoint
++ instruction, hard-wired into the inferior's code. */
++void
++make_breakpoint_permanent (struct breakpoint *b)
++{
++ struct bp_location *bl;
++ b->enable_state = bp_permanent;
++
++ /* By definition, permanent breakpoints are already present in the code.
++ Mark all locations as inserted. For now, make_breakpoint_permanent
++ is called in just one place, so it's hard to say if it's reasonable
++ to have permanent breakpoint with multiple locations or not,
++ but it's easy to implmement. */
++ for (bl = b->loc; bl; bl = bl->next)
++ bl->inserted = 1;
++}
++
++static struct breakpoint *
++create_internal_breakpoint (CORE_ADDR address, enum bptype type)
++{
++ static int internal_breakpoint_number = -1;
++ struct symtab_and_line sal;
++ struct breakpoint *b;
++
++ init_sal (&sal); /* initialize to zeroes */
++
++ sal.pc = address;
++ sal.section = find_pc_overlay (sal.pc);
++
++ b = set_raw_breakpoint (sal, type);
++ b->number = internal_breakpoint_number--;
++ b->disposition = disp_donttouch;
++
++ return b;
++}
++
++
++static void
++create_longjmp_breakpoint (char *func_name)
++{
++ struct breakpoint *b;
++ struct minimal_symbol *m;
++
++ if (func_name == NULL)
++ b = create_internal_breakpoint (0, bp_longjmp_resume);
++ else
++ {
++ if ((m = lookup_minimal_symbol_text (func_name, NULL)) == NULL)
++ return;
++
++ b = create_internal_breakpoint (SYMBOL_VALUE_ADDRESS (m), bp_longjmp);
++ }
++
++ b->enable_state = bp_disabled;
++ b->silent = 1;
++ if (func_name)
++ b->addr_string = xstrdup (func_name);
++}
++
++/* Call this routine when stepping and nexting to enable a breakpoint
++ if we do a longjmp(). When we hit that breakpoint, call
++ set_longjmp_resume_breakpoint() to figure out where we are going. */
++
++void
++enable_longjmp_breakpoint (void)
++{
++ struct breakpoint *b;
++
++ ALL_BREAKPOINTS (b)
++ if (b->type == bp_longjmp)
++ {
++ b->enable_state = bp_enabled;
++ check_duplicates (b);
++ }
++}
++
++void
++disable_longjmp_breakpoint (void)
++{
++ struct breakpoint *b;
++
++ ALL_BREAKPOINTS (b)
++ if (b->type == bp_longjmp
++ || b->type == bp_longjmp_resume)
++ {
++ b->enable_state = bp_disabled;
++ check_duplicates (b);
++ }
++}
++
++static void
++create_overlay_event_breakpoint (char *func_name)
++{
++ struct breakpoint *b;
++ struct minimal_symbol *m;
++
++ if ((m = lookup_minimal_symbol_text (func_name, NULL)) == NULL)
++ return;
++
++ b = create_internal_breakpoint (SYMBOL_VALUE_ADDRESS (m),
++ bp_overlay_event);
++ b->addr_string = xstrdup (func_name);
++
++ if (overlay_debugging == ovly_auto)
++ {
++ b->enable_state = bp_enabled;
++ overlay_events_enabled = 1;
++ }
++ else
++ {
++ b->enable_state = bp_disabled;
++ overlay_events_enabled = 0;
++ }
++}
++
++void
++enable_overlay_breakpoints (void)
++{
++ struct breakpoint *b;
++
++ ALL_BREAKPOINTS (b)
++ if (b->type == bp_overlay_event)
++ {
++ b->enable_state = bp_enabled;
++ check_duplicates (b);
++ overlay_events_enabled = 1;
++ }
++}
++
++void
++disable_overlay_breakpoints (void)
++{
++ struct breakpoint *b;
++
++ ALL_BREAKPOINTS (b)
++ if (b->type == bp_overlay_event)
++ {
++ b->enable_state = bp_disabled;
++ check_duplicates (b);
++ overlay_events_enabled = 0;
++ }
++}
++
++struct breakpoint *
++create_thread_event_breakpoint (CORE_ADDR address)
++{
++ struct breakpoint *b;
++
++ b = create_internal_breakpoint (address, bp_thread_event);
++
++ b->enable_state = bp_enabled;
++ /* addr_string has to be used or breakpoint_re_set will delete me. */
++ b->addr_string = xstrprintf ("*0x%s", paddr (b->loc->address));
++
++ return b;
++}
++
++void
++remove_thread_event_breakpoints (void)
++{
++ struct breakpoint *b, *temp;
++
++ ALL_BREAKPOINTS_SAFE (b, temp)
++ if (b->type == bp_thread_event)
++ delete_breakpoint (b);
++}
++
++struct captured_parse_breakpoint_args
++ {
++ char **arg_p;
++ struct symtabs_and_lines *sals_p;
++ char ***addr_string_p;
++ int *not_found_ptr;
++ };
++
++struct lang_and_radix
++ {
++ enum language lang;
++ int radix;
++ };
++
++
++void
++remove_solib_event_breakpoints (void)
++{
++ struct breakpoint *b, *temp;
++
++ ALL_BREAKPOINTS_SAFE (b, temp)
++ if (b->type == bp_shlib_event)
++ delete_breakpoint (b);
++}
++
++struct breakpoint *
++create_solib_event_breakpoint (CORE_ADDR address)
++{
++ struct breakpoint *b;
++
++ b = create_internal_breakpoint (address, bp_shlib_event);
++ return b;
++}
++
++/* Disable any breakpoints that are on code in shared libraries. Only
++ apply to enabled breakpoints, disabled ones can just stay disabled. */
++
++void
++disable_breakpoints_in_shlibs (void)
++{
++ struct bp_location *loc;
++ int disabled_shlib_breaks = 0;
++
++ ALL_BP_LOCATIONS (loc)
++ {
++ struct breakpoint *b = loc->owner;
++ /* We apply the check to all breakpoints, including disabled
++ for those with loc->duplicate set. This is so that when breakpoint
++ becomes enabled, or the duplicate is removed, gdb will try to insert
++ all breakpoints. If we don't set shlib_disabled here, we'll try
++ to insert those breakpoints and fail. */
++ if (((b->type == bp_breakpoint) || (b->type == bp_hardware_breakpoint))
++ && !loc->shlib_disabled
++#ifdef PC_SOLIB
++ && PC_SOLIB (loc->address)
++#else
++ && solib_address (loc->address)
++#endif
++ )
++ {
++ loc->shlib_disabled = 1;
++ }
++ }
++}
++
++/* Disable any breakpoints that are in in an unloaded shared library. Only
++ apply to enabled breakpoints, disabled ones can just stay disabled. */
++
++static void
++disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
++{
++ struct bp_location *loc;
++ int disabled_shlib_breaks = 0;
++
++ ALL_BP_LOCATIONS (loc)
++ {
++ struct breakpoint *b = loc->owner;
++ if ((loc->loc_type == bp_loc_hardware_breakpoint
++ || loc->loc_type == bp_loc_software_breakpoint)
++ && !loc->shlib_disabled)
++ {
++#ifdef PC_SOLIB
++ char *so_name = PC_SOLIB (loc->address);
++#else
++ char *so_name = solib_address (loc->address);
++#endif
++ if (so_name && !strcmp (so_name, solib->so_name))
++ {
++ loc->shlib_disabled = 1;
++ /* At this point, we cannot rely on remove_breakpoint
++ succeeding so we must mark the breakpoint as not inserted
++ to prevent future errors occurring in remove_breakpoints. */
++ loc->inserted = 0;
++ if (!disabled_shlib_breaks)
++ {
++ target_terminal_ours_for_output ();
++ warning (_("Temporarily disabling breakpoints for unloaded shared library \"%s\""),
++ so_name);
++ }
++ disabled_shlib_breaks = 1;
++ }
++ }
++ }
++}
++
++static void
++create_fork_vfork_event_catchpoint (int tempflag, char *cond_string,
++ enum bptype bp_kind)
++{
++ struct symtab_and_line sal;
++ struct breakpoint *b;
++ int thread = -1; /* All threads. */
++
++ init_sal (&sal);
++ sal.pc = 0;
++ sal.symtab = NULL;
++ sal.line = 0;
++
++ b = set_raw_breakpoint (sal, bp_kind);
++ set_breakpoint_count (breakpoint_count + 1);
++ b->number = breakpoint_count;
++ b->cond_string = (cond_string == NULL) ?
++ NULL : savestring (cond_string, strlen (cond_string));
++ b->thread = thread;
++ b->addr_string = NULL;
++ b->enable_state = bp_enabled;
++ b->disposition = tempflag ? disp_del : disp_donttouch;
++ b->forked_inferior_pid = 0;
++
++ mention (b);
++}
++
++static void
++create_fork_event_catchpoint (int tempflag, char *cond_string)
++{
++ create_fork_vfork_event_catchpoint (tempflag, cond_string, bp_catch_fork);
++}
++
++static void
++create_vfork_event_catchpoint (int tempflag, char *cond_string)
++{
++ create_fork_vfork_event_catchpoint (tempflag, cond_string, bp_catch_vfork);
++}
++
++static void
++create_exec_event_catchpoint (int tempflag, char *cond_string)
++{
++ struct symtab_and_line sal;
++ struct breakpoint *b;
++ int thread = -1; /* All threads. */
++
++ init_sal (&sal);
++ sal.pc = 0;
++ sal.symtab = NULL;
++ sal.line = 0;
++
++ b = set_raw_breakpoint (sal, bp_catch_exec);
++ set_breakpoint_count (breakpoint_count + 1);
++ b->number = breakpoint_count;
++ b->cond_string = (cond_string == NULL) ?
++ NULL : savestring (cond_string, strlen (cond_string));
++ b->thread = thread;
++ b->addr_string = NULL;
++ b->enable_state = bp_enabled;
++ b->disposition = tempflag ? disp_del : disp_donttouch;
++
++ mention (b);
++}
++
++static int
++hw_breakpoint_used_count (void)
++{
++ struct breakpoint *b;
++ int i = 0;
++
++ ALL_BREAKPOINTS (b)
++ {
++ if (b->type == bp_hardware_breakpoint && b->enable_state == bp_enabled)
++ i++;
++ }
++
++ return i;
++}
++
++static int
++hw_watchpoint_used_count (enum bptype type, int *other_type_used)
++{
++ struct breakpoint *b;
++ int i = 0;
++
++ *other_type_used = 0;
++ ALL_BREAKPOINTS (b)
++ {
++ if (breakpoint_enabled (b))
++ {
++ if (b->type == type)
++ i++;
++ else if ((b->type == bp_hardware_watchpoint ||
++ b->type == bp_read_watchpoint ||
++ b->type == bp_access_watchpoint))
++ *other_type_used = 1;
++ }
++ }
++ return i;
++}
++
++/* Call this after hitting the longjmp() breakpoint. Use this to set
++ a new breakpoint at the target of the jmp_buf.
++
++ FIXME - This ought to be done by setting a temporary breakpoint
++ that gets deleted automatically... */
++
++void
++set_longjmp_resume_breakpoint (CORE_ADDR pc, struct frame_id frame_id)
++{
++ struct breakpoint *b;
++
++ ALL_BREAKPOINTS (b)
++ if (b->type == bp_longjmp_resume)
++ {
++ b->loc->requested_address = pc;
++ b->loc->address = adjust_breakpoint_address (b->loc->requested_address,
++ b->type);
++ b->enable_state = bp_enabled;
++ b->frame_id = frame_id;
++ check_duplicates (b);
++ return;
++ }
++}
++
++void
++disable_watchpoints_before_interactive_call_start (void)
++{
++ struct breakpoint *b;
++
++ ALL_BREAKPOINTS (b)
++ {
++ if (((b->type == bp_watchpoint)
++ || (b->type == bp_hardware_watchpoint)
++ || (b->type == bp_read_watchpoint)
++ || (b->type == bp_access_watchpoint))
++ && breakpoint_enabled (b))
++ {
++ b->enable_state = bp_call_disabled;
++ check_duplicates (b);
++ }
++ }
++}
++
++void
++enable_watchpoints_after_interactive_call_stop (void)
++{
++ struct breakpoint *b;
++
++ ALL_BREAKPOINTS (b)
++ {
++ if (((b->type == bp_watchpoint)
++ || (b->type == bp_hardware_watchpoint)
++ || (b->type == bp_read_watchpoint)
++ || (b->type == bp_access_watchpoint))
++ && (b->enable_state == bp_call_disabled))
++ {
++ b->enable_state = bp_enabled;
++ check_duplicates (b);
++ }
++ }
++}
++
++
++/* Set a breakpoint that will evaporate an end of command
++ at address specified by SAL.
++ Restrict it to frame FRAME if FRAME is nonzero. */
++
++struct breakpoint *
++set_momentary_breakpoint (struct symtab_and_line sal, struct frame_id frame_id,
++ enum bptype type)
++{
++ struct breakpoint *b;
++ b = set_raw_breakpoint (sal, type);
++ b->enable_state = bp_enabled;
++ b->disposition = disp_donttouch;
++ b->frame_id = frame_id;
++
++ /* If we're debugging a multi-threaded program, then we
++ want momentary breakpoints to be active in only a
++ single thread of control. */
++ if (in_thread_list (inferior_ptid))
++ b->thread = pid_to_thread_id (inferior_ptid);
++
++ return b;
++}
++
++
++/* Tell the user we have just set a breakpoint B. */
++
++static void
++mention (struct breakpoint *b)
++{
++ int say_where = 0;
++ struct cleanup *old_chain, *ui_out_chain;
++ struct ui_stream *stb;
++
++ stb = ui_out_stream_new (uiout);
++ old_chain = make_cleanup_ui_out_stream_delete (stb);
++
++ /* FIXME: This is misplaced; mention() is called by things (like
++ hitting a watchpoint) other than breakpoint creation. It should
++ be possible to clean this up and at the same time replace the
++ random calls to breakpoint_changed with this hook, as has already
++ been done for deprecated_delete_breakpoint_hook and so on. */
++ if (deprecated_create_breakpoint_hook)
++ deprecated_create_breakpoint_hook (b);
++ breakpoint_create_event (b->number);
++
++ if (b->ops != NULL && b->ops->print_mention != NULL)
++ b->ops->print_mention (b);
++ else
++ switch (b->type)
++ {
++ case bp_none:
++ printf_filtered (_("(apparently deleted?) Eventpoint %d: "), b->number);
++ break;
++ case bp_watchpoint:
++ ui_out_text (uiout, "Watchpoint ");
++ ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt");
++ ui_out_field_int (uiout, "number", b->number);
++ ui_out_text (uiout, ": ");
++ print_expression (b->exp, stb->stream);
++ ui_out_field_stream (uiout, "exp", stb);
++ do_cleanups (ui_out_chain);
++ break;
++ case bp_hardware_watchpoint:
++ ui_out_text (uiout, "Hardware watchpoint ");
++ ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt");
++ ui_out_field_int (uiout, "number", b->number);
++ ui_out_text (uiout, ": ");
++ print_expression (b->exp, stb->stream);
++ ui_out_field_stream (uiout, "exp", stb);
++ do_cleanups (ui_out_chain);
++ break;
++ case bp_read_watchpoint:
++ ui_out_text (uiout, "Hardware read watchpoint ");
++ ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-rwpt");
++ ui_out_field_int (uiout, "number", b->number);
++ ui_out_text (uiout, ": ");
++ print_expression (b->exp, stb->stream);
++ ui_out_field_stream (uiout, "exp", stb);
++ do_cleanups (ui_out_chain);
++ break;
++ case bp_access_watchpoint:
++ ui_out_text (uiout, "Hardware access (read/write) watchpoint ");
++ ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-awpt");
++ ui_out_field_int (uiout, "number", b->number);
++ ui_out_text (uiout, ": ");
++ print_expression (b->exp, stb->stream);
++ ui_out_field_stream (uiout, "exp", stb);
++ do_cleanups (ui_out_chain);
++ break;
++ case bp_breakpoint:
++ if (ui_out_is_mi_like_p (uiout))
++ {
++ say_where = 0;
++ break;
++ }
++ printf_filtered (_("Breakpoint %d"), b->number);
++ say_where = 1;
++ break;
++ case bp_hardware_breakpoint:
++ if (ui_out_is_mi_like_p (uiout))
++ {
++ say_where = 0;
++ break;
++ }
++ printf_filtered (_("Hardware assisted breakpoint %d"), b->number);
++ say_where = 1;
++ break;
++ case bp_catch_load:
++ case bp_catch_unload:
++ printf_filtered (_("Catchpoint %d (%s %s)"),
++ b->number,
++ (b->type == bp_catch_load) ? "load" : "unload",
++ (b->dll_pathname != NULL) ?
++ b->dll_pathname : "<any library>");
++ break;
++ case bp_catch_fork:
++ case bp_catch_vfork:
++ printf_filtered (_("Catchpoint %d (%s)"),
++ b->number,
++ (b->type == bp_catch_fork) ? "fork" : "vfork");
++ break;
++ case bp_catch_exec:
++ printf_filtered (_("Catchpoint %d (exec)"),
++ b->number);
++ break;
++
++ case bp_until:
++ case bp_finish:
++ case bp_longjmp:
++ case bp_longjmp_resume:
++ case bp_step_resume:
++ case bp_call_dummy:
++ case bp_watchpoint_scope:
++ case bp_shlib_event:
++ case bp_thread_event:
++ case bp_overlay_event:
++ break;
++ }
++
++ if (say_where)
++ {
++ /* i18n: cagney/2005-02-11: Below needs to be merged into a
++ single string. */
++ if (b->loc == NULL)
++ {
++ printf_filtered (_(" (%s) pending."), b->addr_string);
++ }
++ else
++ {
++ if (addressprint || b->source_file == NULL)
++ {
++ printf_filtered (" at ");
++ fputs_filtered (paddress (b->loc->address), gdb_stdout);
++ }
++ if (b->source_file)
++ printf_filtered (": file %s, line %d.",
++ b->source_file, b->line_number);
++
++ if (b->loc->next)
++ {
++ struct bp_location *loc = b->loc;
++ int n = 0;
++ for (; loc; loc = loc->next)
++ ++n;
++ printf_filtered (" (%d locations)", n);
++ }
++
++ }
++ }
++ do_cleanups (old_chain);
++ if (ui_out_is_mi_like_p (uiout))
++ return;
++ printf_filtered ("\n");
++}
++
++
++static struct bp_location *
++add_location_to_breakpoint (struct breakpoint *b, enum bptype bptype,
++ const struct symtab_and_line *sal)
++{
++ struct bp_location *loc, **tmp;
++
++ loc = allocate_bp_location (b, bptype);
++ for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
++ ;
++ *tmp = loc;
++ loc->requested_address = sal->pc;
++ loc->address = adjust_breakpoint_address (loc->requested_address,
++ bptype);
++ loc->section = sal->section;
++
++ set_breakpoint_location_function (loc);
++ return loc;
++}
++
++/* Create a breakpoint with SAL as location. Use ADDR_STRING
++ as textual description of the location, and COND_STRING
++ as condition expression. */
++
++static void
++create_breakpoint (struct symtabs_and_lines sals, char *addr_string,
++ char *cond_string,
++ enum bptype type, enum bpdisp disposition,
++ int thread, int ignore_count, int from_tty)
++{
++ struct breakpoint *b = NULL;
++ int i;
++
++ if (type == bp_hardware_breakpoint)
++ {
++ int i = hw_breakpoint_used_count ();
++ int target_resources_ok =
++ TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint,
++ i + 1, 0);
++ if (target_resources_ok == 0)
++ error (_("No hardware breakpoint support in the target."));
++ else if (target_resources_ok < 0)
++ error (_("Hardware breakpoints used exceeds limit."));
++ }
++
++ for (i = 0; i < sals.nelts; ++i)
++ {
++ struct symtab_and_line sal = sals.sals[i];
++ struct bp_location *loc;
++
++ if (from_tty)
++ describe_other_breakpoints (sal.pc, sal.section, thread);
++
++ if (i == 0)
++ {
++ b = set_raw_breakpoint (sal, type);
++ set_breakpoint_count (breakpoint_count + 1);
++ b->number = breakpoint_count;
++ b->thread = thread;
++
++ b->cond_string = cond_string;
++ b->ignore_count = ignore_count;
++ b->enable_state = bp_enabled;
++ b->disposition = disposition;
++
++ loc = b->loc;
++ }
++ else
++ {
++ loc = add_location_to_breakpoint (b, type, &sal);
++ }
++
++ if (b->cond_string)
++ {
++ char *arg = b->cond_string;
++ loc->cond = parse_exp_1 (&arg, block_for_pc (loc->address), 0);
++ if (*arg)
++ error (_("Garbage %s follows condition"), arg);
++ }
++ }
++
++ if (addr_string)
++ b->addr_string = addr_string;
++ else
++ /* addr_string has to be used or breakpoint_re_set will delete
++ me. */
++ b->addr_string = xstrprintf ("*0x%s", paddr (b->loc->address));
++
++ mention (b);
++}
++
++/* Remove element at INDEX_TO_REMOVE from SAL, shifting other
++ elements to fill the void space. */
++static void remove_sal (struct symtabs_and_lines *sal, int index_to_remove)
++{
++ int i = index_to_remove+1;
++ int last_index = sal->nelts-1;
++
++ for (;i <= last_index; ++i)
++ sal->sals[i-1] = sal->sals[i];
++
++ --(sal->nelts);
++}
++
++/* If appropriate, obtains all sals that correspond
++ to the same file and line as SAL. This is done
++ only if SAL does not have explicit PC and has
++ line and file information. If we got just a single
++ expanded sal, return the original.
++
++ Otherwise, if SAL.explicit_line is not set, filter out
++ all sals for which the name of enclosing function
++ is different from SAL. This makes sure that if we have
++ breakpoint originally set in template instantiation, say
++ foo<int>(), we won't expand SAL to locations at the same
++ line in all existing instantiations of 'foo'.
++
++*/
++struct symtabs_and_lines
++expand_line_sal_maybe (struct symtab_and_line sal)
++{
++ struct symtabs_and_lines expanded;
++ CORE_ADDR original_pc = sal.pc;
++ char *original_function = NULL;
++ int found;
++ int i;
++
++ /* If we have explicit pc, don't expand.
++ If we have no line number, we can't expand. */
++ if (sal.explicit_pc || sal.line == 0 || sal.symtab == NULL)
++ {
++ expanded.nelts = 1;
++ expanded.sals = xmalloc (sizeof (struct symtab_and_line));
++ expanded.sals[0] = sal;
++ return expanded;
++ }
++
++ sal.pc = 0;
++ find_pc_partial_function (original_pc, &original_function, NULL, NULL);
++
++ expanded = expand_line_sal (sal);
++ if (expanded.nelts == 1)
++ {
++ /* We had one sal, we got one sal. Without futher
++ processing, just return the original sal. */
++ xfree (expanded.sals);
++ expanded.nelts = 1;
++ expanded.sals = xmalloc (sizeof (struct symtab_and_line));
++ sal.pc = original_pc;
++ expanded.sals[0] = sal;
++ return expanded;
++ }
++
++ if (!sal.explicit_line)
++ {
++ CORE_ADDR func_addr, func_end;
++ for (i = 0; i < expanded.nelts; ++i)
++ {
++ CORE_ADDR pc = expanded.sals[i].pc;
++ char *this_function;
++ if (find_pc_partial_function (pc, &this_function,
++ &func_addr, &func_end))
++ {
++ if (this_function &&
++ strcmp (this_function, original_function) != 0)
++ {
++ remove_sal (&expanded, i);
++ --i;
++ }
++ else if (func_addr == pc)
++ {
++ /* We're at beginning of a function, and should
++ skip prologue. */
++ struct symbol *sym = find_pc_function (pc);
++ if (sym)
++ expanded.sals[i] = find_function_start_sal (sym, 1);
++ else
++ expanded.sals[i].pc
++ = gdbarch_skip_prologue (current_gdbarch, pc);
++ }
++ }
++ }
++ }
++
++
++ if (expanded.nelts <= 1)
++ {
++ /* This is un ugly workaround. If we get zero
++ expanded sals then something is really wrong.
++ Fix that by returnign the original sal. */
++ xfree (expanded.sals);
++ expanded.nelts = 1;
++ expanded.sals = xmalloc (sizeof (struct symtab_and_line));
++ sal.pc = original_pc;
++ expanded.sals[0] = sal;
++ return expanded;
++ }
++
++ if (original_pc)
++ {
++ found = 0;
++ for (i = 0; i < expanded.nelts; ++i)
++ if (expanded.sals[i].pc == original_pc)
++ {
++ found = 1;
++ break;
++ }
++ gdb_assert (found);
++ }
++
++ return expanded;
++}
++
++/* Add SALS.nelts breakpoints to the breakpoint table. For each
++ SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i]
++ value. COND_STRING, if not NULL, specified the condition to be
++ used for all breakpoints. Essentially the only case where
++ SALS.nelts is not 1 is when we set a breakpoint on an overloaded
++ function. In that case, it's still not possible to specify
++ separate conditions for different overloaded functions, so
++ we take just a single condition string.
++
++ NOTE: If the function succeeds, the caller is expected to cleanup
++ the arrays ADDR_STRING, COND_STRING, and SALS (but not the
++ array contents). If the function fails (error() is called), the
++ caller is expected to cleanups both the ADDR_STRING, COND_STRING,
++ COND and SALS arrays and each of those arrays contents. */
++
++static void
++create_breakpoints (struct symtabs_and_lines sals, char **addr_string,
++ char *cond_string,
++ enum bptype type, enum bpdisp disposition,
++ int thread, int ignore_count, int from_tty)
++{
++ int i;
++ for (i = 0; i < sals.nelts; ++i)
++ {
++ struct symtabs_and_lines expanded =
++ expand_line_sal_maybe (sals.sals[i]);
++
++ create_breakpoint (expanded, addr_string[i],
++ cond_string, type, disposition,
++ thread, ignore_count, from_tty);
++ }
++}
++
++/* Parse ARG which is assumed to be a SAL specification possibly
++ followed by conditionals. On return, SALS contains an array of SAL
++ addresses found. ADDR_STRING contains a vector of (canonical)
++ address strings. ARG points to the end of the SAL. */
++
++static void
++parse_breakpoint_sals (char **address,
++ struct symtabs_and_lines *sals,
++ char ***addr_string,
++ int *not_found_ptr)
++{
++ char *addr_start = *address;
++ *addr_string = NULL;
++ /* If no arg given, or if first arg is 'if ', use the default
++ breakpoint. */
++ if ((*address) == NULL
++ || (strncmp ((*address), "if", 2) == 0 && isspace ((*address)[2])))
++ {
++ if (default_breakpoint_valid)
++ {
++ struct symtab_and_line sal;
++ init_sal (&sal); /* initialize to zeroes */
++ sals->sals = (struct symtab_and_line *)
++ xmalloc (sizeof (struct symtab_and_line));
++ sal.pc = default_breakpoint_address;
++ sal.line = default_breakpoint_line;
++ sal.symtab = default_breakpoint_symtab;
++ sal.section = find_pc_overlay (sal.pc);
++ sals->sals[0] = sal;
++ sals->nelts = 1;
++ }
++ else
++ error (_("No default breakpoint address now."));
++ }
++ else
++ {
++ /* Force almost all breakpoints to be in terms of the
++ current_source_symtab (which is decode_line_1's default). This
++ should produce the results we want almost all of the time while
++ leaving default_breakpoint_* alone.
++ ObjC: However, don't match an Objective-C method name which
++ may have a '+' or '-' succeeded by a '[' */
++
++ struct symtab_and_line cursal = get_current_source_symtab_and_line ();
++
++ if (default_breakpoint_valid
++ && (!cursal.symtab
++ || ((strchr ("+-", (*address)[0]) != NULL)
++ && ((*address)[1] != '['))))
++ *sals = decode_line_1 (address, 1, default_breakpoint_symtab,
++ default_breakpoint_line, addr_string,
++ not_found_ptr);
++ else
++ *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0,
++ addr_string, not_found_ptr);
++ }
++ /* For any SAL that didn't have a canonical string, fill one in. */
++ if (sals->nelts > 0 && *addr_string == NULL)
++ *addr_string = xcalloc (sals->nelts, sizeof (char **));
++ if (addr_start != (*address))
++ {
++ int i;
++ for (i = 0; i < sals->nelts; i++)
++ {
++ /* Add the string if not present. */
++ if ((*addr_string)[i] == NULL)
++ (*addr_string)[i] = savestring (addr_start, (*address) - addr_start);
++ }
++ }
++}
++
++
++/* Convert each SAL into a real PC. Verify that the PC can be
++ inserted as a breakpoint. If it can't throw an error. */
++
++static void
++breakpoint_sals_to_pc (struct symtabs_and_lines *sals,
++ char *address)
++{
++ int i;
++ for (i = 0; i < sals->nelts; i++)
++ resolve_sal_pc (&sals->sals[i]);
++}
++
++static void
++do_captured_parse_breakpoint (struct ui_out *ui, void *data)
++{
++ struct captured_parse_breakpoint_args *args = data;
++
++ parse_breakpoint_sals (args->arg_p, args->sals_p, args->addr_string_p,
++ args->not_found_ptr);
++}
++
++/* Given TOK, a string specification of condition and thread, as
++ accepted by the 'break' command, extract the condition
++ string and thread number and set *COND_STRING and *THREAD.
++ PC identifies the context at which the condition should be parsed.
++ If no condition is found, *COND_STRING is set to NULL.
++ If no thread is found, *THREAD is set to -1. */
++static void
++find_condition_and_thread (char *tok, CORE_ADDR pc,
++ char **cond_string, int *thread)
++{
++ *cond_string = NULL;
++ *thread = -1;
++ while (tok && *tok)
++ {
++ char *end_tok;
++ int toklen;
++ char *cond_start = NULL;
++ char *cond_end = NULL;
++ while (*tok == ' ' || *tok == '\t')
++ tok++;
++
++ end_tok = tok;
++
++ while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000')
++ end_tok++;
++
++ toklen = end_tok - tok;
++
++ if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
++ {
++ tok = cond_start = end_tok + 1;
++ parse_exp_1 (&tok, block_for_pc (pc), 0);
++ cond_end = tok;
++ *cond_string = savestring (cond_start,
++ cond_end - cond_start);
++ }
++ else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
++ {
++ char *tmptok;
++
++ tok = end_tok + 1;
++ tmptok = tok;
++ *thread = strtol (tok, &tok, 0);
++ if (tok == tmptok)
++ error (_("Junk after thread keyword."));
++ if (!valid_thread_id (*thread))
++ error (_("Unknown thread %d."), *thread);
++ }
++ else
++ error (_("Junk at end of arguments."));
++ }
++}
++
++/* Set a breakpoint. This function is shared between
++ CLI and MI functions for setting a breakpoint.
++ This function has two major modes of operations,
++ selected by the PARSE_CONDITION_AND_THREAD parameter.
++ If non-zero, the function will parse arg, extracting
++ breakpoint location, address and thread. Otherwise,
++ ARG is just the location of breakpoint, with condition
++ and thread specified by the COND_STRING and THREAD
++ parameters. */
++
++static void
++break_command_really (char *arg, char *cond_string, int thread,
++ int parse_condition_and_thread,
++ int tempflag, int hardwareflag,
++ int ignore_count,
++ enum auto_boolean pending_break_support,
++ int from_tty)
++{
++ struct gdb_exception e;
++ struct symtabs_and_lines sals;
++ struct symtab_and_line pending_sal;
++ char *copy_arg;
++ char *err_msg;
++ char *addr_start = arg;
++ char **addr_string;
++ struct cleanup *old_chain;
++ struct cleanup *breakpoint_chain = NULL;
++ struct captured_parse_breakpoint_args parse_args;
++ int i;
++ int pending = 0;
++ int not_found = 0;
++
++ sals.sals = NULL;
++ sals.nelts = 0;
++ addr_string = NULL;
++
++ parse_args.arg_p = &arg;
++ parse_args.sals_p = &sals;
++ parse_args.addr_string_p = &addr_string;
++ parse_args.not_found_ptr = &not_found;
++
++ e = catch_exception (uiout, do_captured_parse_breakpoint,
++ &parse_args, RETURN_MASK_ALL);
++
++ /* If caller is interested in rc value from parse, set value. */
++ switch (e.reason)
++ {
++ case RETURN_QUIT:
++ throw_exception (e);
++ case RETURN_ERROR:
++ switch (e.error)
++ {
++ case NOT_FOUND_ERROR:
++
++ /* If pending breakpoint support is turned off, throw
++ error. */
++
++ if (pending_break_support == AUTO_BOOLEAN_FALSE)
++ throw_exception (e);
++
++ exception_print (gdb_stderr, e);
++
++ /* If pending breakpoint support is auto query and the user
++ selects no, then simply return the error code. */
++ if (pending_break_support == AUTO_BOOLEAN_AUTO &&
++ !nquery ("Make breakpoint pending on future shared library load? "))
++ return;
++
++ /* At this point, either the user was queried about setting
++ a pending breakpoint and selected yes, or pending
++ breakpoint behavior is on and thus a pending breakpoint
++ is defaulted on behalf of the user. */
++ copy_arg = xstrdup (addr_start);
++ addr_string = &copy_arg;
++ sals.nelts = 1;
++ sals.sals = &pending_sal;
++ pending_sal.pc = 0;
++ pending = 1;
++ break;
++ default:
++ throw_exception (e);
++ }
++ default:
++ if (!sals.nelts)
++ return;
++ }
++
++ /* Create a chain of things that always need to be cleaned up. */
++ old_chain = make_cleanup (null_cleanup, 0);
++
++ if (!pending)
++ {
++ /* Make sure that all storage allocated to SALS gets freed. */
++ make_cleanup (xfree, sals.sals);
++
++ /* Cleanup the addr_string array but not its contents. */
++ make_cleanup (xfree, addr_string);
++ }
++
++ /* ----------------------------- SNIP -----------------------------
++ Anything added to the cleanup chain beyond this point is assumed
++ to be part of a breakpoint. If the breakpoint create succeeds
++ then the memory is not reclaimed. */
++ breakpoint_chain = make_cleanup (null_cleanup, 0);
++
++ /* Mark the contents of the addr_string for cleanup. These go on
++ the breakpoint_chain and only occure if the breakpoint create
++ fails. */
++ for (i = 0; i < sals.nelts; i++)
++ {
++ if (addr_string[i] != NULL)
++ make_cleanup (xfree, addr_string[i]);
++ }
++
++ /* Resolve all line numbers to PC's and verify that the addresses
++ are ok for the target. */
++ if (!pending)
++ breakpoint_sals_to_pc (&sals, addr_start);
++
++ /* Verify that condition can be parsed, before setting any
++ breakpoints. Allocate a separate condition expression for each
++ breakpoint. */
++ if (!pending)
++ {
++ if (parse_condition_and_thread)
++ {
++ /* Here we only parse 'arg' to separate condition
++ from thread number, so parsing in context of first
++ sal is OK. When setting the breakpoint we'll
++ re-parse it in context of each sal. */
++ cond_string = NULL;
++ thread = -1;
++ find_condition_and_thread (arg, sals.sals[0].pc, &cond_string, &thread);
++ if (cond_string)
++ make_cleanup (xfree, cond_string);
++ }
++ else
++ {
++ /* Create a private copy of condition string. */
++ if (cond_string)
++ {
++ cond_string = xstrdup (cond_string);
++ make_cleanup (xfree, cond_string);
++ }
++ }
++ create_breakpoints (sals, addr_string, cond_string,
++ hardwareflag ? bp_hardware_breakpoint
++ : bp_breakpoint,
++ tempflag ? disp_del : disp_donttouch,
++ thread, ignore_count, from_tty);
++ }
++ else
++ {
++ struct symtab_and_line sal = {0};
++ struct breakpoint *b;
++
++ make_cleanup (xfree, copy_arg);
++
++ b = set_raw_breakpoint_without_location (hardwareflag
++ ? bp_hardware_breakpoint
++ : bp_breakpoint);
++ set_breakpoint_count (breakpoint_count + 1);
++ b->number = breakpoint_count;
++ b->thread = -1;
++ b->addr_string = addr_string[0];
++ b->cond_string = NULL;
++ b->ignore_count = ignore_count;
++ b->disposition = tempflag ? disp_del : disp_donttouch;
++ b->condition_not_parsed = 1;
++ mention (b);
++ }
++
++ if (sals.nelts > 1)
++ warning (_("Multiple breakpoints were set.\n"
++ "Use the \"delete\" command to delete unwanted breakpoints."));
++ /* That's it. Discard the cleanups for data inserted into the
++ breakpoint. */
++ discard_cleanups (breakpoint_chain);
++ /* But cleanup everything else. */
++ do_cleanups (old_chain);
++}
++
++/* Set a breakpoint.
++ ARG is a string describing breakpoint address,
++ condition, and thread.
++ FLAG specifies if a breakpoint is hardware on,
++ and if breakpoint is temporary, using BP_HARDWARE_FLAG
++ and BP_TEMPFLAG. */
++
++static void
++break_command_1 (char *arg, int flag, int from_tty)
++{
++ int hardwareflag = flag & BP_HARDWAREFLAG;
++ int tempflag = flag & BP_TEMPFLAG;
++
++ break_command_really (arg,
++ NULL, 0, 1 /* parse arg */,
++ tempflag, hardwareflag,
++ 0 /* Ignore count */,
++ pending_break_support, from_tty);
++}
++
++
++void
++set_breakpoint (char *address, char *condition,
++ int hardwareflag, int tempflag,
++ int thread, int ignore_count,
++ int pending)
++{
++ break_command_really (address, condition, thread,
++ 0 /* condition and thread are valid. */,
++ tempflag, hardwareflag,
++ ignore_count,
++ pending
++ ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
++ 0);
++}
++
++
++/* Helper function for break_command_1 and disassemble_command. */
++
++void
++resolve_sal_pc (struct symtab_and_line *sal)
++{
++ CORE_ADDR pc;
++
++ if (sal->pc == 0 && sal->symtab != NULL)
++ {
++ if (!find_line_pc (sal->symtab, sal->line, &pc))
++ error (_("No line %d in file \"%s\"."),
++ sal->line, sal->symtab->filename);
++ sal->pc = pc;
++ }
++
++ if (sal->section == 0 && sal->symtab != NULL)
++ {
++ struct blockvector *bv;
++ struct block *b;
++ struct symbol *sym;
++
++ bv = blockvector_for_pc_sect (sal->pc, 0, &b, sal->symtab);
++ if (bv != NULL)
++ {
++ sym = block_function (b);
++ if (sym != NULL)
++ {
++ fixup_symbol_section (sym, sal->symtab->objfile);
++ sal->section = SYMBOL_BFD_SECTION (sym);
++ }
++ else
++ {
++ /* It really is worthwhile to have the section, so we'll just
++ have to look harder. This case can be executed if we have
++ line numbers but no functions (as can happen in assembly
++ source). */
++
++ struct minimal_symbol *msym;
++
++ msym = lookup_minimal_symbol_by_pc (sal->pc);
++ if (msym)
++ sal->section = SYMBOL_BFD_SECTION (msym);
++ }
++ }
++ }
++}
++
++void
++break_command (char *arg, int from_tty)
++{
++ break_command_1 (arg, 0, from_tty);
++}
++
++void
++tbreak_command (char *arg, int from_tty)
++{
++ break_command_1 (arg, BP_TEMPFLAG, from_tty);
++}
++
++static void
++hbreak_command (char *arg, int from_tty)
++{
++ break_command_1 (arg, BP_HARDWAREFLAG, from_tty);
++}
++
++static void
++thbreak_command (char *arg, int from_tty)
++{
++ break_command_1 (arg, (BP_TEMPFLAG | BP_HARDWAREFLAG), from_tty);
++}
++
++static void
++stop_command (char *arg, int from_tty)
++{
++ printf_filtered (_("Specify the type of breakpoint to set.\n\
++Usage: stop in <function | address>\n\
++ stop at <line>\n"));
++}
++
++static void
++stopin_command (char *arg, int from_tty)
++{
++ int badInput = 0;
++
++ if (arg == (char *) NULL)
++ badInput = 1;
++ else if (*arg != '*')
++ {
++ char *argptr = arg;
++ int hasColon = 0;
++
++ /* look for a ':'. If this is a line number specification, then
++ say it is bad, otherwise, it should be an address or
++ function/method name */
++ while (*argptr && !hasColon)
++ {
++ hasColon = (*argptr == ':');
++ argptr++;
++ }
++
++ if (hasColon)
++ badInput = (*argptr != ':'); /* Not a class::method */
++ else
++ badInput = isdigit (*arg); /* a simple line number */
++ }
++
++ if (badInput)
++ printf_filtered (_("Usage: stop in <function | address>\n"));
++ else
++ break_command_1 (arg, 0, from_tty);
++}
++
++static void
++stopat_command (char *arg, int from_tty)
++{
++ int badInput = 0;
++
++ if (arg == (char *) NULL || *arg == '*') /* no line number */
++ badInput = 1;
++ else
++ {
++ char *argptr = arg;
++ int hasColon = 0;
++
++ /* look for a ':'. If there is a '::' then get out, otherwise
++ it is probably a line number. */
++ while (*argptr && !hasColon)
++ {
++ hasColon = (*argptr == ':');
++ argptr++;
++ }
++
++ if (hasColon)
++ badInput = (*argptr == ':'); /* we have class::method */
++ else
++ badInput = !isdigit (*arg); /* not a line number */
++ }
++
++ if (badInput)
++ printf_filtered (_("Usage: stop at <line>\n"));
++ else
++ break_command_1 (arg, 0, from_tty);
++}
++
++/* accessflag: hw_write: watch write,
++ hw_read: watch read,
++ hw_access: watch access (read or write) */
++static void
++watch_command_1 (char *arg, int accessflag, int from_tty)
++{
++ struct breakpoint *b, *scope_breakpoint = NULL;
++ struct symtab_and_line sal;
++ struct expression *exp;
++ struct block *exp_valid_block;
++ struct value *val, *mark;
++ struct frame_info *frame;
++ struct frame_info *prev_frame = NULL;
++ char *exp_start = NULL;
++ char *exp_end = NULL;
++ char *tok, *id_tok_start, *end_tok;
++ int toklen;
++ char *cond_start = NULL;
++ char *cond_end = NULL;
++ struct expression *cond = NULL;
++ int i, other_type_used, target_resources_ok = 0;
++ enum bptype bp_type;
++ int mem_cnt = 0;
++ int thread = -1;
++
++ init_sal (&sal); /* initialize to zeroes */
++
++ /* Make sure that we actually have parameters to parse. */
++ if (arg != NULL && arg[0] != '\0')
++ {
++ toklen = strlen (arg); /* Size of argument list. */
++
++ /* Points tok to the end of the argument list. */
++ tok = arg + toklen - 1;
++
++ /* Go backwards in the parameters list. Skip the last parameter.
++ If we're expecting a 'thread <thread_num>' parameter, this should
++ be the thread identifier. */
++ while (tok > arg && (*tok == ' ' || *tok == '\t'))
++ tok--;
++ while (tok > arg && (*tok != ' ' && *tok != '\t'))
++ tok--;
++
++ /* Points end_tok to the beginning of the last token. */
++ id_tok_start = tok + 1;
++
++ /* Go backwards in the parameters list. Skip one more parameter.
++ If we're expecting a 'thread <thread_num>' parameter, we should
++ reach a "thread" token. */
++ while (tok > arg && (*tok == ' ' || *tok == '\t'))
++ tok--;
++
++ end_tok = tok;
++
++ while (tok > arg && (*tok != ' ' && *tok != '\t'))
++ tok--;
++
++ /* Move the pointer forward to skip the whitespace and
++ calculate the length of the token. */
++ tok++;
++ toklen = end_tok - tok;
++
++ if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
++ {
++ /* At this point we've found a "thread" token, which means
++ the user is trying to set a watchpoint that triggers
++ only in a specific thread. */
++ char *endp;
++
++ /* Extract the thread ID from the next token. */
++ thread = strtol (id_tok_start, &endp, 0);
++
++ /* Check if the user provided a valid numeric value for the
++ thread ID. */
++ if (*endp != ' ' && *endp != '\t' && *endp != '\0')
++ error (_("Invalid thread ID specification %s."), id_tok_start);
++
++ /* Check if the thread actually exists. */
++ if (!valid_thread_id (thread))
++ error (_("Unknown thread %d."), thread);
++
++ /* Truncate the string and get rid of the thread <thread_num>
++ parameter before the parameter list is parsed by the
++ evaluate_expression() function. */
++ *tok = '\0';
++ }
++ }
++
++ /* Parse the rest of the arguments. */
++ innermost_block = NULL;
++ exp_start = arg;
++ exp = parse_exp_1 (&arg, 0, 0);
++ exp_end = arg;
++ exp_valid_block = innermost_block;
++ mark = value_mark ();
++ val = evaluate_expression (exp);
++ release_value (val);
++ if (value_lazy (val))
++ value_fetch_lazy (val);
++
++ tok = arg;
++ while (*tok == ' ' || *tok == '\t')
++ tok++;
++ end_tok = tok;
++
++ while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000')
++ end_tok++;
++
++ toklen = end_tok - tok;
++ if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
++ {
++ tok = cond_start = end_tok + 1;
++ cond = parse_exp_1 (&tok, 0, 0);
++ cond_end = tok;
++ }
++ if (*tok)
++ error (_("Junk at end of command."));
++
++ if (accessflag == hw_read)
++ bp_type = bp_read_watchpoint;
++ else if (accessflag == hw_access)
++ bp_type = bp_access_watchpoint;
++ else
++ bp_type = bp_hardware_watchpoint;
++
++ mem_cnt = can_use_hardware_watchpoint (val);
++ if (mem_cnt == 0 && bp_type != bp_hardware_watchpoint)
++ error (_("Expression cannot be implemented with read/access watchpoint."));
++ if (mem_cnt != 0)
++ {
++ i = hw_watchpoint_used_count (bp_type, &other_type_used);
++ target_resources_ok =
++ TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_type, i + mem_cnt,
++ other_type_used);
++ if (target_resources_ok == 0 && bp_type != bp_hardware_watchpoint)
++ error (_("Target does not support this type of hardware watchpoint."));
++
++ if (target_resources_ok < 0 && bp_type != bp_hardware_watchpoint)
++ error (_("Target can only support one kind of HW watchpoint at a time."));
++ }
++
++ /* Change the type of breakpoint to an ordinary watchpoint if a hardware
++ watchpoint could not be set. */
++ if (!mem_cnt || target_resources_ok <= 0)
++ bp_type = bp_watchpoint;
++
++ frame = block_innermost_frame (exp_valid_block);
++ if (frame)
++ prev_frame = get_prev_frame (frame);
++ else
++ prev_frame = NULL;
++
++ /* If the expression is "local", then set up a "watchpoint scope"
++ breakpoint at the point where we've left the scope of the watchpoint
++ expression. Create the scope breakpoint before the watchpoint, so
++ that we will encounter it first in bpstat_stop_status. */
++ if (innermost_block && prev_frame)
++ {
++ scope_breakpoint = create_internal_breakpoint (get_frame_pc (prev_frame),
++ bp_watchpoint_scope);
++
++ scope_breakpoint->enable_state = bp_enabled;
++
++ /* Automatically delete the breakpoint when it hits. */
++ scope_breakpoint->disposition = disp_del;
++
++ /* Only break in the proper frame (help with recursion). */
++ scope_breakpoint->frame_id = get_frame_id (prev_frame);
++
++ /* Set the address at which we will stop. */
++ scope_breakpoint->loc->requested_address
++ = get_frame_pc (prev_frame);
++ scope_breakpoint->loc->address
++ = adjust_breakpoint_address (scope_breakpoint->loc->requested_address,
++ scope_breakpoint->type);
++ }
++
++ /* Now set up the breakpoint. */
++ b = set_raw_breakpoint (sal, bp_type);
++ set_breakpoint_count (breakpoint_count + 1);
++ b->number = breakpoint_count;
++ b->thread = thread;
++ b->disposition = disp_donttouch;
++ b->exp = exp;
++ b->exp_valid_block = exp_valid_block;
++ b->exp_string = savestring (exp_start, exp_end - exp_start);
++ b->val = val;
++ b->loc->cond = cond;
++ if (cond_start)
++ b->cond_string = savestring (cond_start, cond_end - cond_start);
++ else
++ b->cond_string = 0;
++
++ if (frame)
++ b->watchpoint_frame = get_frame_id (frame);
++ else
++ b->watchpoint_frame = null_frame_id;
++
++ if (scope_breakpoint != NULL)
++ {
++ /* The scope breakpoint is related to the watchpoint. We will
++ need to act on them together. */
++ b->related_breakpoint = scope_breakpoint;
++ scope_breakpoint->related_breakpoint = b;
++ }
++
++ value_free_to_mark (mark);
++ mention (b);
++}
++
++/* Return count of locations need to be watched and can be handled
++ in hardware. If the watchpoint can not be handled
++ in hardware return zero. */
++
++static int
++can_use_hardware_watchpoint (struct value *v)
++{
++ int found_memory_cnt = 0;
++ struct value *head = v;
++
++ /* Did the user specifically forbid us to use hardware watchpoints? */
++ if (!can_use_hw_watchpoints)
++ return 0;
++
++ /* Make sure that the value of the expression depends only upon
++ memory contents, and values computed from them within GDB. If we
++ find any register references or function calls, we can't use a
++ hardware watchpoint.
++
++ The idea here is that evaluating an expression generates a series
++ of values, one holding the value of every subexpression. (The
++ expression a*b+c has five subexpressions: a, b, a*b, c, and
++ a*b+c.) GDB's values hold almost enough information to establish
++ the criteria given above --- they identify memory lvalues,
++ register lvalues, computed values, etcetera. So we can evaluate
++ the expression, and then scan the chain of values that leaves
++ behind to decide whether we can detect any possible change to the
++ expression's final value using only hardware watchpoints.
++
++ However, I don't think that the values returned by inferior
++ function calls are special in any way. So this function may not
++ notice that an expression involving an inferior function call
++ can't be watched with hardware watchpoints. FIXME. */
++ for (; v; v = value_next (v))
++ {
++ if (VALUE_LVAL (v) == lval_memory)
++ {
++ if (value_lazy (v))
++ /* A lazy memory lvalue is one that GDB never needed to fetch;
++ we either just used its address (e.g., `a' in `a.b') or
++ we never needed it at all (e.g., `a' in `a,b'). */
++ ;
++ else
++ {
++ /* Ahh, memory we actually used! Check if we can cover
++ it with hardware watchpoints. */
++ 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 a
++ middle of some value chain. */
++ if (v == head
++ || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
++ && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
++ {
++ CORE_ADDR vaddr = VALUE_ADDRESS (v) + value_offset (v);
++ int len = TYPE_LENGTH (value_type (v));
++
++ if (!TARGET_REGION_OK_FOR_HW_WATCHPOINT (vaddr, len))
++ return 0;
++ else
++ found_memory_cnt++;
++ }
++ }
++ }
++ else if (VALUE_LVAL (v) != not_lval
++ && deprecated_value_modifiable (v) == 0)
++ return 0; /* ??? What does this represent? */
++ else if (VALUE_LVAL (v) == lval_register)
++ return 0; /* cannot watch a register with a HW watchpoint */
++ }
++
++ /* The expression itself looks suitable for using a hardware
++ watchpoint, but give the target machine a chance to reject it. */
++ return found_memory_cnt;
++}
++
++void
++watch_command_wrapper (char *arg, int from_tty)
++{
++ watch_command (arg, from_tty);
++}
++
++static void
++watch_command (char *arg, int from_tty)
++{
++ watch_command_1 (arg, hw_write, from_tty);
++}
++
++void
++rwatch_command_wrapper (char *arg, int from_tty)
++{
++ rwatch_command (arg, from_tty);
++}
++
++static void
++rwatch_command (char *arg, int from_tty)
++{
++ watch_command_1 (arg, hw_read, from_tty);
++}
++
++void
++awatch_command_wrapper (char *arg, int from_tty)
++{
++ awatch_command (arg, from_tty);
++}
++
++static void
++awatch_command (char *arg, int from_tty)
++{
++ watch_command_1 (arg, hw_access, from_tty);
++}
++
++
++/* Helper routines for the until_command routine in infcmd.c. Here
++ because it uses the mechanisms of breakpoints. */
++
++/* This function is called by fetch_inferior_event via the
++ cmd_continuation pointer, to complete the until command. It takes
++ care of cleaning up the temporary breakpoints set up by the until
++ command. */
++static void
++until_break_command_continuation (struct continuation_arg *arg)
++{
++ struct cleanup *cleanups;
++
++ cleanups = (struct cleanup *) arg->data.pointer;
++ do_exec_cleanups (cleanups);
++}
++
++void
++until_break_command (char *arg, int from_tty, int anywhere)
++{
++ struct symtabs_and_lines sals;
++ struct symtab_and_line sal;
++ struct frame_info *frame = get_selected_frame (NULL);
++ struct frame_info *prev_frame = get_prev_frame (frame);
++ struct breakpoint *breakpoint;
++ struct cleanup *old_chain;
++ struct continuation_arg *arg1;
++
++
++ clear_proceed_status ();
++
++ /* Set a breakpoint where the user wants it and at return from
++ this function */
++
++ if (default_breakpoint_valid)
++ sals = decode_line_1 (&arg, 1, default_breakpoint_symtab,
++ default_breakpoint_line, (char ***) NULL, NULL);
++ else
++ sals = decode_line_1 (&arg, 1, (struct symtab *) NULL,
++ 0, (char ***) NULL, NULL);
++
++ if (sals.nelts != 1)
++ error (_("Couldn't get information on specified line."));
++
++ sal = sals.sals[0];
++ xfree (sals.sals); /* malloc'd, so freed */
++
++ if (*arg)
++ error (_("Junk at end of arguments."));
++
++ resolve_sal_pc (&sal);
++
++ if (anywhere)
++ /* If the user told us to continue until a specified location,
++ we don't specify a frame at which we need to stop. */
++ breakpoint = set_momentary_breakpoint (sal, null_frame_id, bp_until);
++ else
++ /* Otherwise, specify the current frame, because we want to stop only
++ at the very same frame. */
++ breakpoint = set_momentary_breakpoint (sal, get_frame_id (frame),
++ bp_until);
++
++ if (!target_can_async_p ())
++ old_chain = make_cleanup_delete_breakpoint (breakpoint);
++ else
++ old_chain = make_exec_cleanup_delete_breakpoint (breakpoint);
++
++ /* If we are running asynchronously, and the target supports async
++ execution, we are not waiting for the target to stop, in the call
++ tp proceed, below. This means that we cannot delete the
++ brekpoints until the target has actually stopped. The only place
++ where we get a chance to do that is in fetch_inferior_event, so
++ we must set things up for that. */
++
++ if (target_can_async_p ())
++ {
++ /* In this case the arg for the continuation is just the point
++ in the exec_cleanups chain from where to start doing
++ cleanups, because all the continuation does is the cleanups in
++ the exec_cleanup_chain. */
++ arg1 =
++ (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
++ arg1->next = NULL;
++ arg1->data.pointer = old_chain;
++
++ add_continuation (until_break_command_continuation, arg1);
++ }
++
++ /* Keep within the current frame, or in frames called by the current
++ one. */
++ if (prev_frame)
++ {
++ sal = find_pc_line (get_frame_pc (prev_frame), 0);
++ sal.pc = get_frame_pc (prev_frame);
++ breakpoint = set_momentary_breakpoint (sal, get_frame_id (prev_frame),
++ bp_until);
++ if (!target_can_async_p ())
++ make_cleanup_delete_breakpoint (breakpoint);
++ else
++ make_exec_cleanup_delete_breakpoint (breakpoint);
++ }
++
++ proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
++ /* Do the cleanups now, anly if we are not running asynchronously,
++ of if we are, but the target is still synchronous. */
++ if (!target_can_async_p ())
++ do_cleanups (old_chain);
++}
++
++static void
++ep_skip_leading_whitespace (char **s)
++{
++ if ((s == NULL) || (*s == NULL))
++ return;
++ while (isspace (**s))
++ *s += 1;
++}
++
++/* This function examines a string, and attempts to find a token
++ that might be an event name in the leading characters. If a
++ possible match is found, a pointer to the last character of
++ the token is returned. Else, NULL is returned. */
++
++static char *
++ep_find_event_name_end (char *arg)
++{
++ char *s = arg;
++ char *event_name_end = NULL;
++
++ /* If we could depend upon the presense of strrpbrk, we'd use that... */
++ if (arg == NULL)
++ return NULL;
++
++ /* We break out of the loop when we find a token delimiter.
++ Basically, we're looking for alphanumerics and underscores;
++ anything else delimites the token. */
++ while (*s != '\0')
++ {
++ if (!isalnum (*s) && (*s != '_'))
++ break;
++ event_name_end = s;
++ s++;
++ }
++
++ return event_name_end;
++}
++
++
++/* This function attempts to parse an optional "if <cond>" clause
++ from the arg string. If one is not found, it returns NULL.
++
++ Else, it returns a pointer to the condition string. (It does not
++ attempt to evaluate the string against a particular block.) And,
++ it updates arg to point to the first character following the parsed
++ if clause in the arg string. */
++
++static char *
++ep_parse_optional_if_clause (char **arg)
++{
++ char *cond_string;
++
++ if (((*arg)[0] != 'i') || ((*arg)[1] != 'f') || !isspace ((*arg)[2]))
++ return NULL;
++
++ /* Skip the "if" keyword. */
++ (*arg) += 2;
++
++ /* Skip any extra leading whitespace, and record the start of the
++ condition string. */
++ ep_skip_leading_whitespace (arg);
++ cond_string = *arg;
++
++ /* Assume that the condition occupies the remainder of the arg string. */
++ (*arg) += strlen (cond_string);
++
++ return cond_string;
++}
++
++/* This function attempts to parse an optional filename from the arg
++ string. If one is not found, it returns NULL.
++
++ Else, it returns a pointer to the parsed filename. (This function
++ makes no attempt to verify that a file of that name exists, or is
++ accessible.) And, it updates arg to point to the first character
++ following the parsed filename in the arg string.
++
++ Note that clients needing to preserve the returned filename for
++ future access should copy it to their own buffers. */
++static char *
++ep_parse_optional_filename (char **arg)
++{
++ static char filename[1024];
++ char *arg_p = *arg;
++ int i;
++ char c;
++
++ if ((*arg_p == '\0') || isspace (*arg_p))
++ return NULL;
++
++ for (i = 0;; i++)
++ {
++ c = *arg_p;
++ if (isspace (c))
++ c = '\0';
++ filename[i] = c;
++ if (c == '\0')
++ break;
++ arg_p++;
++ }
++ *arg = arg_p;
++
++ return filename;
++}
++
++/* Commands to deal with catching events, such as signals, exceptions,
++ process start/exit, etc. */
++
++typedef enum
++{
++ catch_fork, catch_vfork
++}
++catch_fork_kind;
++
++static void
++catch_fork_command_1 (catch_fork_kind fork_kind, char *arg, int tempflag,
++ int from_tty)
++{
++ char *cond_string = NULL;
++
++ ep_skip_leading_whitespace (&arg);
++
++ /* The allowed syntax is:
++ catch [v]fork
++ catch [v]fork if <cond>
++
++ First, check if there's an if clause. */
++ cond_string = ep_parse_optional_if_clause (&arg);
++
++ if ((*arg != '\0') && !isspace (*arg))
++ error (_("Junk at end of arguments."));
++
++ /* If this target supports it, create a fork or vfork catchpoint
++ and enable reporting of such events. */
++ switch (fork_kind)
++ {
++ case catch_fork:
++ create_fork_event_catchpoint (tempflag, cond_string);
++ break;
++ case catch_vfork:
++ create_vfork_event_catchpoint (tempflag, cond_string);
++ break;
++ default:
++ error (_("unsupported or unknown fork kind; cannot catch it"));
++ break;
++ }
++}
++
++static void
++catch_exec_command_1 (char *arg, int tempflag, int from_tty)
++{
++ char *cond_string = NULL;
++
++ ep_skip_leading_whitespace (&arg);
++
++ /* The allowed syntax is:
++ catch exec
++ catch exec if <cond>
++
++ First, check if there's an if clause. */
++ cond_string = ep_parse_optional_if_clause (&arg);
++
++ if ((*arg != '\0') && !isspace (*arg))
++ error (_("Junk at end of arguments."));
++
++ /* If this target supports it, create an exec catchpoint
++ and enable reporting of such events. */
++ create_exec_event_catchpoint (tempflag, cond_string);
++}
++
++static void
++catch_load_command_1 (char *arg, int tempflag, int from_tty)
++{
++ char *dll_pathname = NULL;
++ char *cond_string = NULL;
++
++ ep_skip_leading_whitespace (&arg);
++
++ /* The allowed syntax is:
++ catch load
++ catch load if <cond>
++ catch load <filename>
++ catch load <filename> if <cond>
++
++ The user is not allowed to specify the <filename> after an
++ if clause.
++
++ We'll ignore the pathological case of a file named "if".
++
++ First, check if there's an if clause. If so, then there
++ cannot be a filename. */
++ cond_string = ep_parse_optional_if_clause (&arg);
++
++ /* If there was an if clause, then there cannot be a filename.
++ Else, there might be a filename and an if clause. */
++ if (cond_string == NULL)
++ {
++ dll_pathname = ep_parse_optional_filename (&arg);
++ ep_skip_leading_whitespace (&arg);
++ cond_string = ep_parse_optional_if_clause (&arg);
++ }
++
++ if ((*arg != '\0') && !isspace (*arg))
++ error (_("Junk at end of arguments."));
++
++ /* Create a load breakpoint that only triggers when a load of
++ the specified dll (or any dll, if no pathname was specified)
++ occurs. */
++ SOLIB_CREATE_CATCH_LOAD_HOOK (PIDGET (inferior_ptid), tempflag,
++ dll_pathname, cond_string);
++}
++
++static void
++catch_unload_command_1 (char *arg, int tempflag, int from_tty)
++{
++ char *dll_pathname = NULL;
++ char *cond_string = NULL;
++
++ ep_skip_leading_whitespace (&arg);
++
++ /* The allowed syntax is:
++ catch unload
++ catch unload if <cond>
++ catch unload <filename>
++ catch unload <filename> if <cond>
++
++ The user is not allowed to specify the <filename> after an
++ if clause.
++
++ We'll ignore the pathological case of a file named "if".
++
++ First, check if there's an if clause. If so, then there
++ cannot be a filename. */
++ cond_string = ep_parse_optional_if_clause (&arg);
++
++ /* If there was an if clause, then there cannot be a filename.
++ Else, there might be a filename and an if clause. */
++ if (cond_string == NULL)
++ {
++ dll_pathname = ep_parse_optional_filename (&arg);
++ ep_skip_leading_whitespace (&arg);
++ cond_string = ep_parse_optional_if_clause (&arg);
++ }
++
++ if ((*arg != '\0') && !isspace (*arg))
++ error (_("Junk at end of arguments."));
++
++ /* Create an unload breakpoint that only triggers when an unload of
++ the specified dll (or any dll, if no pathname was specified)
++ occurs. */
++ SOLIB_CREATE_CATCH_UNLOAD_HOOK (PIDGET (inferior_ptid), tempflag,
++ dll_pathname, cond_string);
++}
++
++static enum print_stop_action
++print_exception_catchpoint (struct breakpoint *b)
++{
++ annotate_catchpoint (b->number);
++
++ if (strstr (b->addr_string, "throw") != NULL)
++ printf_filtered (_("\nCatchpoint %d (exception thrown)\n"),
++ b->number);
++ else
++ printf_filtered (_("\nCatchpoint %d (exception caught)\n"),
++ b->number);
++
++ return PRINT_SRC_AND_LOC;
++}
++
++static void
++print_one_exception_catchpoint (struct breakpoint *b, CORE_ADDR *last_addr)
++{
++ if (addressprint)
++ {
++ annotate_field (4);
++ ui_out_field_core_addr (uiout, "addr", b->loc->address);
++ }
++ annotate_field (5);
++ *last_addr = b->loc->address;
++ if (strstr (b->addr_string, "throw") != NULL)
++ ui_out_field_string (uiout, "what", "exception throw");
++ else
++ ui_out_field_string (uiout, "what", "exception catch");
++}
++
++static void
++print_mention_exception_catchpoint (struct breakpoint *b)
++{
++ if (strstr (b->addr_string, "throw") != NULL)
++ printf_filtered (_("Catchpoint %d (throw)"), b->number);
++ else
++ printf_filtered (_("Catchpoint %d (catch)"), b->number);
++}
++
++static struct breakpoint_ops gnu_v3_exception_catchpoint_ops = {
++ print_exception_catchpoint,
++ print_one_exception_catchpoint,
++ print_mention_exception_catchpoint
++};
++
++static int
++handle_gnu_v3_exceptions (int tempflag, char *cond_string,
++ enum exception_event_kind ex_event, int from_tty)
++{
++ char *trigger_func_name, *nameptr;
++ struct symtabs_and_lines sals;
++ struct breakpoint *b;
++
++ if (ex_event == EX_EVENT_CATCH)
++ trigger_func_name = xstrdup ("__cxa_begin_catch");
++ else
++ trigger_func_name = xstrdup ("__cxa_throw");
++
++ nameptr = trigger_func_name;
++ sals = decode_line_1 (&nameptr, 1, NULL, 0, NULL, NULL);
++ if (sals.nelts == 0)
++ {
++ xfree (trigger_func_name);
++ return 0;
++ }
++
++ b = set_raw_breakpoint (sals.sals[0], bp_breakpoint);
++ set_breakpoint_count (breakpoint_count + 1);
++ b->number = breakpoint_count;
++ b->cond_string = (cond_string == NULL) ?
++ NULL : savestring (cond_string, strlen (cond_string));
++ b->thread = -1;
++ b->addr_string = trigger_func_name;
++ b->enable_state = bp_enabled;
++ b->disposition = tempflag ? disp_del : disp_donttouch;
++ b->ops = &gnu_v3_exception_catchpoint_ops;
++
++ xfree (sals.sals);
++ mention (b);
++ return 1;
++}
++
++/* Deal with "catch catch" and "catch throw" commands */
++
++static void
++catch_exception_command_1 (enum exception_event_kind ex_event, char *arg,
++ int tempflag, int from_tty)
++{
++ char *cond_string = NULL;
++ struct symtab_and_line *sal = NULL;
++
++ ep_skip_leading_whitespace (&arg);
++
++ cond_string = ep_parse_optional_if_clause (&arg);
++
++ if ((*arg != '\0') && !isspace (*arg))
++ error (_("Junk at end of arguments."));
++
++ if ((ex_event != EX_EVENT_THROW) &&
++ (ex_event != EX_EVENT_CATCH))
++ error (_("Unsupported or unknown exception event; cannot catch it"));
++
++ if (handle_gnu_v3_exceptions (tempflag, cond_string, ex_event, from_tty))
++ return;
++
++ warning (_("Unsupported with this platform/compiler combination."));
++}
++
++/* Create a breakpoint struct for Ada exception catchpoints. */
++
++static void
++create_ada_exception_breakpoint (struct symtab_and_line sal,
++ char *addr_string,
++ char *exp_string,
++ char *cond_string,
++ struct expression *cond,
++ struct breakpoint_ops *ops,
++ int tempflag,
++ int from_tty)
++{
++ struct breakpoint *b;
++
++ if (from_tty)
++ {
++ describe_other_breakpoints (sal.pc, sal.section, -1);
++ /* FIXME: brobecker/2006-12-28: Actually, re-implement a special
++ version for exception catchpoints, because two catchpoints
++ used for different exception names will use the same address.
++ In this case, a "breakpoint ... also set at..." warning is
++ unproductive. Besides. the warning phrasing is also a bit
++ inapropriate, we should use the word catchpoint, and tell
++ the user what type of catchpoint it is. The above is good
++ enough for now, though. */
++ }
++
++ b = set_raw_breakpoint (sal, bp_breakpoint);
++ set_breakpoint_count (breakpoint_count + 1);
++
++ b->enable_state = bp_enabled;
++ b->disposition = tempflag ? disp_del : disp_donttouch;
++ b->number = breakpoint_count;
++ b->ignore_count = 0;
++ b->loc->cond = cond;
++ b->addr_string = addr_string;
++ b->language = language_ada;
++ b->cond_string = cond_string;
++ b->exp_string = exp_string;
++ b->thread = -1;
++ b->ops = ops;
++
++ mention (b);
++}
++
++/* Implement the "catch exception" command. */
++
++static void
++catch_ada_exception_command (char *arg, int tempflag, int from_tty)
++{
++ struct symtab_and_line sal;
++ enum bptype type;
++ char *addr_string = NULL;
++ char *exp_string = NULL;
++ char *cond_string = NULL;
++ struct expression *cond = NULL;
++ struct breakpoint_ops *ops = NULL;
++
++ sal = ada_decode_exception_location (arg, &addr_string, &exp_string,
++ &cond_string, &cond, &ops);
++ create_ada_exception_breakpoint (sal, addr_string, exp_string,
++ cond_string, cond, ops, tempflag,
++ from_tty);
++}
++
++/* Implement the "catch assert" command. */
++
++static void
++catch_assert_command (char *arg, int tempflag, int from_tty)
++{
++ struct symtab_and_line sal;
++ char *addr_string = NULL;
++ struct breakpoint_ops *ops = NULL;
++
++ sal = ada_decode_assert_location (arg, &addr_string, &ops);
++ create_ada_exception_breakpoint (sal, addr_string, NULL, NULL, NULL, ops,
++ tempflag, from_tty);
++}
++
++static void
++catch_command_1 (char *arg, int tempflag, int from_tty)
++{
++
++ /* The first argument may be an event name, such as "start" or "load".
++ If so, then handle it as such. If it doesn't match an event name,
++ then attempt to interpret it as an exception name. (This latter is
++ the v4.16-and-earlier GDB meaning of the "catch" command.)
++
++ First, try to find the bounds of what might be an event name. */
++ char *arg1_start = arg;
++ char *arg1_end;
++ int arg1_length;
++
++ if (arg1_start == NULL)
++ {
++ /* Old behaviour was to use pre-v-4.16 syntax */
++ /* catch_throw_command_1 (arg1_start, tempflag, from_tty); */
++ /* return; */
++ /* Now, this is not allowed */
++ error (_("Catch requires an event name."));
++
++ }
++ arg1_end = ep_find_event_name_end (arg1_start);
++ if (arg1_end == NULL)
++ error (_("catch requires an event"));
++ arg1_length = arg1_end + 1 - arg1_start;
++
++ /* Try to match what we found against known event names. */
++ if (strncmp (arg1_start, "signal", arg1_length) == 0)
++ {
++ error (_("Catch of signal not yet implemented"));
++ }
++ else if (strncmp (arg1_start, "catch", arg1_length) == 0)
++ {
++ catch_exception_command_1 (EX_EVENT_CATCH, arg1_end + 1,
++ tempflag, from_tty);
++ }
++ else if (strncmp (arg1_start, "throw", arg1_length) == 0)
++ {
++ catch_exception_command_1 (EX_EVENT_THROW, arg1_end + 1,
++ tempflag, from_tty);
++ }
++ else if (strncmp (arg1_start, "thread_start", arg1_length) == 0)
++ {
++ error (_("Catch of thread_start not yet implemented"));
++ }
++ else if (strncmp (arg1_start, "thread_exit", arg1_length) == 0)
++ {
++ error (_("Catch of thread_exit not yet implemented"));
++ }
++ else if (strncmp (arg1_start, "thread_join", arg1_length) == 0)
++ {
++ error (_("Catch of thread_join not yet implemented"));
++ }
++ else if (strncmp (arg1_start, "start", arg1_length) == 0)
++ {
++ error (_("Catch of start not yet implemented"));
++ }
++ else if (strncmp (arg1_start, "exit", arg1_length) == 0)
++ {
++ error (_("Catch of exit not yet implemented"));
++ }
++ else if (strncmp (arg1_start, "fork", arg1_length) == 0)
++ {
++ catch_fork_command_1 (catch_fork, arg1_end + 1, tempflag, from_tty);
++ }
++ else if (strncmp (arg1_start, "vfork", arg1_length) == 0)
++ {
++ catch_fork_command_1 (catch_vfork, arg1_end + 1, tempflag, from_tty);
++ }
++ else if (strncmp (arg1_start, "exec", arg1_length) == 0)
++ {
++ catch_exec_command_1 (arg1_end + 1, tempflag, from_tty);
++ }
++ else if (strncmp (arg1_start, "load", arg1_length) == 0)
++ {
++ catch_load_command_1 (arg1_end + 1, tempflag, from_tty);
++ }
++ else if (strncmp (arg1_start, "unload", arg1_length) == 0)
++ {
++ catch_unload_command_1 (arg1_end + 1, tempflag, from_tty);
++ }
++ else if (strncmp (arg1_start, "stop", arg1_length) == 0)
++ {
++ error (_("Catch of stop not yet implemented"));
++ }
++ else if (strncmp (arg1_start, "exception", arg1_length) == 0)
++ {
++ catch_ada_exception_command (arg1_end + 1, tempflag, from_tty);
++ }
++
++ else if (strncmp (arg1_start, "assert", arg1_length) == 0)
++ {
++ catch_assert_command (arg1_end + 1, tempflag, from_tty);
++ }
++
++ /* This doesn't appear to be an event name */
++
++ else
++ {
++ /* Pre-v.4.16 behaviour was to treat the argument
++ as the name of an exception */
++ /* catch_throw_command_1 (arg1_start, tempflag, from_tty); */
++ /* Now this is not allowed */
++ error (_("Unknown event kind specified for catch"));
++
++ }
++}
++
++static void
++catch_command (char *arg, int from_tty)
++{
++ catch_command_1 (arg, 0, from_tty);
++}
++
++
++static void
++tcatch_command (char *arg, int from_tty)
++{
++ catch_command_1 (arg, 1, from_tty);
++}
++
++/* Delete breakpoints by address or line. */
++
++static void
++clear_command (char *arg, int from_tty)
++{
++ struct breakpoint *b;
++ VEC(breakpoint_p) *found = 0;
++ int ix;
++ int default_match;
++ struct symtabs_and_lines sals;
++ struct symtab_and_line sal;
++ int i;
++
++ if (arg)
++ {
++ sals = decode_line_spec (arg, 1);
++ default_match = 0;
++ }
++ else
++ {
++ sals.sals = (struct symtab_and_line *)
++ xmalloc (sizeof (struct symtab_and_line));
++ make_cleanup (xfree, sals.sals);
++ init_sal (&sal); /* initialize to zeroes */
++ sal.line = default_breakpoint_line;
++ sal.symtab = default_breakpoint_symtab;
++ sal.pc = default_breakpoint_address;
++ if (sal.symtab == 0)
++ error (_("No source file specified."));
++
++ sals.sals[0] = sal;
++ sals.nelts = 1;
++
++ default_match = 1;
++ }
++
++ /* We don't call resolve_sal_pc here. That's not
++ as bad as it seems, because all existing breakpoints
++ typically have both file/line and pc set. So, if
++ clear is given file/line, we can match this to existing
++ breakpoint without obtaining pc at all.
++
++ We only support clearing given the address explicitly
++ present in breakpoint table. Say, we've set breakpoint
++ at file:line. There were several PC values for that file:line,
++ due to optimization, all in one block.
++ We've picked one PC value. If "clear" is issued with another
++ PC corresponding to the same file:line, the breakpoint won't
++ be cleared. We probably can still clear the breakpoint, but
++ since the other PC value is never presented to user, user
++ can only find it by guessing, and it does not seem important
++ to support that. */
++
++ /* For each line spec given, delete bps which correspond
++ to it. Do it in two passes, solely to preserve the current
++ behavior that from_tty is forced true if we delete more than
++ one breakpoint. */
++
++ found = NULL;
++ for (i = 0; i < sals.nelts; i++)
++ {
++ /* If exact pc given, clear bpts at that pc.
++ If line given (pc == 0), clear all bpts on specified line.
++ If defaulting, clear all bpts on default line
++ or at default pc.
++
++ defaulting sal.pc != 0 tests to do
++
++ 0 1 pc
++ 1 1 pc _and_ line
++ 0 0 line
++ 1 0 <can't happen> */
++
++ sal = sals.sals[i];
++
++ /* Find all matching breakpoints and add them to
++ 'found'. */
++ ALL_BREAKPOINTS (b)
++ {
++ int match = 0;
++ /* Are we going to delete b? */
++ if (b->type != bp_none
++ && b->type != bp_watchpoint
++ && b->type != bp_hardware_watchpoint
++ && b->type != bp_read_watchpoint
++ && b->type != bp_access_watchpoint)
++ {
++ struct bp_location *loc = b->loc;
++ for (; loc; loc = loc->next)
++ {
++ int pc_match = sal.pc
++ && (loc->address == sal.pc)
++ && (!section_is_overlay (loc->section)
++ || loc->section == sal.section);
++ int line_match = ((default_match || (0 == sal.pc))
++ && b->source_file != NULL
++ && sal.symtab != NULL
++ && strcmp (b->source_file, sal.symtab->filename) == 0
++ && b->line_number == sal.line);
++ if (pc_match || line_match)
++ {
++ match = 1;
++ break;
++ }
++ }
++ }
++
++ if (match)
++ VEC_safe_push(breakpoint_p, found, b);
++ }
++ }
++ /* Now go thru the 'found' chain and delete them. */
++ if (VEC_empty(breakpoint_p, found))
++ {
++ if (arg)
++ error (_("No breakpoint at %s."), arg);
++ else
++ error (_("No breakpoint at this line."));
++ }
++
++ if (VEC_length(breakpoint_p, found) > 1)
++ from_tty = 1; /* Always report if deleted more than one */
++ if (from_tty)
++ {
++ if (VEC_length(breakpoint_p, found) == 1)
++ printf_unfiltered (_("Deleted breakpoint "));
++ else
++ printf_unfiltered (_("Deleted breakpoints "));
++ }
++ breakpoints_changed ();
++
++ for (ix = 0; VEC_iterate(breakpoint_p, found, ix, b); ix++)
++ {
++ if (from_tty)
++ printf_unfiltered ("%d ", b->number);
++ delete_breakpoint (b);
++ }
++ if (from_tty)
++ putchar_unfiltered ('\n');
++}
++
++/* Delete breakpoint in BS if they are `delete' breakpoints and
++ all breakpoints that are marked for deletion, whether hit or not.
++ This is called after any breakpoint is hit, or after errors. */
++
++void
++breakpoint_auto_delete (bpstat bs)
++{
++ struct breakpoint *b, *temp;
++
++ for (; bs; bs = bs->next)
++ if (bs->breakpoint_at && bs->breakpoint_at->owner->disposition == disp_del
++ && bs->stop)
++ delete_breakpoint (bs->breakpoint_at->owner);
++
++ ALL_BREAKPOINTS_SAFE (b, temp)
++ {
++ if (b->disposition == disp_del_at_next_stop)
++ delete_breakpoint (b);
++ }
++}
++
++/* Remove locations of breakpoint BPT from
++ the global list of breakpoint locations. */
++
++static void
++unlink_locations_from_global_list (struct breakpoint *bpt)
++{
++ /* This code assumes that the locations
++ of a breakpoint are found in the global list
++ in the same order, but not necessary adjacent. */
++ struct bp_location **tmp = &bp_location_chain;
++ struct bp_location *here = bpt->loc;
++
++ if (here == NULL)
++ return;
++
++ for (; *tmp && here;)
++ {
++ if (*tmp == here)
++ {
++ *tmp = here->global_next;
++ here = here->next;
++ }
++ else
++ {
++ tmp = &((*tmp)->global_next);
++ }
++ }
++}
++
++/* Delete a breakpoint and clean up all traces of it in the data
++ structures. */
++
++void
++delete_breakpoint (struct breakpoint *bpt)
++{
++ struct breakpoint *b;
++ bpstat bs;
++ struct bp_location *loc;
++
++ gdb_assert (bpt != NULL);
++
++ /* Has this bp already been deleted? This can happen because multiple
++ lists can hold pointers to bp's. bpstat lists are especial culprits.
++
++ One example of this happening is a watchpoint's scope bp. When the
++ scope bp triggers, we notice that the watchpoint is out of scope, and
++ delete it. We also delete its scope bp. But the scope bp is marked
++ "auto-deleting", and is already on a bpstat. That bpstat is then
++ checked for auto-deleting bp's, which are deleted.
++
++ A real solution to this problem might involve reference counts in bp's,
++ and/or giving them pointers back to their referencing bpstat's, and
++ teaching delete_breakpoint to only free a bp's storage when no more
++ references were extent. A cheaper bandaid was chosen. */
++ if (bpt->type == bp_none)
++ return;
++
++ if (deprecated_delete_breakpoint_hook)
++ deprecated_delete_breakpoint_hook (bpt);
++ breakpoint_delete_event (bpt->number);
++
++ for (loc = bpt->loc; loc; loc = loc->next)
++ {
++ if (loc->inserted)
++ remove_breakpoint (loc, mark_inserted);
++
++ if (loc->cond)
++ xfree (loc->cond);
++
++ if (loc->function_name)
++ xfree (loc->function_name);
++ }
++
++ if (breakpoint_chain == bpt)
++ breakpoint_chain = bpt->next;
++
++ ALL_BREAKPOINTS (b)
++ if (b->next == bpt)
++ {
++ b->next = bpt->next;
++ break;
++ }
++
++ unlink_locations_from_global_list (bpt);
++
++ check_duplicates (bpt);
++
++ if (bpt->type != bp_hardware_watchpoint
++ && bpt->type != bp_read_watchpoint
++ && bpt->type != bp_access_watchpoint
++ && bpt->type != bp_catch_fork
++ && bpt->type != bp_catch_vfork
++ && bpt->type != bp_catch_exec)
++ for (loc = bpt->loc; loc; loc = loc->next)
++ {
++ /* If this breakpoint location was inserted, and there is
++ another breakpoint at the same address, we need to
++ insert the other breakpoint. */
++ if (loc->inserted)
++ {
++ struct bp_location *loc2;
++ ALL_BP_LOCATIONS (loc2)
++ if (loc2->address == loc->address
++ && loc2->section == loc->section
++ && !loc->duplicate
++ && loc2->owner->enable_state != bp_disabled
++ && loc2->enabled
++ && !loc2->shlib_disabled
++ && loc2->owner->enable_state != bp_call_disabled)
++ {
++ int val;
++
++ /* We should never reach this point if there is a permanent
++ breakpoint at the same address as the one being deleted.
++ If there is a permanent breakpoint somewhere, it should
++ always be the only one inserted. */
++ if (loc2->owner->enable_state == bp_permanent)
++ internal_error (__FILE__, __LINE__,
++ _("another breakpoint was inserted on top of "
++ "a permanent breakpoint"));
++
++ memset (&loc2->target_info, 0, sizeof (loc2->target_info));
++ loc2->target_info.placed_address = loc2->address;
++ if (b->type == bp_hardware_breakpoint)
++ val = target_insert_hw_breakpoint (&loc2->target_info);
++ else
++ val = target_insert_breakpoint (&loc2->target_info);
++
++ /* If there was an error in the insert, print a message, then stop execution. */
++ if (val != 0)
++ {
++ struct ui_file *tmp_error_stream = mem_fileopen ();
++ make_cleanup_ui_file_delete (tmp_error_stream);
++
++
++ if (b->type == bp_hardware_breakpoint)
++ {
++ fprintf_unfiltered (tmp_error_stream,
++ "Cannot insert hardware breakpoint %d.\n"
++ "You may have requested too many hardware breakpoints.\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 ");
++ fputs_filtered (paddress (loc2->address),
++ tmp_error_stream);
++ fprintf_filtered (tmp_error_stream, ": %s.\n",
++ safe_strerror (val));
++ }
++
++ fprintf_unfiltered (tmp_error_stream,"The same program may be running in another process.");
++ target_terminal_ours_for_output ();
++ error_stream(tmp_error_stream);
++ }
++ else
++ loc2->inserted = 1;
++ }
++ }
++ }
++
++ free_command_lines (&bpt->commands);
++ if (bpt->cond_string != NULL)
++ xfree (bpt->cond_string);
++ if (bpt->addr_string != NULL)
++ xfree (bpt->addr_string);
++ if (bpt->exp != NULL)
++ xfree (bpt->exp);
++ if (bpt->exp_string != NULL)
++ xfree (bpt->exp_string);
++ if (bpt->val != NULL)
++ value_free (bpt->val);
++ if (bpt->source_file != NULL)
++ xfree (bpt->source_file);
++ if (bpt->dll_pathname != NULL)
++ xfree (bpt->dll_pathname);
++ if (bpt->triggered_dll_pathname != NULL)
++ xfree (bpt->triggered_dll_pathname);
++ if (bpt->exec_pathname != NULL)
++ xfree (bpt->exec_pathname);
++
++ /* Be sure no bpstat's are pointing at it after it's been freed. */
++ /* FIXME, how can we find all bpstat's?
++ We just check stop_bpstat for now. Note that we cannot just
++ remove bpstats pointing at bpt from the stop_bpstat list
++ entirely, as breakpoint commands are associated with the bpstat;
++ if we remove it here, then the later call to
++ bpstat_do_actions (&stop_bpstat);
++ in event-top.c won't do anything, and temporary breakpoints
++ with commands won't work. */
++ for (bs = stop_bpstat; bs; bs = bs->next)
++ if (bs->breakpoint_at && bs->breakpoint_at->owner == bpt)
++ {
++ bs->breakpoint_at = NULL;
++ bs->old_val = NULL;
++ /* bs->commands will be freed later. */
++ }
++ /* On the chance that someone will soon try again to delete this same
++ bp, we mark it as deleted before freeing its storage. */
++ bpt->type = bp_none;
++
++ for (loc = bpt->loc; loc;)
++ {
++ struct bp_location *loc_next = loc->next;
++ xfree (loc);
++ loc = loc_next;
++ }
++ xfree (bpt);
++}
++
++static void
++do_delete_breakpoint_cleanup (void *b)
++{
++ delete_breakpoint (b);
++}
++
++struct cleanup *
++make_cleanup_delete_breakpoint (struct breakpoint *b)
++{
++ return make_cleanup (do_delete_breakpoint_cleanup, b);
++}
++
++struct cleanup *
++make_exec_cleanup_delete_breakpoint (struct breakpoint *b)
++{
++ return make_exec_cleanup (do_delete_breakpoint_cleanup, b);
++}
++
++void
++delete_command (char *arg, int from_tty)
++{
++ struct breakpoint *b, *temp;
++
++ dont_repeat ();
++
++ if (arg == 0)
++ {
++ int breaks_to_delete = 0;
++
++ /* Delete all breakpoints if no argument.
++ Do not delete internal or call-dummy breakpoints, these
++ have to be deleted with an explicit breakpoint number argument. */
++ ALL_BREAKPOINTS (b)
++ {
++ if (b->type != bp_call_dummy &&
++ b->type != bp_shlib_event &&
++ b->type != bp_thread_event &&
++ b->type != bp_overlay_event &&
++ b->number >= 0)
++ {
++ breaks_to_delete = 1;
++ break;
++ }
++ }
++
++ /* Ask user only if there are some breakpoints to delete. */
++ if (!from_tty
++ || (breaks_to_delete && query (_("Delete all breakpoints? "))))
++ {
++ ALL_BREAKPOINTS_SAFE (b, temp)
++ {
++ if (b->type != bp_call_dummy &&
++ b->type != bp_shlib_event &&
++ b->type != bp_thread_event &&
++ b->type != bp_overlay_event &&
++ b->number >= 0)
++ delete_breakpoint (b);
++ }
++ }
++ }
++ else
++ map_breakpoint_numbers (arg, delete_breakpoint);
++}
++
++static int
++all_locations_are_pending (struct bp_location *loc)
++{
++ for (; loc; loc = loc->next)
++ if (!loc->shlib_disabled)
++ return 0;
++ return 1;
++}
++
++/* Subroutine of update_breakpoint_locations to simplify it.
++ Return non-zero if multiple fns in list LOC have the same name.
++ Null names are ignored. */
++
++static int
++ambiguous_names_p (struct bp_location *loc)
++{
++ struct bp_location *l;
++ htab_t htab = htab_create_alloc (13, htab_hash_string,
++ (int (*) (const void *, const void *)) streq,
++ NULL, xcalloc, xfree);
++
++ for (l = loc; l != NULL; l = l->next)
++ {
++ const char **slot;
++ const char *name = l->function_name;
++
++ /* Allow for some names to be NULL, ignore them. */
++ if (name == NULL)
++ continue;
++
++ slot = (const char **) htab_find_slot (htab, (const void *) name,
++ INSERT);
++ /* NOTE: We can assume slot != NULL here because xcalloc never returns
++ NULL. */
++ if (*slot != NULL)
++ {
++ htab_delete (htab);
++ return 1;
++ }
++ *slot = name;
++ }
++
++ htab_delete (htab);
++ return 0;
++}
++
++static void
++update_breakpoint_locations (struct breakpoint *b,
++ struct symtabs_and_lines sals)
++{
++ int i;
++ char *s;
++ struct bp_location *existing_locations = b->loc;
++
++ /* If there's no new locations, and all existing locations
++ are pending, don't do anything. This optimizes
++ the common case where all locations are in the same
++ shared library, that was unloaded. We'd like to
++ retain the location, so that when the library
++ is loaded again, we don't loose the enabled/disabled
++ status of the individual locations. */
++ if (all_locations_are_pending (existing_locations) && sals.nelts == 0)
++ return;
++
++ unlink_locations_from_global_list (b);
++ b->loc = NULL;
++
++ for (i = 0; i < sals.nelts; ++i)
++ {
++ struct bp_location *new_loc =
++ add_location_to_breakpoint (b, b->type, &(sals.sals[i]));
++
++ /* Reparse conditions, they might contain references to the
++ old symtab. */
++ if (b->cond_string != NULL)
++ {
++ struct gdb_exception e;
++
++ s = b->cond_string;
++ TRY_CATCH (e, RETURN_MASK_ERROR)
++ {
++ new_loc->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc),
++ 0);
++ }
++ if (e.reason < 0)
++ {
++ warning (_("failed to reevaluate condition for breakpoint %d: %s"),
++ b->number, e.message);
++ new_loc->enabled = 0;
++ }
++ }
++
++ if (b->source_file != NULL)
++ xfree (b->source_file);
++ if (sals.sals[i].symtab == NULL)
++ b->source_file = NULL;
++ else
++ b->source_file =
++ savestring (sals.sals[i].symtab->filename,
++ strlen (sals.sals[i].symtab->filename));
++
++ if (b->line_number == 0)
++ b->line_number = sals.sals[i].line;
++ }
++
++ /* If possible, carry over 'disable' status from existing breakpoints. */
++ {
++ struct bp_location *e = existing_locations;
++ /* If there are multiple breakpoints with the same function name,
++ e.g. for inline functions, comparing function names won't work.
++ Instead compare pc addresses; this is just a heuristic as things
++ may have moved, but in practice it gives the correct answer
++ often enough until a better solution is found. */
++ int have_ambiguous_names = ambiguous_names_p (b->loc);
++
++ for (; e; e = e->next)
++ {
++ if (!e->enabled && e->function_name)
++ {
++ struct bp_location *l = b->loc;
++ if (have_ambiguous_names)
++ {
++ for (; l; l = l->next)
++ if (e->address == l->address)
++ {
++ l->enabled = 0;
++ break;
++ }
++ }
++ else
++ {
++ for (; l; l = l->next)
++ if (l->function_name
++ && strcmp (e->function_name, l->function_name) == 0)
++ {
++ l->enabled = 0;
++ break;
++ }
++ }
++ }
++ }
++ }
++
++ while (existing_locations)
++ {
++ struct bp_location *next = existing_locations->next;
++ free_bp_location (existing_locations);
++ existing_locations = next;
++ }
++}
++
++
++/* Reset a breakpoint given it's struct breakpoint * BINT.
++ The value we return ends up being the return value from catch_errors.
++ Unused in this case. */
++
++static int
++breakpoint_re_set_one (void *bint)
++{
++ /* get past catch_errs */
++ struct breakpoint *b = (struct breakpoint *) bint;
++ struct value *mark;
++ int i;
++ int not_found = 0;
++ int *not_found_ptr = &not_found;
++ struct symtabs_and_lines sals = {};
++ struct symtabs_and_lines expanded;
++ char *s;
++ enum enable_state save_enable;
++ struct gdb_exception e;
++
++
++ switch (b->type)
++ {
++ case bp_none:
++ warning (_("attempted to reset apparently deleted breakpoint #%d?"),
++ b->number);
++ return 0;
++ case bp_breakpoint:
++ case bp_hardware_breakpoint:
++ case bp_catch_load:
++ case bp_catch_unload:
++ if (b->addr_string == NULL)
++ {
++ /* Anything without a string can't be re-set. */
++ delete_breakpoint (b);
++ return 0;
++ }
++
++ set_language (b->language);
++ input_radix = b->input_radix;
++ s = b->addr_string;
++ TRY_CATCH (e, RETURN_MASK_ERROR)
++ {
++ sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL,
++ not_found_ptr);
++ }
++ if (e.reason < 0)
++ {
++ int not_found_and_ok = 0;
++ /* For pending breakpoints, it's expected that parsing
++ will fail until the right shared library is loaded.
++ User has already told to create pending breakpoints and
++ don't need extra messages. If breakpoint is in bp_shlib_disabled
++ state, then user already saw the message about that breakpoint
++ being disabled, and don't want to see more errors. */
++ if (not_found
++ && (b->condition_not_parsed
++ || (b->loc && b->loc->shlib_disabled)
++ || b->enable_state == bp_disabled))
++ not_found_and_ok = 1;
++
++ if (!not_found_and_ok)
++ {
++ /* We surely don't want to warn about the same breakpoint
++ 10 times. One solution, implemented here, is disable
++ the breakpoint on error. Another solution would be to
++ have separate 'warning emitted' flag. Since this
++ happens only when a binary has changed, I don't know
++ which approach is better. */
++ b->enable_state = bp_disabled;
++ throw_exception (e);
++ }
++ }
++
++ if (not_found)
++ break;
++
++ gdb_assert (sals.nelts == 1);
++ resolve_sal_pc (&sals.sals[0]);
++ if (b->condition_not_parsed && s && s[0])
++ {
++ char *cond_string = 0;
++ int thread = -1;
++ find_condition_and_thread (s, sals.sals[0].pc,
++ &cond_string, &thread);
++ if (cond_string)
++ b->cond_string = cond_string;
++ b->thread = thread;
++ b->condition_not_parsed = 0;
++ }
++ expanded = expand_line_sal_maybe (sals.sals[0]);
++ update_breakpoint_locations (b, expanded);
++
++ /* Now that this is re-enabled, check_duplicates
++ can be used. */
++ check_duplicates (b);
++
++ xfree (sals.sals);
++ break;
++
++ case bp_watchpoint:
++ case bp_hardware_watchpoint:
++ case bp_read_watchpoint:
++ case bp_access_watchpoint:
++ /* Watchpoint can be either on expression using entirely global variables,
++ or it can be on local variables.
++
++ Watchpoints of the first kind are never auto-deleted, and even persist
++ across program restarts. Since they can use variables from shared
++ libraries, we need to reparse expression as libraries are loaded
++ and unloaded.
++
++ Watchpoints on local variables can also change meaning as result
++ of solib event. For example, if a watchpoint uses both a local and
++ a global variables in expression, it's a local watchpoint, but
++ unloading of a shared library will make the expression invalid.
++ This is not a very common use case, but we still re-evaluate
++ expression, to avoid surprises to the user.
++
++ Note that for local watchpoints, we re-evaluate it only if
++ watchpoints frame id is still valid. If it's not, it means
++ the watchpoint is out of scope and will be deleted soon. In fact,
++ I'm not sure we'll ever be called in this case.
++
++ If a local watchpoint's frame id is still valid, then
++ b->exp_valid_block is likewise valid, and we can safely use it.
++
++ Don't do anything about disabled watchpoints, since they will
++ be reevaluated again when enabled. */
++ update_watchpoint (b, 1 /* reparse */);
++ break;
++ /* We needn't really do anything to reset these, since the mask
++ that requests them is unaffected by e.g., new libraries being
++ loaded. */
++ case bp_catch_fork:
++ case bp_catch_vfork:
++ case bp_catch_exec:
++ break;
++
++ default:
++ printf_filtered (_("Deleting unknown breakpoint type %d\n"), b->type);
++ /* fall through */
++ /* Delete longjmp and overlay event breakpoints; they will be
++ reset later by breakpoint_re_set. */
++ case bp_longjmp:
++ case bp_longjmp_resume:
++ case bp_overlay_event:
++ delete_breakpoint (b);
++ break;
++
++ /* This breakpoint is special, it's set up when the inferior
++ starts and we really don't want to touch it. */
++ case bp_shlib_event:
++
++ /* Like bp_shlib_event, this breakpoint type is special.
++ Once it is set up, we do not want to touch it. */
++ case bp_thread_event:
++
++ /* Keep temporary breakpoints, which can be encountered when we step
++ over a dlopen call and SOLIB_ADD is resetting the breakpoints.
++ Otherwise these should have been blown away via the cleanup chain
++ or by breakpoint_init_inferior when we rerun the executable. */
++ case bp_until:
++ case bp_finish:
++ case bp_watchpoint_scope:
++ case bp_call_dummy:
++ case bp_step_resume:
++ break;
++ }
++
++ return 0;
++}
++
++/* Re-set all breakpoints after symbols have been re-loaded. */
++void
++breakpoint_re_set (void)
++{
++ struct breakpoint *b, *temp;
++ enum language save_language;
++ int save_input_radix;
++
++ save_language = current_language->la_language;
++ save_input_radix = input_radix;
++ ALL_BREAKPOINTS_SAFE (b, temp)
++ {
++ /* Format possible error msg */
++ char *message = xstrprintf ("Error in re-setting breakpoint %d: ",
++ b->number);
++ struct cleanup *cleanups = make_cleanup (xfree, message);
++ catch_errors (breakpoint_re_set_one, b, message, RETURN_MASK_ALL);
++ do_cleanups (cleanups);
++ }
++ set_language (save_language);
++ input_radix = save_input_radix;
++
++ if (gdbarch_get_longjmp_target_p (current_gdbarch))
++ {
++ create_longjmp_breakpoint ("longjmp");
++ create_longjmp_breakpoint ("_longjmp");
++ create_longjmp_breakpoint ("siglongjmp");
++ create_longjmp_breakpoint ("_siglongjmp");
++ create_longjmp_breakpoint (NULL);
++ }
++
++ create_overlay_event_breakpoint ("_ovly_debug_event");
++}
++
++/* Reset the thread number of this breakpoint:
++
++ - If the breakpoint is for all threads, leave it as-is.
++ - Else, reset it to the current thread for inferior_ptid. */
++void
++breakpoint_re_set_thread (struct breakpoint *b)
++{
++ if (b->thread != -1)
++ {
++ if (in_thread_list (inferior_ptid))
++ b->thread = pid_to_thread_id (inferior_ptid);
++ }
++}
++
++/* Set ignore-count of breakpoint number BPTNUM to COUNT.
++ If from_tty is nonzero, it prints a message to that effect,
++ which ends with a period (no newline). */
++
++void
++set_ignore_count (int bptnum, int count, int from_tty)
++{
++ struct breakpoint *b;
++
++ if (count < 0)
++ count = 0;
++
++ ALL_BREAKPOINTS (b)
++ if (b->number == bptnum)
++ {
++ b->ignore_count = count;
++ if (from_tty)
++ {
++ if (count == 0)
++ printf_filtered (_("Will stop next time breakpoint %d is reached."),
++ bptnum);
++ else if (count == 1)
++ printf_filtered (_("Will ignore next crossing of breakpoint %d."),
++ bptnum);
++ else
++ printf_filtered (_("Will ignore next %d crossings of breakpoint %d."),
++ count, bptnum);
++ }
++ breakpoints_changed ();
++ breakpoint_modify_event (b->number);
++ return;
++ }
++
++ error (_("No breakpoint number %d."), bptnum);
++}
++
++/* Clear the ignore counts of all breakpoints. */
++void
++breakpoint_clear_ignore_counts (void)
++{
++ struct breakpoint *b;
++
++ ALL_BREAKPOINTS (b)
++ b->ignore_count = 0;
++}
++
++/* Command to set ignore-count of breakpoint N to COUNT. */
++
++static void
++ignore_command (char *args, int from_tty)
++{
++ char *p = args;
++ int num;
++
++ if (p == 0)
++ error_no_arg (_("a breakpoint number"));
++
++ num = get_number (&p);
++ if (num == 0)
++ error (_("bad breakpoint number: '%s'"), args);
++ if (*p == 0)
++ error (_("Second argument (specified ignore-count) is missing."));
++
++ set_ignore_count (num,
++ longest_to_int (value_as_long (parse_and_eval (p))),
++ from_tty);
++ if (from_tty)
++ printf_filtered ("\n");
++}
++
++/* Call FUNCTION on each of the breakpoints
++ whose numbers are given in ARGS. */
++
++static void
++map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *))
++{
++ char *p = args;
++ char *p1;
++ int num;
++ struct breakpoint *b, *tmp;
++ int match;
++
++ if (p == 0)
++ error_no_arg (_("one or more breakpoint numbers"));
++
++ while (*p)
++ {
++ match = 0;
++ p1 = p;
++
++ num = get_number_or_range (&p1);
++ if (num == 0)
++ {
++ warning (_("bad breakpoint number at or near '%s'"), p);
++ }
++ else
++ {
++ ALL_BREAKPOINTS_SAFE (b, tmp)
++ if (b->number == num)
++ {
++ struct breakpoint *related_breakpoint = b->related_breakpoint;
++ match = 1;
++ function (b);
++ if (related_breakpoint)
++ function (related_breakpoint);
++ break;
++ }
++ if (match == 0)
++ printf_unfiltered (_("No breakpoint number %d.\n"), num);
++ }
++ p = p1;
++ }
++}
++
++static struct bp_location *
++find_location_by_number (char *number)
++{
++ char *dot = strchr (number, '.');
++ char *p1;
++ int bp_num;
++ int loc_num;
++ struct breakpoint *b;
++ struct bp_location *loc;
++
++ *dot = '\0';
++
++ p1 = number;
++ bp_num = get_number_or_range (&p1);
++ if (bp_num == 0)
++ error (_("Bad breakpoint number '%s'"), number);
++
++ ALL_BREAKPOINTS (b)
++ if (b->number == bp_num)
++ {
++ break;
++ }
++
++ if (!b || b->number != bp_num)
++ error (_("Bad breakpoint number '%s'"), number);
++
++ p1 = dot+1;
++ loc_num = get_number_or_range (&p1);
++ if (loc_num == 0)
++ error (_("Bad breakpoint location number '%s'"), number);
++
++ --loc_num;
++ loc = b->loc;
++ for (;loc_num && loc; --loc_num, loc = loc->next)
++ ;
++ if (!loc)
++ error (_("Bad breakpoint location number '%s'"), dot+1);
++
++ return loc;
++}
++
++
++/* Set ignore-count of breakpoint number BPTNUM to COUNT.
++ If from_tty is nonzero, it prints a message to that effect,
++ which ends with a period (no newline). */
++
++void
++disable_breakpoint (struct breakpoint *bpt)
++{
++ /* Never disable a watchpoint scope breakpoint; we want to
++ hit them when we leave scope so we can delete both the
++ watchpoint and its scope breakpoint at that time. */
++ if (bpt->type == bp_watchpoint_scope)
++ return;
++
++ /* You can't disable permanent breakpoints. */
++ if (bpt->enable_state == bp_permanent)
++ return;
++
++ bpt->enable_state = bp_disabled;
++
++ check_duplicates (bpt);
++
++ if (deprecated_modify_breakpoint_hook)
++ deprecated_modify_breakpoint_hook (bpt);
++ breakpoint_modify_event (bpt->number);
++}
++
++static void
++disable_command (char *args, int from_tty)
++{
++ struct breakpoint *bpt;
++ if (args == 0)
++ ALL_BREAKPOINTS (bpt)
++ switch (bpt->type)
++ {
++ case bp_none:
++ warning (_("attempted to disable apparently deleted breakpoint #%d?"),
++ bpt->number);
++ continue;
++ case bp_breakpoint:
++ case bp_catch_load:
++ case bp_catch_unload:
++ case bp_catch_fork:
++ case bp_catch_vfork:
++ case bp_catch_exec:
++ case bp_hardware_breakpoint:
++ case bp_watchpoint:
++ case bp_hardware_watchpoint:
++ case bp_read_watchpoint:
++ case bp_access_watchpoint:
++ disable_breakpoint (bpt);
++ default:
++ continue;
++ }
++ else if (strchr (args, '.'))
++ {
++ struct bp_location *loc = find_location_by_number (args);
++ if (loc)
++ loc->enabled = 0;
++ check_duplicates (loc->owner);
++ }
++ else
++ map_breakpoint_numbers (args, disable_breakpoint);
++}
++
++static void
++do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition)
++{
++ int target_resources_ok, other_type_used;
++ struct value *mark;
++
++ if (bpt->type == bp_hardware_breakpoint)
++ {
++ int i;
++ i = hw_breakpoint_used_count ();
++ target_resources_ok =
++ TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint,
++ i + 1, 0);
++ if (target_resources_ok == 0)
++ error (_("No hardware breakpoint support in the target."));
++ else if (target_resources_ok < 0)
++ error (_("Hardware breakpoints used exceeds limit."));
++ }
++
++ if (bpt->type == bp_watchpoint ||
++ bpt->type == bp_hardware_watchpoint ||
++ bpt->type == bp_read_watchpoint ||
++ bpt->type == bp_access_watchpoint)
++ {
++ struct frame_id saved_frame_id;
++
++ saved_frame_id = get_frame_id (get_selected_frame (NULL));
++ if (bpt->exp_valid_block != NULL)
++ {
++ struct frame_info *fr =
++ fr = frame_find_by_id (bpt->watchpoint_frame);
++ if (fr == NULL)
++ {
++ printf_filtered (_("\
++Cannot enable watchpoint %d because the block in which its expression\n\
++is valid is not currently in scope.\n"), bpt->number);
++ return;
++ }
++ select_frame (fr);
++ }
++
++ if (bpt->val)
++ value_free (bpt->val);
++ mark = value_mark ();
++ bpt->val = evaluate_expression (bpt->exp);
++ release_value (bpt->val);
++ if (value_lazy (bpt->val))
++ value_fetch_lazy (bpt->val);
++
++ if (bpt->type == bp_hardware_watchpoint ||
++ bpt->type == bp_read_watchpoint ||
++ bpt->type == bp_access_watchpoint)
++ {
++ int i = hw_watchpoint_used_count (bpt->type, &other_type_used);
++ int mem_cnt = can_use_hardware_watchpoint (bpt->val);
++
++ /* Hack around 'unused var' error for some targets here */
++ (void) mem_cnt, (void) i;
++ target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT (
++ bpt->type, i + mem_cnt, other_type_used);
++ /* we can consider of type is bp_hardware_watchpoint, convert to
++ bp_watchpoint in the following condition */
++ if (target_resources_ok < 0)
++ {
++ printf_filtered (_("\
++Cannot enable watchpoint %d because target watch resources\n\
++have been allocated for other watchpoints.\n"), bpt->number);
++ value_free_to_mark (mark);
++ return;
++ }
++ }
++
++ select_frame (frame_find_by_id (saved_frame_id));
++ value_free_to_mark (mark);
++ }
++
++ if (bpt->enable_state != bp_permanent)
++ bpt->enable_state = bp_enabled;
++ bpt->disposition = disposition;
++ check_duplicates (bpt);
++ breakpoints_changed ();
++
++ if (deprecated_modify_breakpoint_hook)
++ deprecated_modify_breakpoint_hook (bpt);
++ breakpoint_modify_event (bpt->number);
++}
++
++
++void
++enable_breakpoint (struct breakpoint *bpt)
++{
++ do_enable_breakpoint (bpt, bpt->disposition);
++}
++
++/* The enable command enables the specified breakpoints (or all defined
++ breakpoints) so they once again become (or continue to be) effective
++ in stopping the inferior. */
++
++static void
++enable_command (char *args, int from_tty)
++{
++ struct breakpoint *bpt;
++ if (args == 0)
++ ALL_BREAKPOINTS (bpt)
++ switch (bpt->type)
++ {
++ case bp_none:
++ warning (_("attempted to enable apparently deleted breakpoint #%d?"),
++ bpt->number);
++ continue;
++ case bp_breakpoint:
++ case bp_catch_load:
++ case bp_catch_unload:
++ case bp_catch_fork:
++ case bp_catch_vfork:
++ case bp_catch_exec:
++ case bp_hardware_breakpoint:
++ case bp_watchpoint:
++ case bp_hardware_watchpoint:
++ case bp_read_watchpoint:
++ case bp_access_watchpoint:
++ enable_breakpoint (bpt);
++ default:
++ continue;
++ }
++ else if (strchr (args, '.'))
++ {
++ struct bp_location *loc = find_location_by_number (args);
++ if (loc)
++ loc->enabled = 1;
++ check_duplicates (loc->owner);
++ }
++ else
++ map_breakpoint_numbers (args, enable_breakpoint);
++}
++
++static void
++enable_once_breakpoint (struct breakpoint *bpt)
++{
++ do_enable_breakpoint (bpt, disp_disable);
++}
++
++static void
++enable_once_command (char *args, int from_tty)
++{
++ map_breakpoint_numbers (args, enable_once_breakpoint);
++}
++
++static void
++enable_delete_breakpoint (struct breakpoint *bpt)
++{
++ do_enable_breakpoint (bpt, disp_del);
++}
++
++static void
++enable_delete_command (char *args, int from_tty)
++{
++ map_breakpoint_numbers (args, enable_delete_breakpoint);
++}
++
++static void
++set_breakpoint_cmd (char *args, int from_tty)
++{
++}
++
++static void
++show_breakpoint_cmd (char *args, int from_tty)
++{
++}
++
++/* Use default_breakpoint_'s, or nothing if they aren't valid. */
++
++struct symtabs_and_lines
++decode_line_spec_1 (char *string, int funfirstline)
++{
++ struct symtabs_and_lines sals;
++ if (string == 0)
++ error (_("Empty line specification."));
++ if (default_breakpoint_valid)
++ sals = decode_line_1 (&string, funfirstline,
++ default_breakpoint_symtab,
++ default_breakpoint_line,
++ (char ***) NULL, NULL);
++ else
++ sals = decode_line_1 (&string, funfirstline,
++ (struct symtab *) NULL, 0, (char ***) NULL, NULL);
++ if (*string)
++ error (_("Junk at end of line specification: %s"), string);
++ return sals;
++}
++
++/* Create and insert a raw software breakpoint at PC. Return an
++ identifier, which should be used to remove the breakpoint later.
++ In general, places which call this should be using something on the
++ breakpoint chain instead; this function should be eliminated
++ someday. */
++
++void *
++deprecated_insert_raw_breakpoint (CORE_ADDR pc)
++{
++ struct bp_target_info *bp_tgt;
++
++ bp_tgt = xmalloc (sizeof (struct bp_target_info));
++ memset (bp_tgt, 0, sizeof (struct bp_target_info));
++
++ bp_tgt->placed_address = pc;
++ if (target_insert_breakpoint (bp_tgt) != 0)
++ {
++ /* Could not insert the breakpoint. */
++ xfree (bp_tgt);
++ return NULL;
++ }
++
++ return bp_tgt;
++}
++
++/* Remove a breakpoint BP inserted by deprecated_insert_raw_breakpoint. */
++
++int
++deprecated_remove_raw_breakpoint (void *bp)
++{
++ struct bp_target_info *bp_tgt = bp;
++ int ret;
++
++ ret = target_remove_breakpoint (bp_tgt);
++ xfree (bp_tgt);
++
++ return ret;
++}
++
++/* One (or perhaps two) breakpoints used for software single stepping. */
++
++static void *single_step_breakpoints[2];
++
++/* Create and insert a breakpoint for software single step. */
++
++void
++insert_single_step_breakpoint (CORE_ADDR next_pc)
++{
++ void **bpt_p;
++
++ if (single_step_breakpoints[0] == NULL)
++ bpt_p = &single_step_breakpoints[0];
++ else
++ {
++ gdb_assert (single_step_breakpoints[1] == NULL);
++ bpt_p = &single_step_breakpoints[1];
++ }
++
++ /* NOTE drow/2006-04-11: A future improvement to this function would be
++ to only create the breakpoints once, and actually put them on the
++ breakpoint chain. That would let us use set_raw_breakpoint. We could
++ adjust the addresses each time they were needed. Doing this requires
++ corresponding changes elsewhere where single step breakpoints are
++ handled, however. So, for now, we use this. */
++
++ *bpt_p = deprecated_insert_raw_breakpoint (next_pc);
++ if (*bpt_p == NULL)
++ error (_("Could not insert single-step breakpoint at 0x%s"),
++ paddr_nz (next_pc));
++}
++
++/* Remove and delete any breakpoints used for software single step. */
++
++void
++remove_single_step_breakpoints (void)
++{
++ gdb_assert (single_step_breakpoints[0] != NULL);
++
++ /* See insert_single_step_breakpoint for more about this deprecated
++ call. */
++ deprecated_remove_raw_breakpoint (single_step_breakpoints[0]);
++ single_step_breakpoints[0] = NULL;
++
++ if (single_step_breakpoints[1] != NULL)
++ {
++ deprecated_remove_raw_breakpoint (single_step_breakpoints[1]);
++ single_step_breakpoints[1] = NULL;
++ }
++}
++
++/* Check whether a software single-step breakpoint is inserted at PC. */
++
++static int
++single_step_breakpoint_inserted_here_p (CORE_ADDR pc)
++{
++ int i;
++
++ for (i = 0; i < 2; i++)
++ {
++ struct bp_target_info *bp_tgt = single_step_breakpoints[i];
++ if (bp_tgt && bp_tgt->placed_address == pc)
++ return 1;
++ }
++
++ return 0;
++}
++
++
++/* This help string is used for the break, hbreak, tbreak and thbreak commands.
++ It is defined as a macro to prevent duplication.
++ COMMAND should be a string constant containing the name of the command. */
++#define BREAK_ARGS_HELP(command) \
++command" [LOCATION] [thread THREADNUM] [if CONDITION]\n\
++LOCATION may be a line number, function name, or \"*\" and an address.\n\
++If a line number is specified, break at start of code for that line.\n\
++If a function is specified, break at start of code for that function.\n\
++If an address is specified, break at that exact address.\n\
++With no LOCATION, uses current execution address of selected stack frame.\n\
++This is useful for breaking on return to a stack frame.\n\
++\n\
++THREADNUM is the number from \"info threads\".\n\
++CONDITION is a boolean expression.\n\
++\n\
++Multiple breakpoints at one place are permitted, and useful if conditional.\n\
++\n\
++Do \"help breakpoints\" for info on other commands dealing with breakpoints."
++
++void
++_initialize_breakpoint (void)
++{
++ static struct cmd_list_element *breakpoint_set_cmdlist;
++ static struct cmd_list_element *breakpoint_show_cmdlist;
++ struct cmd_list_element *c;
++
++ observer_attach_solib_unloaded (disable_breakpoints_in_unloaded_shlib);
++
++ breakpoint_chain = 0;
++ /* Don't bother to call set_breakpoint_count. $bpnum isn't useful
++ before a breakpoint is set. */
++ breakpoint_count = 0;
++
++ add_com ("ignore", class_breakpoint, ignore_command, _("\
++Set ignore-count of breakpoint number N to COUNT.\n\
++Usage is `ignore N COUNT'."));
++ if (xdb_commands)
++ add_com_alias ("bc", "ignore", class_breakpoint, 1);
++
++ add_com ("commands", class_breakpoint, commands_command, _("\
++Set commands to be executed when a breakpoint is hit.\n\
++Give breakpoint number as argument after \"commands\".\n\
++With no argument, the targeted breakpoint is the last one set.\n\
++The commands themselves follow starting on the next line.\n\
++Type a line containing \"end\" to indicate the end of them.\n\
++Give \"silent\" as the first line to make the breakpoint silent;\n\
++then no output is printed when it is hit, except what the commands print."));
++
++ add_com ("condition", class_breakpoint, condition_command, _("\
++Specify breakpoint number N to break only if COND is true.\n\
++Usage is `condition N COND', where N is an integer and COND is an\n\
++expression to be evaluated whenever breakpoint N is reached."));
++
++ c = add_com ("tbreak", class_breakpoint, tbreak_command, _("\
++Set a temporary breakpoint.\n\
++Like \"break\" except the breakpoint is only temporary,\n\
++so it will be deleted when hit. Equivalent to \"break\" followed\n\
++by using \"enable delete\" on the breakpoint number.\n\
++\n"
++BREAK_ARGS_HELP ("tbreak")));
++ set_cmd_completer (c, location_completer);
++
++ c = add_com ("hbreak", class_breakpoint, hbreak_command, _("\
++Set a hardware assisted breakpoint.\n\
++Like \"break\" except the breakpoint requires hardware support,\n\
++some target hardware may not have this support.\n\
++\n"
++BREAK_ARGS_HELP ("hbreak")));
++ set_cmd_completer (c, location_completer);
++
++ c = add_com ("thbreak", class_breakpoint, thbreak_command, _("\
++Set a temporary hardware assisted breakpoint.\n\
++Like \"hbreak\" except the breakpoint is only temporary,\n\
++so it will be deleted when hit.\n\
++\n"
++BREAK_ARGS_HELP ("thbreak")));
++ set_cmd_completer (c, location_completer);
++
++ add_prefix_cmd ("enable", class_breakpoint, enable_command, _("\
++Enable some breakpoints.\n\
++Give breakpoint numbers (separated by spaces) as arguments.\n\
++With no subcommand, breakpoints are enabled until you command otherwise.\n\
++This is used to cancel the effect of the \"disable\" command.\n\
++With a subcommand you can enable temporarily."),
++ &enablelist, "enable ", 1, &cmdlist);
++ if (xdb_commands)
++ add_com ("ab", class_breakpoint, enable_command, _("\
++Enable some breakpoints.\n\
++Give breakpoint numbers (separated by spaces) as arguments.\n\
++With no subcommand, breakpoints are enabled until you command otherwise.\n\
++This is used to cancel the effect of the \"disable\" command.\n\
++With a subcommand you can enable temporarily."));
++
++ add_com_alias ("en", "enable", class_breakpoint, 1);
++
++ add_abbrev_prefix_cmd ("breakpoints", class_breakpoint, enable_command, _("\
++Enable some breakpoints.\n\
++Give breakpoint numbers (separated by spaces) as arguments.\n\
++This is used to cancel the effect of the \"disable\" command.\n\
++May be abbreviated to simply \"enable\".\n"),
++ &enablebreaklist, "enable breakpoints ", 1, &enablelist);
++
++ add_cmd ("once", no_class, enable_once_command, _("\
++Enable breakpoints for one hit. Give breakpoint numbers.\n\
++If a breakpoint is hit while enabled in this fashion, it becomes disabled."),
++ &enablebreaklist);
++
++ add_cmd ("delete", no_class, enable_delete_command, _("\
++Enable breakpoints and delete when hit. Give breakpoint numbers.\n\
++If a breakpoint is hit while enabled in this fashion, it is deleted."),
++ &enablebreaklist);
++
++ add_cmd ("delete", no_class, enable_delete_command, _("\
++Enable breakpoints and delete when hit. Give breakpoint numbers.\n\
++If a breakpoint is hit while enabled in this fashion, it is deleted."),
++ &enablelist);
++
++ add_cmd ("once", no_class, enable_once_command, _("\
++Enable breakpoints for one hit. Give breakpoint numbers.\n\
++If a breakpoint is hit while enabled in this fashion, it becomes disabled."),
++ &enablelist);
++
++ add_prefix_cmd ("disable", class_breakpoint, disable_command, _("\
++Disable some breakpoints.\n\
++Arguments are breakpoint numbers with spaces in between.\n\
++To disable all breakpoints, give no argument.\n\
++A disabled breakpoint is not forgotten, but has no effect until reenabled."),
++ &disablelist, "disable ", 1, &cmdlist);
++ add_com_alias ("dis", "disable", class_breakpoint, 1);
++ add_com_alias ("disa", "disable", class_breakpoint, 1);
++ if (xdb_commands)
++ add_com ("sb", class_breakpoint, disable_command, _("\
++Disable some breakpoints.\n\
++Arguments are breakpoint numbers with spaces in between.\n\
++To disable all breakpoints, give no argument.\n\
++A disabled breakpoint is not forgotten, but has no effect until reenabled."));
++
++ add_cmd ("breakpoints", class_alias, disable_command, _("\
++Disable some breakpoints.\n\
++Arguments are breakpoint numbers with spaces in between.\n\
++To disable all breakpoints, give no argument.\n\
++A disabled breakpoint is not forgotten, but has no effect until reenabled.\n\
++This command may be abbreviated \"disable\"."),
++ &disablelist);
++
++ add_prefix_cmd ("delete", class_breakpoint, delete_command, _("\
++Delete some breakpoints or auto-display expressions.\n\
++Arguments are breakpoint numbers with spaces in between.\n\
++To delete all breakpoints, give no argument.\n\
++\n\
++Also a prefix command for deletion of other GDB objects.\n\
++The \"unset\" command is also an alias for \"delete\"."),
++ &deletelist, "delete ", 1, &cmdlist);
++ add_com_alias ("d", "delete", class_breakpoint, 1);
++ add_com_alias ("del", "delete", class_breakpoint, 1);
++ if (xdb_commands)
++ add_com ("db", class_breakpoint, delete_command, _("\
++Delete some breakpoints.\n\
++Arguments are breakpoint numbers with spaces in between.\n\
++To delete all breakpoints, give no argument.\n"));
++
++ add_cmd ("breakpoints", class_alias, delete_command, _("\
++Delete some breakpoints or auto-display expressions.\n\
++Arguments are breakpoint numbers with spaces in between.\n\
++To delete all breakpoints, give no argument.\n\
++This command may be abbreviated \"delete\"."),
++ &deletelist);
++
++ add_com ("clear", class_breakpoint, clear_command, _("\
++Clear breakpoint at specified line or function.\n\
++Argument may be line number, function name, or \"*\" and an address.\n\
++If line number is specified, all breakpoints in that line are cleared.\n\
++If function is specified, breakpoints at beginning of function are cleared.\n\
++If an address is specified, breakpoints at that address are cleared.\n\
++\n\
++With no argument, clears all breakpoints in the line that the selected frame\n\
++is executing in.\n\
++\n\
++See also the \"delete\" command which clears breakpoints by number."));
++
++ c = add_com ("break", class_breakpoint, break_command, _("\
++Set breakpoint at specified line or function.\n"
++BREAK_ARGS_HELP ("break")));
++ set_cmd_completer (c, location_completer);
++
++ add_com_alias ("b", "break", class_run, 1);
++ add_com_alias ("br", "break", class_run, 1);
++ add_com_alias ("bre", "break", class_run, 1);
++ add_com_alias ("brea", "break", class_run, 1);
++
++ if (xdb_commands)
++ {
++ add_com_alias ("ba", "break", class_breakpoint, 1);
++ add_com_alias ("bu", "ubreak", class_breakpoint, 1);
++ }
++
++ if (dbx_commands)
++ {
++ add_abbrev_prefix_cmd ("stop", class_breakpoint, stop_command, _("\
++Break in function/address or break at a line in the current file."),
++ &stoplist, "stop ", 1, &cmdlist);
++ add_cmd ("in", class_breakpoint, stopin_command,
++ _("Break in function or address."), &stoplist);
++ add_cmd ("at", class_breakpoint, stopat_command,
++ _("Break at a line in the current file."), &stoplist);
++ add_com ("status", class_info, breakpoints_info, _("\
++Status of user-settable breakpoints, or breakpoint number NUMBER.\n\
++The \"Type\" column indicates one of:\n\
++\tbreakpoint - normal breakpoint\n\
++\twatchpoint - watchpoint\n\
++The \"Disp\" column contains one of \"keep\", \"del\", or \"dis\" to indicate\n\
++the disposition of the breakpoint after it gets hit. \"dis\" means that the\n\
++breakpoint will be disabled. The \"Address\" and \"What\" columns indicate the\n\
++address and file/line number respectively.\n\
++\n\
++Convenience variable \"$_\" and default examine address for \"x\"\n\
++are set to the address of the last breakpoint listed unless the command\n\
++is prefixed with \"server \".\n\n\
++Convenience variable \"$bpnum\" contains the number of the last\n\
++breakpoint set."));
++ }
++
++ add_info ("breakpoints", breakpoints_info, _("\
++Status of user-settable breakpoints, or breakpoint number NUMBER.\n\
++The \"Type\" column indicates one of:\n\
++\tbreakpoint - normal breakpoint\n\
++\twatchpoint - watchpoint\n\
++The \"Disp\" column contains one of \"keep\", \"del\", or \"dis\" to indicate\n\
++the disposition of the breakpoint after it gets hit. \"dis\" means that the\n\
++breakpoint will be disabled. The \"Address\" and \"What\" columns indicate the\n\
++address and file/line number respectively.\n\
++\n\
++Convenience variable \"$_\" and default examine address for \"x\"\n\
++are set to the address of the last breakpoint listed unless the command\n\
++is prefixed with \"server \".\n\n\
++Convenience variable \"$bpnum\" contains the number of the last\n\
++breakpoint set."));
++
++ if (xdb_commands)
++ add_com ("lb", class_breakpoint, breakpoints_info, _("\
++Status of user-settable breakpoints, or breakpoint number NUMBER.\n\
++The \"Type\" column indicates one of:\n\
++\tbreakpoint - normal breakpoint\n\
++\twatchpoint - watchpoint\n\
++The \"Disp\" column contains one of \"keep\", \"del\", or \"dis\" to indicate\n\
++the disposition of the breakpoint after it gets hit. \"dis\" means that the\n\
++breakpoint will be disabled. The \"Address\" and \"What\" columns indicate the\n\
++address and file/line number respectively.\n\
++\n\
++Convenience variable \"$_\" and default examine address for \"x\"\n\
++are set to the address of the last breakpoint listed unless the command\n\
++is prefixed with \"server \".\n\n\
++Convenience variable \"$bpnum\" contains the number of the last\n\
++breakpoint set."));
++
++ add_cmd ("breakpoints", class_maintenance, maintenance_info_breakpoints, _("\
++Status of all breakpoints, or breakpoint number NUMBER.\n\
++The \"Type\" column indicates one of:\n\
++\tbreakpoint - normal breakpoint\n\
++\twatchpoint - watchpoint\n\
++\tlongjmp - internal breakpoint used to step through longjmp()\n\
++\tlongjmp resume - internal breakpoint at the target of longjmp()\n\
++\tuntil - internal breakpoint used by the \"until\" command\n\
++\tfinish - internal breakpoint used by the \"finish\" command\n\
++The \"Disp\" column contains one of \"keep\", \"del\", or \"dis\" to indicate\n\
++the disposition of the breakpoint after it gets hit. \"dis\" means that the\n\
++breakpoint will be disabled. The \"Address\" and \"What\" columns indicate the\n\
++address and file/line number respectively.\n\
++\n\
++Convenience variable \"$_\" and default examine address for \"x\"\n\
++are set to the address of the last breakpoint listed unless the command\n\
++is prefixed with \"server \".\n\n\
++Convenience variable \"$bpnum\" contains the number of the last\n\
++breakpoint set."),
++ &maintenanceinfolist);
++
++ add_com ("catch", class_breakpoint, catch_command, _("\
++Set catchpoints to catch events.\n\
++Raised signals may be caught:\n\
++\tcatch signal - all signals\n\
++\tcatch signal <signame> - a particular signal\n\
++Raised exceptions may be caught:\n\
++\tcatch throw - all exceptions, when thrown\n\
++\tcatch throw <exceptname> - a particular exception, when thrown\n\
++\tcatch catch - all exceptions, when caught\n\
++\tcatch catch <exceptname> - a particular exception, when caught\n\
++Thread or process events may be caught:\n\
++\tcatch thread_start - any threads, just after creation\n\
++\tcatch thread_exit - any threads, just before expiration\n\
++\tcatch thread_join - any threads, just after joins\n\
++Process events may be caught:\n\
++\tcatch start - any processes, just after creation\n\
++\tcatch exit - any processes, just before expiration\n\
++\tcatch fork - calls to fork()\n\
++\tcatch vfork - calls to vfork()\n\
++\tcatch exec - calls to exec()\n\
++Dynamically-linked library events may be caught:\n\
++\tcatch load - loads of any library\n\
++\tcatch load <libname> - loads of a particular library\n\
++\tcatch unload - unloads of any library\n\
++\tcatch unload <libname> - unloads of a particular library\n\
++The act of your program's execution stopping may also be caught:\n\
++\tcatch stop\n\n\
++C++ exceptions may be caught:\n\
++\tcatch throw - all exceptions, when thrown\n\
++\tcatch catch - all exceptions, when caught\n\
++Ada exceptions may be caught:\n\
++\tcatch exception - all exceptions, when raised\n\
++\tcatch exception <name> - a particular exception, when raised\n\
++\tcatch exception unhandled - all unhandled exceptions, when raised\n\
++\tcatch assert - all failed assertions, when raised\n\
++\n\
++Do \"help set follow-fork-mode\" for info on debugging your program\n\
++after a fork or vfork is caught.\n\n\
++Do \"help breakpoints\" for info on other commands dealing with breakpoints."));
++
++ add_com ("tcatch", class_breakpoint, tcatch_command, _("\
++Set temporary catchpoints to catch events.\n\
++Args like \"catch\" command.\n\
++Like \"catch\" except the catchpoint is only temporary,\n\
++so it will be deleted when hit. Equivalent to \"catch\" followed\n\
++by using \"enable delete\" on the catchpoint number."));
++
++ c = add_com ("watch", class_breakpoint, watch_command, _("\
++Set a watchpoint for an expression.\n\
++A watchpoint stops execution of your program whenever the value of\n\
++an expression changes."));
++ set_cmd_completer (c, location_completer);
++
++ c = add_com ("rwatch", class_breakpoint, rwatch_command, _("\
++Set a read watchpoint for an expression.\n\
++A watchpoint stops execution of your program whenever the value of\n\
++an expression is read."));
++ set_cmd_completer (c, location_completer);
++
++ c = add_com ("awatch", class_breakpoint, awatch_command, _("\
++Set a watchpoint for an expression.\n\
++A watchpoint stops execution of your program whenever the value of\n\
++an expression is either read or written."));
++ set_cmd_completer (c, location_completer);
++
++ add_info ("watchpoints", breakpoints_info,
++ _("Synonym for ``info breakpoints''."));
++
++
++ /* XXX: cagney/2005-02-23: This should be a boolean, and should
++ respond to changes - contrary to the description. */
++ add_setshow_zinteger_cmd ("can-use-hw-watchpoints", class_support,
++ &can_use_hw_watchpoints, _("\
++Set debugger's willingness to use watchpoint hardware."), _("\
++Show debugger's willingness to use watchpoint hardware."), _("\
++If zero, gdb will not use hardware for new watchpoints, even if\n\
++such is available. (However, any hardware watchpoints that were\n\
++created before setting this to nonzero, will continue to use watchpoint\n\
++hardware.)"),
++ NULL,
++ show_can_use_hw_watchpoints,
++ &setlist, &showlist);
++
++ can_use_hw_watchpoints = 1;
++
++ add_prefix_cmd ("breakpoint", class_maintenance, set_breakpoint_cmd, _("\
++Breakpoint specific settings\n\
++Configure various breakpoint-specific variables such as\n\
++pending breakpoint behavior"),
++ &breakpoint_set_cmdlist, "set breakpoint ",
++ 0/*allow-unknown*/, &setlist);
++ add_prefix_cmd ("breakpoint", class_maintenance, show_breakpoint_cmd, _("\
++Breakpoint specific settings\n\
++Configure various breakpoint-specific variables such as\n\
++pending breakpoint behavior"),
++ &breakpoint_show_cmdlist, "show breakpoint ",
++ 0/*allow-unknown*/, &showlist);
++
++ add_setshow_auto_boolean_cmd ("pending", no_class,
++ &pending_break_support, _("\
++Set debugger's behavior regarding pending breakpoints."), _("\
++Show debugger's behavior regarding pending breakpoints."), _("\
++If on, an unrecognized breakpoint location will cause gdb to create a\n\
++pending breakpoint. If off, an unrecognized breakpoint location results in\n\
++an error. If auto, an unrecognized breakpoint location results in a\n\
++user-query to see if a pending breakpoint should be created."),
++ NULL,
++ show_pending_break_support,
++ &breakpoint_set_cmdlist,
++ &breakpoint_show_cmdlist);
++
++ pending_break_support = AUTO_BOOLEAN_AUTO;
++
++ add_setshow_boolean_cmd ("auto-hw", no_class,
++ &automatic_hardware_breakpoints, _("\
++Set automatic usage of hardware breakpoints."), _("\
++Show automatic usage of hardware breakpoints."), _("\
++If set, the debugger will automatically use hardware breakpoints for\n\
++breakpoints set with \"break\" but falling in read-only memory. If not set,\n\
++a warning will be emitted for such breakpoints."),
++ NULL,
++ show_automatic_hardware_breakpoints,
++ &breakpoint_set_cmdlist,
++ &breakpoint_show_cmdlist);
++
++ automatic_hardware_breakpoints = 1;
++}
+diff -Naur gdb-6.8.orig/gdb/breakpoint.h gdb-6.8/gdb/breakpoint.h
+--- gdb-6.8.orig/gdb/breakpoint.h 2008-02-01 17:24:46.000000000 +0100
++++ gdb-6.8/gdb/breakpoint.h 2008-09-17 16:32:32.000000000 +0200
+@@ -391,8 +391,13 @@
+ /* The largest block within which it is valid, or NULL if it is
+ valid anywhere (e.g. consists just of global symbols). */
+ struct block *exp_valid_block;
+- /* Value of the watchpoint the last time we checked it. */
++ /* Value of the watchpoint the last time we checked it, or NULL
++ when we do not know the value yet or the value was not
++ readable. VAL is never lazy. */
+ struct value *val;
++ /* Nonzero if VAL is valid. If VAL_VALID is set but VAL is NULL,
++ then an error occurred reading the value. */
++ int val_valid;
+
+ /* Holds the address of the related watchpoint_scope breakpoint
+ when using watchpoints on local variables (might the concept
+diff -Naur gdb-6.8.orig/gdb/NEWS gdb-6.8/gdb/NEWS
+--- gdb-6.8.orig/gdb/NEWS 2008-03-27 19:14:10.000000000 +0100
++++ gdb-6.8/gdb/NEWS 2008-09-17 16:32:32.000000000 +0200
+@@ -1,6 +1,9 @@
+ What has changed in GDB?
+ (Organized release by release)
+
++* Watchpoints can now be set on unreadable memory locations, e.g. addresses
++which will be allocated using malloc later in program execution.
++
+ *** Changes in GDB 6.8
+
+ * New native configurations
+diff -Naur gdb-6.8.orig/gdb/NEWS.orig gdb-6.8/gdb/NEWS.orig
+--- gdb-6.8.orig/gdb/NEWS.orig 1970-01-01 01:00:00.000000000 +0100
++++ gdb-6.8/gdb/NEWS.orig 2008-03-27 19:14:10.000000000 +0100
+@@ -0,0 +1,3249 @@
++ What has changed in GDB?
++ (Organized release by release)
++
++*** Changes in GDB 6.8
++
++* New native configurations
++
++NetBSD/hppa hppa*-*netbsd*
++Xtensa GNU/Linux xtensa*-*-linux*
++
++* New targets
++
++NetBSD/hppa hppa*-*-netbsd*
++Xtensa GNU/Lunux xtensa*-*-linux*
++
++* Change in command line behavior -- corefiles vs. process ids.
++
++ When the '-p NUMBER' or '--pid NUMBER' options are used, and
++ attaching to process NUMBER fails, GDB no longer attempts to open a
++ core file named NUMBER. Attaching to a program using the -c option
++ is no longer supported. Instead, use the '-p' or '--pid' options.
++
++* GDB can now be built as a native debugger for debugging Windows x86
++(mingw32) Portable Executable (PE) programs.
++
++* Pending breakpoints no longer change their number when their address
++is resolved.
++
++* GDB now supports breakpoints with multiple locations,
++including breakpoints on C++ constructors, inside C++ templates,
++and in inlined functions.
++
++* GDB's ability to debug optimized code has been improved. GDB more
++accurately identifies function bodies and lexical blocks that occupy
++more than one contiguous range of addresses.
++
++* Target descriptions can now describe registers for PowerPC.
++
++* The GDB remote stub, gdbserver, now supports the AltiVec and SPE
++registers on PowerPC targets.
++
++* The GDB remote stub, gdbserver, now supports thread debugging on GNU/Linux
++targets even when the libthread_db library is not available.
++
++* The GDB remote stub, gdbserver, now supports the new file transfer
++commands (remote put, remote get, and remote delete).
++
++* The GDB remote stub, gdbserver, now supports run and attach in
++extended-remote mode.
++
++* hppa*64*-*-hpux11* target broken
++ The debugger is unable to start a program and fails with the following
++ error: "Error trying to get information about dynamic linker".
++ The gdb-6.7 release is also affected.
++
++* GDB now supports the --enable-targets= configure option to allow
++building a single GDB executable that supports multiple remote
++target architectures.
++
++* GDB now supports debugging C and C++ programs which use the
++Decimal Floating Point extension. In addition, the PowerPC target
++now has a set of pseudo-registers to inspect decimal float values
++stored in two consecutive float registers.
++
++* The -break-insert MI command can optionally create pending
++breakpoints now.
++
++* Improved support for debugging Ada
++ Many improvements to the Ada language support have been made. These
++ include:
++ - Better support for Ada2005 interface types
++ - Improved handling of arrays and slices in general
++ - Better support for Taft-amendment types
++ - The '{type} ADDRESS' expression is now allowed on the left hand-side
++ of an assignment
++ - Improved command completion in Ada
++ - Several bug fixes
++
++* New commands
++
++set print frame-arguments (all|scalars|none)
++show print frame-arguments
++ The value of this variable can be changed to control which argument
++ values should be printed by the debugger when displaying a frame.
++
++remote put
++remote get
++remote delete
++ Transfer files to and from a remote target, and delete remote files.
++
++* New MI commands
++
++-target-file-put
++-target-file-get
++-target-file-delete
++ Transfer files to and from a remote target, and delete remote files.
++
++* New remote packets
++
++vFile:open:
++vFile:close:
++vFile:pread:
++vFile:pwrite:
++vFile:unlink:
++ Open, close, read, write, and delete files on the remote system.
++
++* GDB on GNU/Linux and HP/UX can now debug through "exec" of a new
++process.
++
++vAttach
++ Attach to an existing process on the remote system, in extended-remote
++ mode.
++
++vRun
++ Run a new process on the remote system, in extended-remote mode.
++
++*** Changes in GDB 6.7
++
++* Resolved 101 resource leaks, null pointer dereferences, etc. in gdb,
++bfd, libiberty and opcodes, as revealed by static analysis donated by
++Coverity, Inc. (http://scan.coverity.com).
++
++* When looking up multiply-defined global symbols, GDB will now prefer the
++symbol definition in the current shared library if it was built using the
++-Bsymbolic linker option.
++
++* When the Text User Interface (TUI) is not configured, GDB will now
++recognize the -tui command-line option and print a message that the TUI
++is not supported.
++
++* The GDB remote stub, gdbserver, now has lower overhead for high
++frequency signals (e.g. SIGALRM) via the QPassSignals packet.
++
++* GDB for MIPS targets now autodetects whether a remote target provides
++32-bit or 64-bit register values.
++
++* Support for C++ member pointers has been improved.
++
++* GDB now understands XML target descriptions, which specify the
++target's overall architecture. GDB can read a description from
++a local file or over the remote serial protocol.
++
++* Vectors of single-byte data use a new integer type which is not
++automatically displayed as character or string data.
++
++* The /s format now works with the print command. It displays
++arrays of single-byte integers and pointers to single-byte integers
++as strings.
++
++* Target descriptions can now describe target-specific registers,
++for architectures which have implemented the support (currently
++only ARM, M68K, and MIPS).
++
++* GDB and the GDB remote stub, gdbserver, now support the XScale
++iWMMXt coprocessor.
++
++* The GDB remote stub, gdbserver, has been updated to support
++ARM Windows CE (mingw32ce) debugging, and GDB Windows CE support
++has been rewritten to use the standard GDB remote protocol.
++
++* GDB can now step into C++ functions which are called through thunks.
++
++* GDB for the Cell/B.E. SPU now supports overlay debugging.
++
++* The GDB remote protocol "qOffsets" packet can now honor ELF segment
++layout. It also supports a TextSeg= and DataSeg= response when only
++segment base addresses (rather than offsets) are available.
++
++* The /i format now outputs any trailing branch delay slot instructions
++immediately following the last instruction within the count specified.
++
++* The GDB remote protocol "T" stop reply packet now supports a
++"library" response. Combined with the new "qXfer:libraries:read"
++packet, this response allows GDB to debug shared libraries on targets
++where the operating system manages the list of loaded libraries (e.g.
++Windows and SymbianOS).
++
++* The GDB remote stub, gdbserver, now supports dynamic link libraries
++(DLLs) on Windows and Windows CE targets.
++
++* GDB now supports a faster verification that a .debug file matches its binary
++according to its build-id signature, if the signature is present.
++
++* New commands
++
++set remoteflow
++show remoteflow
++ Enable or disable hardware flow control (RTS/CTS) on the serial port
++ when debugging using remote targets.
++
++set mem inaccessible-by-default
++show mem inaccessible-by-default
++ If the target supplies a memory map, for instance via the remote
++ protocol's "qXfer:memory-map:read" packet, setting this variable
++ prevents GDB from accessing memory outside the memory map. This
++ is useful for targets with memory mapped registers or which react
++ badly to accesses of unmapped address space.
++
++set breakpoint auto-hw
++show breakpoint auto-hw
++ If the target supplies a memory map, for instance via the remote
++ protocol's "qXfer:memory-map:read" packet, setting this variable
++ lets GDB use hardware breakpoints automatically for memory regions
++ where it can not use software breakpoints. This covers both the
++ "break" command and internal breakpoints used for other commands
++ including "next" and "finish".
++
++catch exception
++catch exception unhandled
++ Stop the program execution when Ada exceptions are raised.
++
++catch assert
++ Stop the program execution when an Ada assertion failed.
++
++set sysroot
++show sysroot
++ Set an alternate system root for target files. This is a more
++ general version of "set solib-absolute-prefix", which is now
++ an alias to "set sysroot".
++
++info spu
++ Provide extended SPU facility status information. This set of
++ commands is available only when debugging the Cell/B.E. SPU
++ architecture.
++
++* New native configurations
++
++OpenBSD/sh sh*-*openbsd*
++
++set tdesc filename
++unset tdesc filename
++show tdesc filename
++ Use the specified local file as an XML target description, and do
++ not query the target for its built-in description.
++
++* New targets
++
++OpenBSD/sh sh*-*-openbsd*
++MIPS64 GNU/Linux (gdbserver) mips64-linux-gnu
++Toshiba Media Processor mep-elf
++
++* New remote packets
++
++QPassSignals:
++ Ignore the specified signals; pass them directly to the debugged program
++ without stopping other threads or reporting them to GDB.
++
++qXfer:features:read:
++ Read an XML target description from the target, which describes its
++ features.
++
++qXfer:spu:read:
++qXfer:spu:write:
++ Read or write contents of an spufs file on the target system. These
++ packets are available only on the Cell/B.E. SPU architecture.
++
++qXfer:libraries:read:
++ Report the loaded shared libraries. Combined with new "T" packet
++ response, this packet allows GDB to debug shared libraries on
++ targets where the operating system manages the list of loaded
++ libraries (e.g. Windows and SymbianOS).
++
++* Removed targets
++
++Support for these obsolete configurations has been removed.
++
++alpha*-*-osf1*
++alpha*-*-osf2*
++d10v-*-*
++hppa*-*-hiux*
++i[34567]86-ncr-*
++i[34567]86-*-dgux*
++i[34567]86-*-lynxos*
++i[34567]86-*-netware*
++i[34567]86-*-sco3.2v5*
++i[34567]86-*-sco3.2v4*
++i[34567]86-*-sco*
++i[34567]86-*-sysv4.2*
++i[34567]86-*-sysv4*
++i[34567]86-*-sysv5*
++i[34567]86-*-unixware2*
++i[34567]86-*-unixware*
++i[34567]86-*-sysv*
++i[34567]86-*-isc*
++m68*-cisco*-*
++m68*-tandem-*
++mips*-*-pe
++rs6000-*-lynxos*
++sh*-*-pe
++
++* Other removed features
++
++target abug
++target cpu32bug
++target est
++target rom68k
++
++ Various m68k-only ROM monitors.
++
++target hms
++target e7000
++target sh3
++target sh3e
++
++ Various Renesas ROM monitors and debugging interfaces for SH and
++ H8/300.
++
++target ocd
++
++ Support for a Macraigor serial interface to on-chip debugging.
++ GDB does not directly support the newer parallel or USB
++ interfaces.
++
++DWARF 1 support
++
++ A debug information format. The predecessor to DWARF 2 and
++ DWARF 3, which are still supported.
++
++Support for the HP aCC compiler on HP-UX/PA-RISC
++
++ SOM-encapsulated symbolic debugging information, automatic
++ invocation of pxdb, and the aCC custom C++ ABI. This does not
++ affect HP-UX for Itanium or GCC for HP-UX/PA-RISC. Code compiled
++ with aCC can still be debugged on an assembly level.
++
++MIPS ".pdr" sections
++
++ A MIPS-specific format used to describe stack frame layout
++ in debugging information.
++
++Scheme support
++
++ GDB could work with an older version of Guile to debug
++ the interpreter and Scheme programs running in it.
++
++set mips stack-arg-size
++set mips saved-gpreg-size
++
++ Use "set mips abi" to control parameter passing for MIPS.
++
++*** Changes in GDB 6.6
++
++* New targets
++
++Xtensa xtensa-elf
++Cell Broadband Engine SPU spu-elf
++
++* GDB can now be configured as a cross-debugger targeting native Windows
++(mingw32) or Cygwin. It can communicate with a remote debugging stub
++running on a Windows system over TCP/IP to debug Windows programs.
++
++* The GDB remote stub, gdbserver, has been updated to support Windows and
++Cygwin debugging. Both single-threaded and multi-threaded programs are
++supported.
++
++* The "set trust-readonly-sections" command works again. This command was
++broken in GDB 6.3, 6.4, and 6.5.
++
++* The "load" command now supports writing to flash memory, if the remote
++stub provides the required support.
++
++* Support for GNU/Linux Thread Local Storage (TLS, per-thread variables) no
++longer requires symbolic debug information (e.g. DWARF-2).
++
++* New commands
++
++set substitute-path
++unset substitute-path
++show substitute-path
++ Manage a list of substitution rules that GDB uses to rewrite the name
++ of the directories where the sources are located. This can be useful
++ for instance when the sources were moved to a different location
++ between compilation and debugging.
++
++set trace-commands
++show trace-commands
++ Print each CLI command as it is executed. Each command is prefixed with
++ a number of `+' symbols representing the nesting depth.
++ The source command now has a `-v' option to enable the same feature.
++
++* REMOVED features
++
++The ARM Demon monitor support (RDP protocol, "target rdp").
++
++Kernel Object Display, an embedded debugging feature which only worked with
++an obsolete version of Cisco IOS.
++
++The 'set download-write-size' and 'show download-write-size' commands.
++
++* New remote packets
++
++qSupported:
++ Tell a stub about GDB client features, and request remote target features.
++ The first feature implemented is PacketSize, which allows the target to
++ specify the size of packets it can handle - to minimize the number of
++ packets required and improve performance when connected to a remote
++ target.
++
++qXfer:auxv:read:
++ Fetch an OS auxilliary vector from the remote stub. This packet is a
++ more efficient replacement for qPart:auxv:read.
++
++qXfer:memory-map:read:
++ Fetch a memory map from the remote stub, including information about
++ RAM, ROM, and flash memory devices.
++
++vFlashErase:
++vFlashWrite:
++vFlashDone:
++ Erase and program a flash memory device.
++
++* Removed remote packets
++
++qPart:auxv:read:
++ This packet has been replaced by qXfer:auxv:read. Only GDB 6.4 and 6.5
++ used it, and only gdbserver implemented it.
++
++*** Changes in GDB 6.5
++
++* New targets
++
++Renesas M32C/M16C m32c-elf
++
++Morpho Technologies ms1 ms1-elf
++
++* New commands
++
++init-if-undefined Initialize a convenience variable, but
++ only if it doesn't already have a value.
++
++The following commands are presently only implemented for native GNU/Linux:
++
++checkpoint Save a snapshot of the program state.
++
++restart <n> Return the program state to a
++ previously saved state.
++
++info checkpoints List currently saved checkpoints.
++
++delete-checkpoint <n> Delete a previously saved checkpoint.
++
++set|show detach-on-fork Tell gdb whether to detach from a newly
++ forked process, or to keep debugging it.
++
++info forks List forks of the user program that
++ are available to be debugged.
++
++fork <n> Switch to debugging one of several
++ forks of the user program that are
++ available to be debugged.
++
++delete-fork <n> Delete a fork from the list of forks
++ that are available to be debugged (and
++ kill the forked process).
++
++detach-fork <n> Delete a fork from the list of forks
++ that are available to be debugged (and
++ allow the process to continue).
++
++* New architecture
++
++Morpho Technologies ms2 ms1-elf
++
++* Improved Windows host support
++
++GDB now builds as a cross debugger hosted on i686-mingw32, including
++native console support, and remote communications using either
++network sockets or serial ports.
++
++* Improved Modula-2 language support
++
++GDB can now print most types in the Modula-2 syntax. This includes:
++basic types, set types, record types, enumerated types, range types,
++pointer types and ARRAY types. Procedure var parameters are correctly
++printed and hexadecimal addresses and character constants are also
++written in the Modula-2 syntax. Best results can be obtained by using
++GNU Modula-2 together with the -gdwarf-2 command line option.
++
++* REMOVED features
++
++The ARM rdi-share module.
++
++The Netware NLM debug server.
++
++*** Changes in GDB 6.4
++
++* New native configurations
++
++OpenBSD/arm arm*-*-openbsd*
++OpenBSD/mips64 mips64-*-openbsd*
++
++* New targets
++
++Morpho Technologies ms1 ms1-elf
++
++* New command line options
++
++--batch-silent As for --batch, but totally silent.
++--return-child-result The debugger will exist with the same value
++ the child (debugged) program exited with.
++--eval-command COMMAND, -ex COMMAND
++ Execute a single GDB CLI command. This may be
++ specified multiple times and in conjunction
++ with the --command (-x) option.
++
++* Deprecated commands removed
++
++The following commands, that were deprecated in 2000, have been
++removed:
++
++ Command Replacement
++ set|show arm disassembly-flavor set|show arm disassembler
++ othernames set arm disassembler
++ set|show remotedebug set|show debug remote
++ set|show archdebug set|show debug arch
++ set|show eventdebug set|show debug event
++ regs info registers
++
++* New BSD user-level threads support
++
++It is now possible to debug programs using the user-level threads
++library on OpenBSD and FreeBSD. Currently supported (target)
++configurations are:
++
++FreeBSD/amd64 x86_64-*-freebsd*
++FreeBSD/i386 i386-*-freebsd*
++OpenBSD/i386 i386-*-openbsd*
++
++Note that the new kernel threads libraries introduced in FreeBSD 5.x
++are not yet supported.
++
++* New support for Matsushita MN10300 w/sim added
++(Work in progress). mn10300-elf.
++
++* REMOVED configurations and files
++
++VxWorks and the XDR protocol *-*-vxworks
++Motorola MCORE mcore-*-*
++National Semiconductor NS32000 ns32k-*-*
++
++* New "set print array-indexes" command
++
++After turning this setting "on", GDB prints the index of each element
++when displaying arrays. The default is "off" to preserve the previous
++behavior.
++
++* VAX floating point support
++
++GDB now supports the not-quite-ieee VAX F and D floating point formats.
++
++* User-defined command support
++
++In addition to using $arg0..$arg9 for argument passing, it is now possible
++to use $argc to determine now many arguments have been passed. See the
++section on user-defined commands in the user manual for more information.
++
++*** Changes in GDB 6.3:
++
++* New command line option
++
++GDB now accepts -l followed by a number to set the timeout for remote
++debugging.
++
++* GDB works with GCC -feliminate-dwarf2-dups
++
++GDB now supports a more compact representation of DWARF-2 debug
++information using DW_FORM_ref_addr references. These are produced
++by GCC with the option -feliminate-dwarf2-dups and also by some
++proprietary compilers. With GCC, you must use GCC 3.3.4 or later
++to use -feliminate-dwarf2-dups.
++
++* Internationalization
++
++When supported by the host system, GDB will be built with
++internationalization (libintl). The task of marking up the sources is
++continued, we're looking forward to our first translation.
++
++* Ada
++
++Initial support for debugging programs compiled with the GNAT
++implementation of the Ada programming language has been integrated
++into GDB. In this release, support is limited to expression evaluation.
++
++* New native configurations
++
++GNU/Linux/m32r m32r-*-linux-gnu
++
++* Remote 'p' packet
++
++GDB's remote protocol now includes support for the 'p' packet. This
++packet is used to fetch individual registers from a remote inferior.
++
++* END-OF-LIFE registers[] compatibility module
++
++GDB's internal register infrastructure has been completely rewritten.
++The new infrastructure making possible the implementation of key new
++features including 32x64 (e.g., 64-bit amd64 GDB debugging a 32-bit
++i386 application).
++
++GDB 6.3 will be the last release to include the the registers[]
++compatibility module that allowed out-of-date configurations to
++continue to work. This change directly impacts the following
++configurations:
++
++hppa-*-hpux
++ia64-*-aix
++mips-*-irix*
++*-*-lynx
++mips-*-linux-gnu
++sds protocol
++xdr protocol
++powerpc bdm protocol
++
++Unless there is activity to revive these configurations, they will be
++made OBSOLETE in GDB 6.4, and REMOVED from GDB 6.5.
++
++* OBSOLETE configurations and files
++
++Configurations that have been declared obsolete in this release have
++been commented out. Unless there is activity to revive these
++configurations, the next release of GDB will have their sources
++permanently REMOVED.
++
++h8300-*-*
++mcore-*-*
++mn10300-*-*
++ns32k-*-*
++sh64-*-*
++v850-*-*
++
++*** Changes in GDB 6.2.1:
++
++* MIPS `break main; run' gave an heuristic-fence-post warning
++
++When attempting to run even a simple program, a warning about
++heuristic-fence-post being hit would be reported. This problem has
++been fixed.
++
++* MIPS IRIX 'long double' crashed GDB
++
++When examining a long double variable, GDB would get a segmentation
++fault. The crash has been fixed (but GDB 6.2 cannot correctly examine
++IRIX long double values).
++
++* VAX and "next"
++
++A bug in the VAX stack code was causing problems with the "next"
++command. This problem has been fixed.
++
++*** Changes in GDB 6.2:
++
++* Fix for ``many threads''
++
++On GNU/Linux systems that use the NPTL threads library, a program
++rapidly creating and deleting threads would confuse GDB leading to the
++error message:
++
++ ptrace: No such process.
++ thread_db_get_info: cannot get thread info: generic error
++
++This problem has been fixed.
++
++* "-async" and "-noasync" options removed.
++
++Support for the broken "-noasync" option has been removed (it caused
++GDB to dump core).
++
++* New ``start'' command.
++
++This command runs the program until the begining of the main procedure.
++
++* New BSD Kernel Data Access Library (libkvm) interface
++
++Using ``target kvm'' it is now possible to debug kernel core dumps and
++live kernel memory images on various FreeBSD, NetBSD and OpenBSD
++platforms. Currently supported (native-only) configurations are:
++
++FreeBSD/amd64 x86_64-*-freebsd*
++FreeBSD/i386 i?86-*-freebsd*
++NetBSD/i386 i?86-*-netbsd*
++NetBSD/m68k m68*-*-netbsd*
++NetBSD/sparc sparc-*-netbsd*
++OpenBSD/amd64 x86_64-*-openbsd*
++OpenBSD/i386 i?86-*-openbsd*
++OpenBSD/m68k m68*-openbsd*
++OpenBSD/sparc sparc-*-openbsd*
++
++* Signal trampoline code overhauled
++
++Many generic problems with GDB's signal handling code have been fixed.
++These include: backtraces through non-contiguous stacks; recognition
++of sa_sigaction signal trampolines; backtrace from a NULL pointer
++call; backtrace through a signal trampoline; step into and out of
++signal handlers; and single-stepping in the signal trampoline.
++
++Please note that kernel bugs are a limiting factor here. These
++features have been shown to work on an s390 GNU/Linux system that
++include a 2.6.8-rc1 kernel. Ref PR breakpoints/1702.
++
++* Cygwin support for DWARF 2 added.
++
++* New native configurations
++
++GNU/Linux/hppa hppa*-*-linux*
++OpenBSD/hppa hppa*-*-openbsd*
++OpenBSD/m68k m68*-*-openbsd*
++OpenBSD/m88k m88*-*-openbsd*
++OpenBSD/powerpc powerpc-*-openbsd*
++NetBSD/vax vax-*-netbsd*
++OpenBSD/vax vax-*-openbsd*
++
++* END-OF-LIFE frame compatibility module
++
++GDB's internal frame infrastructure has been completely rewritten.
++The new infrastructure making it possible to support key new features
++including DWARF 2 Call Frame Information. To aid in the task of
++migrating old configurations to this new infrastructure, a
++compatibility module, that allowed old configurations to continue to
++work, was also included.
++
++GDB 6.2 will be the last release to include this frame compatibility
++module. This change directly impacts the following configurations:
++
++h8300-*-*
++mcore-*-*
++mn10300-*-*
++ns32k-*-*
++sh64-*-*
++v850-*-*
++xstormy16-*-*
++
++Unless there is activity to revive these configurations, they will be
++made OBSOLETE in GDB 6.3, and REMOVED from GDB 6.4.
++
++* REMOVED configurations and files
++
++Sun 3, running SunOS 3 m68*-*-sunos3*
++Sun 3, running SunOS 4 m68*-*-sunos4*
++Sun 2, running SunOS 3 m68000-*-sunos3*
++Sun 2, running SunOS 4 m68000-*-sunos4*
++Motorola 680x0 running LynxOS m68*-*-lynxos*
++AT&T 3b1/Unix pc m68*-att-*
++Bull DPX2 (68k, System V release 3) m68*-bull-sysv*
++decstation mips-dec-* mips-little-*
++riscos mips-*-riscos* mips-*-sysv*
++sonymips mips-sony-*
++sysv mips*-*-sysv4* (IRIX 5/6 not included)
++
++*** Changes in GDB 6.1.1:
++
++* TUI (Text-mode User Interface) built-in (also included in GDB 6.1)
++
++The TUI (Text-mode User Interface) is now built as part of a default
++GDB configuration. It is enabled by either selecting the TUI with the
++command line option "-i=tui" or by running the separate "gdbtui"
++program. For more information on the TUI, see the manual "Debugging
++with GDB".
++
++* Pending breakpoint support (also included in GDB 6.1)
++
++Support has been added to allow you to specify breakpoints in shared
++libraries that have not yet been loaded. If a breakpoint location
++cannot be found, and the "breakpoint pending" option is set to auto,
++GDB queries you if you wish to make the breakpoint pending on a future
++shared-library load. If and when GDB resolves the breakpoint symbol,
++the pending breakpoint is removed as one or more regular breakpoints
++are created.
++
++Pending breakpoints are very useful for GCJ Java debugging.
++
++* Fixed ISO-C build problems
++
++The files bfd/elf-bfd.h, gdb/dictionary.c and gdb/types.c contained
++non ISO-C code that stopped them being built using a more strict ISO-C
++compiler (e.g., IBM's C compiler).
++
++* Fixed build problem on IRIX 5
++
++Due to header problems with <sys/proc.h>, the file gdb/proc-api.c
++wasn't able to compile compile on an IRIX 5 system.
++
++* Added execute permission to gdb/gdbserver/configure
++
++The shell script gdb/testsuite/gdb.stabs/configure lacked execute
++permission. This bug would cause configure to fail on a number of
++systems (Solaris, IRIX). Ref: server/519.
++
++* Fixed build problem on hpux2.0w-hp-hpux11.00 using the HP ANSI C compiler
++
++Older HPUX ANSI C compilers did not accept variable array sizes. somsolib.c
++has been updated to use constant array sizes.
++
++* Fixed a panic in the DWARF Call Frame Info code on Solaris 2.7
++
++GCC 3.3.2, on Solaris 2.7, includes the DW_EH_PE_funcrel encoding in
++its generated DWARF Call Frame Info. This encoding was causing GDB to
++panic, that panic has been fixed. Ref: gdb/1628.
++
++* Fixed a problem when examining parameters in shared library code.
++
++When examining parameters in optimized shared library code generated
++by a mainline GCC, GDB would incorrectly report ``Variable "..." is
++not available''. GDB now correctly displays the variable's value.
++
++*** Changes in GDB 6.1:
++
++* Removed --with-mmalloc
++
++Support for the mmalloc memory manager has been removed, as it
++conflicted with the internal gdb byte cache.
++
++* Changes in AMD64 configurations
++
++The AMD64 target now includes the %cs and %ss registers. As a result
++the AMD64 remote protocol has changed; this affects the floating-point
++and SSE registers. If you rely on those registers for your debugging,
++you should upgrade gdbserver on the remote side.
++
++* Revised SPARC target
++
++The SPARC target has been completely revised, incorporating the
++FreeBSD/sparc64 support that was added for GDB 6.0. As a result
++support for LynxOS and SunOS 4 has been dropped. Calling functions
++from within GDB on operating systems with a non-executable stack
++(Solaris, OpenBSD) now works.
++
++* New C++ demangler
++
++GDB has a new C++ demangler which does a better job on the mangled
++names generated by current versions of g++. It also runs faster, so
++with this and other changes gdb should now start faster on large C++
++programs.
++
++* DWARF 2 Location Expressions
++
++GDB support for location expressions has been extended to support function
++arguments and frame bases. Older versions of GDB could crash when they
++encountered these.
++
++* C++ nested types and namespaces
++
++GDB's support for nested types and namespaces in C++ has been
++improved, especially if you use the DWARF 2 debugging format. (This
++is the default for recent versions of GCC on most platforms.)
++Specifically, if you have a class "Inner" defined within a class or
++namespace "Outer", then GDB realizes that the class's name is
++"Outer::Inner", not simply "Inner". This should greatly reduce the
++frequency of complaints about not finding RTTI symbols. In addition,
++if you are stopped at inside of a function defined within a namespace,
++GDB modifies its name lookup accordingly.
++
++* New native configurations
++
++NetBSD/amd64 x86_64-*-netbsd*
++OpenBSD/amd64 x86_64-*-openbsd*
++OpenBSD/alpha alpha*-*-openbsd*
++OpenBSD/sparc sparc-*-openbsd*
++OpenBSD/sparc64 sparc64-*-openbsd*
++
++* New debugging protocols
++
++M32R with SDI protocol m32r-*-elf*
++
++* "set prompt-escape-char" command deleted.
++
++The command "set prompt-escape-char" has been deleted. This command,
++and its very obscure effet on GDB's prompt, was never documented,
++tested, nor mentioned in the NEWS file.
++
++* OBSOLETE configurations and files
++
++Configurations that have been declared obsolete in this release have
++been commented out. Unless there is activity to revive these
++configurations, the next release of GDB will have their sources
++permanently REMOVED.
++
++Sun 3, running SunOS 3 m68*-*-sunos3*
++Sun 3, running SunOS 4 m68*-*-sunos4*
++Sun 2, running SunOS 3 m68000-*-sunos3*
++Sun 2, running SunOS 4 m68000-*-sunos4*
++Motorola 680x0 running LynxOS m68*-*-lynxos*
++AT&T 3b1/Unix pc m68*-att-*
++Bull DPX2 (68k, System V release 3) m68*-bull-sysv*
++decstation mips-dec-* mips-little-*
++riscos mips-*-riscos* mips-*-sysv*
++sonymips mips-sony-*
++sysv mips*-*-sysv4* (IRIX 5/6 not included)
++
++* REMOVED configurations and files
++
++SGI Irix-4.x mips-sgi-irix4 or iris4
++SGI Iris (MIPS) running Irix V3: mips-sgi-irix or iris
++Z8000 simulator z8k-zilog-none or z8ksim
++Matsushita MN10200 w/simulator mn10200-*-*
++H8/500 simulator h8500-hitachi-hms or h8500hms
++HP/PA running BSD hppa*-*-bsd*
++HP/PA running OSF/1 hppa*-*-osf*
++HP/PA Pro target hppa*-*-pro*
++PMAX (MIPS) running Mach 3.0 mips*-*-mach3*
++386BSD i[3456]86-*-bsd*
++Sequent family i[3456]86-sequent-sysv4*
++ i[3456]86-sequent-sysv*
++ i[3456]86-sequent-bsd*
++SPARC running LynxOS sparc-*-lynxos*
++SPARC running SunOS 4 sparc-*-sunos4*
++Tsqware Sparclet sparclet-*-*
++Fujitsu SPARClite sparclite-fujitsu-none or sparclite
++
++*** Changes in GDB 6.0:
++
++* Objective-C
++
++Support for debugging the Objective-C programming language has been
++integrated into GDB.
++
++* New backtrace mechanism (includes DWARF 2 Call Frame Information).
++
++DWARF 2's Call Frame Information makes available compiler generated
++information that more exactly describes the program's run-time stack.
++By using this information, GDB is able to provide more robust stack
++backtraces.
++
++The i386, amd64 (nee, x86-64), Alpha, m68hc11, ia64, and m32r targets
++have been updated to use a new backtrace mechanism which includes
++DWARF 2 CFI support.
++
++* Hosted file I/O.
++
++GDB's remote protocol has been extended to include support for hosted
++file I/O (where the remote target uses GDB's file system). See GDB's
++remote protocol documentation for details.
++
++* All targets using the new architecture framework.
++
++All of GDB's targets have been updated to use the new internal
++architecture framework. The way is now open for future GDB releases
++to include cross-architecture native debugging support (i386 on amd64,
++ppc32 on ppc64).
++
++* GNU/Linux's Thread Local Storage (TLS)
++
++GDB now includes support for for the GNU/Linux implementation of
++per-thread variables.
++
++* GNU/Linux's Native POSIX Thread Library (NPTL)
++
++GDB's thread code has been updated to work with either the new
++GNU/Linux NPTL thread library or the older "LinuxThreads" library.
++
++* Separate debug info.
++
++GDB, in conjunction with BINUTILS, now supports a mechanism for
++automatically loading debug information from a separate file. Instead
++of shipping full debug and non-debug versions of system libraries,
++system integrators can now instead ship just the stripped libraries
++and optional debug files.
++
++* DWARF 2 Location Expressions
++
++DWARF 2 Location Expressions allow the compiler to more completely
++describe the location of variables (even in optimized code) to the
++debugger.
++
++GDB now includes preliminary support for location expressions (support
++for DW_OP_piece is still missing).
++
++* Java
++
++A number of long standing bugs that caused GDB to die while starting a
++Java application have been fixed. GDB's Java support is now
++considered "useable".
++
++* GNU/Linux support for fork, vfork, and exec.
++
++The "catch fork", "catch exec", "catch vfork", and "set follow-fork-mode"
++commands are now implemented for GNU/Linux. They require a 2.5.x or later
++kernel.
++
++* GDB supports logging output to a file
++
++There are two new commands, "set logging" and "show logging", which can be
++used to capture GDB's output to a file.
++
++* The meaning of "detach" has changed for gdbserver
++
++The "detach" command will now resume the application, as documented. To
++disconnect from gdbserver and leave it stopped, use the new "disconnect"
++command.
++
++* d10v, m68hc11 `regs' command deprecated
++
++The `info registers' command has been updated so that it displays the
++registers using a format identical to the old `regs' command.
++
++* Profiling support
++
++A new command, "maint set profile on/off", has been added. This command can
++be used to enable or disable profiling while running GDB, to profile a
++session or a set of commands. In addition there is a new configure switch,
++"--enable-profiling", which will cause GDB to be compiled with profiling
++data, for more informative profiling results.
++
++* Default MI syntax changed to "mi2".
++
++The default MI (machine interface) syntax, enabled by the command line
++option "-i=mi", has been changed to "mi2". The previous MI syntax,
++"mi1", can be enabled by specifying the option "-i=mi1".
++
++Support for the original "mi0" syntax (included in GDB 5.0) has been
++removed.
++
++Fix for gdb/192: removed extraneous space when displaying frame level.
++Fix for gdb/672: update changelist is now output in mi list format.
++Fix for gdb/702: a -var-assign that updates the value now shows up
++ in a subsequent -var-update.
++
++* New native configurations.
++
++FreeBSD/amd64 x86_64-*-freebsd*
++
++* Multi-arched targets.
++
++HP/PA HPUX11 hppa*-*-hpux*
++Renesas M32R/D w/simulator m32r-*-elf*
++
++* OBSOLETE configurations and files
++
++Configurations that have been declared obsolete in this release have
++been commented out. Unless there is activity to revive these
++configurations, the next release of GDB will have their sources
++permanently REMOVED.
++
++Z8000 simulator z8k-zilog-none or z8ksim
++Matsushita MN10200 w/simulator mn10200-*-*
++H8/500 simulator h8500-hitachi-hms or h8500hms
++HP/PA running BSD hppa*-*-bsd*
++HP/PA running OSF/1 hppa*-*-osf*
++HP/PA Pro target hppa*-*-pro*
++PMAX (MIPS) running Mach 3.0 mips*-*-mach3*
++Sequent family i[3456]86-sequent-sysv4*
++ i[3456]86-sequent-sysv*
++ i[3456]86-sequent-bsd*
++Tsqware Sparclet sparclet-*-*
++Fujitsu SPARClite sparclite-fujitsu-none or sparclite
++
++* REMOVED configurations and files
++
++V850EA ISA
++Motorola Delta 88000 running Sys V m88k-motorola-sysv or delta88
++IBM AIX PS/2 i[3456]86-*-aix
++i386 running Mach 3.0 i[3456]86-*-mach3*
++i386 running Mach i[3456]86-*-mach*
++i386 running OSF/1 i[3456]86-*osf1mk*
++HP/Apollo 68k Family m68*-apollo*-sysv*,
++ m68*-apollo*-bsd*,
++ m68*-hp-bsd*, m68*-hp-hpux*
++Argonaut Risc Chip (ARC) arc-*-*
++Mitsubishi D30V d30v-*-*
++Fujitsu FR30 fr30-*-elf*
++OS/9000 i[34]86-*-os9k
++I960 with MON960 i960-*-coff
++
++* MIPS $fp behavior changed
++
++The convenience variable $fp, for the MIPS, now consistently returns
++the address of the current frame's base. Previously, depending on the
++context, $fp could refer to either $sp or the current frame's base
++address. See ``8.10 Registers'' in the manual ``Debugging with GDB:
++The GNU Source-Level Debugger''.
++
++*** Changes in GDB 5.3:
++
++* GNU/Linux shared library multi-threaded performance improved.
++
++When debugging a multi-threaded application on GNU/Linux, GDB now uses
++`/proc', in preference to `ptrace' for memory reads. This may result
++in an improvement in the start-up time of multi-threaded, shared
++library applications when run under GDB. One GDB user writes: ``loads
++shared libs like mad''.
++
++* ``gdbserver'' now supports multi-threaded applications on some targets
++
++Support for debugging multi-threaded applications which use
++the GNU/Linux LinuxThreads package has been added for
++arm*-*-linux*-gnu*, i[3456]86-*-linux*-gnu*, mips*-*-linux*-gnu*,
++powerpc*-*-linux*-gnu*, and sh*-*-linux*-gnu*.
++
++* GDB now supports C/C++ preprocessor macros.
++
++GDB now expands preprocessor macro invocations in C/C++ expressions,
++and provides various commands for showing macro definitions and how
++they expand.
++
++The new command `macro expand EXPRESSION' expands any macro
++invocations in expression, and shows the result.
++
++The new command `show macro MACRO-NAME' shows the definition of the
++macro named MACRO-NAME, and where it was defined.
++
++Most compilers don't include information about macros in the debugging
++information by default. In GCC 3.1, for example, you need to compile
++your program with the options `-gdwarf-2 -g3'. If the macro
++information is present in the executable, GDB will read it.
++
++* Multi-arched targets.
++
++DEC Alpha (partial) alpha*-*-*
++DEC VAX (partial) vax-*-*
++NEC V850 v850-*-*
++National Semiconductor NS32000 (partial) ns32k-*-*
++Motorola 68000 (partial) m68k-*-*
++Motorola MCORE mcore-*-*
++
++* New targets.
++
++Fujitsu FRV architecture added by Red Hat frv*-*-*
++
++
++* New native configurations
++
++Alpha NetBSD alpha*-*-netbsd*
++SH NetBSD sh*-*-netbsdelf*
++MIPS NetBSD mips*-*-netbsd*
++UltraSPARC NetBSD sparc64-*-netbsd*
++
++* OBSOLETE configurations and files
++
++Configurations that have been declared obsolete in this release have
++been commented out. Unless there is activity to revive these
++configurations, the next release of GDB will have their sources
++permanently REMOVED.
++
++Mitsubishi D30V d30v-*-*
++OS/9000 i[34]86-*-os9k
++IBM AIX PS/2 i[3456]86-*-aix
++Fujitsu FR30 fr30-*-elf*
++Motorola Delta 88000 running Sys V m88k-motorola-sysv or delta88
++Argonaut Risc Chip (ARC) arc-*-*
++i386 running Mach 3.0 i[3456]86-*-mach3*
++i386 running Mach i[3456]86-*-mach*
++i386 running OSF/1 i[3456]86-*osf1mk*
++HP/Apollo 68k Family m68*-apollo*-sysv*,
++ m68*-apollo*-bsd*,
++ m68*-hp-bsd*, m68*-hp-hpux*
++I960 with MON960 i960-*-coff
++
++* OBSOLETE languages
++
++CHILL, a Pascal like language used by telecommunications companies.
++
++* REMOVED configurations and files
++
++AMD 29k family via UDI a29k-amd-udi, udi29k
++A29K VxWorks a29k-*-vxworks
++AMD 29000 embedded, using EBMON a29k-none-none
++AMD 29000 embedded with COFF a29k-none-coff
++AMD 29000 embedded with a.out a29k-none-aout
++
++testsuite/gdb.hp/gdb.threads-hp/ directory
++
++* New command "set max-user-call-depth <nnn>"
++
++This command allows the user to limit the call depth of user-defined
++commands. The default is 1024.
++
++* Changes in FreeBSD/i386 native debugging.
++
++Support for the "generate-core-file" has been added.
++
++* New commands "dump", "append", and "restore".
++
++These commands allow data to be copied from target memory
++to a bfd-format or binary file (dump and append), and back
++from a file into memory (restore).
++
++* Improved "next/step" support on multi-processor Alpha Tru64.
++
++The previous single-step mechanism could cause unpredictable problems,
++including the random appearance of SIGSEGV or SIGTRAP signals. The use
++of a software single-step mechanism prevents this.
++
++*** Changes in GDB 5.2.1:
++
++* New targets.
++
++Atmel AVR avr*-*-*
++
++* Bug fixes
++
++gdb/182: gdb/323: gdb/237: On alpha, gdb was reporting:
++mdebugread.c:2443: gdb-internal-error: sect_index_data not initialized
++Fix, by Joel Brobecker imported from mainline.
++
++gdb/439: gdb/291: On some ELF object files, gdb was reporting:
++dwarf2read.c:1072: gdb-internal-error: sect_index_text not initialize
++Fix, by Fred Fish, imported from mainline.
++
++Dwarf2 .debug_frame & .eh_frame handler improved in many ways.
++Surprisingly enough, it works now.
++By Michal Ludvig, imported from mainline.
++
++i386 hardware watchpoint support:
++avoid misses on second run for some targets.
++By Pierre Muller, imported from mainline.
++
++*** Changes in GDB 5.2:
++
++* New command "set trust-readonly-sections on[off]".
++
++This command is a hint that tells gdb that read-only sections
++really are read-only (ie. that their contents will not change).
++In this mode, gdb will go to the object file rather than the
++target to read memory from read-only sections (such as ".text").
++This can be a significant performance improvement on some
++(notably embedded) targets.
++
++* New command "generate-core-file" (or "gcore").
++
++This new gdb command allows the user to drop a core file of the child
++process state at any time. So far it's been implemented only for
++GNU/Linux and Solaris, but should be relatively easily ported to other
++hosts. Argument is core file name (defaults to core.<pid>).
++
++* New command line option
++
++GDB now accepts --pid or -p followed by a process id.
++
++* Change in command line behavior -- corefiles vs. process ids.
++
++There is a subtle behavior in the way in which GDB handles
++command line arguments. The first non-flag argument is always
++a program to debug, but the second non-flag argument may either
++be a corefile or a process id. Previously, GDB would attempt to
++open the second argument as a corefile, and if that failed, would
++issue a superfluous error message and then attempt to attach it as
++a process. Now, if the second argument begins with a non-digit,
++it will be treated as a corefile. If it begins with a digit,
++GDB will attempt to attach it as a process, and if no such process
++is found, will then attempt to open it as a corefile.
++
++* Changes in ARM configurations.
++
++Multi-arch support is enabled for all ARM configurations. The ARM/NetBSD
++configuration is fully multi-arch.
++
++* New native configurations
++
++ARM NetBSD arm*-*-netbsd*
++x86 OpenBSD i[3456]86-*-openbsd*
++AMD x86-64 running GNU/Linux x86_64-*-linux-*
++Sparc64 running FreeBSD sparc64-*-freebsd*
++
++* New targets
++
++Sanyo XStormy16 xstormy16-elf
++
++* OBSOLETE configurations and files
++
++Configurations that have been declared obsolete in this release have
++been commented out. Unless there is activity to revive these
++configurations, the next release of GDB will have their sources
++permanently REMOVED.
++
++AMD 29k family via UDI a29k-amd-udi, udi29k
++A29K VxWorks a29k-*-vxworks
++AMD 29000 embedded, using EBMON a29k-none-none
++AMD 29000 embedded with COFF a29k-none-coff
++AMD 29000 embedded with a.out a29k-none-aout
++
++testsuite/gdb.hp/gdb.threads-hp/ directory
++
++* REMOVED configurations and files
++
++TI TMS320C80 tic80-*-*
++WDC 65816 w65-*-*
++PowerPC Solaris powerpcle-*-solaris*
++PowerPC Windows NT powerpcle-*-cygwin32
++PowerPC Netware powerpc-*-netware*
++Harris/CXUX m88k m88*-harris-cxux*
++Most ns32k hosts and targets ns32k-*-mach3* ns32k-umax-*
++ ns32k-utek-sysv* ns32k-utek-*
++SunOS 4.0.Xi on i386 i[3456]86-*-sunos*
++Ultracomputer (29K) running Sym1 a29k-nyu-sym1 a29k-*-kern*
++Sony NEWS (68K) running NEWSOS 3.x m68*-sony-sysv news
++ISI Optimum V (3.05) under 4.3bsd. m68*-isi-*
++Apple Macintosh (MPW) host and target N/A host, powerpc-*-macos*
++
++* Changes to command line processing
++
++The new `--args' feature can be used to specify command-line arguments
++for the inferior from gdb's command line.
++
++* Changes to key bindings
++
++There is a new `operate-and-get-next' function bound to `C-o'.
++
++*** Changes in GDB 5.1.1
++
++Fix compile problem on DJGPP.
++
++Fix a problem with floating-point registers on the i386 being
++corrupted.
++
++Fix to stop GDB crashing on .debug_str debug info.
++
++Numerous documentation fixes.
++
++Numerous testsuite fixes.
++
++*** Changes in GDB 5.1:
++
++* New native configurations
++
++Alpha FreeBSD alpha*-*-freebsd*
++x86 FreeBSD 3.x and 4.x i[3456]86*-freebsd[34]*
++MIPS GNU/Linux mips*-*-linux*
++MIPS SGI Irix 6.x mips*-sgi-irix6*
++ia64 AIX ia64-*-aix*
++s390 and s390x GNU/Linux {s390,s390x}-*-linux*
++
++* New targets
++
++Motorola 68HC11 and 68HC12 m68hc11-elf
++CRIS cris-axis
++UltraSparc running GNU/Linux sparc64-*-linux*
++
++* OBSOLETE configurations and files
++
++x86 FreeBSD before 2.2 i[3456]86*-freebsd{1,2.[01]}*,
++Harris/CXUX m88k m88*-harris-cxux*
++Most ns32k hosts and targets ns32k-*-mach3* ns32k-umax-*
++ ns32k-utek-sysv* ns32k-utek-*
++TI TMS320C80 tic80-*-*
++WDC 65816 w65-*-*
++Ultracomputer (29K) running Sym1 a29k-nyu-sym1 a29k-*-kern*
++PowerPC Solaris powerpcle-*-solaris*
++PowerPC Windows NT powerpcle-*-cygwin32
++PowerPC Netware powerpc-*-netware*
++SunOS 4.0.Xi on i386 i[3456]86-*-sunos*
++Sony NEWS (68K) running NEWSOS 3.x m68*-sony-sysv news
++ISI Optimum V (3.05) under 4.3bsd. m68*-isi-*
++Apple Macintosh (MPW) host N/A
++
++stuff.c (Program to stuff files into a specially prepared space in kdb)
++kdb-start.c (Main loop for the standalone kernel debugger)
++
++Configurations that have been declared obsolete in this release have
++been commented out. Unless there is activity to revive these
++configurations, the next release of GDB will have their sources
++permanently REMOVED.
++
++* REMOVED configurations and files
++
++Altos 3068 m68*-altos-*
++Convex c1-*-*, c2-*-*
++Pyramid pyramid-*-*
++ARM RISCix arm-*-* (as host)
++Tahoe tahoe-*-*
++ser-ocd.c *-*-*
++
++* GDB has been converted to ISO C.
++
++GDB's source code has been converted to ISO C. In particular, the
++sources are fully protoized, and rely on standard headers being
++present.
++
++* Other news:
++
++* "info symbol" works on platforms which use COFF, ECOFF, XCOFF, and NLM.
++
++* The MI enabled by default.
++
++The new machine oriented interface (MI) introduced in GDB 5.0 has been
++revised and enabled by default. Packages which use GDB as a debugging
++engine behind a UI or another front end are encouraged to switch to
++using the GDB/MI interface, instead of the old annotations interface
++which is now deprecated.
++
++* Support for debugging Pascal programs.
++
++GDB now includes support for debugging Pascal programs. The following
++main features are supported:
++
++ - Pascal-specific data types such as sets;
++
++ - automatic recognition of Pascal sources based on file-name
++ extension;
++
++ - Pascal-style display of data types, variables, and functions;
++
++ - a Pascal expression parser.
++
++However, some important features are not yet supported.
++
++ - Pascal string operations are not supported at all;
++
++ - there are some problems with boolean types;
++
++ - Pascal type hexadecimal constants are not supported
++ because they conflict with the internal variables format;
++
++ - support for Pascal objects and classes is not full yet;
++
++ - unlike Pascal, GDB is case-sensitive for symbol names.
++
++* Changes in completion.
++
++Commands such as `shell', `run' and `set args', which pass arguments
++to inferior programs, now complete on file names, similar to what
++users expect at the shell prompt.
++
++Commands which accept locations, such as `disassemble', `print',
++`breakpoint', `until', etc. now complete on filenames as well as
++program symbols. Thus, if you type "break foob TAB", and the source
++files linked into the programs include `foobar.c', that file name will
++be one of the candidates for completion. However, file names are not
++considered for completion after you typed a colon that delimits a file
++name from a name of a function in that file, as in "break foo.c:bar".
++
++`set demangle-style' completes on available demangling styles.
++
++* New platform-independent commands:
++
++It is now possible to define a post-hook for a command as well as a
++hook that runs before the command. For more details, see the
++documentation of `hookpost' in the GDB manual.
++
++* Changes in GNU/Linux native debugging.
++
++Support for debugging multi-threaded programs has been completely
++revised for all platforms except m68k and sparc. You can now debug as
++many threads as your system allows you to have.
++
++Attach/detach is supported for multi-threaded programs.
++
++Support for SSE registers was added for x86. This doesn't work for
++multi-threaded programs though.
++
++* Changes in MIPS configurations.
++
++Multi-arch support is enabled for all MIPS configurations.
++
++GDB can now be built as native debugger on SGI Irix 6.x systems for
++debugging n32 executables. (Debugging 64-bit executables is not yet
++supported.)
++
++* Unified support for hardware watchpoints in all x86 configurations.
++
++Most (if not all) native x86 configurations support hardware-assisted
++breakpoints and watchpoints in a unified manner. This support
++implements debug register sharing between watchpoints, which allows to
++put a virtually infinite number of watchpoints on the same address,
++and also supports watching regions up to 16 bytes with several debug
++registers.
++
++The new maintenance command `maintenance show-debug-regs' toggles
++debugging print-outs in functions that insert, remove, and test
++watchpoints and hardware breakpoints.
++
++* Changes in the DJGPP native configuration.
++
++New command ``info dos sysinfo'' displays assorted information about
++the CPU, OS, memory, and DPMI server.
++
++New commands ``info dos gdt'', ``info dos ldt'', and ``info dos idt''
++display information about segment descriptors stored in GDT, LDT, and
++IDT.
++
++New commands ``info dos pde'' and ``info dos pte'' display entries
++from Page Directory and Page Tables (for now works with CWSDPMI only).
++New command ``info dos address-pte'' displays the Page Table entry for
++a given linear address.
++
++GDB can now pass command lines longer than 126 characters to the
++program being debugged (requires an update to the libdbg.a library
++which is part of the DJGPP development kit).
++
++DWARF2 debug info is now supported.
++
++It is now possible to `step' and `next' through calls to `longjmp'.
++
++* Changes in documentation.
++
++All GDB documentation was converted to GFDL, the GNU Free
++Documentation License.
++
++Tracepoints-related commands are now fully documented in the GDB
++manual.
++
++TUI, the Text-mode User Interface, is now documented in the manual.
++
++Tracepoints-related commands are now fully documented in the GDB
++manual.
++
++The "GDB Internals" manual now has an index. It also includes
++documentation of `ui_out' functions, GDB coding standards, x86
++hardware watchpoints, and memory region attributes.
++
++* GDB's version number moved to ``version.in''
++
++The Makefile variable VERSION has been replaced by the file
++``version.in''. People creating GDB distributions should update the
++contents of this file.
++
++* gdba.el deleted
++
++GUD support is now a standard part of the EMACS distribution.
++
++*** Changes in GDB 5.0:
++
++* Improved support for debugging FP programs on x86 targets
++
++Unified and much-improved support for debugging floating-point
++programs on all x86 targets. In particular, ``info float'' now
++displays the FP registers in the same format on all x86 targets, with
++greater level of detail.
++
++* Improvements and bugfixes in hardware-assisted watchpoints
++
++It is now possible to watch array elements, struct members, and
++bitfields with hardware-assisted watchpoints. Data-read watchpoints
++on x86 targets no longer erroneously trigger when the address is
++written.
++
++* Improvements in the native DJGPP version of GDB
++
++The distribution now includes all the scripts and auxiliary files
++necessary to build the native DJGPP version on MS-DOS/MS-Windows
++machines ``out of the box''.
++
++The DJGPP version can now debug programs that use signals. It is
++possible to catch signals that happened in the debuggee, deliver
++signals to it, interrupt it with Ctrl-C, etc. (Previously, a signal
++would kill the program being debugged.) Programs that hook hardware
++interrupts (keyboard, timer, etc.) can also be debugged.
++
++It is now possible to debug DJGPP programs that redirect their
++standard handles or switch them to raw (as opposed to cooked) mode, or
++even close them. The command ``run < foo > bar'' works as expected,
++and ``info terminal'' reports useful information about the debuggee's
++terminal, including raw/cooked mode, redirection, etc.
++
++The DJGPP version now uses termios functions for console I/O, which
++enables debugging graphics programs. Interrupting GDB with Ctrl-C
++also works.
++
++DOS-style file names with drive letters are now fully supported by
++GDB.
++
++It is now possible to debug DJGPP programs that switch their working
++directory. It is also possible to rerun the debuggee any number of
++times without restarting GDB; thus, you can use the same setup,
++breakpoints, etc. for many debugging sessions.
++
++* New native configurations
++
++ARM GNU/Linux arm*-*-linux*
++PowerPC GNU/Linux powerpc-*-linux*
++
++* New targets
++
++Motorola MCore mcore-*-*
++x86 VxWorks i[3456]86-*-vxworks*
++PowerPC VxWorks powerpc-*-vxworks*
++TI TMS320C80 tic80-*-*
++
++* OBSOLETE configurations
++
++Altos 3068 m68*-altos-*
++Convex c1-*-*, c2-*-*
++Pyramid pyramid-*-*
++ARM RISCix arm-*-* (as host)
++Tahoe tahoe-*-*
++
++Configurations that have been declared obsolete will be commented out,
++but the code will be left in place. If there is no activity to revive
++these configurations before the next release of GDB, the sources will
++be permanently REMOVED.
++
++* Gould support removed
++
++Support for the Gould PowerNode and NP1 has been removed.
++
++* New features for SVR4
++
++On SVR4 native platforms (such as Solaris), if you attach to a process
++without first loading a symbol file, GDB will now attempt to locate and
++load symbols from the running process's executable file.
++
++* Many C++ enhancements
++
++C++ support has been greatly improved. Overload resolution now works properly
++in almost all cases. RTTI support is on the way.
++
++* Remote targets can connect to a sub-program
++
++A popen(3) style serial-device has been added. This device starts a
++sub-process (such as a stand-alone simulator) and then communicates
++with that. The sub-program to run is specified using the syntax
++``|<program> <args>'' vis:
++
++ (gdb) set remotedebug 1
++ (gdb) target extended-remote |mn10300-elf-sim program-args
++
++* MIPS 64 remote protocol
++
++A long standing bug in the mips64 remote protocol where by GDB
++expected certain 32 bit registers (ex SR) to be transfered as 32
++instead of 64 bits has been fixed.
++
++The command ``set remote-mips64-transfers-32bit-regs on'' has been
++added to provide backward compatibility with older versions of GDB.
++
++* ``set remotebinarydownload'' replaced by ``set remote X-packet''
++
++The command ``set remotebinarydownload'' command has been replaced by
++``set remote X-packet''. Other commands in ``set remote'' family
++include ``set remote P-packet''.
++
++* Breakpoint commands accept ranges.
++
++The breakpoint commands ``enable'', ``disable'', and ``delete'' now
++accept a range of breakpoints, e.g. ``5-7''. The tracepoint command
++``tracepoint passcount'' also accepts a range of tracepoints.
++
++* ``apropos'' command added.
++
++The ``apropos'' command searches through command names and
++documentation strings, printing out matches, making it much easier to
++try to find a command that does what you are looking for.
++
++* New MI interface
++
++A new machine oriented interface (MI) has been added to GDB. This
++interface is designed for debug environments running GDB as a separate
++process. This is part of the long term libGDB project. See the
++"GDB/MI" chapter of the GDB manual for further information. It can be
++enabled by configuring with:
++
++ .../configure --enable-gdbmi
++
++*** Changes in GDB-4.18:
++
++* New native configurations
++
++HP-UX 10.20 hppa*-*-hpux10.20
++HP-UX 11.x hppa*-*-hpux11.0*
++M68K GNU/Linux m68*-*-linux*
++
++* New targets
++
++Fujitsu FR30 fr30-*-elf*
++Intel StrongARM strongarm-*-*
++Mitsubishi D30V d30v-*-*
++
++* OBSOLETE configurations
++
++Gould PowerNode, NP1 np1-*-*, pn-*-*
++
++Configurations that have been declared obsolete will be commented out,
++but the code will be left in place. If there is no activity to revive
++these configurations before the next release of GDB, the sources will
++be permanently REMOVED.
++
++* ANSI/ISO C
++
++As a compatibility experiment, GDB's source files buildsym.h and
++buildsym.c have been converted to pure standard C, no longer
++containing any K&R compatibility code. We believe that all systems in
++use today either come with a standard C compiler, or have a GCC port
++available. If this is not true, please report the affected
++configuration to bug-gdb@gnu.org immediately. See the README file for
++information about getting a standard C compiler if you don't have one
++already.
++
++* Readline 2.2
++
++GDB now uses readline 2.2.
++
++* set extension-language
++
++You can now control the mapping between filename extensions and source
++languages by using the `set extension-language' command. For instance,
++you can ask GDB to treat .c files as C++ by saying
++ set extension-language .c c++
++The command `info extensions' lists all of the recognized extensions
++and their associated languages.
++
++* Setting processor type for PowerPC and RS/6000
++
++When GDB is configured for a powerpc*-*-* or an rs6000*-*-* target,
++you can use the `set processor' command to specify what variant of the
++PowerPC family you are debugging. The command
++
++ set processor NAME
++
++sets the PowerPC/RS6000 variant to NAME. GDB knows about the
++following PowerPC and RS6000 variants:
++
++ ppc-uisa PowerPC UISA - a PPC processor as viewed by user-level code
++ rs6000 IBM RS6000 ("POWER") architecture, user-level view
++ 403 IBM PowerPC 403
++ 403GC IBM PowerPC 403GC
++ 505 Motorola PowerPC 505
++ 860 Motorola PowerPC 860 or 850
++ 601 Motorola PowerPC 601
++ 602 Motorola PowerPC 602
++ 603 Motorola/IBM PowerPC 603 or 603e
++ 604 Motorola PowerPC 604 or 604e
++ 750 Motorola/IBM PowerPC 750 or 750
++
++At the moment, this command just tells GDB what to name the
++special-purpose processor registers. Since almost all the affected
++registers are inaccessible to user-level programs, this command is
++only useful for remote debugging in its present form.
++
++* HP-UX support
++
++Thanks to a major code donation from Hewlett-Packard, GDB now has much
++more extensive support for HP-UX. Added features include shared
++library support, kernel threads and hardware watchpoints for 11.00,
++support for HP's ANSI C and C++ compilers, and a compatibility mode
++for xdb and dbx commands.
++
++* Catchpoints
++
++HP's donation includes the new concept of catchpoints, which is a
++generalization of the old catch command. On HP-UX, it is now possible
++to catch exec, fork, and vfork, as well as library loading.
++
++This means that the existing catch command has changed; its first
++argument now specifies the type of catch to be set up. See the
++output of "help catch" for a list of catchpoint types.
++
++* Debugging across forks
++
++On HP-UX, you can choose which process to debug when a fork() happens
++in the inferior.
++
++* TUI
++
++HP has donated a curses-based terminal user interface (TUI). To get
++it, build with --enable-tui. Although this can be enabled for any
++configuration, at present it only works for native HP debugging.
++
++* GDB remote protocol additions
++
++A new protocol packet 'X' that writes binary data is now available.
++Default behavior is to try 'X', then drop back to 'M' if the stub
++fails to respond. The settable variable `remotebinarydownload'
++allows explicit control over the use of 'X'.
++
++For 64-bit targets, the memory packets ('M' and 'm') can now contain a
++full 64-bit address. The command
++
++ set remoteaddresssize 32
++
++can be used to revert to the old behaviour. For existing remote stubs
++the change should not be noticed, as the additional address information
++will be discarded.
++
++In order to assist in debugging stubs, you may use the maintenance
++command `packet' to send any text string to the stub. For instance,
++
++ maint packet heythere
++
++sends the packet "$heythere#<checksum>". Note that it is very easy to
++disrupt a debugging session by sending the wrong packet at the wrong
++time.
++
++The compare-sections command allows you to compare section data on the
++target to what is in the executable file without uploading or
++downloading, by comparing CRC checksums.
++
++* Tracing can collect general expressions
++
++You may now collect general expressions at tracepoints. This requires
++further additions to the target-side stub; see tracepoint.c and
++doc/agentexpr.texi for further details.
++
++* mask-address variable for Mips
++
++For Mips targets, you may control the zeroing of the upper 32 bits of
++a 64-bit address by entering `set mask-address on'. This is mainly
++of interest to users of embedded R4xxx and R5xxx processors.
++
++* Higher serial baud rates
++
++GDB's serial code now allows you to specify baud rates 57600, 115200,
++230400, and 460800 baud. (Note that your host system may not be able
++to achieve all of these rates.)
++
++* i960 simulator
++
++The i960 configuration now includes an initial implementation of a
++builtin simulator, contributed by Jim Wilson.
++
++
++*** Changes in GDB-4.17:
++
++* New native configurations
++
++Alpha GNU/Linux alpha*-*-linux*
++Unixware 2.x i[3456]86-unixware2*
++Irix 6.x mips*-sgi-irix6*
++PowerPC GNU/Linux powerpc-*-linux*
++PowerPC Solaris powerpcle-*-solaris*
++Sparc GNU/Linux sparc-*-linux*
++Motorola sysV68 R3V7.1 m68k-motorola-sysv
++
++* New targets
++
++Argonaut Risc Chip (ARC) arc-*-*
++Hitachi H8/300S h8300*-*-*
++Matsushita MN10200 w/simulator mn10200-*-*
++Matsushita MN10300 w/simulator mn10300-*-*
++MIPS NEC VR4100 mips64*vr4100*{,el}-*-elf*
++MIPS NEC VR5000 mips64*vr5000*{,el}-*-elf*
++MIPS Toshiba TX39 mips64*tx39*{,el}-*-elf*
++Mitsubishi D10V w/simulator d10v-*-*
++Mitsubishi M32R/D w/simulator m32r-*-elf*
++Tsqware Sparclet sparclet-*-*
++NEC V850 w/simulator v850-*-*
++
++* New debugging protocols
++
++ARM with RDI protocol arm*-*-*
++M68K with dBUG monitor m68*-*-{aout,coff,elf}
++DDB and LSI variants of PMON protocol mips*-*-*
++PowerPC with DINK32 monitor powerpc{,le}-*-eabi
++PowerPC with SDS protocol powerpc{,le}-*-eabi
++Macraigor OCD (Wiggler) devices powerpc{,le}-*-eabi
++
++* DWARF 2
++
++All configurations can now understand and use the DWARF 2 debugging
++format. The choice is automatic, if the symbol file contains DWARF 2
++information.
++
++* Java frontend
++
++GDB now includes basic Java language support. This support is
++only useful with Java compilers that produce native machine code.
++
++* solib-absolute-prefix and solib-search-path
++
++For SunOS and SVR4 shared libraries, you may now set the prefix for
++loading absolute shared library symbol files, and the search path for
++locating non-absolute shared library symbol files.
++
++* Live range splitting
++
++GDB can now effectively debug code for which GCC has performed live
++range splitting as part of its optimization. See gdb/doc/LRS for
++more details on the expected format of the stabs information.
++
++* Hurd support
++
++GDB's support for the GNU Hurd, including thread debugging, has been
++updated to work with current versions of the Hurd.
++
++* ARM Thumb support
++
++GDB's ARM target configuration now handles the ARM7T (Thumb) 16-bit
++instruction set. ARM GDB automatically detects when Thumb
++instructions are in use, and adjusts disassembly and backtracing
++accordingly.
++
++* MIPS16 support
++
++GDB's MIPS target configurations now handle the MIP16 16-bit
++instruction set.
++
++* Overlay support
++
++GDB now includes support for overlays; if an executable has been
++linked such that multiple sections are based at the same address, GDB
++will decide which section to use for symbolic info. You can choose to
++control the decision manually, using overlay commands, or implement
++additional target-side support and use "overlay load-target" to bring
++in the overlay mapping. Do "help overlay" for more detail.
++
++* info symbol
++
++The command "info symbol <address>" displays information about
++the symbol at the specified address.
++
++* Trace support
++
++The standard remote protocol now includes an extension that allows
++asynchronous collection and display of trace data. This requires
++extensive support in the target-side debugging stub. Tracing mode
++includes a new interaction mode in GDB and new commands: see the
++file tracepoint.c for more details.
++
++* MIPS simulator
++
++Configurations for embedded MIPS now include a simulator contributed
++by Cygnus Solutions. The simulator supports the instruction sets
++of most MIPS variants.
++
++* Sparc simulator
++
++Sparc configurations may now include the ERC32 simulator contributed
++by the European Space Agency. The simulator is not built into
++Sparc targets by default; configure with --enable-sim to include it.
++
++* set architecture
++
++For target configurations that may include multiple variants of a
++basic architecture (such as MIPS and SH), you may now set the
++architecture explicitly. "set arch" sets, "info arch" lists
++the possible architectures.
++
++*** Changes in GDB-4.16:
++
++* New native configurations
++
++Windows 95, x86 Windows NT i[345]86-*-cygwin32
++M68K NetBSD m68k-*-netbsd*
++PowerPC AIX 4.x powerpc-*-aix*
++PowerPC MacOS powerpc-*-macos*
++PowerPC Windows NT powerpcle-*-cygwin32
++RS/6000 AIX 4.x rs6000-*-aix4*
++
++* New targets
++
++ARM with RDP protocol arm-*-*
++I960 with MON960 i960-*-coff
++MIPS VxWorks mips*-*-vxworks*
++MIPS VR4300 with PMON mips64*vr4300{,el}-*-elf*
++PowerPC with PPCBUG monitor powerpc{,le}-*-eabi*
++Hitachi SH3 sh-*-*
++Matra Sparclet sparclet-*-*
++
++* PowerPC simulator
++
++The powerpc-eabi configuration now includes the PSIM simulator,
++contributed by Andrew Cagney, with assistance from Mike Meissner.
++PSIM is a very elaborate model of the PowerPC, including not only
++basic instruction set execution, but also details of execution unit
++performance and I/O hardware. See sim/ppc/README for more details.
++
++* Solaris 2.5
++
++GDB now works with Solaris 2.5.
++
++* Windows 95/NT native
++
++GDB will now work as a native debugger on Windows 95 and Windows NT.
++To build it from source, you must use the "gnu-win32" environment,
++which uses a DLL to emulate enough of Unix to run the GNU tools.
++Further information, binaries, and sources are available at
++ftp.cygnus.com, under pub/gnu-win32.
++
++* dont-repeat command
++
++If a user-defined command includes the command `dont-repeat', then the
++command will not be repeated if the user just types return. This is
++useful if the command is time-consuming to run, so that accidental
++extra keystrokes don't run the same command many times.
++
++* Send break instead of ^C
++
++The standard remote protocol now includes an option to send a break
++rather than a ^C to the target in order to interrupt it. By default,
++GDB will send ^C; to send a break, set the variable `remotebreak' to 1.
++
++* Remote protocol timeout
++
++The standard remote protocol includes a new variable `remotetimeout'
++that allows you to set the number of seconds before GDB gives up trying
++to read from the target. The default value is 2.
++
++* Automatic tracking of dynamic object loading (HPUX and Solaris only)
++
++By default GDB will automatically keep track of objects as they are
++loaded and unloaded by the dynamic linker. By using the command `set
++stop-on-solib-events 1' you can arrange for GDB to stop the inferior
++when shared library events occur, thus allowing you to set breakpoints
++in shared libraries which are explicitly loaded by the inferior.
++
++Note this feature does not work on hpux8. On hpux9 you must link
++/usr/lib/end.o into your program. This feature should work
++automatically on hpux10.
++
++* Irix 5.x hardware watchpoint support
++
++Irix 5 configurations now support the use of hardware watchpoints.
++
++* Mips protocol "SYN garbage limit"
++
++When debugging a Mips target using the `target mips' protocol, you
++may set the number of characters that GDB will ignore by setting
++the `syn-garbage-limit'. A value of -1 means that GDB will ignore
++every character. The default value is 1050.
++
++* Recording and replaying remote debug sessions
++
++If you set `remotelogfile' to the name of a file, gdb will write to it
++a recording of a remote debug session. This recording may then be
++replayed back to gdb using "gdbreplay". See gdbserver/README for
++details. This is useful when you have a problem with GDB while doing
++remote debugging; you can make a recording of the session and send it
++to someone else, who can then recreate the problem.
++
++* Speedups for remote debugging
++
++GDB includes speedups for downloading and stepping MIPS systems using
++the IDT monitor, fast downloads to the Hitachi SH E7000 emulator,
++and more efficient S-record downloading.
++
++* Memory use reductions and statistics collection
++
++GDB now uses less memory and reports statistics about memory usage.
++Try the `maint print statistics' command, for example.
++
++*** Changes in GDB-4.15:
++
++* Psymtabs for XCOFF
++
++The symbol reader for AIX GDB now uses partial symbol tables. This
++can greatly improve startup time, especially for large executables.
++
++* Remote targets use caching
++
++Remote targets now use a data cache to speed up communication with the
++remote side. The data cache could lead to incorrect results because
++it doesn't know about volatile variables, thus making it impossible to
++debug targets which use memory mapped I/O devices. `set remotecache
++off' turns the the data cache off.
++
++* Remote targets may have threads
++
++The standard remote protocol now includes support for multiple threads
++in the target system, using new protocol commands 'H' and 'T'. See
++gdb/remote.c for details.
++
++* NetROM support
++
++If GDB is configured with `--enable-netrom', then it will include
++support for the NetROM ROM emulator from XLNT Designs. The NetROM
++acts as though it is a bank of ROM on the target board, but you can
++write into it over the network. GDB's support consists only of
++support for fast loading into the emulated ROM; to debug, you must use
++another protocol, such as standard remote protocol. The usual
++sequence is something like
++
++ target nrom <netrom-hostname>
++ load <prog>
++ target remote <netrom-hostname>:1235
++
++* Macintosh host
++
++GDB now includes support for the Apple Macintosh, as a host only. It
++may be run as either an MPW tool or as a standalone application, and
++it can debug through the serial port. All the usual GDB commands are
++available, but to the target command, you must supply "serial" as the
++device type instead of "/dev/ttyXX". See mpw-README in the main
++directory for more information on how to build. The MPW configuration
++scripts */mpw-config.in support only a few targets, and only the
++mips-idt-ecoff target has been tested.
++
++* Autoconf
++
++GDB configuration now uses autoconf. This is not user-visible,
++but does simplify configuration and building.
++
++* hpux10
++
++GDB now supports hpux10.
++
++*** Changes in GDB-4.14:
++
++* New native configurations
++
++x86 FreeBSD i[345]86-*-freebsd
++x86 NetBSD i[345]86-*-netbsd
++NS32k NetBSD ns32k-*-netbsd
++Sparc NetBSD sparc-*-netbsd
++
++* New targets
++
++A29K VxWorks a29k-*-vxworks
++HP PA PRO embedded (WinBond W89K & Oki OP50N) hppa*-*-pro*
++CPU32 EST-300 emulator m68*-*-est*
++PowerPC ELF powerpc-*-elf
++WDC 65816 w65-*-*
++
++* Alpha OSF/1 support for procfs
++
++GDB now supports procfs under OSF/1-2.x and higher, which makes it
++possible to attach to running processes. As the mounting of the /proc
++filesystem is optional on the Alpha, GDB automatically determines
++the availability of /proc during startup. This can lead to problems
++if /proc is unmounted after GDB has been started.
++
++* Arguments to user-defined commands
++
++User commands may accept up to 10 arguments separated by whitespace.
++Arguments are accessed within the user command via $arg0..$arg9. A
++trivial example:
++define adder
++ print $arg0 + $arg1 + $arg2
++
++To execute the command use:
++adder 1 2 3
++
++Defines the command "adder" which prints the sum of its three arguments.
++Note the arguments are text substitutions, so they may reference variables,
++use complex expressions, or even perform inferior function calls.
++
++* New `if' and `while' commands
++
++This makes it possible to write more sophisticated user-defined
++commands. Both commands take a single argument, which is the
++expression to evaluate, and must be followed by the commands to
++execute, one per line, if the expression is nonzero, the list being
++terminated by the word `end'. The `if' command list may include an
++`else' word, which causes the following commands to be executed only
++if the expression is zero.
++
++* Fortran source language mode
++
++GDB now includes partial support for Fortran 77. It will recognize
++Fortran programs and can evaluate a subset of Fortran expressions, but
++variables and functions may not be handled correctly. GDB will work
++with G77, but does not yet know much about symbols emitted by other
++Fortran compilers.
++
++* Better HPUX support
++
++Most debugging facilities now work on dynamic executables for HPPAs
++running hpux9 or later. You can attach to running dynamically linked
++processes, but by default the dynamic libraries will be read-only, so
++for instance you won't be able to put breakpoints in them. To change
++that behavior do the following before running the program:
++
++ adb -w a.out
++ __dld_flags?W 0x5
++ control-d
++
++This will cause the libraries to be mapped private and read-write.
++To revert to the normal behavior, do this:
++
++ adb -w a.out
++ __dld_flags?W 0x4
++ control-d
++
++You cannot set breakpoints or examine data in the library until after
++the library is loaded if the function/data symbols do not have
++external linkage.
++
++GDB can now also read debug symbols produced by the HP C compiler on
++HPPAs (sorry, no C++, Fortran or 68k support).
++
++* Target byte order now dynamically selectable
++
++You can choose which byte order to use with a target system, via the
++commands "set endian big" and "set endian little", and you can see the
++current setting by using "show endian". You can also give the command
++"set endian auto", in which case GDB will use the byte order
++associated with the executable. Currently, only embedded MIPS
++configurations support dynamic selection of target byte order.
++
++* New DOS host serial code
++
++This version uses DPMI interrupts to handle buffered I/O, so you
++no longer need to run asynctsr when debugging boards connected to
++a PC's serial port.
++
++*** Changes in GDB-4.13:
++
++* New "complete" command
++
++This lists all the possible completions for the rest of the line, if it
++were to be given as a command itself. This is intended for use by emacs.
++
++* Trailing space optional in prompt
++
++"set prompt" no longer adds a space for you after the prompt you set. This
++allows you to set a prompt which ends in a space or one that does not.
++
++* Breakpoint hit counts
++
++"info break" now displays a count of the number of times the breakpoint
++has been hit. This is especially useful in conjunction with "ignore"; you
++can ignore a large number of breakpoint hits, look at the breakpoint info
++to see how many times the breakpoint was hit, then run again, ignoring one
++less than that number, and this will get you quickly to the last hit of
++that breakpoint.
++
++* Ability to stop printing at NULL character
++
++"set print null-stop" will cause GDB to stop printing the characters of
++an array when the first NULL is encountered. This is useful when large
++arrays actually contain only short strings.
++
++* Shared library breakpoints
++
++In SunOS 4.x, SVR4, and Alpha OSF/1 configurations, you can now set
++breakpoints in shared libraries before the executable is run.
++
++* Hardware watchpoints
++
++There is a new hardware breakpoint for the watch command for sparclite
++targets. See gdb/sparclite/hw_breakpoint.note.
++
++Hardware watchpoints are also now supported under GNU/Linux.
++
++* Annotations
++
++Annotations have been added. These are for use with graphical interfaces,
++and are still experimental. Currently only gdba.el uses these.
++
++* Improved Irix 5 support
++
++GDB now works properly with Irix 5.2.
++
++* Improved HPPA support
++
++GDB now works properly with the latest GCC and GAS.
++
++* New native configurations
++
++Sequent PTX4 i[34]86-sequent-ptx4
++HPPA running OSF/1 hppa*-*-osf*
++Atari TT running SVR4 m68*-*-sysv4*
++RS/6000 LynxOS rs6000-*-lynxos*
++
++* New targets
++
++OS/9000 i[34]86-*-os9k
++MIPS R4000 mips64*{,el}-*-{ecoff,elf}
++Sparc64 sparc64-*-*
++
++* Hitachi SH7000 and E7000-PC ICE support
++
++There is now support for communicating with the Hitachi E7000-PC ICE.
++This is available automatically when GDB is configured for the SH.
++
++* Fixes
++
++As usual, a variety of small fixes and improvements, both generic
++and configuration-specific. See the ChangeLog for more detail.
++
++*** Changes in GDB-4.12:
++
++* Irix 5 is now supported
++
++* HPPA support
++
++GDB-4.12 on the HPPA has a number of changes which make it unable
++to debug the output from the currently released versions of GCC and
++GAS (GCC 2.5.8 and GAS-2.2 or PAGAS-1.36). Until the next major release
++of GCC and GAS, versions of these tools designed to work with GDB-4.12
++can be retrieved via anonymous ftp from jaguar.cs.utah.edu:/dist.
++
++
++*** Changes in GDB-4.11:
++
++* User visible changes:
++
++* Remote Debugging
++
++The "set remotedebug" option is now consistent between the mips remote
++target, remote targets using the gdb-specific protocol, UDI (AMD's
++debug protocol for the 29k) and the 88k bug monitor. It is now an
++integer specifying a debug level (normally 0 or 1, but 2 means more
++debugging info for the mips target).
++
++* DEC Alpha native support
++
++GDB now works on the DEC Alpha. GCC 2.4.5 does not produce usable
++debug info, but GDB works fairly well with the DEC compiler and should
++work with a future GCC release. See the README file for a few
++Alpha-specific notes.
++
++* Preliminary thread implementation
++
++GDB now has preliminary thread support for both SGI/Irix and LynxOS.
++
++* LynxOS native and target support for 386
++
++This release has been hosted on LynxOS 2.2, and also can be configured
++to remotely debug programs running under LynxOS (see gdb/gdbserver/README
++for details).
++
++* Improvements in C++ mangling/demangling.
++
++This release has much better g++ debugging, specifically in name
++mangling/demangling, virtual function calls, print virtual table,
++call methods, ...etc.
++
++*** Changes in GDB-4.10:
++
++ * User visible changes:
++
++Remote debugging using the GDB-specific (`target remote') protocol now
++supports the `load' command. This is only useful if you have some
++other way of getting the stub to the target system, and you can put it
++somewhere in memory where it won't get clobbered by the download.
++
++Filename completion now works.
++
++When run under emacs mode, the "info line" command now causes the
++arrow to point to the line specified. Also, "info line" prints
++addresses in symbolic form (as well as hex).
++
++All vxworks based targets now support a user settable option, called
++vxworks-timeout. This option represents the number of seconds gdb
++should wait for responses to rpc's. You might want to use this if
++your vxworks target is, perhaps, a slow software simulator or happens
++to be on the far side of a thin network line.
++
++ * DEC alpha support
++
++This release contains support for using a DEC alpha as a GDB host for
++cross debugging. Native alpha debugging is not supported yet.
++
++
++*** Changes in GDB-4.9:
++
++ * Testsuite
++
++This is the first GDB release which is accompanied by a matching testsuite.
++The testsuite requires installation of dejagnu, which should be available
++via ftp from most sites that carry GNU software.
++
++ * C++ demangling
++
++'Cfront' style demangling has had its name changed to 'ARM' style, to
++emphasize that it was written from the specifications in the C++ Annotated
++Reference Manual, not necessarily to be compatible with AT&T cfront. Despite
++disclaimers, it still generated too much confusion with users attempting to
++use gdb with AT&T cfront.
++
++ * Simulators
++
++GDB now uses a standard remote interface to a simulator library.
++So far, the library contains simulators for the Zilog Z8001/2, the
++Hitachi H8/300, H8/500 and Super-H.
++
++ * New targets supported
++
++H8/300 simulator h8300-hitachi-hms or h8300hms
++H8/500 simulator h8500-hitachi-hms or h8500hms
++SH simulator sh-hitachi-hms or sh
++Z8000 simulator z8k-zilog-none or z8ksim
++IDT MIPS board over serial line mips-idt-ecoff
++
++Cross-debugging to GO32 targets is supported. It requires a custom
++version of the i386-stub.c module which is integrated with the
++GO32 memory extender.
++
++ * New remote protocols
++
++MIPS remote debugging protocol.
++
++ * New source languages supported
++
++This version includes preliminary support for Chill, a Pascal like language
++used by telecommunications companies. Chill support is also being integrated
++into the GNU compiler, but we don't know when it will be publically available.
++
++
++*** Changes in GDB-4.8:
++
++ * HP Precision Architecture supported
++
++GDB now supports HP PA-RISC machines running HPUX. A preliminary
++version of this support was available as a set of patches from the
++University of Utah. GDB does not support debugging of programs
++compiled with the HP compiler, because HP will not document their file
++format. Instead, you must use GCC (version 2.3.2 or later) and PA-GAS
++(as available from jaguar.cs.utah.edu:/dist/pa-gas.u4.tar.Z).
++
++Many problems in the preliminary version have been fixed.
++
++ * Faster and better demangling
++
++We have improved template demangling and fixed numerous bugs in the GNU style
++demangler. It can now handle type modifiers such as `static' or `const'. Wide
++character types (wchar_t) are now supported. Demangling of each symbol is now
++only done once, and is cached when the symbol table for a file is read in.
++This results in a small increase in memory usage for C programs, a moderate
++increase in memory usage for C++ programs, and a fantastic speedup in
++symbol lookups.
++
++`Cfront' style demangling still doesn't work with AT&T cfront. It was written
++from the specifications in the Annotated Reference Manual, which AT&T's
++compiler does not actually implement.
++
++ * G++ multiple inheritance compiler problem
++
++In the 2.3.2 release of gcc/g++, how the compiler resolves multiple
++inheritance lattices was reworked to properly discover ambiguities. We
++recently found an example which causes this new algorithm to fail in a
++very subtle way, producing bad debug information for those classes.
++The file 'gcc.patch' (in this directory) can be applied to gcc to
++circumvent the problem. A future GCC release will contain a complete
++fix.
++
++The previous G++ debug info problem (mentioned below for the gdb-4.7
++release) is fixed in gcc version 2.3.2.
++
++ * Improved configure script
++
++The `configure' script will now attempt to guess your system type if
++you don't supply a host system type. The old scheme of supplying a
++host system triplet is preferable over using this. All the magic is
++done in the new `config.guess' script. Examine it for details.
++
++We have also brought our configure script much more in line with the FSF's
++version. It now supports the --with-xxx options. In particular,
++`--with-minimal-bfd' can be used to make the GDB binary image smaller.
++The resulting GDB will not be able to read arbitrary object file formats --
++only the format ``expected'' to be used on the configured target system.
++We hope to make this the default in a future release.
++
++ * Documentation improvements
++
++There's new internal documentation on how to modify GDB, and how to
++produce clean changes to the code. We implore people to read it
++before submitting changes.
++
++The GDB manual uses new, sexy Texinfo conditionals, rather than arcane
++M4 macros. The new texinfo.tex is provided in this release. Pre-built
++`info' files are also provided. To build `info' files from scratch,
++you will need the latest `makeinfo' release, which will be available in
++a future texinfo-X.Y release.
++
++*NOTE* The new texinfo.tex can cause old versions of TeX to hang.
++We're not sure exactly which versions have this problem, but it has
++been seen in 3.0. We highly recommend upgrading to TeX version 3.141
++or better. If that isn't possible, there is a patch in
++`texinfo/tex3patch' that will modify `texinfo/texinfo.tex' to work
++around this problem.
++
++ * New features
++
++GDB now supports array constants that can be used in expressions typed in by
++the user. The syntax is `{element, element, ...}'. Ie: you can now type
++`print {1, 2, 3}', and it will build up an array in memory malloc'd in
++the target program.
++
++The new directory `gdb/sparclite' contains a program that demonstrates
++how the sparc-stub.c remote stub runs on a Fujitsu SPARClite processor.
++
++ * New native hosts supported
++
++HP/PA-RISC under HPUX using GNU tools hppa1.1-hp-hpux
++386 CPUs running SCO Unix 3.2v4 i386-unknown-sco3.2v4
++
++ * New targets supported
++
++AMD 29k family via UDI a29k-amd-udi or udi29k
++
++ * New file formats supported
++
++BFD now supports reading HP/PA-RISC executables (SOM file format?),
++HPUX core files, and SCO 3.2v2 core files.
++
++ * Major bug fixes
++
++Attaching to processes now works again; thanks for the many bug reports.
++
++We have also stomped on a bunch of core dumps caused by
++printf_filtered("%s") problems.
++
++We eliminated a copyright problem on the rpc and ptrace header files
++for VxWorks, which was discovered at the last minute during the 4.7
++release. You should now be able to build a VxWorks GDB.
++
++You can now interrupt gdb while an attached process is running. This
++will cause the attached process to stop, and give control back to GDB.
++
++We fixed problems caused by using too many file descriptors
++for reading symbols from object files and libraries. This was
++especially a problem for programs that used many (~100) shared
++libraries.
++
++The `step' command now only enters a subroutine if there is line number
++information for the subroutine. Otherwise it acts like the `next'
++command. Previously, `step' would enter subroutines if there was
++any debugging information about the routine. This avoids problems
++when using `cc -g1' on MIPS machines.
++
++ * Internal improvements
++
++GDB's internal interfaces have been improved to make it easier to support
++debugging of multiple languages in the future.
++
++GDB now uses a common structure for symbol information internally.
++Minimal symbols (derived from linkage symbols in object files), partial
++symbols (from a quick scan of debug information), and full symbols
++contain a common subset of information, making it easier to write
++shared code that handles any of them.
++
++ * New command line options
++
++We now accept --silent as an alias for --quiet.
++
++ * Mmalloc licensing
++
++The memory-mapped-malloc library is now licensed under the GNU Library
++General Public License.
++
++*** Changes in GDB-4.7:
++
++ * Host/native/target split
++
++GDB has had some major internal surgery to untangle the support for
++hosts and remote targets. Now, when you configure GDB for a remote
++target, it will no longer load in all of the support for debugging
++local programs on the host. When fully completed and tested, this will
++ensure that arbitrary host/target combinations are possible.
++
++The primary conceptual shift is to separate the non-portable code in
++GDB into three categories. Host specific code is required any time GDB
++is compiled on that host, regardless of the target. Target specific
++code relates to the peculiarities of the target, but can be compiled on
++any host. Native specific code is everything else: it can only be
++built when the host and target are the same system. Child process
++handling and core file support are two common `native' examples.
++
++GDB's use of /proc for controlling Unix child processes is now cleaner.
++It has been split out into a single module under the `target_ops' vector,
++plus two native-dependent functions for each system that uses /proc.
++
++ * New hosts supported
++
++HP/Apollo 68k (under the BSD domain) m68k-apollo-bsd or apollo68bsd
++386 CPUs running various BSD ports i386-unknown-bsd or 386bsd
++386 CPUs running SCO Unix i386-unknown-scosysv322 or i386sco
++
++ * New targets supported
++
++Fujitsu SPARClite sparclite-fujitsu-none or sparclite
++68030 and CPU32 m68030-*-*, m68332-*-*
++
++ * New native hosts supported
++
++386 CPUs running various BSD ports i386-unknown-bsd or 386bsd
++ (386bsd is not well tested yet)
++386 CPUs running SCO Unix i386-unknown-scosysv322 or sco
++
++ * New file formats supported
++
++BFD now supports COFF files for the Zilog Z8000 microprocessor. It
++supports reading of `a.out.adobe' object files, which are an a.out
++format extended with minimal information about multiple sections.
++
++ * New commands
++
++`show copying' is the same as the old `info copying'.
++`show warranty' is the same as `info warrantee'.
++These were renamed for consistency. The old commands continue to work.
++
++`info handle' is a new alias for `info signals'.
++
++You can now define pre-command hooks, which attach arbitrary command
++scripts to any command. The commands in the hook will be executed
++prior to the user's command. You can also create a hook which will be
++executed whenever the program stops. See gdb.texinfo.
++
++ * C++ improvements
++
++We now deal with Cfront style name mangling, and can even extract type
++info from mangled symbols. GDB can automatically figure out which
++symbol mangling style your C++ compiler uses.
++
++Calling of methods and virtual functions has been improved as well.
++
++ * Major bug fixes
++
++The crash that occured when debugging Sun Ansi-C compiled binaries is
++fixed. This was due to mishandling of the extra N_SO stabs output
++by the compiler.
++
++We also finally got Ultrix 4.2 running in house, and fixed core file
++support, with help from a dozen people on the net.
++
++John M. Farrell discovered that the reason that single-stepping was so
++slow on all of the Mips based platforms (primarily SGI and DEC) was
++that we were trying to demangle and lookup a symbol used for internal
++purposes on every instruction that was being stepped through. Changing
++the name of that symbol so that it couldn't be mistaken for a C++
++mangled symbol sped things up a great deal.
++
++Rich Pixley sped up symbol lookups in general by getting much smarter
++about when C++ symbol mangling is necessary. This should make symbol
++completion (TAB on the command line) much faster. It's not as fast as
++we'd like, but it's significantly faster than gdb-4.6.
++
++ * AMD 29k support
++
++A new user controllable variable 'call_scratch_address' can
++specify the location of a scratch area to be used when GDB
++calls a function in the target. This is necessary because the
++usual method of putting the scratch area on the stack does not work
++in systems that have separate instruction and data spaces.
++
++We integrated changes to support the 29k UDI (Universal Debugger
++Interface), but discovered at the last minute that we didn't have all
++of the appropriate copyright paperwork. We are working with AMD to
++resolve this, and hope to have it available soon.
++
++ * Remote interfaces
++
++We have sped up the remote serial line protocol, especially for targets
++with lots of registers. It now supports a new `expedited status' ('T')
++message which can be used in place of the existing 'S' status message.
++This allows the remote stub to send only the registers that GDB
++needs to make a quick decision about single-stepping or conditional
++breakpoints, eliminating the need to fetch the entire register set for
++each instruction being stepped through.
++
++The GDB remote serial protocol now implements a write-through cache for
++registers, only re-reading the registers if the target has run.
++
++There is also a new remote serial stub for SPARC processors. You can
++find it in gdb-4.7/gdb/sparc-stub.c. This was written to support the
++Fujitsu SPARClite processor, but will run on any stand-alone SPARC
++processor with a serial port.
++
++ * Configuration
++
++Configure.in files have become much easier to read and modify. A new
++`table driven' format makes it more obvious what configurations are
++supported, and what files each one uses.
++
++ * Library changes
++
++There is a new opcodes library which will eventually contain all of the
++disassembly routines and opcode tables. At present, it only contains
++Sparc and Z8000 routines. This will allow the assembler, debugger, and
++disassembler (binutils/objdump) to share these routines.
++
++The libiberty library is now copylefted under the GNU Library General
++Public License. This allows more liberal use, and was done so libg++
++can use it. This makes no difference to GDB, since the Library License
++grants all the rights from the General Public License.
++
++ * Documentation
++
++The file gdb-4.7/gdb/doc/stabs.texinfo is a (relatively) complete
++reference to the stabs symbol info used by the debugger. It is (as far
++as we know) the only published document on this fascinating topic. We
++encourage you to read it, compare it to the stabs information on your
++system, and send improvements on the document in general (to
++bug-gdb@prep.ai.mit.edu).
++
++And, of course, many bugs have been fixed.
++
++
++*** Changes in GDB-4.6:
++
++ * Better support for C++ function names
++
++GDB now accepts as input the "demangled form" of C++ overloaded function
++names and member function names, and can do command completion on such names
++(using TAB, TAB-TAB, and ESC-?). The names have to be quoted with a pair of
++single quotes. Examples are 'func (int, long)' and 'obj::operator==(obj&)'.
++Make use of command completion, it is your friend.
++
++GDB also now accepts a variety of C++ mangled symbol formats. They are
++the GNU g++ style, the Cfront (ARM) style, and the Lucid (lcc) style.
++You can tell GDB which format to use by doing a 'set demangle-style {gnu,
++lucid, cfront, auto}'. 'gnu' is the default. Do a 'set demangle-style foo'
++for the list of formats.
++
++ * G++ symbol mangling problem
++
++Recent versions of gcc have a bug in how they emit debugging information for
++C++ methods (when using dbx-style stabs). The file 'gcc.patch' (in this
++directory) can be applied to gcc to fix the problem. Alternatively, if you
++can't fix gcc, you can #define GCC_MANGLE_BUG when compling gdb/symtab.c. The
++usual symptom is difficulty with setting breakpoints on methods. GDB complains
++about the method being non-existent. (We believe that version 2.2.2 of GCC has
++this problem.)
++
++ * New 'maintenance' command
++
++All of the commands related to hacking GDB internals have been moved out of
++the main command set, and now live behind the 'maintenance' command. This
++can also be abbreviated as 'mt'. The following changes were made:
++
++ dump-me -> maintenance dump-me
++ info all-breakpoints -> maintenance info breakpoints
++ printmsyms -> maintenance print msyms
++ printobjfiles -> maintenance print objfiles
++ printpsyms -> maintenance print psymbols
++ printsyms -> maintenance print symbols
++
++The following commands are new:
++
++ maintenance demangle Call internal GDB demangler routine to
++ demangle a C++ link name and prints the result.
++ maintenance print type Print a type chain for a given symbol
++
++ * Change to .gdbinit file processing
++
++We now read the $HOME/.gdbinit file before processing the argv arguments
++(e.g. reading symbol files or core files). This allows global parameters to
++be set, which will apply during the symbol reading. The ./.gdbinit is still
++read after argv processing.
++
++ * New hosts supported
++
++Solaris-2.0 !!! sparc-sun-solaris2 or sun4sol2
++
++GNU/Linux support i386-unknown-linux or linux
++
++We are also including code to support the HP/PA running BSD and HPUX. This
++is almost guaranteed not to work, as we didn't have time to test or build it
++for this release. We are including it so that the more adventurous (or
++masochistic) of you can play with it. We also had major problems with the
++fact that the compiler that we got from HP doesn't support the -g option.
++It costs extra.
++
++ * New targets supported
++
++Hitachi H8/300 h8300-hitachi-hms or h8300hms
++
++ * More smarts about finding #include files
++
++GDB now remembers the compilation directory for all include files, and for
++all files from which C is generated (like yacc and lex sources). This
++greatly improves GDB's ability to find yacc/lex sources, and include files,
++especially if you are debugging your program from a directory different from
++the one that contains your sources.
++
++We also fixed a bug which caused difficulty with listing and setting
++breakpoints in include files which contain C code. (In the past, you had to
++try twice in order to list an include file that you hadn't looked at before.)
++
++ * Interesting infernals change
++
++GDB now deals with arbitrary numbers of sections, where the symbols for each
++section must be relocated relative to that section's landing place in the
++target's address space. This work was needed to support ELF with embedded
++stabs used by Solaris-2.0.
++
++ * Bug fixes (of course!)
++
++There have been loads of fixes for the following things:
++ mips, rs6000, 29k/udi, m68k, g++, type handling, elf/dwarf, m88k,
++ i960, stabs, DOS(GO32), procfs, etc...
++
++See the ChangeLog for details.
++
++*** Changes in GDB-4.5:
++
++ * New machines supported (host and target)
++
++IBM RS6000 running AIX rs6000-ibm-aix or rs6000
++
++SGI Irix-4.x mips-sgi-irix4 or iris4
++
++ * New malloc package
++
++GDB now uses a new memory manager called mmalloc, based on gmalloc.
++Mmalloc is capable of handling mutiple heaps of memory. It is also
++capable of saving a heap to a file, and then mapping it back in later.
++This can be used to greatly speedup the startup of GDB by using a
++pre-parsed symbol table which lives in a mmalloc managed heap. For
++more details, please read mmalloc/mmalloc.texi.
++
++ * info proc
++
++The 'info proc' command (SVR4 only) has been enhanced quite a bit. See
++'help info proc' for details.
++
++ * MIPS ecoff symbol table format
++
++The code that reads MIPS symbol table format is now supported on all hosts.
++Thanks to MIPS for releasing the sym.h and symconst.h files to make this
++possible.
++
++ * File name changes for MS-DOS
++
++Many files in the config directories have been renamed to make it easier to
++support GDB on MS-DOSe systems (which have very restrictive file name
++conventions :-( ). MS-DOSe host support (under DJ Delorie's GO32
++environment) is close to working but has some remaining problems. Note
++that debugging of DOS programs is not supported, due to limitations
++in the ``operating system'', but it can be used to host cross-debugging.
++
++ * Cross byte order fixes
++
++Many fixes have been made to support cross debugging of Sparc and MIPS
++targets from hosts whose byte order differs.
++
++ * New -mapped and -readnow options
++
++If memory-mapped files are available on your system through the 'mmap'
++system call, you can use the -mapped option on the `file' or
++`symbol-file' commands to cause GDB to write the symbols from your
++program into a reusable file. If the program you are debugging is
++called `/path/fred', the mapped symbol file will be `./fred.syms'.
++Future GDB debugging sessions will notice the presence of this file,
++and will quickly map in symbol information from it, rather than reading
++the symbol table from the executable program. Using the '-mapped'
++option in a GDB `file' or `symbol-file' command has the same effect as
++starting GDB with the '-mapped' command-line option.
++
++You can cause GDB to read the entire symbol table immediately by using
++the '-readnow' option with any of the commands that load symbol table
++information (or on the GDB command line). This makes the command
++slower, but makes future operations faster.
++
++The -mapped and -readnow options are typically combined in order to
++build a `fred.syms' file that contains complete symbol information.
++A simple GDB invocation to do nothing but build a `.syms' file for future
++use is:
++
++ gdb -batch -nx -mapped -readnow programname
++
++The `.syms' file is specific to the host machine on which GDB is run.
++It holds an exact image of GDB's internal symbol table. It cannot be
++shared across multiple host platforms.
++
++ * longjmp() handling
++
++GDB is now capable of stepping and nexting over longjmp(), _longjmp(), and
++siglongjmp() without losing control. This feature has not yet been ported to
++all systems. It currently works on many 386 platforms, all MIPS-based
++platforms (SGI, DECstation, etc), and Sun3/4.
++
++ * Solaris 2.0
++
++Preliminary work has been put in to support the new Solaris OS from Sun. At
++this time, it can control and debug processes, but it is not capable of
++reading symbols.
++
++ * Bug fixes
++
++As always, many many bug fixes. The major areas were with g++, and mipsread.
++People using the MIPS-based platforms should experience fewer mysterious
++crashes and trashed symbol tables.
++
++*** Changes in GDB-4.4:
++
++ * New machines supported (host and target)
++
++SCO Unix on i386 IBM PC clones i386-sco-sysv or i386sco
++ (except core files)
++BSD Reno on Vax vax-dec-bsd
++Ultrix on Vax vax-dec-ultrix
++
++ * New machines supported (target)
++
++AMD 29000 embedded, using EBMON a29k-none-none
++
++ * C++ support
++
++GDB continues to improve its handling of C++. `References' work better.
++The demangler has also been improved, and now deals with symbols mangled as
++per the Annotated C++ Reference Guide.
++
++GDB also now handles `stabs' symbol information embedded in MIPS
++`ecoff' symbol tables. Since the ecoff format was not easily
++extensible to handle new languages such as C++, this appeared to be a
++good way to put C++ debugging info into MIPS binaries. This option
++will be supported in the GNU C compiler, version 2, when it is
++released.
++
++ * New features for SVR4
++
++GDB now handles SVR4 shared libraries, in the same fashion as SunOS
++shared libraries. Debugging dynamically linked programs should present
++only minor differences from debugging statically linked programs.
++
++The `info proc' command will print out information about any process
++on an SVR4 system (including the one you are debugging). At the moment,
++it prints the address mappings of the process.
++
++If you bring up GDB on another SVR4 system, please send mail to
++bug-gdb@prep.ai.mit.edu to let us know what changes were reqired (if any).
++
++ * Better dynamic linking support in SunOS
++
++Reading symbols from shared libraries which contain debugging symbols
++now works properly. However, there remain issues such as automatic
++skipping of `transfer vector' code during function calls, which
++make it harder to debug code in a shared library, than to debug the
++same code linked statically.
++
++ * New Getopt
++
++GDB is now using the latest `getopt' routines from the FSF. This
++version accepts the -- prefix for options with long names. GDB will
++continue to accept the old forms (-option and +option) as well.
++Various single letter abbreviations for options have been explicity
++added to the option table so that they won't get overshadowed in the
++future by other options that begin with the same letter.
++
++ * Bugs fixed
++
++The `cleanup_undefined_types' bug that many of you noticed has been squashed.
++Many assorted bugs have been handled. Many more remain to be handled.
++See the various ChangeLog files (primarily in gdb and bfd) for details.
++
++
++*** Changes in GDB-4.3:
++
++ * New machines supported (host and target)
++
++Amiga 3000 running Amix m68k-cbm-svr4 or amix
++NCR 3000 386 running SVR4 i386-ncr-svr4 or ncr3000
++Motorola Delta 88000 running Sys V m88k-motorola-sysv or delta88
++
++ * Almost SCO Unix support
++
++We had hoped to support:
++SCO Unix on i386 IBM PC clones i386-sco-sysv or i386sco
++(except for core file support), but we discovered very late in the release
++that it has problems with process groups that render gdb unusable. Sorry
++about that. I encourage people to fix it and post the fixes.
++
++ * Preliminary ELF and DWARF support
++
++GDB can read ELF object files on System V Release 4, and can handle
++debugging records for C, in DWARF format, in ELF files. This support
++is preliminary. If you bring up GDB on another SVR4 system, please
++send mail to bug-gdb@prep.ai.mit.edu to let us know what changes were
++reqired (if any).
++
++ * New Readline
++
++GDB now uses the latest `readline' library. One user-visible change
++is that two tabs will list possible command completions, which previously
++required typing M-? (meta-question mark, or ESC ?).
++
++ * Bugs fixed
++
++The `stepi' bug that many of you noticed has been squashed.
++Many bugs in C++ have been handled. Many more remain to be handled.
++See the various ChangeLog files (primarily in gdb and bfd) for details.
++
++ * State of the MIPS world (in case you wondered):
++
++GDB can understand the symbol tables emitted by the compilers
++supplied by most vendors of MIPS-based machines, including DEC. These
++symbol tables are in a format that essentially nobody else uses.
++
++Some versions of gcc come with an assembler post-processor called
++mips-tfile. This program is required if you want to do source-level
++debugging of gcc-compiled programs. I believe FSF does not ship
++mips-tfile with gcc version 1, but it will eventually come with gcc
++version 2.
++
++Debugging of g++ output remains a problem. g++ version 1.xx does not
++really support it at all. (If you're lucky, you should be able to get
++line numbers and stack traces to work, but no parameters or local
++variables.) With some work it should be possible to improve the
++situation somewhat.
++
++When gcc version 2 is released, you will have somewhat better luck.
++However, even then you will get confusing results for inheritance and
++methods.
++
++We will eventually provide full debugging of g++ output on
++DECstations. This will probably involve some kind of stabs-in-ecoff
++encapulation, but the details have not been worked out yet.
++
++
++*** Changes in GDB-4.2:
++
++ * Improved configuration
++
++Only one copy of `configure' exists now, and it is not self-modifying.
++Porting BFD is simpler.
++
++ * Stepping improved
++
++The `step' and `next' commands now only stop at the first instruction
++of a source line. This prevents the multiple stops that used to occur
++in switch statements, for-loops, etc. `Step' continues to stop if a
++function that has debugging information is called within the line.
++
++ * Bug fixing
++
++Lots of small bugs fixed. More remain.
++
++ * New host supported (not target)
++
++Intel 386 PC clone running Mach i386-none-mach
++
++
++*** Changes in GDB-4.1:
++
++ * Multiple source language support
++
++GDB now has internal scaffolding to handle several source languages.
++It determines the type of each source file from its filename extension,
++and will switch expression parsing and number formatting to match the
++language of the function in the currently selected stack frame.
++You can also specifically set the language to be used, with
++`set language c' or `set language modula-2'.
++
++ * GDB and Modula-2
++
++GDB now has preliminary support for the GNU Modula-2 compiler,
++currently under development at the State University of New York at
++Buffalo. Development of both GDB and the GNU Modula-2 compiler will
++continue through the fall of 1991 and into 1992.
++
++Other Modula-2 compilers are currently not supported, and attempting to
++debug programs compiled with them will likely result in an error as the
++symbol table is read. Feel free to work on it, though!
++
++There are hooks in GDB for strict type checking and range checking,
++in the `Modula-2 philosophy', but they do not currently work.
++
++ * set write on/off
++
++GDB can now write to executable and core files (e.g. patch
++a variable's value). You must turn this switch on, specify
++the file ("exec foo" or "core foo"), *then* modify it, e.g.
++by assigning a new value to a variable. Modifications take
++effect immediately.
++
++ * Automatic SunOS shared library reading
++
++When you run your program, GDB automatically determines where its
++shared libraries (if any) have been loaded, and reads their symbols.
++The `share' command is no longer needed. This also works when
++examining core files.
++
++ * set listsize
++
++You can specify the number of lines that the `list' command shows.
++The default is 10.
++
++ * New machines supported (host and target)
++
++SGI Iris (MIPS) running Irix V3: mips-sgi-irix or iris
++Sony NEWS (68K) running NEWSOS 3.x: m68k-sony-sysv or news
++Ultracomputer (29K) running Sym1: a29k-nyu-sym1 or ultra3
++
++ * New hosts supported (not targets)
++
++IBM RT/PC: romp-ibm-aix or rtpc
++
++ * New targets supported (not hosts)
++
++AMD 29000 embedded with COFF a29k-none-coff
++AMD 29000 embedded with a.out a29k-none-aout
++Ultracomputer remote kernel debug a29k-nyu-kern
++
++ * New remote interfaces
++
++AMD 29000 Adapt
++AMD 29000 Minimon
++
++
++*** Changes in GDB-4.0:
++
++ * New Facilities
++
++Wide output is wrapped at good places to make the output more readable.
++
++Gdb now supports cross-debugging from a host machine of one type to a
++target machine of another type. Communication with the target system
++is over serial lines. The ``target'' command handles connecting to the
++remote system; the ``load'' command will download a program into the
++remote system. Serial stubs for the m68k and i386 are provided. Gdb
++also supports debugging of realtime processes running under VxWorks,
++using SunRPC Remote Procedure Calls over TCP/IP to talk to a debugger
++stub on the target system.
++
++New CPUs supported include the AMD 29000 and Intel 960.
++
++GDB now reads object files and symbol tables via a ``binary file''
++library, which allows a single copy of GDB to debug programs of multiple
++object file types such as a.out and coff.
++
++There is now a GDB reference card in "doc/refcard.tex". (Make targets
++refcard.dvi and refcard.ps are available to format it).
++
++
++ * Control-Variable user interface simplified
++
++All variables that control the operation of the debugger can be set
++by the ``set'' command, and displayed by the ``show'' command.
++
++For example, ``set prompt new-gdb=>'' will change your prompt to new-gdb=>.
++``Show prompt'' produces the response:
++Gdb's prompt is new-gdb=>.
++
++What follows are the NEW set commands. The command ``help set'' will
++print a complete list of old and new set commands. ``help set FOO''
++will give a longer description of the variable FOO. ``show'' will show
++all of the variable descriptions and their current settings.
++
++confirm on/off: Enables warning questions for operations that are
++ hard to recover from, e.g. rerunning the program while
++ it is already running. Default is ON.
++
++editing on/off: Enables EMACS style command line editing
++ of input. Previous lines can be recalled with
++ control-P, the current line can be edited with control-B,
++ you can search for commands with control-R, etc.
++ Default is ON.
++
++history filename NAME: NAME is where the gdb command history
++ will be stored. The default is .gdb_history,
++ or the value of the environment variable
++ GDBHISTFILE.
++
++history size N: The size, in commands, of the command history. The
++ default is 256, or the value of the environment variable
++ HISTSIZE.
++
++history save on/off: If this value is set to ON, the history file will
++ be saved after exiting gdb. If set to OFF, the
++ file will not be saved. The default is OFF.
++
++history expansion on/off: If this value is set to ON, then csh-like
++ history expansion will be performed on
++ command line input. The default is OFF.
++
++radix N: Sets the default radix for input and output. It can be set
++ to 8, 10, or 16. Note that the argument to "radix" is interpreted
++ in the current radix, so "set radix 10" is always a no-op.
++
++height N: This integer value is the number of lines on a page. Default
++ is 24, the current `stty rows'' setting, or the ``li#''
++ setting from the termcap entry matching the environment
++ variable TERM.
++
++width N: This integer value is the number of characters on a line.
++ Default is 80, the current `stty cols'' setting, or the ``co#''
++ setting from the termcap entry matching the environment
++ variable TERM.
++
++Note: ``set screensize'' is obsolete. Use ``set height'' and
++``set width'' instead.
++
++print address on/off: Print memory addresses in various command displays,
++ such as stack traces and structure values. Gdb looks
++ more ``symbolic'' if you turn this off; it looks more
++ ``machine level'' with it on. Default is ON.
++
++print array on/off: Prettyprint arrays. New convenient format! Default
++ is OFF.
++
++print demangle on/off: Print C++ symbols in "source" form if on,
++ "raw" form if off.
++
++print asm-demangle on/off: Same, for assembler level printouts
++ like instructions.
++
++print vtbl on/off: Prettyprint C++ virtual function tables. Default is OFF.
++
++
++ * Support for Epoch Environment.
++
++The epoch environment is a version of Emacs v18 with windowing. One
++new command, ``inspect'', is identical to ``print'', except that if you
++are running in the epoch environment, the value is printed in its own
++window.
++
++
++ * Support for Shared Libraries
++
++GDB can now debug programs and core files that use SunOS shared libraries.
++Symbols from a shared library cannot be referenced
++before the shared library has been linked with the program (this
++happens after you type ``run'' and before the function main() is entered).
++At any time after this linking (including when examining core files
++from dynamically linked programs), gdb reads the symbols from each
++shared library when you type the ``sharedlibrary'' command.
++It can be abbreviated ``share''.
++
++sharedlibrary REGEXP: Load shared object library symbols for files
++ matching a unix regular expression. No argument
++ indicates to load symbols for all shared libraries.
++
++info sharedlibrary: Status of loaded shared libraries.
++
++
++ * Watchpoints
++
++A watchpoint stops execution of a program whenever the value of an
++expression changes. Checking for this slows down execution
++tremendously whenever you are in the scope of the expression, but is
++quite useful for catching tough ``bit-spreader'' or pointer misuse
++problems. Some machines such as the 386 have hardware for doing this
++more quickly, and future versions of gdb will use this hardware.
++
++watch EXP: Set a watchpoint (breakpoint) for an expression.
++
++info watchpoints: Information about your watchpoints.
++
++delete N: Deletes watchpoint number N (same as breakpoints).
++disable N: Temporarily turns off watchpoint number N (same as breakpoints).
++enable N: Re-enables watchpoint number N (same as breakpoints).
++
++
++ * C++ multiple inheritance
++
++When used with a GCC version 2 compiler, GDB supports multiple inheritance
++for C++ programs.
++
++ * C++ exception handling
++
++Gdb now supports limited C++ exception handling. Besides the existing
++ability to breakpoint on an exception handler, gdb can breakpoint on
++the raising of an exception (before the stack is peeled back to the
++handler's context).
++
++catch FOO: If there is a FOO exception handler in the dynamic scope,
++ set a breakpoint to catch exceptions which may be raised there.
++ Multiple exceptions (``catch foo bar baz'') may be caught.
++
++info catch: Lists all exceptions which may be caught in the
++ current stack frame.
++
++
++ * Minor command changes
++
++The command ``call func (arg, arg, ...)'' now acts like the print
++command, except it does not print or save a value if the function's result
++is void. This is similar to dbx usage.
++
++The ``up'' and ``down'' commands now always print the frame they end up
++at; ``up-silently'' and `down-silently'' can be used in scripts to change
++frames without printing.
++
++ * New directory command
++
++'dir' now adds directories to the FRONT of the source search path.
++The path starts off empty. Source files that contain debug information
++about the directory in which they were compiled can be found even
++with an empty path; Sun CC and GCC include this information. If GDB can't
++find your source file in the current directory, type "dir .".
++
++ * Configuring GDB for compilation
++
++For normal use, type ``./configure host''. See README or gdb.texinfo
++for more details.
++
++GDB now handles cross debugging. If you are remotely debugging between
++two different machines, type ``./configure host -target=targ''.
++Host is the machine where GDB will run; targ is the machine
++where the program that you are debugging will run.
+diff -Naur gdb-6.8.orig/gdb/testsuite/gdb.base/watchpoint.c gdb-6.8/gdb/testsuite/gdb.base/watchpoint.c
+--- gdb-6.8.orig/gdb/testsuite/gdb.base/watchpoint.c 2003-03-17 20:51:58.000000000 +0100
++++ gdb-6.8/gdb/testsuite/gdb.base/watchpoint.c 2008-09-17 16:32:32.000000000 +0200
+@@ -39,6 +39,8 @@
+
+ int doread = 0;
+
++char *global_ptr;
++
+ void marker1 ()
+ {
+ }
+@@ -110,6 +112,14 @@
+ return 73;
+ }
+
++void
++func4 ()
++{
++ buf[0] = 3;
++ global_ptr = buf;
++ buf[0] = 7;
++}
++
+ int main ()
+ {
+ #ifdef usestubs
+@@ -185,5 +195,7 @@
+
+ func3 ();
+
++ func4 ();
++
+ return 0;
+ }
+diff -Naur gdb-6.8.orig/gdb/testsuite/gdb.base/watchpoint.exp gdb-6.8/gdb/testsuite/gdb.base/watchpoint.exp
+--- gdb-6.8.orig/gdb/testsuite/gdb.base/watchpoint.exp 2008-01-01 23:53:19.000000000 +0100
++++ gdb-6.8/gdb/testsuite/gdb.base/watchpoint.exp 2008-09-17 16:32:32.000000000 +0200
+@@ -645,6 +645,30 @@
+ }
+ }
+
++proc test_inaccessible_watchpoint {} {
++ global gdb_prompt
++
++ # This is a test for watchpoints on currently inaccessible (but later
++ # valid) memory.
++
++ if [runto func4] then {
++ gdb_test "watch *global_ptr" ".*atchpoint \[0-9\]+: \\*global_ptr"
++ gdb_test "next" ".*global_ptr = buf.*"
++ gdb_test_multiple "next" "next over ptr init" {
++ -re ".*atchpoint \[0-9\]+: \\*global_ptr\r\n\r\nOld value = .*\r\nNew value = 3 .*\r\n.*$gdb_prompt $" {
++ # We can not test for <unknown> here because NULL may be readable.
++ # This test does rely on *NULL != 3.
++ pass "next over ptr init"
++ }
++ }
++ gdb_test_multiple "next" "next over buffer set" {
++ -re ".*atchpoint \[0-9\]+: \\*global_ptr\r\n\r\nOld value = 3 .*\r\nNew value = 7 .*\r\n.*$gdb_prompt $" {
++ pass "next over buffer set"
++ }
++ }
++ }
++}
++
+ # Start with a fresh gdb.
+
+ gdb_exit
+@@ -797,6 +821,8 @@
+ }
+ }
+
++ test_inaccessible_watchpoint
++
+ # See above.
+ if [istarget "mips-idt-*"] then {
+ gdb_exit
+diff -Naur gdb-6.8.orig/sim/common/aclocal.m4 gdb-6.8/sim/common/aclocal.m4
+--- gdb-6.8.orig/sim/common/aclocal.m4 2006-06-13 10:06:48.000000000 +0200
++++ gdb-6.8/sim/common/aclocal.m4 2008-09-17 16:33:00.000000000 +0200
+@@ -18,7 +18,7 @@
+ #
+ # SIM_AC_OUTPUT
+
+-AC_DEFUN(SIM_AC_COMMON,
++AC_DEFUN([SIM_AC_COMMON],
+ [
+ # autoconf.info says this should be called right after AC_INIT.
+ AC_CONFIG_HEADER(ifelse([$1],,config.h,[$1]):config.in)
+@@ -245,7 +245,7 @@
+ dnl supported.
+ dnl ??? Until there is demonstrable value in doing something more complicated,
+ dnl let's not.
+-AC_DEFUN(SIM_AC_OPTION_ENVIRONMENT,
++AC_DEFUN([SIM_AC_OPTION_ENVIRONMENT],
+ [
+ AC_ARG_ENABLE(sim-environment,
+ [ --enable-sim-environment=environment Specify mixed, user, virtual or operating environment.],
+@@ -269,7 +269,7 @@
+ dnl Without this option all possible alignment restrictions are accommodated.
+ dnl arg[1] is hardwired target alignment
+ dnl arg[2] is default target alignment
+-AC_DEFUN(SIM_AC_OPTION_ALIGNMENT,
++AC_DEFUN([SIM_AC_OPTION_ALIGNMENT],
+ wire_alignment="[$1]"
+ default_alignment="[$2]"
+ [
+@@ -318,7 +318,7 @@
+
+
+ dnl Conditionally compile in assertion statements.
+-AC_DEFUN(SIM_AC_OPTION_ASSERT,
++AC_DEFUN([SIM_AC_OPTION_ASSERT],
+ [
+ AC_ARG_ENABLE(sim-assert,
+ [ --enable-sim-assert Specify whether to perform random assertions.],
+@@ -342,7 +342,7 @@
+ dnl arg[3] is the number of bits in an address
+ dnl arg[4] is the number of bits in an OpenFirmware cell.
+ dnl FIXME: this information should be obtained from bfd/archure
+-AC_DEFUN(SIM_AC_OPTION_BITSIZE,
++AC_DEFUN([SIM_AC_OPTION_BITSIZE],
+ wire_word_bitsize="[$1]"
+ wire_word_msb="[$2]"
+ wire_address_bitsize="[$3]"
+@@ -408,7 +408,7 @@
+ dnl that support both big and little endian targets.
+ dnl arg[1] is hardwired target endianness.
+ dnl arg[2] is default target endianness.
+-AC_DEFUN(SIM_AC_OPTION_ENDIAN,
++AC_DEFUN([SIM_AC_OPTION_ENDIAN],
+ [
+ wire_endian="[$1]"
+ default_endian="[$2]"
+@@ -458,7 +458,7 @@
+ dnl --enable-sim-hostendian is for users of the simulator when
+ dnl they find that AC_C_BIGENDIAN does not function correctly
+ dnl (for instance in a canadian cross)
+-AC_DEFUN(SIM_AC_OPTION_HOSTENDIAN,
++AC_DEFUN([SIM_AC_OPTION_HOSTENDIAN],
+ [
+ AC_ARG_ENABLE(sim-hostendian,
+ [ --enable-sim-hostendian=end Specify host byte endian orientation.],
+@@ -490,7 +490,7 @@
+ dnl And optionally the bitsize of the floating point register.
+ dnl arg[1] specifies the presence (or absence) of floating point hardware
+ dnl arg[2] specifies the number of bits in a floating point register
+-AC_DEFUN(SIM_AC_OPTION_FLOAT,
++AC_DEFUN([SIM_AC_OPTION_FLOAT],
+ [
+ default_sim_float="[$1]"
+ default_sim_float_bitsize="[$2]"
+@@ -519,7 +519,7 @@
+
+
+ dnl The argument is the default cache size if none is specified.
+-AC_DEFUN(SIM_AC_OPTION_SCACHE,
++AC_DEFUN([SIM_AC_OPTION_SCACHE],
+ [
+ default_sim_scache="ifelse([$1],,0,[$1])"
+ AC_ARG_ENABLE(sim-scache,
+@@ -539,7 +539,7 @@
+
+
+ dnl The argument is the default model if none is specified.
+-AC_DEFUN(SIM_AC_OPTION_DEFAULT_MODEL,
++AC_DEFUN([SIM_AC_OPTION_DEFAULT_MODEL],
+ [
+ default_sim_default_model="ifelse([$1],,0,[$1])"
+ AC_ARG_ENABLE(sim-default-model,
+@@ -559,7 +559,7 @@
+ dnl arg[1] Enable sim-hw by default? ("yes" or "no")
+ dnl arg[2] is a space separated list of devices that override the defaults
+ dnl arg[3] is a space separated list of extra target specific devices.
+-AC_DEFUN(SIM_AC_OPTION_HARDWARE,
++AC_DEFUN([SIM_AC_OPTION_HARDWARE],
+ [
+ if test x"[$1]" = x"yes"; then
+ sim_hw_p=yes
+@@ -621,7 +621,7 @@
+ dnl performance by inlining functions.
+ dnl Guarantee that unconfigured simulators do not do any inlining
+ sim_inline="-DDEFAULT_INLINE=0"
+-AC_DEFUN(SIM_AC_OPTION_INLINE,
++AC_DEFUN([SIM_AC_OPTION_INLINE],
+ [
+ default_sim_inline="ifelse([$1],,,-DDEFAULT_INLINE=[$1])"
+ AC_ARG_ENABLE(sim-inline,
+@@ -666,7 +666,7 @@
+ AC_SUBST(sim_inline)
+
+
+-AC_DEFUN(SIM_AC_OPTION_PACKAGES,
++AC_DEFUN([SIM_AC_OPTION_PACKAGES],
+ [
+ AC_ARG_ENABLE(sim-packages,
+ [ --enable-sim-packages=list Specify the packages to be included in the build.],
+@@ -692,7 +692,7 @@
+ AC_SUBST(sim_packages)
+
+
+-AC_DEFUN(SIM_AC_OPTION_REGPARM,
++AC_DEFUN([SIM_AC_OPTION_REGPARM],
+ [
+ AC_ARG_ENABLE(sim-regparm,
+ [ --enable-sim-regparm=nr-parm Pass parameters in registers instead of on the stack - x86/GCC specific.],
+@@ -709,7 +709,7 @@
+ AC_SUBST(sim_regparm)
+
+
+-AC_DEFUN(SIM_AC_OPTION_RESERVED_BITS,
++AC_DEFUN([SIM_AC_OPTION_RESERVED_BITS],
+ [
+ default_sim_reserved_bits="ifelse([$1],,1,[$1])"
+ AC_ARG_ENABLE(sim-reserved-bits,
+@@ -726,7 +726,7 @@
+ AC_SUBST(sim_reserved_bits)
+
+
+-AC_DEFUN(SIM_AC_OPTION_SMP,
++AC_DEFUN([SIM_AC_OPTION_SMP],
+ [
+ default_sim_smp="ifelse([$1],,5,[$1])"
+ AC_ARG_ENABLE(sim-smp,
+@@ -746,7 +746,7 @@
+ AC_SUBST(sim_smp)
+
+
+-AC_DEFUN(SIM_AC_OPTION_STDCALL,
++AC_DEFUN([SIM_AC_OPTION_STDCALL],
+ [
+ AC_ARG_ENABLE(sim-stdcall,
+ [ --enable-sim-stdcall=type Use an alternative function call/return mechanism - x86/GCC specific.],
+@@ -763,7 +763,7 @@
+ AC_SUBST(sim_stdcall)
+
+
+-AC_DEFUN(SIM_AC_OPTION_XOR_ENDIAN,
++AC_DEFUN([SIM_AC_OPTION_XOR_ENDIAN],
+ [
+ default_sim_xor_endian="ifelse([$1],,8,[$1])"
+ AC_ARG_ENABLE(sim-xor-endian,
+@@ -782,7 +782,7 @@
+
+ dnl --enable-build-warnings is for developers of the simulator.
+ dnl it enables extra GCC specific warnings.
+-AC_DEFUN(SIM_AC_OPTION_WARNINGS,
++AC_DEFUN([SIM_AC_OPTION_WARNINGS],
+ [
+ # NOTE: Don't add -Wall or -Wunused, they both include
+ # -Wunused-parameter which reports bogus warnings.
+@@ -866,7 +866,7 @@
+ dnl one afterwards. The two pieces of the common fragment are inserted into
+ dnl the target's fragment at the appropriate points.
+
+-AC_DEFUN(SIM_AC_OUTPUT,
++AC_DEFUN([SIM_AC_OUTPUT],
+ [
+ AC_LINK_FILES($sim_link_files, $sim_link_links)
+ dnl Make @cgen_breaks@ non-null only if the sim uses CGEN.
+@@ -895,7 +895,7 @@
+ sinclude(../../config/gettext-sister.m4)
+
+ dnl --enable-cgen-maint support
+-AC_DEFUN(SIM_AC_OPTION_CGEN_MAINT,
++AC_DEFUN([SIM_AC_OPTION_CGEN_MAINT],
+ [
+ cgen_maint=no
+ dnl Default is to use one in build tree.
+diff -Naur gdb-6.8.orig/sim/erc32/configure gdb-6.8/sim/erc32/configure
+--- gdb-6.8.orig/sim/erc32/configure 2006-12-20 23:35:51.000000000 +0100
++++ gdb-6.8/sim/erc32/configure 2008-09-17 16:33:00.000000000 +0200
+@@ -309,7 +309,7 @@
+ # include <unistd.h>
+ #endif"
+
+-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS sim_environment sim_alignment sim_assert sim_bitsize sim_endian sim_hostendian sim_float sim_scache sim_default_model sim_hw_cflags sim_hw_objs sim_hw sim_inline sim_packages sim_regparm sim_reserved_bits sim_smp sim_stdcall sim_xor_endian WARN_CFLAGS WERROR_CFLAGS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CC_FOR_BUILD HDEFINES AR RANLIB ac_ct_RANLIB USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT CPP EGREP MAINT sim_bswap sim_cflags sim_debug sim_stdio sim_trace sim_profile TERMCAP READLINE cgen_breaks LIBOBJS LTLIBOBJS'
++ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS sim_environment sim_alignment sim_assert sim_bitsize sim_endian sim_hostendian sim_float sim_scache sim_default_model sim_hw_cflags sim_hw_objs sim_hw sim_inline sim_packages sim_regparm sim_reserved_bits sim_smp sim_stdcall sim_xor_endian WARN_CFLAGS WERROR_CFLAGS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CC_FOR_BUILD HDEFINES AR RANLIB ac_ct_RANLIB USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT CPP EGREP MAINT sim_bswap sim_cflags sim_debug sim_stdio sim_trace sim_profile READLINE READLINE_DEPS READLINE_CFLAGS cgen_breaks LIBOBJS LTLIBOBJS'
+ ac_subst_files=''
+
+ # Initialize some variables set by options.
+@@ -858,6 +858,11 @@
+ --enable-sim-trace=opts Enable tracing flags
+ --enable-sim-profile=opts Enable profiling flags
+
++Optional Packages:
++ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
++ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
++ --with-system-readline use installed readline library
++
+ Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+@@ -4493,57 +4498,36 @@
+ done
+
+
+-# In the Cygwin environment, we need some additional flags.
+-echo "$as_me:$LINENO: checking for cygwin" >&5
+-echo $ECHO_N "checking for cygwin... $ECHO_C" >&6
+-if test "${sim_cv_os_cygwin+set}" = set; then
+- echo $ECHO_N "(cached) $ECHO_C" >&6
+-else
+- cat >conftest.$ac_ext <<_ACEOF
+-/* confdefs.h. */
+-_ACEOF
+-cat confdefs.h >>conftest.$ac_ext
+-cat >>conftest.$ac_ext <<_ACEOF
+-/* end confdefs.h. */
+
+-#ifdef __CYGWIN__
+-lose
+-#endif
+-_ACEOF
+-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+- $EGREP "lose" >/dev/null 2>&1; then
+- sim_cv_os_cygwin=yes
+-else
+- sim_cv_os_cygwin=no
+-fi
+-rm -f conftest*
++# Check whether --with-system-readline or --without-system-readline was given.
++if test "${with_system_readline+set}" = set; then
++ withval="$with_system_readline"
+
+-fi
+-echo "$as_me:$LINENO: result: $sim_cv_os_cygwin" >&5
+-echo "${ECHO_T}$sim_cv_os_cygwin" >&6
++fi;
+
+-if test x$sim_cv_os_cygwin = xyes; then
+- TERMCAP='`if test -r ../../libtermcap/libtermcap.a; then echo ../../libtermcap/libtermcap.a; else echo -ltermcap; fi` -luser32'
+-else
+- echo "$as_me:$LINENO: checking for main in -ltermcap" >&5
+-echo $ECHO_N "checking for main in -ltermcap... $ECHO_C" >&6
+-if test "${ac_cv_lib_termcap_main+set}" = set; then
+- echo $ECHO_N "(cached) $ECHO_C" >&6
+-else
+- ac_check_lib_save_LIBS=$LIBS
+-LIBS="-ltermcap $LIBS"
+-cat >conftest.$ac_ext <<_ACEOF
++if test "$with_system_readline" = yes; then
++ echo "$as_me:$LINENO: checking for readline" >&5
++echo $ECHO_N "checking for readline... $ECHO_C" >&6
++ save_LIBS="$LIBS"
++ LIBS="-lreadline $save_LIBS"
++ cat >conftest.$ac_ext <<_ACEOF
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+ cat >>conftest.$ac_ext <<_ACEOF
+ /* end confdefs.h. */
+
+-
++/* Override any gcc2 internal prototype to avoid an error. */
++#ifdef __cplusplus
++extern "C"
++#endif
++/* We use char because int might match the return type of a gcc2
++ builtin and then its argument prototype would still apply. */
++char add_history ();
+ int
+ main ()
+ {
+-main ();
++add_history ();
+ ;
+ return 0;
+ }
+@@ -4570,41 +4554,13 @@
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+- ac_cv_lib_termcap_main=yes
++ READLINE=-lreadline
+ else
+ echo "$as_me: failed program was:" >&5
+ sed 's/^/| /' conftest.$ac_ext >&5
+
+-ac_cv_lib_termcap_main=no
+-fi
+-rm -f conftest.err conftest.$ac_objext \
+- conftest$ac_exeext conftest.$ac_ext
+-LIBS=$ac_check_lib_save_LIBS
+-fi
+-echo "$as_me:$LINENO: result: $ac_cv_lib_termcap_main" >&5
+-echo "${ECHO_T}$ac_cv_lib_termcap_main" >&6
+-if test $ac_cv_lib_termcap_main = yes; then
+- TERMCAP=-ltermcap
+-else
+- TERMCAP=""
+-fi
+-
+-fi
+-
+-
+-# We prefer the in-tree readline. Top-level dependencies make sure
+-# src/readline (if it's there) is configured before src/sim.
+-if test -r ../../readline/Makefile; then
+- READLINE=../../readline/libreadline.a
+-else
+- echo "$as_me:$LINENO: checking for readline in -lreadline" >&5
+-echo $ECHO_N "checking for readline in -lreadline... $ECHO_C" >&6
+-if test "${ac_cv_lib_readline_readline+set}" = set; then
+- echo $ECHO_N "(cached) $ECHO_C" >&6
+-else
+- ac_check_lib_save_LIBS=$LIBS
+-LIBS="-lreadline $TERMCAP $LIBS"
+-cat >conftest.$ac_ext <<_ACEOF
++ LIBS="-lreadline -lncurses $save_LIBS"
++ cat >conftest.$ac_ext <<_ACEOF
+ /* confdefs.h. */
+ _ACEOF
+ cat confdefs.h >>conftest.$ac_ext
+@@ -4617,11 +4573,11 @@
+ #endif
+ /* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+-char readline ();
++char add_history ();
+ int
+ main ()
+ {
+-readline ();
++add_history ();
+ ;
+ return 0;
+ }
+@@ -4648,28 +4604,34 @@
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+- ac_cv_lib_readline_readline=yes
++ READLINE="-lreadline -lncurses"
+ else
+ echo "$as_me: failed program was:" >&5
+ sed 's/^/| /' conftest.$ac_ext >&5
+
+-ac_cv_lib_readline_readline=no
++{ { echo "$as_me:$LINENO: error: unable to detect readline" >&5
++echo "$as_me: error: unable to detect readline" >&2;}
++ { (exit 1); exit 1; }; }
+ fi
+ rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+-LIBS=$ac_check_lib_save_LIBS
++
+ fi
+-echo "$as_me:$LINENO: result: $ac_cv_lib_readline_readline" >&5
+-echo "${ECHO_T}$ac_cv_lib_readline_readline" >&6
+-if test $ac_cv_lib_readline_readline = yes; then
+- READLINE=-lreadline
+-else
+- { { echo "$as_me:$LINENO: error: the required \"readline\" library is missing" >&5
+-echo "$as_me: error: the required \"readline\" library is missing" >&2;}
+- { (exit 1); exit 1; }; }
++rm -f conftest.err conftest.$ac_objext \
++ conftest$ac_exeext conftest.$ac_ext
++ LIBS="$save_LIBS"
++ echo "$as_me:$LINENO: result: $READLINE" >&5
++echo "${ECHO_T}$READLINE" >&6
++ READLINE_DEPS=
++ READLINE_CFLAGS=
++else
++ READLINE='$(READLINE_DIR)/libreadline.a'
++ READLINE_DEPS='$(READLINE)'
++ READLINE_CFLAGS='-I$(READLINE_SRC)/..'
+ fi
+
+-fi
++
++
+
+
+ ac_sources="$sim_link_files"
+@@ -5389,8 +5351,9 @@
+ s,@sim_stdio@,$sim_stdio,;t t
+ s,@sim_trace@,$sim_trace,;t t
+ s,@sim_profile@,$sim_profile,;t t
+-s,@TERMCAP@,$TERMCAP,;t t
+ s,@READLINE@,$READLINE,;t t
++s,@READLINE_DEPS@,$READLINE_DEPS,;t t
++s,@READLINE_CFLAGS@,$READLINE_CFLAGS,;t t
+ s,@cgen_breaks@,$cgen_breaks,;t t
+ s,@LIBOBJS@,$LIBOBJS,;t t
+ s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+diff -Naur gdb-6.8.orig/sim/erc32/configure.ac gdb-6.8/sim/erc32/configure.ac
+--- gdb-6.8.orig/sim/erc32/configure.ac 2006-12-20 23:35:51.000000000 +0100
++++ gdb-6.8/sim/erc32/configure.ac 2008-09-17 16:33:00.000000000 +0200
+@@ -11,27 +11,32 @@
+
+ AC_CHECK_HEADERS(stdlib.h)
+
+-# In the Cygwin environment, we need some additional flags.
+-AC_CACHE_CHECK([for cygwin], sim_cv_os_cygwin,
+-[AC_EGREP_CPP(lose, [
+-#ifdef __CYGWIN__
+-lose
+-#endif],[sim_cv_os_cygwin=yes],[sim_cv_os_cygwin=no])])
++AC_ARG_WITH([system-readline],
++ [AS_HELP_STRING([--with-system-readline],
++ [use installed readline library])])
+
+-if test x$sim_cv_os_cygwin = xyes; then
+- TERMCAP='`if test -r ../../libtermcap/libtermcap.a; then echo ../../libtermcap/libtermcap.a; else echo -ltermcap; fi` -luser32'
++if test "$with_system_readline" = yes; then
++ AC_MSG_CHECKING([for readline])
++ save_LIBS="$LIBS"
++ LIBS="-lreadline $save_LIBS"
++ AC_LINK_IFELSE([AC_LANG_CALL([],
++ [add_history])], [READLINE=-lreadline],
++ [ LIBS="-lreadline -lncurses $save_LIBS"
++ AC_LINK_IFELSE([AC_LANG_CALL([],
++ [add_history])], [READLINE="-lreadline -lncurses"],
++ [AC_MSG_ERROR([unable to detect readline])])
++ ])
++ LIBS="$save_LIBS"
++ AC_MSG_RESULT($READLINE)
++ READLINE_DEPS=
++ READLINE_CFLAGS=
+ else
+- AC_CHECK_LIB(termcap, main, TERMCAP=-ltermcap, TERMCAP="")
+-fi
+-AC_SUBST(TERMCAP)
+-
+-# We prefer the in-tree readline. Top-level dependencies make sure
+-# src/readline (if it's there) is configured before src/sim.
+-if test -r ../../readline/Makefile; then
+- READLINE=../../readline/libreadline.a
+-else
+- AC_CHECK_LIB(readline, readline, READLINE=-lreadline,
+- AC_ERROR([the required "readline" library is missing]), $TERMCAP)
++ READLINE='$(READLINE_DIR)/libreadline.a'
++ READLINE_DEPS='$(READLINE)'
++ READLINE_CFLAGS='-I$(READLINE_SRC)/..'
+ fi
+ AC_SUBST(READLINE)
++AC_SUBST(READLINE_DEPS)
++AC_SUBST(READLINE_CFLAGS)
++
+ SIM_AC_OUTPUT
+diff -Naur gdb-6.8.orig/sim/erc32/erc32.c gdb-6.8/sim/erc32/erc32.c
+--- gdb-6.8.orig/sim/erc32/erc32.c 1999-04-16 03:35:00.000000000 +0200
++++ gdb-6.8/sim/erc32/erc32.c 2008-09-17 16:33:00.000000000 +0200
+@@ -24,6 +24,7 @@
+
+ #include <sys/types.h>
+ #include <stdio.h>
++#include <string.h>
+ #include <termios.h>
+ #include <sys/fcntl.h>
+ #include <sys/file.h>
+@@ -413,7 +414,7 @@
+ if (rom8) mec_memcfg &= ~0x20000;
+ else mec_memcfg |= 0x20000;
+
+- mem_ramsz = (256 * 1024) << ((mec_memcfg >> 10) & 7);
++ mem_ramsz = (512 * 1024) << ((mec_memcfg >> 10) & 7);
+ mem_romsz = (128 * 1024) << ((mec_memcfg >> 18) & 7);
+
+ if (sparclite_board) {
+@@ -1659,7 +1660,7 @@
+ errmec = 0;
+ return(1);
+ }
+-#endif;
++#endif
+
+ if ((addr >= mem_ramstart) && (addr < (mem_ramstart + mem_ramsz))) {
+ fetch_bytes (asi, &ramb[addr & mem_rammask], data, sz);
+@@ -1736,7 +1737,7 @@
+ errmec = 0;
+ return(1);
+ }
+-#endif;
++#endif
+
+ if ((addr >= mem_ramstart) && (addr < (mem_ramstart + mem_ramsz))) {
+ if (mem_accprot) {
+diff -Naur gdb-6.8.orig/sim/erc32/exec.c gdb-6.8/sim/erc32/exec.c
+--- gdb-6.8.orig/sim/erc32/exec.c 2005-03-07 12:09:05.000000000 +0100
++++ gdb-6.8/sim/erc32/exec.c 2008-09-17 16:33:00.000000000 +0200
+@@ -1713,7 +1713,7 @@
+ sregs->fdp[rs2 | 1] = sregs->fs[rs2 & ~1];
+ sregs->fdp[rs2 & ~1] = sregs->fs[rs2 | 1];
+ default:
+- ;
++ break;
+ }
+ #endif
+
+@@ -1886,7 +1886,7 @@
+ sregs->fs[rd & ~1] = sregs->fdp[rd | 1];
+ sregs->fs[rd | 1] = sregs->fdp[rd & ~1];
+ default:
+- ;
++ break;
+ }
+ #endif
+ if (sregs->fpstate == FP_EXC_PE) {
+diff -Naur gdb-6.8.orig/sim/erc32/Makefile.in gdb-6.8/sim/erc32/Makefile.in
+--- gdb-6.8.orig/sim/erc32/Makefile.in 2008-01-01 23:53:24.000000000 +0100
++++ gdb-6.8/sim/erc32/Makefile.in 2008-09-17 16:33:00.000000000 +0200
+@@ -18,12 +18,12 @@
+
+ ## COMMON_PRE_CONFIG_FRAG
+
+-TERMCAP_LIB = @TERMCAP@
++# TERMCAP_LIB = -lncurses
+ READLINE_LIB = @READLINE@
+
+ SIM_OBJS = exec.o erc32.o func.o help.o float.o interf.o
+ SIM_EXTRA_LIBS = $(READLINE_LIB) $(TERMCAP_LIB) -lm
+-SIM_EXTRA_ALL = sis
++SIM_EXTRA_ALL = sis$(EXEEXT)
+ SIM_EXTRA_INSTALL = install-sis
+ SIM_EXTRA_CLEAN = clean-sis
+
+@@ -37,8 +37,8 @@
+ # `sis' doesn't need interf.o.
+ SIS_OFILES = exec.o erc32.o func.o help.o float.o
+
+-sis: sis.o $(SIS_OFILES) $(COMMON_OBJS) $(LIBDEPS)
+- $(CC) $(ALL_CFLAGS) -o sis \
++sis$(EXEEXT): sis.o $(SIS_OFILES) $(COMMON_OBJS) $(LIBDEPS)
++ $(CC) $(ALL_CFLAGS) -o sis$(EXEEXT) \
+ sis.o $(SIS_OFILES) $(COMMON_OBJS) $(EXTRA_LIBS)
+
+ # FIXME: This computes the build host's endianness, doesn't it?
+@@ -51,11 +51,11 @@
+
+ # Copy the files into directories where they will be run.
+ install-sis: installdirs
+- n=`echo sis | sed '$(program_transform_name)'`; \
+- $(INSTALL_PROGRAM) sis$(EXEEXT) $(DESTDIR)$(bindir)/$$n$(EXEEXT)
++ n=`echo sis$(EXEEXT) | sed '$(program_transform_name)'`; \
++ $(INSTALL_PROGRAM) sis$(EXEEXT) $(DESTDIR)$(bindir)/$$n
+
+ clean-sis:
+- rm -f sis end end.h
++ rm -f sis$(EXEEXT) end end.h
+
+ configure:
+ @echo "Rebuilding configure..."
+diff -Naur gdb-6.8.orig/sim/ppc/configure.ac gdb-6.8/sim/ppc/configure.ac
+--- gdb-6.8.orig/sim/ppc/configure.ac 2008-03-14 22:35:27.000000000 +0100
++++ gdb-6.8/sim/ppc/configure.ac 2008-09-17 16:33:00.000000000 +0200
+@@ -209,10 +209,105 @@
+ esac
+ ])dnl
+
++AC_CACHE_CHECK([if union semun defined],
++ ac_cv_HAS_UNION_SEMUN,
++ [AC_TRY_COMPILE([
++#include <sys/types.h>
++#include <sys/ipc.h>
++#include <sys/sem.h>],
++[union semun arg ;],
++[ac_cv_has_union_semun="yes"],
++[ac_cv_has_union_semun="no"])
++AC_MSG_RESULT($ac_cv_has_union_semun)
++])
++
++
++if test "$ac_cv_has_union_semun" = "yes"; then
++ AC_CACHE_CHECK(whether System V semaphores are supported,
++ ac_cv_sysv_sem,
++ [
++ AC_TRY_RUN(
++ [
++ #include <sys/types.h>
++ #include <sys/ipc.h>
++ #include <sys/sem.h>
++ int main () {
++ union semun arg ;
++
++ int id=semget(IPC_PRIVATE,1,IPC_CREAT|0400);
++ if (id == -1)
++ exit(1);
++ arg.val = 0; /* avoid implicit type cast to union */
++ if (semctl(id, 0, IPC_RMID, arg) == -1)
++ exit(1);
++ exit(0);
++ }
++ ],
++ ac_cv_sysv_sem="yes", ac_cv_sysv_sem="no", :)
++ ])
++else # semun is not defined
++ AC_CACHE_CHECK(whether System V semaphores are supported,
++ ac_cv_sysv_sem,
++ [
++ AC_TRY_RUN(
++ [
++ #include <sys/types.h>
++ #include <sys/ipc.h>
++ #include <sys/sem.h>
++ union semun {
++ int val;
++ struct semid_ds *buf;
++ ushort *array;
++ };
++ int main () {
++ union semun arg ;
++
++ int id=semget(IPC_PRIVATE,1,IPC_CREAT|0400);
++ if (id == -1)
++ exit(1);
++ arg.val = 0; /* avoid implicit type cast to union */
++ if (semctl(id, 0, IPC_RMID, arg) == -1)
++ exit(1);
++ exit(0);
++ }
++ ],
++ ac_cv_sysv_sem="yes", ac_cv_sysv_sem="no", :)
++ ])
++fi
++
++AC_CACHE_CHECK(whether System V shared memory is supported,
++ac_cv_sysv_shm,
++[
++AC_TRY_RUN([
++#include <sys/types.h>
++#include <sys/ipc.h>
++#include <sys/shm.h>
++int main () {
++ int id=shmget(IPC_PRIVATE,1,IPC_CREAT|0400);
++ if (id == -1)
++ exit(1);
++ if (shmctl(id, IPC_RMID, 0) == -1)
++ exit(1);
++ exit(0);
++}
++],
++ac_cv_sysv_shm="yes", ac_cv_sysv_shm="no", :)
++])
++
++if test x"$ac_cv_sysv_shm" = x"yes" -a x"$ac_cv_sysv_sem" = x"yes" ; then
++ sim_sysv_ipc_hw=",sem,shm";
++else
++ sim_sysv_ipc_hw="";
++fi
++
++if test x"$ac_cv_has_union_semun" = x"yes" -a x"$ac_cv_sysv_sem" = x"yes" ; then
++ sim_hwflags="-DHAS_UNION_SEMUN";
++fi
++
+
+ AC_ARG_ENABLE(sim-hardware,
+ [ --enable-sim-hardware=list Specify the hardware to be included in the build.],
+-[hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide"
++[hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide${sim_sysv_ipc_hw}"
+ case "${enableval}" in
+ yes) ;;
+ no) AC_MSG_ERROR("List of hardware must be specified for --enable-sim-hardware"); hardware="";;
+@@ -224,14 +319,13 @@
+ sim_hw_obj=`echo $sim_hw_src | sed -e 's/\.c/.o/g'`
+ if test x"$silent" != x"yes" && test x"$hardware" != x""; then
+ echo "Setting hardware to $sim_hw_src, $sim_hw_obj"
+-fi],[hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide"
++fi],[hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide${sim_sysv_ipc_hw}"
+ sim_hw_src=`echo $hardware | sed -e 's/,/.c hw_/g' -e 's/^/hw_/' -e s'/$/.c/'`
+ sim_hw_obj=`echo $sim_hw_src | sed -e 's/\.c/.o/g'`
+ if test x"$silent" != x"yes"; then
+ echo "Setting hardware to $sim_hw_src, $sim_hw_obj"
+ fi])dnl
+
+-
+ AC_ARG_ENABLE(sim-hostbitsize,
+ [ --enable-sim-hostbitsize=32|64 Specify host bitsize (32 or 64).],
+ [case "${enableval}" in
+diff -Naur gdb-6.8.orig/sim/ppc/debug.c gdb-6.8/sim/ppc/debug.c
+--- gdb-6.8.orig/sim/ppc/debug.c 1999-04-16 03:35:08.000000000 +0200
++++ gdb-6.8/sim/ppc/debug.c 2008-09-17 16:33:00.000000000 +0200
+@@ -70,6 +70,8 @@
+ { trace_pass_device, "pass-device" },
+ { trace_phb_device, "phb-device" },
+ { trace_register_device, "register-device", "Device initializing registers" },
++ { trace_sem_device, "sem-device" },
++ { trace_shm_device, "shm-device" },
+ { trace_stack_device, "stack-device" },
+ { trace_vm_device, "vm-device" },
+ /* packages */
+diff -Naur gdb-6.8.orig/sim/ppc/debug.h gdb-6.8/sim/ppc/debug.h
+--- gdb-6.8.orig/sim/ppc/debug.h 1999-04-16 03:35:08.000000000 +0200
++++ gdb-6.8/sim/ppc/debug.h 2008-09-17 16:33:00.000000000 +0200
+@@ -51,6 +51,8 @@
+ trace_pal_device,
+ trace_pass_device,
+ trace_phb_device,
++ trace_sem_device,
++ trace_shm_device,
+ trace_stack_device,
+ trace_register_device,
+ trace_vm_device,
+diff -Naur gdb-6.8.orig/sim/ppc/hw_sem.c gdb-6.8/sim/ppc/hw_sem.c
+--- gdb-6.8.orig/sim/ppc/hw_sem.c 1970-01-01 01:00:00.000000000 +0100
++++ gdb-6.8/sim/ppc/hw_sem.c 2008-09-17 16:33:00.000000000 +0200
+@@ -0,0 +1,301 @@
++/* This file is part of the program psim.
++
++ Copyright (C) 1997,2008, Joel Sherrill <joel@OARcorp.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++ */
++
++
++#ifndef _HW_SEM_C_
++#define _HW_SEM_C_
++
++#include "device_table.h"
++
++#ifdef HAVE_STRING_H
++#include <string.h>
++#else
++#ifdef HAVE_STRINGS_H
++#include <strings.h>
++#endif
++#endif
++
++#include <sys/ipc.h>
++#include <sys/sem.h>
++
++#include <errno.h>
++
++/* DEVICE
++
++
++ sem - provide access to a unix semaphore
++
++
++ DESCRIPTION
++
++
++ This device implements an interface to a unix semaphore.
++
++
++ PROPERTIES
++
++
++ reg = <address> <size> (required)
++
++ Determine where the memory lives in the parents address space.
++
++ key = <integer> (required)
++
++ This is the key of the unix semaphore.
++
++ EXAMPLES
++
++
++ Enable tracing of the sem:
++
++ | bash$ psim -t sem-device \
++
++
++ Configure a UNIX semaphore using key 0x12345678 mapped into psim
++ address space at 0xfff00000:
++
++ | -o '/sem@0xfff00000/reg 0xfff00000 0x80000' \
++ | -o '/sem@0xfff00000/key 0x12345678' \
++
++ sim/ppc/run -o '/#address-cells 1' \
++ -o '/sem@0xc0000000/reg 0xc0000000 0x80000' \
++ -o '/sem@0xc0000000/key 0x12345678' ../psim-hello/hello
++
++ REGISTERS
++
++ offset 0 - lock count
++ offset 4 - lock operation
++ offset 8 - unlock operation
++
++ All reads return the current or resulting count.
++
++ BUGS
++
++ None known.
++
++ */
++
++typedef struct _hw_sem_device {
++ unsigned_word physical_address;
++ key_t key;
++ int id;
++ int initial;
++ int count;
++} hw_sem_device;
++
++static void
++hw_sem_init_data(device *me)
++{
++ hw_sem_device *sem = (hw_sem_device*)device_data(me);
++ const device_unit *d;
++ int status;
++#if !HAS_UNION_SEMUN
++ union semun {
++ int val;
++ struct semid_ds *buf;
++ unsigned short int *array;
++#if defined(__linux__)
++ struct seminfo *__buf;
++#endif
++ } ;
++#endif
++ union semun help;
++
++ /* initialize the properties of the sem */
++
++ if (device_find_property(me, "key") == NULL)
++ error("sem_init_data() required key property is missing\n");
++
++ if (device_find_property(me, "value") == NULL)
++ error("sem_init_data() required value property is missing\n");
++
++ sem->key = (key_t) device_find_integer_property(me, "key");
++ DTRACE(sem, ("semaphore key (%d)\n", sem->key) );
++
++ sem->initial = (int) device_find_integer_property(me, "value");
++ DTRACE(sem, ("semaphore initial value (%d)\n", sem->initial) );
++
++ d = device_unit_address(me);
++ sem->physical_address = d->cells[ d->nr_cells-1 ];
++ DTRACE(sem, ("semaphore physical_address=0x%x\n", sem->physical_address));
++
++ /* Now to initialize the semaphore */
++
++ if ( sem->initial != -1 ) {
++
++ sem->id = semget(sem->key, 1, IPC_CREAT | 0660);
++ if (sem->id == -1)
++ error("hw_sem_init_data() semget failed\n");
++
++ help.val = sem->initial;
++ status = semctl( sem->id, 0, SETVAL, help );
++ if (status == -1)
++ error("hw_sem_init_data() semctl -- set value failed\n");
++
++ } else {
++ sem->id = semget(sem->key, 1, 0660);
++ if (sem->id == -1)
++ error("hw_sem_init_data() semget failed\n");
++ }
++
++ sem->count = semctl( sem->id, 0, GETVAL, help );
++ if (sem->count == -1)
++ error("hw_sem_init_data() semctl -- get value failed\n");
++ DTRACE(sem, ("semaphore OS value (%d)\n", sem->count) );
++
++ if (sizeof(int) != 4)
++ error("hw_sem_init_data() typing problem\n");
++}
++
++static void
++hw_sem_attach_address_callback(device *me,
++ attach_type attach,
++ int space,
++ unsigned_word addr,
++ unsigned nr_bytes,
++ access_type access,
++ device *client) /*callback/default*/
++{
++ hw_sem_device *sem = (hw_sem_device*)device_data(me);
++
++ if (space != 0)
++ error("sem_attach_address_callback() invalid address space\n");
++
++ if (nr_bytes == 12)
++ error("sem_attach_address_callback() invalid size\n");
++
++ sem->physical_address = addr;
++ DTRACE(sem, ("semaphore physical_address=0x%x\n", addr));
++}
++
++static unsigned
++hw_sem_io_read_buffer(device *me,
++ void *dest,
++ int space,
++ unsigned_word addr,
++ unsigned nr_bytes,
++ cpu *processor,
++ unsigned_word cia)
++{
++ hw_sem_device *sem = (hw_sem_device*)device_data(me);
++ struct sembuf sb;
++ int status;
++ unsigned32 u32;
++#if !HAS_UNION_SEMUN
++ union semun {
++ int val;
++ struct semid_ds *buf;
++ unsigned short int *array;
++#if defined(__linux__)
++ struct seminfo *__buf;
++#endif
++ } ;
++#endif
++ union semun help;
++
++ /* do we need to worry about out of range addresses? */
++
++ DTRACE(sem, ("semaphore read addr=0x%x length=%d\n", addr, nr_bytes));
++
++ if (!(addr >= sem->physical_address && addr <= sem->physical_address + 11))
++ error("hw_sem_io_read_buffer() invalid address - out of range\n");
++
++ if ((addr % 4) != 0)
++ error("hw_sem_io_read_buffer() invalid address - alignment\n");
++
++ if (nr_bytes != 4)
++ error("hw_sem_io_read_buffer() invalid length\n");
++
++ switch ( (addr - sem->physical_address) / 4 ) {
++
++ case 0: /* OBTAIN CURRENT VALUE */
++ break;
++
++ case 1: /* LOCK */
++ sb.sem_num = 0;
++ sb.sem_op = -1;
++ sb.sem_flg = 0;
++
++ status = semop(sem->id, &sb, 1);
++ if (status == -1) {
++ perror( "hw_sem.c: lock" );
++ error("hw_sem_io_read_buffer() sem lock\n");
++ }
++
++ DTRACE(sem, ("semaphore lock %d\n", sem->count));
++ break;
++
++ case 2: /* UNLOCK */
++ sb.sem_num = 0;
++ sb.sem_op = 1;
++ sb.sem_flg = 0;
++
++ status = semop(sem->id, &sb, 1);
++ if (status == -1) {
++ perror( "hw_sem.c: unlock" );
++ error("hw_sem_io_read_buffer() sem unlock\n");
++ }
++ DTRACE(sem, ("semaphore unlock %d\n", sem->count));
++ break;
++
++ default:
++ error("hw_sem_io_read_buffer() invalid address - unknown error\n");
++ break;
++ }
++
++ /* assume target is big endian */
++ u32 = H2T_4(semctl( sem->id, 0, GETVAL, help ));
++
++ DTRACE(sem, ("semaphore OS value (%d)\n", u32) );
++ if (u32 == 0xffffffff) {
++ perror( "hw_sem.c: getval" );
++ error("hw_sem_io_read_buffer() semctl -- get value failed\n");
++ }
++
++ memcpy(dest, &u32, nr_bytes);
++ return nr_bytes;
++
++}
++
++static device_callbacks const hw_sem_callbacks = {
++ { generic_device_init_address, hw_sem_init_data },
++ { hw_sem_attach_address_callback, }, /* address */
++ { hw_sem_io_read_buffer, NULL }, /* IO */
++ { NULL, }, /* DMA */
++ { NULL, }, /* interrupt */
++ { NULL, }, /* unit */
++ NULL,
++};
++
++static void *
++hw_sem_create(const char *name,
++ const device_unit *unit_address,
++ const char *args)
++{
++ hw_sem_device *sem = ZALLOC(hw_sem_device);
++ return sem;
++}
++
++const device_descriptor hw_sem_device_descriptor[] = {
++ { "sem", hw_sem_create, &hw_sem_callbacks },
++ { NULL },
++};
++
++#endif /* _HW_SEM_C_ */
+diff -Naur gdb-6.8.orig/sim/ppc/hw_shm.c gdb-6.8/sim/ppc/hw_shm.c
+--- gdb-6.8.orig/sim/ppc/hw_shm.c 1970-01-01 01:00:00.000000000 +0100
++++ gdb-6.8/sim/ppc/hw_shm.c 2008-09-17 16:33:00.000000000 +0200
+@@ -0,0 +1,236 @@
++/* This file is part of the program psim.
++
++ Copyright (C) 1997,2008, Joel Sherrill <joel@OARcorp.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++ */
++
++
++#ifndef _HW_SHM_C_
++#define _HW_SHM_C_
++
++#include "device_table.h"
++
++#ifdef HAVE_STRING_H
++#include <string.h>
++#else
++#ifdef HAVE_STRINGS_H
++#include <strings.h>
++#endif
++#endif
++
++#include <sys/ipc.h>
++#include <sys/shm.h>
++
++
++/* DEVICE
++
++
++ shm - map unix shared memory into psim address space
++
++
++ DESCRIPTION
++
++
++ This device implements an area of memory which is mapped into UNIX
++ shared memory.
++
++
++ PROPERTIES
++
++
++ reg = <address> <size> (required)
++
++ Determine where the memory lives in the parents address space.
++ The SHM area is assumed to be of the same length.
++
++ key = <integer> (required)
++
++ This is the key of the unix shared memory area.
++
++ EXAMPLES
++
++
++ Enable tracing of the shm:
++
++ | bash$ psim -t shm-device \
++
++
++ Configure a 512 kilobytes of UNIX shared memory with the key 0x12345678
++ mapped into psim address space at 0x0c000000.
++
++ | -o '/shm@0x0c000000/reg 0x0c000000 0x80000' \
++ | -o '/shm@0x0c000000/key 0x12345678' \
++
++ sim/ppc/run -o '/#address-cells 1' \
++ -o '/shm@0x0c000000/reg 0x0c000000 0x80000' \
++ -o '/shm@0x0c000000/key 0x12345678' ../psim-hello/hello
++
++ BUGS
++
++ None known.
++
++ */
++
++typedef struct _hw_shm_device {
++ unsigned_word physical_address;
++ char *shm_address;
++ unsigned sizeof_memory;
++ key_t key;
++ int id;
++} hw_shm_device;
++
++static void
++hw_shm_init_data(device *me)
++{
++ hw_shm_device *shm = (hw_shm_device*)device_data(me);
++ const device_unit *d;
++ reg_property_spec reg;
++ int i;
++
++ /* Obtain the Key Value */
++ if (device_find_property(me, "key") == NULL)
++ error("shm_init_data() required key property is missing\n");
++
++ shm->key = (key_t) device_find_integer_property(me, "key");
++ DTRACE(shm, ("shm key (0x%08x)\n", shm->key) );
++
++ /* Figure out where this memory is in address space and how long it is */
++ if ( !device_find_reg_array_property(me, "reg", 0, &reg) )
++ error("hw_shm_init_data() no address registered\n");
++
++ /* Determine the address and length being as paranoid as possible */
++ shm->physical_address = 0xffffffff;
++ shm->sizeof_memory = 0xffffffff;
++
++ for ( i=0 ; i<reg.address.nr_cells; i++ ) {
++ if (reg.address.cells[0] == 0 && reg.size.cells[0] == 0)
++ continue;
++
++ if ( shm->physical_address != 0xffffffff )
++ device_error(me, "Only single celled address ranges supported\n");
++
++ shm->physical_address = reg.address.cells[i];
++ DTRACE(shm, ("shm physical_address=0x%x\n", shm->physical_address));
++
++ shm->sizeof_memory = reg.size.cells[i];
++ DTRACE(shm, ("shm length=0x%x\n", shm->sizeof_memory));
++ }
++
++ if ( shm->physical_address == 0xffffffff )
++ device_error(me, "Address not specified\n" );
++
++ if ( shm->sizeof_memory == 0xffffffff )
++ device_error(me, "Length not specified\n" );
++
++ /* Now actually attach to or create the shared memory area */
++ shm->id = shmget(shm->key, shm->sizeof_memory, IPC_CREAT | 0660);
++ if (shm->id == -1)
++ error("hw_shm_init_data() shmget failed\n");
++
++ shm->shm_address = shmat(shm->id, (char *)0, SHM_RND);
++ if (shm->shm_address == (void *)-1)
++ error("hw_shm_init_data() shmat failed\n");
++}
++
++static void
++hw_shm_attach_address_callback(device *me,
++ attach_type attach,
++ int space,
++ unsigned_word addr,
++ unsigned nr_bytes,
++ access_type access,
++ device *client) /*callback/default*/
++{
++ hw_shm_device *shm = (hw_shm_device*)device_data(me);
++
++ if (space != 0)
++ error("shm_attach_address_callback() invalid address space\n");
++
++ if (nr_bytes == 0)
++ error("shm_attach_address_callback() invalid size\n");
++}
++
++
++static unsigned
++hw_shm_io_read_buffer(device *me,
++ void *dest,
++ int space,
++ unsigned_word addr,
++ unsigned nr_bytes,
++ cpu *processor,
++ unsigned_word cia)
++{
++ hw_shm_device *shm = (hw_shm_device*)device_data(me);
++
++ /* do we need to worry about out of range addresses? */
++
++ DTRACE(shm, ("read %p %x %x %x\n", \
++ shm->shm_address, shm->physical_address, addr, nr_bytes) );
++
++ memcpy(dest, &shm->shm_address[addr - shm->physical_address], nr_bytes);
++ return nr_bytes;
++}
++
++
++static unsigned
++hw_shm_io_write_buffer(device *me,
++ const void *source,
++ int space,
++ unsigned_word addr,
++ unsigned nr_bytes,
++ cpu *processor,
++ unsigned_word cia)
++{
++ hw_shm_device *shm = (hw_shm_device*)device_data(me);
++
++ /* do we need to worry about out of range addresses? */
++
++ DTRACE(shm, ("write %p %x %x %x\n", \
++ shm->shm_address, shm->physical_address, addr, nr_bytes) );
++
++ memcpy(&shm->shm_address[addr - shm->physical_address], source, nr_bytes);
++ return nr_bytes;
++}
++
++static device_callbacks const hw_shm_callbacks = {
++ { generic_device_init_address, hw_shm_init_data },
++ { hw_shm_attach_address_callback, }, /* address */
++ { hw_shm_io_read_buffer,
++ hw_shm_io_write_buffer }, /* IO */
++ { NULL, }, /* DMA */
++ { NULL, }, /* interrupt */
++ { NULL, }, /* unit */
++ NULL,
++};
++
++static void *
++hw_shm_create(const char *name,
++ const device_unit *unit_address,
++ const char *args)
++{
++ hw_shm_device *shm = ZALLOC(hw_shm_device);
++ return shm;
++}
++
++
++
++const device_descriptor hw_shm_device_descriptor[] = {
++ { "shm", hw_shm_create, &hw_shm_callbacks },
++ { NULL },
++};
++
++#endif /* _HW_SHM_C_ */
+diff -Naur gdb-6.8.orig/sim/ppc/Makefile.in gdb-6.8/sim/ppc/Makefile.in
+--- gdb-6.8.orig/sim/ppc/Makefile.in 2006-05-31 17:14:45.000000000 +0200
++++ gdb-6.8/sim/ppc/Makefile.in 2008-09-17 16:33:00.000000000 +0200
+@@ -834,6 +834,8 @@
+ hw_pal.o: hw_pal.c $(DEVICE_TABLE_H) $(CPU_H)
+ hw_phb.o: hw_phb.c $(DEVICE_TABLE_H) $(HW_PHB_H) $(COREFILE_H)
+ hw_register.o: hw_register.c $(DEVICE_TABLE_H) $(PSIM_H)
++hw_sem.o: hw_sem.c $(DEVICE_TABLE_H) $(PSIM_H)
++hw_shm.o: hw_shm.c $(DEVICE_TABLE_H) $(PSIM_H)
+ hw_trace.o: hw_trace.c $(DEVICE_TABLE_H)
+ hw_vm.o: hw_vm.c $(DEVICE_TABLE_H) $(CPU_H)
+ # ignore this line, it stops make from getting confused
+diff -Naur gdb-6.8.orig/sim/ppc/ppc-instructions gdb-6.8/sim/ppc/ppc-instructions
+--- gdb-6.8.orig/sim/ppc/ppc-instructions 2006-11-29 16:20:55.000000000 +0100
++++ gdb-6.8/sim/ppc/ppc-instructions 2008-09-17 16:33:00.000000000 +0200
+@@ -3402,6 +3402,14 @@
+ case spr_dec:
+ *rT = cpu_get_decrementer(processor);
+ break;
++ case spr_tbrl:
++ if (is_64bit_implementation) *rT = TB;
++ else *rT = EXTRACTED64(TB, 32, 63);
++ break;
++ case spr_tbru:
++ if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
++ else *rT = EXTRACTED64(TB, 0, 31);
++ break;
+ case spr_tbu:
+ case spr_tbl:
+ /* NOTE - these SPR's are not readable. Use mftb[ul] */
+diff -Naur gdb-6.8.orig/sim/ppc/ppc-spr-table gdb-6.8/sim/ppc/ppc-spr-table
+--- gdb-6.8.orig/sim/ppc/ppc-spr-table 2003-06-22 18:48:12.000000000 +0200
++++ gdb-6.8/sim/ppc/ppc-spr-table 2008-09-17 16:33:00.000000000 +0200
+@@ -32,6 +32,8 @@
+ SRR0:26:0:0
+ SRR1:27:0:0
+ VRSAVE:256:0:0
++TBRL:268:0:0
++TBRU:269:0:0
+ SPRG0:272:0:0
+ SPRG1:273:0:0
+ SPRG2:274:0:0