From aa9a6dce1c3a7728ef2b4c8a5bc0020ef32d9d14 Mon Sep 17 00:00:00 2001 From: Ralf Corsepius Date: Wed, 17 Sep 2008 14:34:15 +0000 Subject: Add patch from http://sourceware.org/ml/gdb-patches/2008-02/msg00472.html --- .../patches/gdb-6.8-rtems4.10-20080917.diff | 13354 +++++++++++++++++++ 1 file changed, 13354 insertions(+) create mode 100644 contrib/crossrpms/patches/gdb-6.8-rtems4.10-20080917.diff (limited to 'contrib') 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, _("")); ++ 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 . */ ++ ++#include "defs.h" ++#include ++#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 - , 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 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 . ++ */ ++ ++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 ( - ). ++ 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 (¤t_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", ""); ++ 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", ""); ++ if (b->loc == NULL || loc->shlib_disabled) ++ ui_out_field_string (uiout, "addr", ""); ++ 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 : ""); ++ 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(), 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 = ¬_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 = ©_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 \n\ ++ stop at \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 \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 \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 ' 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 ' 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 ++ 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 " 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 ++ ++ 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 ++ ++ 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 ++ catch load ++ catch load if ++ ++ The user is not allowed to specify the 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 ++ catch unload ++ catch unload if ++ ++ The user is not allowed to specify the 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 */ ++ ++ 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 = ¬_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 - a particular signal\n\ ++Raised exceptions may be caught:\n\ ++\tcatch throw - all exceptions, when thrown\n\ ++\tcatch throw - a particular exception, when thrown\n\ ++\tcatch catch - all exceptions, when caught\n\ ++\tcatch catch - 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 - loads of a particular library\n\ ++\tcatch unload - unloads of any library\n\ ++\tcatch unload - 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 - 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 Return the program state to a ++ previously saved state. ++ ++info checkpoints List currently saved checkpoints. ++ ++delete-checkpoint 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 Switch to debugging one of several ++ forks of the user program that are ++ available to be debugged. ++ ++delete-fork Delete a fork from the list of forks ++ that are available to be debugged (and ++ kill the forked process). ++ ++detach-fork 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 , 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 " ++ ++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.). ++ ++* 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 ++``| '' 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#". 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
" 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 ++ load ++ target remote :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 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 + #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 + #include ++#include + #include + #include + #include +@@ -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 ++#include ++#include ], ++[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 ++ #include ++ #include ++ 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 ++ #include ++ #include ++ 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 ++#include ++#include ++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 ++ ++ 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 ++#else ++#ifdef HAVE_STRINGS_H ++#include ++#endif ++#endif ++ ++#include ++#include ++ ++#include ++ ++/* DEVICE ++ ++ ++ sem - provide access to a unix semaphore ++ ++ ++ DESCRIPTION ++ ++ ++ This device implements an interface to a unix semaphore. ++ ++ ++ PROPERTIES ++ ++ ++ reg =
(required) ++ ++ Determine where the memory lives in the parents address space. ++ ++ key = (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 ++ ++ 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 ++#else ++#ifdef HAVE_STRINGS_H ++#include ++#endif ++#endif ++ ++#include ++#include ++ ++ ++/* 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 =
(required) ++ ++ Determine where the memory lives in the parents address space. ++ The SHM area is assumed to be of the same length. ++ ++ key = (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, ®) ) ++ 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 ; iphysical_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 -- cgit v1.2.3