X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fbreakpoint.c;h=1c0a417bd1ad62c940df5b50b85960a53abac9c7;hb=eb822aa6d0f2cdc1a3125da084b96c5bbe32cb86;hp=b98ca9e100e3c8751d73c51042cde5abc4bd5d22;hpb=dfd4cc6311a8cf56cd6f4e0249fc243cface5a7f;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index b98ca9e100..1c0a417bd1 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -1,6 +1,6 @@ /* Everything about breakpoints, for GDB. - Copyright (C) 1986-2013 Free Software Foundation, Inc. + Copyright (C) 1986-2014 Free Software Foundation, Inc. This file is part of GDB. @@ -32,10 +32,10 @@ #include "value.h" #include "command.h" #include "inferior.h" +#include "infrun.h" #include "gdbthread.h" #include "target.h" #include "language.h" -#include "gdb_string.h" #include "gdb-demangle.h" #include "filenames.h" #include "annotate.h" @@ -47,12 +47,10 @@ #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" @@ -66,7 +64,6 @@ #include "continuations.h" #include "stack.h" #include "skip.h" -#include "gdb_regex.h" #include "ax-gdb.h" #include "dummy-frame.h" @@ -80,7 +77,7 @@ #undef savestring #include "mi/mi-common.h" -#include "python/python.h" +#include "extension.h" /* Enums for exception-handling support. */ enum exception_event_kind @@ -154,7 +151,8 @@ struct breakpoint *set_raw_breakpoint (struct gdbarch *gdbarch, static struct breakpoint * momentary_breakpoint_from_master (struct breakpoint *orig, enum bptype type, - const struct breakpoint_ops *ops); + const struct breakpoint_ops *ops, + int loc_enabled); static void breakpoint_adjustment_warning (CORE_ADDR, CORE_ADDR, int, int); @@ -166,11 +164,6 @@ static void describe_other_breakpoints (struct gdbarch *, struct program_space *, CORE_ADDR, struct obj_section *, int); -static int breakpoint_address_match (struct address_space *aspace1, - CORE_ADDR addr1, - struct address_space *aspace2, - CORE_ADDR addr2); - static int watchpoint_locations_match (struct bp_location *loc1, struct bp_location *loc2); @@ -232,20 +225,50 @@ static void stopat_command (char *arg, int from_tty); static void tcatch_command (char *arg, int from_tty); -static void detach_single_step_breakpoints (void); - -static int single_step_breakpoint_inserted_here_p (struct address_space *, - CORE_ADDR pc); - static void free_bp_location (struct bp_location *loc); static void incref_bp_location (struct bp_location *loc); static void decref_bp_location (struct bp_location **loc); static struct bp_location *allocate_bp_location (struct breakpoint *bpt); -static void update_global_location_list (int); +/* update_global_location_list's modes of operation wrt to whether to + insert locations now. */ +enum ugll_insert_mode +{ + /* Don't insert any breakpoint locations into the inferior, only + remove already-inserted locations that no longer should be + inserted. Functions that delete a breakpoint or breakpoints + should specify this mode, so that deleting a breakpoint doesn't + have the side effect of inserting the locations of other + breakpoints that are marked not-inserted, but should_be_inserted + returns true on them. + + This behavior is useful is situations close to tear-down -- e.g., + after an exec, while the target still has execution, but + breakpoint shadows of the previous executable image should *NOT* + be restored to the new image; or before detaching, where the + target still has execution and wants to delete breakpoints from + GDB's lists, and all breakpoints had already been removed from + the inferior. */ + UGLL_DONT_INSERT, + + /* May insert breakpoints iff breakpoints_should_be_inserted_now + claims breakpoints should be inserted now. */ + UGLL_MAY_INSERT, + + /* Insert locations now, irrespective of + breakpoints_should_be_inserted_now. E.g., say all threads are + stopped right now, and the user did "continue". We need to + insert breakpoints _before_ resuming the target, but + UGLL_MAY_INSERT wouldn't insert them, because + breakpoints_should_be_inserted_now returns false at that point, + as no thread is running yet. */ + UGLL_INSERT +}; -static void update_global_location_list_nothrow (int); +static void update_global_location_list (enum ugll_insert_mode); + +static void update_global_location_list_nothrow (enum ugll_insert_mode); static int is_hardware_watchpoint (const struct breakpoint *bpt); @@ -421,34 +444,48 @@ show_automatic_hardware_breakpoints (struct ui_file *file, int from_tty, value); } -/* If on, gdb will keep breakpoints inserted even as inferior is - stopped, and immediately insert any new breakpoints. If off, gdb - will insert breakpoints into inferior only when resuming it, and - will remove breakpoints upon stop. If auto, GDB will behave as ON - if in non-stop mode, and as OFF if all-stop mode.*/ - -static enum auto_boolean always_inserted_mode = AUTO_BOOLEAN_AUTO; +/* If on, GDB keeps breakpoints inserted even if the inferior is + stopped, and immediately inserts any new breakpoints as soon as + they're created. If off (default), GDB keeps breakpoints off of + the target as long as possible. That is, it delays inserting + breakpoints until the next resume, and removes them again when the + target fully stops. This is a bit safer in case GDB crashes while + processing user input. */ +static int always_inserted_mode = 0; static void show_always_inserted_mode (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - if (always_inserted_mode == AUTO_BOOLEAN_AUTO) - fprintf_filtered (file, - _("Always inserted breakpoint " - "mode is %s (currently %s).\n"), - value, - breakpoints_always_inserted_mode () ? "on" : "off"); - else - fprintf_filtered (file, _("Always inserted breakpoint mode is %s.\n"), - value); + fprintf_filtered (file, _("Always inserted breakpoint mode is %s.\n"), + value); } +/* See breakpoint.h. */ + int -breakpoints_always_inserted_mode (void) +breakpoints_should_be_inserted_now (void) { - return (always_inserted_mode == AUTO_BOOLEAN_TRUE - || (always_inserted_mode == AUTO_BOOLEAN_AUTO && non_stop)); + if (gdbarch_has_global_breakpoints (target_gdbarch ())) + { + /* If breakpoints are global, they should be inserted even if no + thread under gdb's control is running, or even if there are + no threads under GDB's control yet. */ + return 1; + } + else if (target_has_execution) + { + if (always_inserted_mode) + { + /* The user wants breakpoints inserted even if all threads + are stopped. */ + return 1; + } + + if (threads_are_executing ()) + return 1; + } + return 0; } static const char condition_evaluation_both[] = "host or target"; @@ -835,7 +872,7 @@ set_condition_evaluation_mode (char *args, int from_tty, } /* Do the update. */ - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); } return; @@ -1048,18 +1085,22 @@ condition_command (char *arg, int from_tty) ALL_BREAKPOINTS (b) if (b->number == bnum) { - /* Check if this breakpoint has a Python object assigned to - it, and if it has a definition of the "stop" - method. This method and conditions entered into GDB from - the CLI are mutually exclusive. */ - if (b->py_bp_object - && gdbpy_breakpoint_has_py_cond (b->py_bp_object)) - error (_("Cannot set a condition where a Python 'stop' " - "method has been defined in the breakpoint.")); + /* Check if this breakpoint has a "stop" method implemented in an + extension language. This method and conditions entered into GDB + from the CLI are mutually exclusive. */ + const struct extension_language_defn *extlang + = get_breakpoint_cond_ext_lang (b, EXT_LANG_NONE); + + if (extlang != NULL) + { + error (_("Only one stop condition allowed. There is currently" + " a %s stop condition defined for this breakpoint."), + ext_lang_capitalized_name (extlang)); + } set_breakpoint_condition (b, p, from_tty); if (is_breakpoint (b)) - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); return; } @@ -1414,6 +1455,100 @@ bp_location_has_shadow (struct bp_location *bl) return 1; } +/* Update BUF, which is LEN bytes read from the target address + MEMADDR, by replacing a memory breakpoint with its shadowed + contents. + + If READBUF is not NULL, this buffer must not overlap with the of + the breakpoint location's shadow_contents buffer. Otherwise, a + failed assertion internal error will be raised. */ + +static void +one_breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf, + const gdb_byte *writebuf_org, + ULONGEST memaddr, LONGEST len, + struct bp_target_info *target_info, + struct gdbarch *gdbarch) +{ + /* Now do full processing of the found relevant range of elements. */ + CORE_ADDR bp_addr = 0; + int bp_size = 0; + int bptoffset = 0; + + if (!breakpoint_address_match (target_info->placed_address_space, 0, + current_program_space->aspace, 0)) + { + /* The breakpoint is inserted in a different address space. */ + return; + } + + /* Addresses and length of the part of the breakpoint that + we need to copy. */ + bp_addr = target_info->placed_address; + bp_size = target_info->shadow_len; + + if (bp_addr + bp_size <= memaddr) + { + /* The breakpoint is entirely before the chunk of memory we are + reading. */ + return; + } + + if (bp_addr >= memaddr + len) + { + /* The breakpoint is entirely after the chunk of memory we are + reading. */ + return; + } + + /* Offset within shadow_contents. */ + 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); + } + + if (readbuf != NULL) + { + /* Verify that the readbuf buffer does not overlap with the + shadow_contents buffer. */ + gdb_assert (target_info->shadow_contents >= readbuf + len + || readbuf >= (target_info->shadow_contents + + target_info->shadow_len)); + + /* Update the read buffer with this inserted breakpoint's + shadow. */ + memcpy (readbuf + bp_addr - memaddr, + target_info->shadow_contents + bptoffset, bp_size); + } + else + { + const unsigned char *bp; + CORE_ADDR addr = target_info->reqstd_address; + int placed_size; + + /* Update the shadow with what we want to write to memory. */ + memcpy (target_info->shadow_contents + bptoffset, + writebuf_org + bp_addr - memaddr, bp_size); + + /* Determine appropriate breakpoint contents and size for this + address. */ + bp = gdbarch_breakpoint_from_pc (gdbarch, &addr, &placed_size); + + /* Update the final write buffer with this inserted + breakpoint's INSN. */ + memcpy (writebuf + bp_addr - memaddr, bp + bptoffset, bp_size); + } +} + /* Update BUF, which is LEN bytes read from the target address MEMADDR, by replacing any memory breakpoints with their shadowed contents. @@ -1440,6 +1575,7 @@ breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf, /* Left boundary, right boundary and median element of our binary search. */ unsigned bc_l, bc_r, bc; + size_t i; /* Find BC_L which is a leftmost element which may affect BUF content. It is safe to report lower value but a failure to @@ -1513,74 +1649,12 @@ breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf, if (!bp_location_has_shadow (bl)) continue; - if (!breakpoint_address_match (bl->target_info.placed_address_space, 0, - current_program_space->aspace, 0)) - continue; - /* Addresses and length of the part of the breakpoint that - we need to copy. */ - bp_addr = bl->target_info.placed_address; - bp_size = bl->target_info.shadow_len; - - 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; - - /* Offset within shadow_contents. */ - 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); - } - - if (readbuf != NULL) - { - /* Verify that the readbuf buffer does not overlap with - the shadow_contents buffer. */ - gdb_assert (bl->target_info.shadow_contents >= readbuf + len - || readbuf >= (bl->target_info.shadow_contents - + bl->target_info.shadow_len)); - - /* Update the read buffer with this inserted breakpoint's - shadow. */ - memcpy (readbuf + bp_addr - memaddr, - bl->target_info.shadow_contents + bptoffset, bp_size); - } - else - { - struct gdbarch *gdbarch = bl->gdbarch; - const unsigned char *bp; - CORE_ADDR placed_address = bl->target_info.placed_address; - int placed_size = bl->target_info.placed_size; - - /* Update the shadow with what we want to write to memory. */ - memcpy (bl->target_info.shadow_contents + bptoffset, - writebuf_org + bp_addr - memaddr, bp_size); - - /* Determine appropriate breakpoint contents and size for this - address. */ - bp = gdbarch_breakpoint_from_pc (gdbarch, &placed_address, &placed_size); - - /* Update the final write buffer with this inserted - breakpoint's INSN. */ - memcpy (writebuf + bp_addr - memaddr, bp + bptoffset, bp_size); - } + one_breakpoint_xfer_memory (readbuf, writebuf, writebuf_org, + memaddr, len, &bl->target_info, bl->gdbarch); } } + /* Return true if BPT is either a software breakpoint or a hardware @@ -1651,6 +1725,29 @@ watchpoint_del_at_next_stop (struct watchpoint *w) b->disposition = disp_del_at_next_stop; } +/* Extract a bitfield value from value VAL using the bit parameters contained in + watchpoint W. */ + +static struct value * +extract_bitfield_from_watchpoint_value (struct watchpoint *w, struct value *val) +{ + struct value *bit_val; + + if (val == NULL) + return NULL; + + bit_val = allocate_value (value_type (val)); + + unpack_value_bitfield (bit_val, + w->val_bitpos, + w->val_bitsize, + value_contents_for_printing (val), + value_offset (val), + val); + + return bit_val; +} + /* Assuming that B is a watchpoint: - Reparse watchpoint expression, if REPARSE is non-zero - Evaluate expression and store the result in B->val @@ -1795,11 +1892,19 @@ update_watchpoint (struct watchpoint *b, int reparse) 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 ( !target_has_execution) + if (!target_has_execution) { /* Without execution, memory can't change. No use to try and set watchpoint locations. The watchpoint will be reset when the target gains execution, through breakpoint_re_set. */ + if (!can_use_hw_watchpoints) + { + if (b->base.ops->works_in_software_mode (&b->base)) + b->base.type = bp_watchpoint; + else + error (_("Can't set read/access watchpoint when " + "hardware watchpoints are disabled.")); + } } else if (within_current_scope && b->exp) { @@ -1817,6 +1922,12 @@ update_watchpoint (struct watchpoint *b, int reparse) watchpoints. */ if (!b->val_valid && !is_masked_watchpoint (&b->base)) { + if (b->val_bitsize != 0) + { + v = extract_bitfield_from_watchpoint_value (b, v); + if (v != NULL) + release_value (v); + } b->val = v; b->val_valid = 1; } @@ -1846,8 +1957,31 @@ update_watchpoint (struct watchpoint *b, int reparse) CORE_ADDR addr; int type; struct bp_location *loc, **tmp; + int bitpos = 0, bitsize = 0; + + if (value_bitsize (v) != 0) + { + /* Extract the bit parameters out from the bitfield + sub-expression. */ + bitpos = value_bitpos (v); + bitsize = value_bitsize (v); + } + else if (v == result && b->val_bitsize != 0) + { + /* If VAL_BITSIZE != 0 then RESULT is actually a bitfield + lvalue whose bit parameters are saved in the fields + VAL_BITPOS and VAL_BITSIZE. */ + bitpos = b->val_bitpos; + bitsize = b->val_bitsize; + } addr = value_address (v); + if (bitsize != 0) + { + /* Skip the bytes that don't contain the bitfield. */ + addr += bitpos / 8; + } + type = hw_write; if (b->base.type == bp_read_watchpoint) type = hw_read; @@ -1862,7 +1996,15 @@ update_watchpoint (struct watchpoint *b, int reparse) loc->pspace = frame_pspace; loc->address = addr; - loc->length = TYPE_LENGTH (value_type (v)); + + if (bitsize != 0) + { + /* Just cover the bytes that make up the bitfield. */ + loc->length = ((bitpos % 8) + bitsize + 7) / 8; + } + else + loc->length = TYPE_LENGTH (value_type (v)); + loc->watchpoint_type = type; } } @@ -1939,8 +2081,14 @@ update_watchpoint (struct watchpoint *b, int reparse) } } else if (!b->base.ops->works_in_software_mode (&b->base)) - error (_("Expression cannot be implemented with " - "read/access watchpoint.")); + { + if (!can_use_hw_watchpoints) + error (_("Can't set read/access watchpoint when " + "hardware watchpoints are disabled.")); + else + error (_("Expression cannot be implemented with " + "read/access watchpoint.")); + } else b->base.type = bp_watchpoint; @@ -2017,6 +2165,39 @@ should_be_inserted (struct bp_location *bl) if (bl->pspace->breakpoints_not_allowed) return 0; + /* Don't insert a breakpoint if we're trying to step past its + location. */ + if ((bl->loc_type == bp_loc_software_breakpoint + || bl->loc_type == bp_loc_hardware_breakpoint) + && stepping_past_instruction_at (bl->pspace->aspace, + bl->address)) + { + if (debug_infrun) + { + fprintf_unfiltered (gdb_stdlog, + "infrun: skipping breakpoint: " + "stepping past insn at: %s\n", + paddress (bl->gdbarch, bl->address)); + } + return 0; + } + + /* Don't insert watchpoints if we're trying to step past the + instruction that triggered one. */ + if ((bl->loc_type == bp_loc_hardware_watchpoint) + && stepping_past_nonsteppable_watchpoint ()) + { + if (debug_infrun) + { + fprintf_unfiltered (gdb_stdlog, + "infrun: stepping past non-steppable watchpoint. " + "skipping watchpoint at %s:%d\n", + paddress (bl->gdbarch, bl->address), + bl->length); + } + return 0; + } + return 1; } @@ -2082,6 +2263,9 @@ build_target_condition_list (struct bp_location *bl) int modified = bl->needs_update; struct bp_location *loc; + /* Release conditions left over from a previous insert. */ + VEC_free (agent_expr_p, bl->target_info.conditions); + /* This is only meaningful if the target is evaluating conditions and if the user has opted for condition evaluation on the target's @@ -2273,14 +2457,29 @@ build_target_command_list (struct bp_location *bl) int modified = bl->needs_update; struct bp_location *loc; - /* For now, limit to agent-style dprintf breakpoints. */ - if (bl->owner->type != bp_dprintf - || strcmp (dprintf_style, dprintf_style_agent) != 0) - return; + /* Release commands left over from a previous insert. */ + VEC_free (agent_expr_p, bl->target_info.tcommands); if (!target_can_run_breakpoint_commands ()) return; + /* For now, limit to agent-style dprintf breakpoints. */ + if (dprintf_style != dprintf_style_agent) + return; + + /* For now, if we have any duplicate location that isn't a dprintf, + don't install the target-side commands, as that would make the + breakpoint not be reported to the core, and we'd lose + control. */ + ALL_BP_LOCATIONS_AT_ADDR (loc2p, locp, bl->address) + { + loc = (*loc2p); + if (is_breakpoint (loc->owner) + && loc->pspace->num == bl->pspace->num + && loc->owner->type != bp_dprintf) + return; + } + /* Do a first pass to check for locations with no assigned conditions or conditions that fail to parse to a valid agent expression bytecode. If any of these happen, then it's no use to send conditions @@ -2375,9 +2574,9 @@ insert_bp_location (struct bp_location *bl, int *hw_breakpoint_error, int *hw_bp_error_explained_already) { - int val = 0; - char *hw_bp_err_string = NULL; - struct gdb_exception e; + enum errors bp_err = GDB_NO_ERROR; + const char *bp_err_message = NULL; + volatile struct gdb_exception e; if (!should_be_inserted (bl) || (bl->inserted && !bl->needs_update)) return 0; @@ -2391,7 +2590,7 @@ insert_bp_location (struct bp_location *bl, we have a breakpoint inserted at that address and thus read the breakpoint instead of returning the data saved in the breakpoint location's shadow contents. */ - bl->target_info.placed_address = bl->address; + bl->target_info.reqstd_address = bl->address; bl->target_info.placed_address_space = bl->pspace->aspace; bl->target_info.length = bl->length; @@ -2432,7 +2631,7 @@ insert_bp_location (struct bp_location *bl, program, but it's not going to work anyway with current gdb. */ struct mem_region *mr - = lookup_mem_region (bl->target_info.placed_address); + = lookup_mem_region (bl->target_info.reqstd_address); if (mr) { @@ -2461,10 +2660,16 @@ insert_bp_location (struct bp_location *bl, } } else if (bl->loc_type == bp_loc_software_breakpoint - && mr->attrib.mode != MEM_RW) - warning (_("cannot set software breakpoint " - "at readonly address %s"), - paddress (bl->gdbarch, bl->address)); + && mr->attrib.mode != MEM_RW) + { + fprintf_unfiltered (tmp_error_stream, + _("Cannot insert breakpoint %d.\n" + "Cannot set software breakpoint " + "at read-only address %s\n"), + bl->owner->number, + paddress (bl->gdbarch, bl->address)); + return 1; + } } } @@ -2476,12 +2681,16 @@ insert_bp_location (struct bp_location *bl, /* No overlay handling: just set the breakpoint. */ TRY_CATCH (e, RETURN_MASK_ALL) { + int val; + val = bl->owner->ops->insert_location (bl); + if (val) + bp_err = GENERIC_ERROR; } if (e.reason < 0) { - val = 1; - hw_bp_err_string = (char *) e.message; + bp_err = e.error; + bp_err_message = e.message; } } else @@ -2502,10 +2711,25 @@ insert_bp_location (struct bp_location *bl, bl->section); /* Set a software (trap) breakpoint at the LMA. */ bl->overlay_target_info = bl->target_info; - bl->overlay_target_info.placed_address = addr; - val = target_insert_breakpoint (bl->gdbarch, - &bl->overlay_target_info); - if (val != 0) + bl->overlay_target_info.reqstd_address = addr; + + /* No overlay handling: just set the breakpoint. */ + TRY_CATCH (e, RETURN_MASK_ALL) + { + int val; + + val = target_insert_breakpoint (bl->gdbarch, + &bl->overlay_target_info); + if (val) + bp_err = GENERIC_ERROR; + } + if (e.reason < 0) + { + bp_err = e.error; + bp_err_message = e.message; + } + + if (bp_err != GDB_NO_ERROR) fprintf_unfiltered (tmp_error_stream, "Overlay breakpoint %d " "failed: in ROM?\n", @@ -2518,12 +2742,16 @@ insert_bp_location (struct bp_location *bl, /* Yes. This overlay section is mapped into memory. */ TRY_CATCH (e, RETURN_MASK_ALL) { + int val; + val = bl->owner->ops->insert_location (bl); + if (val) + bp_err = GENERIC_ERROR; } if (e.reason < 0) { - val = 1; - hw_bp_err_string = (char *) e.message; + bp_err = e.error; + bp_err_message = e.message; } } else @@ -2534,13 +2762,25 @@ insert_bp_location (struct bp_location *bl, } } - if (val) + if (bp_err != GDB_NO_ERROR) { /* Can't set the breakpoint. */ - if (solib_name_from_address (bl->pspace, bl->address)) + + /* In some cases, we might not be able to insert a + breakpoint in a shared library that has already been + removed, but we have not yet processed the shlib unload + event. Unfortunately, some targets that implement + breakpoint insertion themselves can't tell why the + breakpoint insertion failed (e.g., the remote target + doesn't define error codes), so we must treat generic + errors as memory errors. */ + if ((bp_err == GENERIC_ERROR || bp_err == MEMORY_ERROR) + && bl->loc_type == bp_loc_software_breakpoint + && (solib_name_from_address (bl->pspace, bl->address) + || shared_objfile_contains_address_p (bl->pspace, + bl->address))) { /* See also: disable_breakpoints_in_shlibs. */ - val = 0; bl->shlib_disabled = 1; observer_notify_breakpoint_modified (bl->owner); if (!*disabled_breaks) @@ -2555,38 +2795,51 @@ insert_bp_location (struct bp_location *bl, *disabled_breaks = 1; fprintf_unfiltered (tmp_error_stream, "breakpoint #%d\n", bl->owner->number); + return 0; } else { if (bl->loc_type == bp_loc_hardware_breakpoint) { - *hw_breakpoint_error = 1; - *hw_bp_error_explained_already = hw_bp_err_string != NULL; + *hw_breakpoint_error = 1; + *hw_bp_error_explained_already = bp_err_message != NULL; fprintf_unfiltered (tmp_error_stream, "Cannot insert hardware breakpoint %d%s", - bl->owner->number, hw_bp_err_string ? ":" : ".\n"); - if (hw_bp_err_string) - fprintf_unfiltered (tmp_error_stream, "%s.\n", hw_bp_err_string); + bl->owner->number, bp_err_message ? ":" : ".\n"); + if (bp_err_message != NULL) + fprintf_unfiltered (tmp_error_stream, "%s.\n", bp_err_message); } else { - fprintf_unfiltered (tmp_error_stream, - "Cannot insert breakpoint %d.\n", - bl->owner->number); - fprintf_filtered (tmp_error_stream, - "Error accessing memory address "); - fputs_filtered (paddress (bl->gdbarch, bl->address), - tmp_error_stream); - fprintf_filtered (tmp_error_stream, ": %s.\n", - safe_strerror (val)); + if (bp_err_message == NULL) + { + char *message + = memory_error_message (TARGET_XFER_E_IO, + bl->gdbarch, bl->address); + struct cleanup *old_chain = make_cleanup (xfree, message); + + fprintf_unfiltered (tmp_error_stream, + "Cannot insert breakpoint %d.\n" + "%s\n", + bl->owner->number, message); + do_cleanups (old_chain); + } + else + { + fprintf_unfiltered (tmp_error_stream, + "Cannot insert breakpoint %d: %s\n", + bl->owner->number, + bp_err_message); + } } + return 1; } } else bl->inserted = 1; - return val; + return 0; } else if (bl->loc_type == bp_loc_hardware_watchpoint @@ -2594,6 +2847,8 @@ insert_bp_location (struct bp_location *bl, watchpoints. It's not clear that it's necessary... */ && bl->owner->disposition != disp_del_at_next_stop) { + int val; + gdb_assert (bl->owner->ops != NULL && bl->owner->ops->insert_location != NULL); @@ -2637,6 +2892,8 @@ insert_bp_location (struct bp_location *bl, else if (bl->owner->type == bp_catchpoint) { + int val; + gdb_assert (bl->owner->ops != NULL && bl->owner->ops->insert_location != NULL); @@ -2704,7 +2961,7 @@ breakpoint_program_space_exit (struct program_space *pspace) /* Now update the global location list to permanently delete the removed locations above. */ - update_global_location_list (0); + update_global_location_list (UGLL_DONT_INSERT); } /* Make sure all breakpoints are inserted in inferior. @@ -2724,13 +2981,10 @@ insert_breakpoints (void) update_watchpoint (w, 0 /* don't reparse. */); } - update_global_location_list (1); - - /* update_global_location_list does not insert breakpoints when - always_inserted_mode is not enabled. Explicitly insert them - now. */ - if (!breakpoints_always_inserted_mode ()) - insert_breakpoint_locations (); + /* Updating watchpoints creates new locations, so update the global + location list. Explicitly tell ugll to insert locations and + ignore breakpoints_always_inserted_mode. */ + update_global_location_list (UGLL_INSERT); } /* Invoke CALLBACK for each of bp_location. */ @@ -2943,7 +3197,7 @@ remove_threaded_breakpoints (struct thread_info *tp, int silent) b->disposition = disp_del_at_next_stop; printf_filtered (_("\ -Thread-specific breakpoint %d deleted - thread %d is gone.\n"), +Thread-specific breakpoint %d deleted - thread %d no longer in the thread list.\n"), b->number, tp->num); /* Hide it from the user. */ @@ -3073,10 +3327,10 @@ static const char *const longjmp_names[] = struct breakpoint_objfile_data { /* Minimal symbol for "_ovly_debug_event" (if any). */ - struct minimal_symbol *overlay_msym; + struct bound_minimal_symbol overlay_msym; /* Minimal symbol(s) for "longjmp", "siglongjmp", etc. (if any). */ - struct minimal_symbol *longjmp_msym[NUM_LONGJMP_NAMES]; + struct bound_minimal_symbol longjmp_msym[NUM_LONGJMP_NAMES]; /* True if we have looked for longjmp probes. */ int longjmp_searched; @@ -3085,10 +3339,10 @@ struct breakpoint_objfile_data VEC (probe_p) *longjmp_probes; /* Minimal symbol for "std::terminate()" (if any). */ - struct minimal_symbol *terminate_msym; + struct bound_minimal_symbol terminate_msym; /* Minimal symbol for "_Unwind_DebugHook" (if any). */ - struct minimal_symbol *exception_msym; + struct bound_minimal_symbol exception_msym; /* True if we have looked for exception probes. */ int exception_searched; @@ -3153,24 +3407,24 @@ create_overlay_event_breakpoint (void) bp_objfile_data = get_breakpoint_objfile_data (objfile); - if (msym_not_found_p (bp_objfile_data->overlay_msym)) + if (msym_not_found_p (bp_objfile_data->overlay_msym.minsym)) continue; - if (bp_objfile_data->overlay_msym == NULL) + if (bp_objfile_data->overlay_msym.minsym == NULL) { - struct minimal_symbol *m; + struct bound_minimal_symbol m; m = lookup_minimal_symbol_text (func_name, objfile); - if (m == NULL) + if (m.minsym == NULL) { /* Avoid future lookups in this objfile. */ - bp_objfile_data->overlay_msym = &msym_not_found; + bp_objfile_data->overlay_msym.minsym = &msym_not_found; continue; } bp_objfile_data->overlay_msym = m; } - addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->overlay_msym); + addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->overlay_msym); b = create_internal_breakpoint (get_objfile_arch (objfile), addr, bp_overlay_event, &internal_breakpoint_ops); @@ -3187,7 +3441,7 @@ create_overlay_event_breakpoint (void) overlay_events_enabled = 0; } } - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); } static void @@ -3211,8 +3465,6 @@ create_longjmp_master_breakpoint (void) struct breakpoint_objfile_data *bp_objfile_data; gdbarch = get_objfile_arch (objfile); - if (!gdbarch_get_longjmp_target_p (gdbarch)) - continue; bp_objfile_data = get_breakpoint_objfile_data (objfile); @@ -3252,7 +3504,9 @@ create_longjmp_master_breakpoint (void) { struct breakpoint *b; - b = create_internal_breakpoint (gdbarch, probe->address, + b = create_internal_breakpoint (gdbarch, + get_probe_address (probe, + objfile), bp_longjmp_master, &internal_breakpoint_ops); b->addr_string = xstrdup ("-probe-stap libc:longjmp"); @@ -3262,31 +3516,34 @@ create_longjmp_master_breakpoint (void) continue; } + if (!gdbarch_get_longjmp_target_p (gdbarch)) + continue; + for (i = 0; i < NUM_LONGJMP_NAMES; i++) { struct breakpoint *b; const char *func_name; CORE_ADDR addr; - if (msym_not_found_p (bp_objfile_data->longjmp_msym[i])) + if (msym_not_found_p (bp_objfile_data->longjmp_msym[i].minsym)) continue; func_name = longjmp_names[i]; - if (bp_objfile_data->longjmp_msym[i] == NULL) + if (bp_objfile_data->longjmp_msym[i].minsym == NULL) { - struct minimal_symbol *m; + struct bound_minimal_symbol m; m = lookup_minimal_symbol_text (func_name, objfile); - if (m == NULL) + if (m.minsym == NULL) { /* Prevent future lookups in this objfile. */ - bp_objfile_data->longjmp_msym[i] = &msym_not_found; + bp_objfile_data->longjmp_msym[i].minsym = &msym_not_found; continue; } bp_objfile_data->longjmp_msym[i] = m; } - addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]); + addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]); b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master, &internal_breakpoint_ops); b->addr_string = xstrdup (func_name); @@ -3294,7 +3551,7 @@ create_longjmp_master_breakpoint (void) } } } - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); do_cleanups (old_chain); } @@ -3323,25 +3580,25 @@ create_std_terminate_master_breakpoint (void) bp_objfile_data = get_breakpoint_objfile_data (objfile); - if (msym_not_found_p (bp_objfile_data->terminate_msym)) + if (msym_not_found_p (bp_objfile_data->terminate_msym.minsym)) continue; - if (bp_objfile_data->terminate_msym == NULL) + if (bp_objfile_data->terminate_msym.minsym == NULL) { - struct minimal_symbol *m; + struct bound_minimal_symbol m; m = lookup_minimal_symbol (func_name, NULL, objfile); - if (m == NULL || (MSYMBOL_TYPE (m) != mst_text - && MSYMBOL_TYPE (m) != mst_file_text)) + if (m.minsym == NULL || (MSYMBOL_TYPE (m.minsym) != mst_text + && MSYMBOL_TYPE (m.minsym) != mst_file_text)) { /* Prevent future lookups in this objfile. */ - bp_objfile_data->terminate_msym = &msym_not_found; + bp_objfile_data->terminate_msym.minsym = &msym_not_found; continue; } bp_objfile_data->terminate_msym = m; } - addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->terminate_msym); + addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->terminate_msym); b = create_internal_breakpoint (get_objfile_arch (objfile), addr, bp_std_terminate_master, &internal_breakpoint_ops); @@ -3350,7 +3607,7 @@ create_std_terminate_master_breakpoint (void) } } - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); do_cleanups (old_chain); } @@ -3410,7 +3667,9 @@ create_exception_master_breakpoint (void) { struct breakpoint *b; - b = create_internal_breakpoint (gdbarch, probe->address, + b = create_internal_breakpoint (gdbarch, + get_probe_address (probe, + objfile), bp_exception_master, &internal_breakpoint_ops); b->addr_string = xstrdup ("-probe-stap libgcc:unwind"); @@ -3422,26 +3681,26 @@ create_exception_master_breakpoint (void) /* Otherwise, try the hook function. */ - if (msym_not_found_p (bp_objfile_data->exception_msym)) + if (msym_not_found_p (bp_objfile_data->exception_msym.minsym)) continue; gdbarch = get_objfile_arch (objfile); - if (bp_objfile_data->exception_msym == NULL) + if (bp_objfile_data->exception_msym.minsym == NULL) { - struct minimal_symbol *debug_hook; + struct bound_minimal_symbol debug_hook; debug_hook = lookup_minimal_symbol (func_name, NULL, objfile); - if (debug_hook == NULL) + if (debug_hook.minsym == NULL) { - bp_objfile_data->exception_msym = &msym_not_found; + bp_objfile_data->exception_msym.minsym = &msym_not_found; continue; } bp_objfile_data->exception_msym = debug_hook; } - addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->exception_msym); + addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->exception_msym); addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, ¤t_target); b = create_internal_breakpoint (gdbarch, addr, bp_exception_master, @@ -3450,7 +3709,7 @@ create_exception_master_breakpoint (void) b->enable_state = bp_disabled; } - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); } void @@ -3507,6 +3766,13 @@ update_breakpoints_after_exec (void) continue; } + /* Just like single-step breakpoints. */ + if (b->type == bp_single_step) + { + delete_breakpoint (b); + continue; + } + /* Longjmp and longjmp-resume breakpoints are also meaningless after an exec. */ if (b->type == bp_longjmp || b->type == bp_longjmp_resume @@ -3566,11 +3832,6 @@ update_breakpoints_after_exec (void) continue; } } - /* FIXME what about longjmp breakpoints? Re-create them here? */ - create_overlay_event_breakpoint (); - create_longjmp_master_breakpoint (); - create_std_terminate_master_breakpoint (); - create_exception_master_breakpoint (); } int @@ -3604,9 +3865,6 @@ detach_breakpoints (ptid_t ptid) val |= remove_breakpoint_1 (bl, mark_inserted); } - /* Detach single-step breakpoints as well. */ - detach_single_step_breakpoints (); - do_cleanups (old_chain); return val; } @@ -3625,7 +3883,7 @@ remove_breakpoint_1 (struct bp_location *bl, insertion_state_t is) /* BL is never in moribund_locations by our callers. */ gdb_assert (bl->owner != NULL); - if (bl->owner->enable_state == bp_permanent) + if (bl->permanent) /* Permanent breakpoints cannot be inserted or removed. */ return 0; @@ -3646,7 +3904,31 @@ remove_breakpoint_1 (struct bp_location *bl, insertion_state_t is) || !(section_is_overlay (bl->section))) { /* No overlay handling: just remove the breakpoint. */ - val = bl->owner->ops->remove_location (bl); + + /* If we're trying to uninsert a memory breakpoint that we + know is set in a dynamic object that is marked + shlib_disabled, then either the dynamic object was + removed with "remove-symbol-file" or with + "nosharedlibrary". In the former case, we don't know + whether another dynamic object might have loaded over the + breakpoint's address -- the user might well let us know + about it next with add-symbol-file (the whole point of + add-symbol-file is letting the user manually maintain a + list of dynamically loaded objects). If we have the + breakpoint's shadow memory, that is, this is a software + breakpoint managed by GDB, check whether the breakpoint + is still inserted in memory, to avoid overwriting wrong + code with stale saved shadow contents. Note that HW + breakpoints don't have shadow memory, as they're + implemented using a mechanism that is not dependent on + being able to modify the target's memory, and as such + they should always be removed. */ + if (bl->shlib_disabled + && bl->target_info.shadow_len != 0 + && !memory_validate_breakpoint (bl->gdbarch, &bl->target_info)) + val = 0; + else + val = bl->owner->ops->remove_location (bl); } else { @@ -3691,10 +3973,21 @@ remove_breakpoint_1 (struct bp_location *bl, insertion_state_t is) } } - /* In some cases, we might not be able to remove a breakpoint - in a shared library that has already been removed, but we - have not yet processed the shlib unload event. */ - if (val && solib_name_from_address (bl->pspace, bl->address)) + /* In some cases, we might not be able to remove a breakpoint in + a shared library that has already been removed, but we have + not yet processed the shlib unload event. Similarly for an + unloaded add-symbol-file object - the user might not yet have + had the chance to remove-symbol-file it. shlib_disabled will + be set if the library/object has already been removed, but + the breakpoint hasn't been uninserted yet, e.g., after + "nosharedlibrary" or "remove-symbol-file" with breakpoints + always-inserted mode. */ + if (val + && (bl->loc_type == bp_loc_software_breakpoint + && (bl->shlib_disabled + || solib_name_from_address (bl->pspace, bl->address) + || shared_objfile_contains_address_p (bl->pspace, + bl->address)))) val = 0; if (val) @@ -3740,7 +4033,7 @@ remove_breakpoint (struct bp_location *bl, insertion_state_t is) /* BL is never in moribund_locations by our callers. */ gdb_assert (bl->owner != NULL); - if (bl->owner->enable_state == bp_permanent) + if (bl->permanent) /* Permanent breakpoints cannot be inserted or removed. */ return 0; @@ -3766,7 +4059,8 @@ mark_breakpoints_out (void) struct bp_location *bl, **blp_tmp; ALL_BP_LOCATIONS (bl, blp_tmp) - if (bl->pspace == current_program_space) + if (bl->pspace == current_program_space + && !bl->permanent) bl->inserted = 0; } @@ -3795,13 +4089,7 @@ breakpoint_init_inferior (enum inf_context context) if (gdbarch_has_global_breakpoints (target_gdbarch ())) return; - ALL_BP_LOCATIONS (bl, blp_tmp) - { - /* ALL_BP_LOCATIONS bp_location has BL->OWNER always non-NULL. */ - if (bl->pspace == pspace - && bl->owner->enable_state != bp_permanent) - bl->inserted = 0; - } + mark_breakpoints_out (); ALL_BREAKPOINTS_SAFE (b, b_tmp) { @@ -3841,6 +4129,10 @@ breakpoint_init_inferior (enum inf_context context) /* Also remove step-resume breakpoints. */ + case bp_single_step: + + /* Also remove single-step breakpoints. */ + delete_breakpoint (b); break; @@ -3905,14 +4197,14 @@ breakpoint_here_p (struct address_space *aspace, CORE_ADDR pc) /* ALL_BP_LOCATIONS bp_location has BL->OWNER always non-NULL. */ if ((breakpoint_enabled (bl->owner) - || bl->owner->enable_state == bp_permanent) + || bl->permanent) && breakpoint_location_address_match (bl, aspace, pc)) { if (overlay_debugging && section_is_overlay (bl->section) && !section_is_mapped (bl->section)) continue; /* unmapped overlay -- can't be a match */ - else if (bl->owner->enable_state == bp_permanent) + else if (bl->permanent) return permanent_breakpoint_here; else any_breakpoint_here = 1; @@ -3937,14 +4229,10 @@ moribund_breakpoint_here_p (struct address_space *aspace, CORE_ADDR pc) return 0; } -/* Returns non-zero if there's a breakpoint inserted at PC, which is - inserted using regular breakpoint_chain / bp_location array - mechanism. This does not check for single-step breakpoints, which - are inserted and removed using direct target manipulation. */ +/* Returns non-zero iff there's a breakpoint inserted at PC. */ int -regular_breakpoint_inserted_here_p (struct address_space *aspace, - CORE_ADDR pc) +breakpoint_inserted_here_p (struct address_space *aspace, CORE_ADDR pc) { struct bp_location *bl, **blp_tmp; @@ -3968,21 +4256,6 @@ regular_breakpoint_inserted_here_p (struct address_space *aspace, return 0; } -/* Returns non-zero iff there's either regular breakpoint - or a single step breakpoint inserted at PC. */ - -int -breakpoint_inserted_here_p (struct address_space *aspace, CORE_ADDR pc) -{ - if (regular_breakpoint_inserted_here_p (aspace, pc)) - return 1; - - if (single_step_breakpoint_inserted_here_p (aspace, pc)) - return 1; - - return 0; -} - /* This function returns non-zero iff there is a software breakpoint inserted at PC. */ @@ -4010,10 +4283,6 @@ software_breakpoint_inserted_here_p (struct address_space *aspace, } } - /* Also check for software single-step breakpoints. */ - if (single_step_breakpoint_inserted_here_p (aspace, pc)) - return 1; - return 0; } @@ -4048,65 +4317,6 @@ hardware_watchpoint_inserted_in_range (struct address_space *aspace, } return 0; } - -/* breakpoint_thread_match (PC, PTID) returns true if the breakpoint at - PC is valid for process/thread PTID. */ - -int -breakpoint_thread_match (struct address_space *aspace, CORE_ADDR pc, - ptid_t ptid) -{ - struct bp_location *bl, **blp_tmp; - /* The thread and task IDs associated to PTID, computed lazily. */ - int thread = -1; - int task = 0; - - ALL_BP_LOCATIONS (bl, blp_tmp) - { - if (bl->loc_type != bp_loc_software_breakpoint - && bl->loc_type != bp_loc_hardware_breakpoint) - continue; - - /* ALL_BP_LOCATIONS bp_location has bl->OWNER always non-NULL. */ - if (!breakpoint_enabled (bl->owner) - && bl->owner->enable_state != bp_permanent) - continue; - - if (!breakpoint_location_address_match (bl, aspace, pc)) - continue; - - if (bl->owner->thread != -1) - { - /* This is a thread-specific breakpoint. Check that ptid - matches that thread. If thread hasn't been computed yet, - it is now time to do so. */ - if (thread == -1) - thread = pid_to_thread_id (ptid); - if (bl->owner->thread != thread) - continue; - } - - if (bl->owner->task != 0) - { - /* This is a task-specific breakpoint. Check that ptid - matches that task. If task hasn't been computed yet, - it is now time to do so. */ - if (task == 0) - task = ada_get_task_number (ptid); - if (bl->owner->task != task) - continue; - } - - if (overlay_debugging - && section_is_overlay (bl->section) - && !section_is_mapped (bl->section)) - continue; /* unmapped overlay -- can't be a match */ - - return 1; - } - - return 0; -} /* bpstat stuff. External routines' interfaces are documented @@ -4206,35 +4416,27 @@ bpstat_find_breakpoint (bpstat bsp, struct breakpoint *breakpoint) /* See breakpoint.h. */ -enum bpstat_signal_value +int bpstat_explains_signal (bpstat bsp, enum gdb_signal sig) { - enum bpstat_signal_value result = BPSTAT_SIGNAL_NO; - for (; bsp != NULL; bsp = bsp->next) { - /* Ensure that, if we ever entered this loop, then we at least - return BPSTAT_SIGNAL_HIDE. */ - enum bpstat_signal_value newval; - if (bsp->breakpoint_at == NULL) { /* A moribund location can never explain a signal other than GDB_SIGNAL_TRAP. */ if (sig == GDB_SIGNAL_TRAP) - newval = BPSTAT_SIGNAL_HIDE; - else - newval = BPSTAT_SIGNAL_NO; + return 1; } else - newval = bsp->breakpoint_at->ops->explains_signal (bsp->breakpoint_at, - sig); - - if (newval > result) - result = newval; + { + if (bsp->breakpoint_at->ops->explains_signal (bsp->breakpoint_at, + sig)) + return 1; + } } - return result; + return 0; } /* Put in *NUM the breakpoint number of the first breakpoint we are @@ -4633,10 +4835,12 @@ bpstat_print (bpstat bs, int kind) 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. +/* Evaluate the expression EXP and return 1 if value is zero. + This returns the inverse of the condition because it is called + from catch_errors which returns 0 if an exception happened, and if an + exception happens we want execution to stop. The argument is a "struct expression *" that has been cast to a - "char *" to make it pass through catch_errors. */ + "void *" to make it pass through catch_errors. */ static int breakpoint_cond_eval (void *exp) @@ -4706,7 +4910,7 @@ watchpoints_triggered (struct target_waitstatus *ws) w->watchpoint_triggered = watch_triggered_unknown; } - return stopped_by_watchpoint; + return 1; } /* The target could report the data address. Mark watchpoints @@ -4848,6 +5052,9 @@ watchpoint_check (void *p) mark = value_mark (); fetch_subexp_value (b->exp, &pc, &new_val, NULL, NULL, 0); + if (b->val_bitsize != 0) + new_val = extract_bitfield_from_watchpoint_value (b, new_val); + /* We use value_equal_contents instead of value_equal because the latter coerces an array to a pointer, thus comparing just the address of the array instead of its contents. This is @@ -5083,17 +5290,20 @@ bpstat_check_watchpoint (bpstat bs) } } - -/* Check conditions (condition proper, frame, thread and ignore count) +/* For breakpoints that are currently marked as telling gdb to stop, + check conditions (condition proper, frame, thread and ignore count) of breakpoint referred to by BS. If we should not stop for this breakpoint, set BS->stop to 0. */ static void bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) { - int thread_id = pid_to_thread_id (ptid); const struct bp_location *bl; struct breakpoint *b; + int value_is_zero = 0; + struct expression *cond; + + gdb_assert (bs->stop); /* BS is built for existing struct breakpoint. */ bl = bs->bp_location_at; @@ -5101,115 +5311,119 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) b = bs->breakpoint_at; gdb_assert (b != NULL); - /* Even if the target evaluated the condition on its end and notified GDB, we - need to do so again since GDB does not know if we stopped due to a - breakpoint or a single step breakpoint. */ + /* Even if the target evaluated the condition on its end and notified GDB, we + need to do so again since GDB does not know if we stopped due to a + breakpoint or a single step breakpoint. */ + + if (frame_id_p (b->frame_id) + && !frame_id_eq (b->frame_id, get_stack_frame_id (get_current_frame ()))) + { + bs->stop = 0; + return; + } + + /* If this is a thread/task-specific breakpoint, don't waste cpu + evaluating the condition if this isn't the specified + thread/task. */ + if ((b->thread != -1 && b->thread != pid_to_thread_id (ptid)) + || (b->task != 0 && b->task != ada_get_task_number (ptid))) + + { + bs->stop = 0; + return; + } + + /* Evaluate extension language breakpoints that have a "stop" method + implemented. */ + bs->stop = breakpoint_ext_lang_cond_says_stop (b); + + if (is_watchpoint (b)) + { + struct watchpoint *w = (struct watchpoint *) b; + + cond = w->cond_exp; + } + else + cond = bl->cond; - if (frame_id_p (b->frame_id) - && !frame_id_eq (b->frame_id, get_stack_frame_id (get_current_frame ()))) - bs->stop = 0; - else if (bs->stop) + if (cond && b->disposition != disp_del_at_next_stop) { - int value_is_zero = 0; - struct expression *cond; + int within_current_scope = 1; + struct watchpoint * w; - /* Evaluate Python breakpoints that have a "stop" - method implemented. */ - if (b->py_bp_object) - bs->stop = gdbpy_should_stop (b->py_bp_object); + /* We use value_mark and 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 (); if (is_watchpoint (b)) - { - struct watchpoint *w = (struct watchpoint *) b; - - cond = w->cond_exp; - } + w = (struct watchpoint *) b; else - cond = bl->cond; + w = NULL; - if (cond && b->disposition != disp_del_at_next_stop) + /* Need to select the frame, with all that implies so that + the conditions will have the right context. Because we + use the frame, we will not see an inlined function's + variables when we arrive at a breakpoint at the start + of the inlined function; the current frame will be the + call site. */ + if (w == NULL || w->cond_exp_valid_block == NULL) + select_frame (get_current_frame ()); + else { - int within_current_scope = 1; - struct watchpoint * w; - - /* We use value_mark and 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 (); - - if (is_watchpoint (b)) - w = (struct watchpoint *) b; - else - w = NULL; - - /* Need to select the frame, with all that implies so that - the conditions will have the right context. Because we - use the frame, we will not see an inlined function's - variables when we arrive at a breakpoint at the start - of the inlined function; the current frame will be the - call site. */ - if (w == NULL || w->cond_exp_valid_block == NULL) - select_frame (get_current_frame ()); - else - { - struct frame_info *frame; - - /* For local watchpoint expressions, which particular - instance of a local is being watched matters, so we - keep track of the frame to evaluate the expression - in. To evaluate the condition however, it doesn't - really matter which instantiation of the function - where the condition makes sense triggers the - watchpoint. This allows an expression like "watch - global if q > 10" set in `func', catch writes to - global on all threads that call `func', or catch - writes on all recursive calls of `func' by a single - thread. We simply always evaluate the condition in - the innermost frame that's executing where it makes - sense to evaluate the condition. It seems - intuitive. */ - frame = block_innermost_frame (w->cond_exp_valid_block); - if (frame != NULL) - select_frame (frame); - else - within_current_scope = 0; - } - if (within_current_scope) - value_is_zero - = catch_errors (breakpoint_cond_eval, cond, - "Error in testing breakpoint condition:\n", - RETURN_MASK_ALL); + struct frame_info *frame; + + /* For local watchpoint expressions, which particular + instance of a local is being watched matters, so we + keep track of the frame to evaluate the expression + in. To evaluate the condition however, it doesn't + really matter which instantiation of the function + where the condition makes sense triggers the + watchpoint. This allows an expression like "watch + global if q > 10" set in `func', catch writes to + global on all threads that call `func', or catch + writes on all recursive calls of `func' by a single + thread. We simply always evaluate the condition in + the innermost frame that's executing where it makes + sense to evaluate the condition. It seems + intuitive. */ + frame = block_innermost_frame (w->cond_exp_valid_block); + if (frame != NULL) + select_frame (frame); else - { - warning (_("Watchpoint condition cannot be tested " - "in the current scope")); - /* If we failed to set the right context for this - watchpoint, unconditionally report it. */ - value_is_zero = 0; - } - /* FIXME-someday, should give breakpoint #. */ - value_free_to_mark (mark); - } - - if (cond && value_is_zero) - { - bs->stop = 0; + within_current_scope = 0; } - else if (b->thread != -1 && b->thread != thread_id) + if (within_current_scope) + value_is_zero + = catch_errors (breakpoint_cond_eval, cond, + "Error in testing breakpoint condition:\n", + RETURN_MASK_ALL); + else { - bs->stop = 0; + warning (_("Watchpoint condition cannot be tested " + "in the current scope")); + /* If we failed to set the right context for this + watchpoint, unconditionally report it. */ + value_is_zero = 0; } - else if (b->ignore_count > 0) - { - b->ignore_count--; - bs->stop = 0; - /* Increase the hit count even though we don't stop. */ - ++(b->hit_count); - observer_notify_breakpoint_modified (b); - } + /* FIXME-someday, should give breakpoint #. */ + value_free_to_mark (mark); + } + + if (cond && value_is_zero) + { + bs->stop = 0; } + else if (b->ignore_count > 0) + { + b->ignore_count--; + bs->stop = 0; + /* Increase the hit count even though we don't stop. */ + ++(b->hit_count); + observer_notify_breakpoint_modified (b); + } } @@ -5256,7 +5470,7 @@ bpstat_stop_status (struct address_space *aspace, ALL_BREAKPOINTS (b) { - if (!breakpoint_enabled (b) && b->enable_state != bp_permanent) + if (!breakpoint_enabled (b)) continue; for (bl = b->loc; bl != NULL; bl = bl->next) @@ -5300,6 +5514,7 @@ bpstat_stop_status (struct address_space *aspace, } } + /* Check if a moribund breakpoint explains the stop. */ for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix) { if (breakpoint_location_address_match (loc, aspace, bp_addr)) @@ -5351,8 +5566,7 @@ bpstat_stop_status (struct address_space *aspace, if (b->disposition == disp_disable) { --(b->enable_count); - if (b->enable_count <= 0 - && b->enable_state != bp_permanent) + if (b->enable_count <= 0) b->enable_state = bp_disabled; removed_any = 1; } @@ -5393,9 +5607,9 @@ bpstat_stop_status (struct address_space *aspace, } if (need_remove_insert) - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); else if (removed_any) - update_global_location_list (0); + update_global_location_list (UGLL_DONT_INSERT); return bs_head; } @@ -5455,6 +5669,7 @@ bpstat_what (bpstat bs_head) break; case bp_breakpoint: case bp_hardware_breakpoint: + case bp_single_step: case bp_until: case bp_finish: case bp_shlib_event: @@ -5813,6 +6028,7 @@ bptype_string (enum bptype type) {bp_none, "?deleted?"}, {bp_breakpoint, "breakpoint"}, {bp_hardware_breakpoint, "hw breakpoint"}, + {bp_single_step, "sw single-step"}, {bp_until, "until"}, {bp_finish, "finish"}, {bp_watchpoint, "watchpoint"}, @@ -6004,6 +6220,7 @@ print_one_breakpoint_location (struct breakpoint *b, case bp_breakpoint: case bp_hardware_breakpoint: + case bp_single_step: case bp_until: case bp_finish: case bp_longjmp: @@ -6633,8 +6850,6 @@ describe_other_breakpoints (struct gdbarch *gdbarch, ((b->enable_state == bp_disabled || b->enable_state == bp_call_disabled) ? " (disabled)" - : b->enable_state == bp_permanent - ? " (permanent)" : ""), (others > 1) ? "," : ((others == 1) ? " and" : "")); @@ -6713,12 +6928,9 @@ watchpoint_locations_match (struct bp_location *loc1, && loc1->length == loc2->length); } -/* Returns true if {ASPACE1,ADDR1} and {ASPACE2,ADDR2} represent the - same breakpoint location. In most targets, this can only be true - if ASPACE1 matches ASPACE2. On targets that have global - breakpoints, the address space doesn't really matter. */ +/* See breakpoint.h. */ -static int +int breakpoint_address_match (struct address_space *aspace1, CORE_ADDR addr1, struct address_space *aspace2, CORE_ADDR addr2) { @@ -6849,6 +7061,16 @@ adjust_breakpoint_address (struct gdbarch *gdbarch, have their addresses modified. */ return bpaddr; } + else if (bptype == bp_single_step) + { + /* Single-step breakpoints should not have their addresses + modified. If there's any architectural constrain that + applies to this address, then it should have already been + taken into account when the breakpoint was created in the + first place. If we didn't do this, stepping through e.g., + Thumb-2 IT blocks would break. */ + return bpaddr; + } else { CORE_ADDR adjusted_bpaddr; @@ -6885,6 +7107,7 @@ init_bp_location (struct bp_location *loc, const struct bp_location_ops *ops, switch (owner->type) { case bp_breakpoint: + case bp_single_step: case bp_until: case bp_finish: case bp_longjmp: @@ -7091,7 +7314,7 @@ get_sal_arch (struct symtab_and_line sal) if (sal.section) return get_objfile_arch (sal.section->objfile); if (sal.symtab) - return get_objfile_arch (sal.symtab->objfile); + return get_objfile_arch (SYMTAB_OBJFILE (sal.symtab)); return NULL; } @@ -7158,15 +7381,16 @@ 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 implement. */ for (bl = b->loc; bl; bl = bl->next) - bl->inserted = 1; + { + bl->permanent = 1; + bl->inserted = 1; + } } /* Call this routine when stepping and nexting to enable a breakpoint @@ -7194,7 +7418,7 @@ set_longjmp_breakpoint (struct thread_info *tp, struct frame_id frame) /* longjmp_breakpoint_ops ensures INITIATING_FRAME is cleared again after their removal. */ clone = momentary_breakpoint_from_master (b, type, - &longjmp_breakpoint_ops); + &longjmp_breakpoint_ops, 1); clone->thread = thread; } @@ -7244,7 +7468,8 @@ set_longjmp_breakpoint_for_call_dummy (void) struct breakpoint *new_b; new_b = momentary_breakpoint_from_master (b, bp_longjmp_call_dummy, - &momentary_breakpoint_ops); + &momentary_breakpoint_ops, + 1); new_b->thread = pid_to_thread_id (inferior_ptid); /* Link NEW_B into the chain of RETVAL breakpoints. */ @@ -7262,7 +7487,7 @@ set_longjmp_breakpoint_for_call_dummy (void) } /* Verify all existing dummy frames and their associated breakpoints for - THREAD. Remove those which can no longer be found in the current frame + TP. Remove those which can no longer be found in the current frame stack. You should call this function only at places where it is safe to currently @@ -7270,12 +7495,12 @@ set_longjmp_breakpoint_for_call_dummy (void) frames. */ void -check_longjmp_breakpoint_for_call_dummy (int thread) +check_longjmp_breakpoint_for_call_dummy (struct thread_info *tp) { struct breakpoint *b, *b_tmp; ALL_BREAKPOINTS_SAFE (b, b_tmp) - if (b->type == bp_longjmp_call_dummy && b->thread == thread) + if (b->type == bp_longjmp_call_dummy && b->thread == tp->num) { struct breakpoint *dummy_b = b->related_breakpoint; @@ -7285,7 +7510,7 @@ check_longjmp_breakpoint_for_call_dummy (int thread) || frame_find_by_id (dummy_b->frame_id) != NULL) continue; - dummy_frame_discard (dummy_b->frame_id); + dummy_frame_discard (dummy_b->frame_id, tp->ptid); while (b->related_breakpoint != b) { @@ -7306,7 +7531,7 @@ enable_overlay_breakpoints (void) if (b->type == bp_overlay_event) { b->enable_state = bp_enabled; - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); overlay_events_enabled = 1; } } @@ -7320,7 +7545,7 @@ disable_overlay_breakpoints (void) if (b->type == bp_overlay_event) { b->enable_state = bp_disabled; - update_global_location_list (0); + update_global_location_list (UGLL_DONT_INSERT); overlay_events_enabled = 0; } } @@ -7337,7 +7562,7 @@ set_std_terminate_breakpoint (void) && b->type == bp_std_terminate_master) { momentary_breakpoint_from_master (b, bp_std_terminate, - &momentary_breakpoint_ops); + &momentary_breakpoint_ops, 1); } } @@ -7365,7 +7590,7 @@ create_thread_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address) b->addr_string = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address)); - update_global_location_list_nothrow (1); + update_global_location_list_nothrow (UGLL_MAY_INSERT); return b; } @@ -7396,7 +7621,7 @@ create_jit_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address) b = create_internal_breakpoint (gdbarch, address, bp_jit_event, &internal_breakpoint_ops); - update_global_location_list_nothrow (1); + update_global_location_list_nothrow (UGLL_MAY_INSERT); return b; } @@ -7424,14 +7649,56 @@ remove_solib_event_breakpoints (void) delete_breakpoint (b); } -struct breakpoint * -create_solib_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address) +/* See breakpoint.h. */ + +void +remove_solib_event_breakpoints_at_next_stop (void) +{ + struct breakpoint *b, *b_tmp; + + ALL_BREAKPOINTS_SAFE (b, b_tmp) + if (b->type == bp_shlib_event + && b->loc->pspace == current_program_space) + b->disposition = disp_del_at_next_stop; +} + +/* Helper for create_solib_event_breakpoint / + create_and_insert_solib_event_breakpoint. Allows specifying which + INSERT_MODE to pass through to update_global_location_list. */ + +static struct breakpoint * +create_solib_event_breakpoint_1 (struct gdbarch *gdbarch, CORE_ADDR address, + enum ugll_insert_mode insert_mode) { struct breakpoint *b; b = create_internal_breakpoint (gdbarch, address, bp_shlib_event, &internal_breakpoint_ops); - update_global_location_list_nothrow (1); + update_global_location_list_nothrow (insert_mode); + return b; +} + +struct breakpoint * +create_solib_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address) +{ + return create_solib_event_breakpoint_1 (gdbarch, address, UGLL_MAY_INSERT); +} + +/* See breakpoint.h. */ + +struct breakpoint * +create_and_insert_solib_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address) +{ + struct breakpoint *b; + + /* Explicitly tell update_global_location_list to insert + locations. */ + b = create_solib_event_breakpoint_1 (gdbarch, address, UGLL_INSERT); + if (!b->loc->inserted) + { + delete_breakpoint (b); + return NULL; + } return b; } @@ -7467,9 +7734,9 @@ disable_breakpoints_in_shlibs (void) } } -/* Disable any breakpoints and tracepoints that are in an unloaded shared - library. Only apply to enabled breakpoints, disabled ones can just stay - disabled. */ +/* Disable any breakpoints and tracepoints that are in SOLIB upon + notification of unloaded_shlib. Only apply to enabled breakpoints, + disabled ones can just stay disabled. */ static void disable_breakpoints_in_unloaded_shlib (struct so_list *solib) @@ -7521,6 +7788,79 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib) } } +/* Disable any breakpoints and tracepoints in OBJFILE upon + notification of free_objfile. Only apply to enabled breakpoints, + disabled ones can just stay disabled. */ + +static void +disable_breakpoints_in_freed_objfile (struct objfile *objfile) +{ + struct breakpoint *b; + + if (objfile == NULL) + return; + + /* OBJF_SHARED|OBJF_USERLOADED objfiles are dynamic modules manually + managed by the user with add-symbol-file/remove-symbol-file. + Similarly to how breakpoints in shared libraries are handled in + response to "nosharedlibrary", mark breakpoints in such modules + shlib_disabled so they end up uninserted on the next global + location list update. Shared libraries not loaded by the user + aren't handled here -- they're already handled in + disable_breakpoints_in_unloaded_shlib, called by solib.c's + solib_unloaded observer. We skip objfiles that are not + OBJF_SHARED as those aren't considered dynamic objects (e.g. the + main objfile). */ + if ((objfile->flags & OBJF_SHARED) == 0 + || (objfile->flags & OBJF_USERLOADED) == 0) + return; + + ALL_BREAKPOINTS (b) + { + struct bp_location *loc; + int bp_modified = 0; + + if (!is_breakpoint (b) && !is_tracepoint (b)) + continue; + + for (loc = b->loc; loc != NULL; loc = loc->next) + { + CORE_ADDR loc_addr = loc->address; + + if (loc->loc_type != bp_loc_hardware_breakpoint + && loc->loc_type != bp_loc_software_breakpoint) + continue; + + if (loc->shlib_disabled != 0) + continue; + + if (objfile->pspace != loc->pspace) + continue; + + if (loc->loc_type != bp_loc_hardware_breakpoint + && loc->loc_type != bp_loc_software_breakpoint) + continue; + + if (is_addr_in_objfile (loc_addr, objfile)) + { + loc->shlib_disabled = 1; + /* At this point, we don't know whether the object was + unmapped from the inferior or not, so leave the + inserted flag alone. We'll handle failure to + uninsert quietly, in case the object was indeed + unmapped. */ + + mark_breakpoint_location_modified (loc); + + bp_modified = 1; + } + } + + if (bp_modified) + observer_notify_breakpoint_modified (b); + } +} + /* FORK & VFORK catchpoints. */ /* An instance of this type is used to represent a fork or vfork @@ -8109,7 +8449,7 @@ get_catch_syscall_inferior_data (struct inferior *inf) inf_data = inferior_data (inf, catch_syscall_inferior_data); if (inf_data == NULL) { - inf_data = XZALLOC (struct catch_syscall_inferior_data); + inf_data = XCNEW (struct catch_syscall_inferior_data); set_inferior_data (inf, catch_syscall_inferior_data, inf_data); } @@ -8244,10 +8584,9 @@ breakpoint_hit_catch_syscall (const struct bp_location *bl, VEC_iterate (int, c->syscalls_to_be_caught, i, iter); i++) if (syscall_number == iter) - break; - /* Not the same. */ - if (!iter) - return 0; + return 1; + + return 0; } return 1; @@ -8476,7 +8815,7 @@ install_breakpoint (int internal, struct breakpoint *b, int update_gll) observer_notify_breakpoint_created (b); if (update_gll) - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); } static void @@ -8718,7 +9057,7 @@ disable_watchpoints_before_interactive_call_start (void) if (is_watchpoint (b) && breakpoint_enabled (b)) { b->enable_state = bp_call_disabled; - update_global_location_list (0); + update_global_location_list (UGLL_DONT_INSERT); } } } @@ -8733,7 +9072,7 @@ enable_watchpoints_after_interactive_call_stop (void) if (is_watchpoint (b) && b->enable_state == bp_call_disabled) { b->enable_state = bp_enabled; - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); } } } @@ -8742,7 +9081,7 @@ void disable_breakpoints_before_startup (void) { current_program_space->executing_startup = 1; - update_global_location_list (0); + update_global_location_list (UGLL_DONT_INSERT); } void @@ -8752,10 +9091,31 @@ enable_breakpoints_after_startup (void) breakpoint_re_set (); } +/* Create a new single-step breakpoint for thread THREAD, with no + locations. */ + +static struct breakpoint * +new_single_step_breakpoint (int thread, struct gdbarch *gdbarch) +{ + struct breakpoint *b = XNEW (struct breakpoint); + + init_raw_breakpoint_without_location (b, gdbarch, bp_single_step, + &momentary_breakpoint_ops); + + b->disposition = disp_donttouch; + b->frame_id = null_frame_id; + + b->thread = thread; + gdb_assert (b->thread != 0); + + add_to_breakpoint_chain (b); + + return 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. */ +/* Set a momentary breakpoint of type TYPE at address specified by + SAL. If FRAME_ID is valid, the breakpoint is restricted to that + frame. */ struct breakpoint * set_momentary_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line sal, @@ -8778,19 +9138,20 @@ set_momentary_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line sal, if (in_thread_list (inferior_ptid)) b->thread = pid_to_thread_id (inferior_ptid); - update_global_location_list_nothrow (1); + update_global_location_list_nothrow (UGLL_MAY_INSERT); return b; } /* Make a momentary breakpoint based on the master breakpoint ORIG. - The new breakpoint will have type TYPE, and use OPS as it - breakpoint_ops. */ + The new breakpoint will have type TYPE, use OPS as its + breakpoint_ops, and will set enabled to LOC_ENABLED. */ static struct breakpoint * momentary_breakpoint_from_master (struct breakpoint *orig, enum bptype type, - const struct breakpoint_ops *ops) + const struct breakpoint_ops *ops, + int loc_enabled) { struct breakpoint *copy; @@ -8806,6 +9167,7 @@ momentary_breakpoint_from_master (struct breakpoint *orig, copy->loc->probe = orig->loc->probe; copy->loc->line_number = orig->loc->line_number; copy->loc->symtab = orig->loc->symtab; + copy->loc->enabled = loc_enabled; copy->frame_id = orig->frame_id; copy->thread = orig->thread; copy->pspace = orig->pspace; @@ -8814,7 +9176,7 @@ momentary_breakpoint_from_master (struct breakpoint *orig, copy->disposition = disp_donttouch; copy->number = internal_breakpoint_number--; - update_global_location_list_nothrow (0); + update_global_location_list_nothrow (UGLL_DONT_INSERT); return copy; } @@ -8828,7 +9190,7 @@ clone_momentary_breakpoint (struct breakpoint *orig) if (orig == NULL) return NULL; - return momentary_breakpoint_from_master (orig, orig->type, orig->ops); + return momentary_breakpoint_from_master (orig, orig->type, orig->ops, 0); } struct breakpoint * @@ -8858,6 +9220,8 @@ mention (struct breakpoint *b) } +static int bp_loc_is_permanent (struct bp_location *loc); + static struct bp_location * add_location_to_breakpoint (struct breakpoint *b, const struct symtab_and_line *sal) @@ -8889,7 +9253,8 @@ add_location_to_breakpoint (struct breakpoint *b, loc->requested_address = sal->pc; loc->address = adjusted_address; loc->pspace = sal->pspace; - loc->probe = sal->probe; + loc->probe.probe = sal->probe; + loc->probe.objfile = sal->objfile; gdb_assert (loc->pspace != NULL); loc->section = sal->section; loc->gdbarch = loc_gdbarch; @@ -8898,6 +9263,13 @@ add_location_to_breakpoint (struct breakpoint *b, set_breakpoint_location_function (loc, sal->explicit_pc || sal->explicit_line); + + if (bp_loc_is_permanent (loc)) + { + loc->inserted = 1; + loc->permanent = 1; + } + return loc; } @@ -9140,9 +9512,6 @@ init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch, loc->inserted = 1; } - if (bp_loc_is_permanent (loc)) - make_breakpoint_permanent (b); - if (b->cond_string) { const char *arg = b->cond_string; @@ -9768,7 +10137,7 @@ create_breakpoint (struct gdbarch *gdbarch, do_cleanups (old_chain); /* error call may happen here - have BKPT_CHAIN already discarded. */ - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); return 1; } @@ -9831,8 +10200,8 @@ resolve_sal_pc (struct symtab_and_line *sal) if (sal->section == 0 && sal->symtab != NULL) { - struct blockvector *bv; - struct block *b; + const struct blockvector *bv; + const struct block *b; struct symbol *sym; bv = blockvector_for_pc_sect (sal->pc, 0, &b, sal->symtab); @@ -9841,8 +10210,9 @@ resolve_sal_pc (struct symtab_and_line *sal) sym = block_linkage_function (b); if (sym != NULL) { - fixup_symbol_section (sym, sal->symtab->objfile); - sal->section = SYMBOL_OBJ_SECTION (sal->symtab->objfile, sym); + fixup_symbol_section (sym, SYMTAB_OBJFILE (sal->symtab)); + sal->section = SYMBOL_OBJ_SECTION (SYMTAB_OBJFILE (sal->symtab), + sym); } else { @@ -9858,7 +10228,7 @@ resolve_sal_pc (struct symtab_and_line *sal) msym = lookup_minimal_symbol_by_pc (sal->pc); if (msym.minsym) - sal->section = SYMBOL_OBJ_SECTION (msym.objfile, msym.minsym); + sal->section = MSYMBOL_OBJ_SECTION (msym.objfile, msym.minsym); do_cleanups (old_chain); } @@ -10280,7 +10650,7 @@ break_range_command (char *arg, int from_tty) mention (b); observer_notify_breakpoint_created (b); - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); } /* Return non-zero if EXP is verified as constant. Returned zero @@ -10329,8 +10699,6 @@ watchpoint_exp_is_const (const struct expression *exp) case BINOP_MAX: case BINOP_INTDIV: case BINOP_CONCAT: - case BINOP_IN: - case BINOP_RANGE: case TERNOP_COND: case TERNOP_SLICE: @@ -10688,15 +11056,15 @@ print_recreate_watchpoint (struct breakpoint *b, struct ui_file *fp) /* Implement the "explains_signal" breakpoint_ops method for watchpoints. */ -static enum bpstat_signal_value +static int explains_signal_watchpoint (struct breakpoint *b, enum gdb_signal sig) { /* A software watchpoint cannot cause a signal other than GDB_SIGNAL_TRAP. */ if (b->type == bp_watchpoint && sig != GDB_SIGNAL_TRAP) - return BPSTAT_SIGNAL_NO; + return 0; - return BPSTAT_SIGNAL_HIDE; + return 1; } /* The breakpoint_ops structure to be used in hardware watchpoints. */ @@ -10903,6 +11271,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty, struct expression *exp; const struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL; struct value *val, *mark, *result; + int saved_bitpos = 0, saved_bitsize = 0; struct frame_info *frame; const char *exp_start = NULL; const char *exp_end = NULL; @@ -11036,6 +11405,12 @@ watch_command_1 (const char *arg, int accessflag, int from_tty, mark = value_mark (); fetch_subexp_value (exp, &pc, &val, &result, NULL, just_location); + if (val != NULL && just_location) + { + saved_bitpos = value_bitpos (val); + saved_bitsize = value_bitsize (val); + } + if (just_location) { int ret; @@ -11080,13 +11455,6 @@ watch_command_1 (const char *arg, int accessflag, int from_tty, 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; - frame = block_innermost_frame (exp_valid_block); /* If the expression is "local", then set up a "watchpoint scope" @@ -11123,7 +11491,17 @@ watch_command_1 (const char *arg, int accessflag, int from_tty, } } - /* Now set up the breakpoint. */ + /* Now set up the breakpoint. We create all watchpoints as hardware + watchpoints here even if hardware watchpoints are turned off, a call + to update_watchpoint later in this function will cause the type to + drop back to bp_watchpoint (software watchpoint) if required. */ + + 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; w = XCNEW (struct watchpoint); b = &w->base; @@ -11168,6 +11546,8 @@ watch_command_1 (const char *arg, int accessflag, int from_tty, else { w->val = val; + w->val_bitpos = saved_bitpos; + w->val_bitsize = saved_bitsize; w->val_valid = 1; } @@ -11394,7 +11774,7 @@ until_break_command (char *arg, int from_tty, int anywhere) int thread; struct thread_info *tp; - clear_proceed_status (); + clear_proceed_status (0); /* Set a breakpoint where the user wants it and at return from this function. */ @@ -11620,6 +12000,7 @@ init_ada_exception_breakpoint (struct breakpoint *b, char *addr_string, const struct breakpoint_ops *ops, int tempflag, + int enabled, int from_tty) { if (from_tty) @@ -11642,7 +12023,7 @@ init_ada_exception_breakpoint (struct breakpoint *b, init_raw_breakpoint (b, gdbarch, sal, bp_breakpoint, ops); - b->enable_state = bp_enabled; + b->enable_state = enabled ? bp_enabled : bp_disabled; b->disposition = tempflag ? disp_del : disp_donttouch; b->addr_string = addr_string; b->language = language_ada; @@ -11971,7 +12352,7 @@ breakpoint_auto_delete (bpstat bs) /* A comparison function for bp_location AP and BP being interfaced to qsort. Sort elements primarily by their ADDRESS (no matter what does breakpoint_address_is_meaningful say for its OWNER), - secondarily by ordering first bp_permanent OWNERed elements and + secondarily by ordering first permanent elements and terciarily just ensuring the array is sorted stable way despite qsort being an unstable algorithm. */ @@ -11980,9 +12361,6 @@ bp_location_compare (const void *ap, const void *bp) { struct bp_location *a = *(void **) ap; struct bp_location *b = *(void **) bp; - /* A and B come from existing breakpoints having non-NULL OWNER. */ - int a_perm = a->owner->enable_state == bp_permanent; - int b_perm = b->owner->enable_state == bp_permanent; if (a->address != b->address) return (a->address > b->address) - (a->address < b->address); @@ -11996,8 +12374,8 @@ bp_location_compare (const void *ap, const void *bp) - (a->pspace->num < b->pspace->num)); /* Sort permanent breakpoints first. */ - if (a_perm != b_perm) - return (a_perm < b_perm) - (a_perm > b_perm); + if (a->permanent != b->permanent) + return (a->permanent < b->permanent) - (a->permanent > b->permanent); /* Make the internal GDB representation stable across GDB runs where A and B memory inside GDB can differ. Breakpoint locations of @@ -12172,24 +12550,16 @@ force_breakpoint_reinsertion (struct bp_location *bl) } } } +/* Called whether new breakpoints are created, or existing breakpoints + deleted, to update the global location list and recompute which + locations are duplicate of which. -/* If SHOULD_INSERT is false, do not insert any breakpoint locations - into the inferior, only remove already-inserted locations that no - longer should be inserted. Functions that delete a breakpoint or - breakpoints should pass false, so that deleting a breakpoint - doesn't have the side effect of inserting the locations of other - breakpoints that are marked not-inserted, but should_be_inserted - returns true on them. - - This behaviour is useful is situations close to tear-down -- e.g., - after an exec, while the target still has execution, but breakpoint - shadows of the previous executable image should *NOT* be restored - to the new image; or before detaching, where the target still has - execution and wants to delete breakpoints from GDB's lists, and all - breakpoints had already been removed from the inferior. */ + The INSERT_MODE flag determines whether locations may not, may, or + shall be inserted now. See 'enum ugll_insert_mode' for more + info. */ static void -update_global_location_list (int should_insert) +update_global_location_list (enum ugll_insert_mode insert_mode) { struct breakpoint *b; struct bp_location **locp, *loc; @@ -12476,7 +12846,7 @@ update_global_location_list (int should_insert) } /* Permanent breakpoint should always be inserted. */ - if (b->enable_state == bp_permanent && ! loc->inserted) + if (loc->permanent && ! loc->inserted) internal_error (__FILE__, __LINE__, _("allegedly permanent breakpoint is not " "actually inserted")); @@ -12517,30 +12887,30 @@ update_global_location_list (int should_insert) /* Clear the condition modification flag. */ loc->condition_changed = condition_unchanged; - if ((*loc_first_p)->owner->enable_state == bp_permanent && loc->inserted - && b->enable_state != bp_permanent) + if (loc->inserted && !loc->permanent + && (*loc_first_p)->permanent) internal_error (__FILE__, __LINE__, _("another breakpoint was inserted on top of " "a permanent breakpoint")); } - if (breakpoints_always_inserted_mode () - && (have_live_inferiors () - || (gdbarch_has_global_breakpoints (target_gdbarch ())))) + if (insert_mode == UGLL_INSERT || breakpoints_should_be_inserted_now ()) { - if (should_insert) + if (insert_mode != UGLL_DONT_INSERT) insert_breakpoint_locations (); else { - /* Though should_insert is false, we may need to update conditions - on the target's side if it is evaluating such conditions. We + /* Even though the caller told us to not insert new + locations, we may still need to update conditions on the + target's side of breakpoints that were already inserted + if the target is evaluating breakpoint conditions. We only update conditions for locations that are marked "needs_update". */ update_inserted_breakpoint_locations (); } } - if (should_insert) + if (insert_mode != UGLL_DONT_INSERT) download_tracepoint_locations (); do_cleanups (cleanups); @@ -12562,12 +12932,12 @@ breakpoint_retire_moribund (void) } static void -update_global_location_list_nothrow (int inserting) +update_global_location_list_nothrow (enum ugll_insert_mode insert_mode) { volatile struct gdb_exception e; TRY_CATCH (e, RETURN_MASK_ERROR) - update_global_location_list (inserting); + update_global_location_list (insert_mode); } /* Clear BKP from a BPS. */ @@ -12655,6 +13025,9 @@ bp_location_dtor (struct bp_location *self) if (self->cond_bytecode) free_agent_expr (self->cond_bytecode); xfree (self->function_name); + + VEC_free (agent_expr_p, self->target_info.conditions); + VEC_free (agent_expr_p, self->target_info.tcommands); } static const struct bp_location_ops bp_location_ops = @@ -12800,10 +13173,10 @@ base_breakpoint_decode_linespec (struct breakpoint *b, char **s, /* The default 'explains_signal' method. */ -static enum bpstat_signal_value +static int base_breakpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig) { - return BPSTAT_SIGNAL_HIDE; + return 1; } /* The default "after_condition_true" method. */ @@ -12857,11 +13230,9 @@ static int bkpt_insert_location (struct bp_location *bl) { if (bl->loc_type == bp_loc_hardware_breakpoint) - return target_insert_hw_breakpoint (bl->gdbarch, - &bl->target_info); + return target_insert_hw_breakpoint (bl->gdbarch, &bl->target_info); else - return target_insert_breakpoint (bl->gdbarch, - &bl->target_info); + return target_insert_breakpoint (bl->gdbarch, &bl->target_info); } static int @@ -12894,6 +13265,23 @@ bkpt_breakpoint_hit (const struct bp_location *bl, return 1; } +static int +dprintf_breakpoint_hit (const struct bp_location *bl, + struct address_space *aspace, CORE_ADDR bp_addr, + const struct target_waitstatus *ws) +{ + if (dprintf_style == dprintf_style_agent + && target_can_run_breakpoint_commands ()) + { + /* An agent-style dprintf never causes a stop. If we see a trap + for this address it must be for a breakpoint that happens to + be set at the same address. */ + return 0; + } + + return bkpt_breakpoint_hit (bl, aspace, bp_addr, ws); +} + static int bkpt_resources_needed (const struct bp_location *bl) { @@ -13199,7 +13587,10 @@ bkpt_probe_insert_location (struct bp_location *bl) { /* The insertion was successful, now let's set the probe's semaphore if needed. */ - bl->probe->pops->set_semaphore (bl->probe, bl->gdbarch); + if (bl->probe.probe->pops->set_semaphore != NULL) + bl->probe.probe->pops->set_semaphore (bl->probe.probe, + bl->probe.objfile, + bl->gdbarch); } return v; @@ -13209,7 +13600,10 @@ static int bkpt_probe_remove_location (struct bp_location *bl) { /* Let's clear the semaphore before removing the location. */ - bl->probe->pops->clear_semaphore (bl->probe, bl->gdbarch); + if (bl->probe.probe->pops->clear_semaphore != NULL) + bl->probe.probe->pops->clear_semaphore (bl->probe.probe, + bl->probe.objfile, + bl->gdbarch); return bkpt_remove_location (bl); } @@ -13654,7 +14048,7 @@ delete_breakpoint (struct breakpoint *bpt) itself, since remove_breakpoint looks at location's owner. It might be better design to have location completely self-contained, but it's not the case now. */ - update_global_location_list (0); + update_global_location_list (UGLL_DONT_INSERT); bpt->ops->dtor (bpt); /* On the chance that someone will soon try again to delete this @@ -13983,7 +14377,7 @@ update_breakpoint_locations (struct breakpoint *b, /* Ranged breakpoints have only one start location and one end location. */ b->enable_state = bp_disabled; - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); printf_unfiltered (_("Could not reset ranged breakpoint %d: " "multiple locations found\n"), b->number); @@ -14040,10 +14434,6 @@ update_breakpoint_locations (struct breakpoint *b, } } - /* Update locations of permanent breakpoints. */ - if (b->enable_state == bp_permanent) - make_breakpoint_permanent (b); - /* If possible, carry over 'disable' status from existing breakpoints. */ { @@ -14086,7 +14476,7 @@ update_breakpoint_locations (struct breakpoint *b, if (!locations_are_equal (existing_locations, b->loc)) observer_notify_breakpoint_modified (b); - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); } /* Find the SaL locations corresponding to the given ADDR_STRING. @@ -14447,7 +14837,7 @@ map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *, while (!state.finished) { - char *p = state.string; + const char *p = state.string; match = 0; @@ -14526,10 +14916,6 @@ disable_breakpoint (struct breakpoint *bpt) 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; /* Mark breakpoint locations modified. */ @@ -14544,7 +14930,7 @@ disable_breakpoint (struct breakpoint *bpt) target_disable_tracepoint (location); } - update_global_location_list (0); + update_global_location_list (UGLL_DONT_INSERT); observer_notify_breakpoint_modified (bpt); } @@ -14599,7 +14985,7 @@ disable_command (char *args, int from_tty) && is_tracepoint (loc->owner)) target_disable_tracepoint (loc); } - update_global_location_list (0); + update_global_location_list (UGLL_DONT_INSERT); } else map_breakpoint_numbers (num, do_map_disable_breakpoint, NULL); @@ -14650,9 +15036,6 @@ enable_breakpoint_disp (struct breakpoint *bpt, enum bpdisp disposition, } } - if (bpt->enable_state != bp_permanent) - bpt->enable_state = bp_enabled; - bpt->enable_state = bp_enabled; /* Mark breakpoint locations modified. */ @@ -14669,7 +15052,7 @@ enable_breakpoint_disp (struct breakpoint *bpt, enum bpdisp disposition, bpt->disposition = disposition; bpt->enable_count = count; - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); observer_notify_breakpoint_modified (bpt); } @@ -14733,7 +15116,7 @@ enable_command (char *args, int from_tty) && is_tracepoint (loc->owner)) target_enable_tracepoint (loc); } - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); } else map_breakpoint_numbers (num, do_map_enable_breakpoint, NULL); @@ -14847,54 +15230,6 @@ invalidate_bp_value_on_memory_change (struct inferior *inferior, } } -/* 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 (struct gdbarch *gdbarch, - struct address_space *aspace, CORE_ADDR pc) -{ - struct bp_target_info *bp_tgt; - - bp_tgt = XZALLOC (struct bp_target_info); - - bp_tgt->placed_address_space = aspace; - bp_tgt->placed_address = pc; - - if (target_insert_breakpoint (gdbarch, 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 (struct gdbarch *gdbarch, void *bp) -{ - struct bp_target_info *bp_tgt = bp; - int ret; - - ret = target_remove_breakpoint (gdbarch, bp_tgt); - xfree (bp_tgt); - - return ret; -} - -/* One (or perhaps two) breakpoints used for software single - stepping. */ - -static void *single_step_breakpoints[2]; -static struct gdbarch *single_step_gdbarch[2]; - /* Create and insert a breakpoint for software single step. */ void @@ -14902,118 +15237,57 @@ insert_single_step_breakpoint (struct gdbarch *gdbarch, struct address_space *aspace, CORE_ADDR next_pc) { - void **bpt_p; + struct thread_info *tp = inferior_thread (); + struct symtab_and_line sal; + CORE_ADDR pc = next_pc; - if (single_step_breakpoints[0] == NULL) - { - bpt_p = &single_step_breakpoints[0]; - single_step_gdbarch[0] = gdbarch; - } - else + if (tp->control.single_step_breakpoints == NULL) { - gdb_assert (single_step_breakpoints[1] == NULL); - bpt_p = &single_step_breakpoints[1]; - single_step_gdbarch[1] = gdbarch; + tp->control.single_step_breakpoints + = new_single_step_breakpoint (tp->num, gdbarch); } - /* 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. */ + sal = find_pc_line (pc, 0); + sal.pc = pc; + sal.section = find_pc_overlay (pc); + sal.explicit_pc = 1; + add_location_to_breakpoint (tp->control.single_step_breakpoints, &sal); - *bpt_p = deprecated_insert_raw_breakpoint (gdbarch, aspace, next_pc); - if (*bpt_p == NULL) - error (_("Could not insert single-step breakpoint at %s"), - paddress (gdbarch, next_pc)); + update_global_location_list (UGLL_INSERT); } -/* Check if the breakpoints used for software single stepping - were inserted or not. */ +/* See breakpoint.h. */ int -single_step_breakpoints_inserted (void) -{ - return (single_step_breakpoints[0] != NULL - || single_step_breakpoints[1] != NULL); -} - -/* Remove and delete any breakpoints used for software single step. */ - -void -remove_single_step_breakpoints (void) +breakpoint_has_location_inserted_here (struct breakpoint *bp, + struct address_space *aspace, + CORE_ADDR pc) { - gdb_assert (single_step_breakpoints[0] != NULL); - - /* See insert_single_step_breakpoint for more about this deprecated - call. */ - deprecated_remove_raw_breakpoint (single_step_gdbarch[0], - single_step_breakpoints[0]); - single_step_gdbarch[0] = NULL; - single_step_breakpoints[0] = NULL; - - if (single_step_breakpoints[1] != NULL) - { - deprecated_remove_raw_breakpoint (single_step_gdbarch[1], - single_step_breakpoints[1]); - single_step_gdbarch[1] = NULL; - single_step_breakpoints[1] = NULL; - } -} - -/* Delete software single step breakpoints without removing them from - the inferior. This is intended to be used if the inferior's address - space where they were inserted is already gone, e.g. after exit or - exec. */ - -void -cancel_single_step_breakpoints (void) -{ - int i; - - for (i = 0; i < 2; i++) - if (single_step_breakpoints[i]) - { - xfree (single_step_breakpoints[i]); - single_step_breakpoints[i] = NULL; - single_step_gdbarch[i] = NULL; - } -} - -/* Detach software single-step breakpoints from INFERIOR_PTID without - removing them. */ + struct bp_location *loc; -static void -detach_single_step_breakpoints (void) -{ - int i; + for (loc = bp->loc; loc != NULL; loc = loc->next) + if (loc->inserted + && breakpoint_location_address_match (loc, aspace, pc)) + return 1; - for (i = 0; i < 2; i++) - if (single_step_breakpoints[i]) - target_remove_breakpoint (single_step_gdbarch[i], - single_step_breakpoints[i]); + return 0; } /* Check whether a software single-step breakpoint is inserted at PC. */ -static int -single_step_breakpoint_inserted_here_p (struct address_space *aspace, +int +single_step_breakpoint_inserted_here_p (struct address_space *aspace, CORE_ADDR pc) { - int i; + struct breakpoint *bpt; - for (i = 0; i < 2; i++) + ALL_BREAKPOINTS (bpt) { - struct bp_target_info *bp_tgt = single_step_breakpoints[i]; - if (bp_tgt - && breakpoint_address_match (bp_tgt->placed_address_space, - bp_tgt->placed_address, - aspace, pc)) + if (bpt->type == bp_single_step + && breakpoint_has_location_inserted_here (bpt, aspace, pc)) return 1; } - return 0; } @@ -15382,7 +15656,7 @@ trace_pass_command (char *args, int from_tty) } else if (*args == '\0') { - t1 = get_tracepoint_by_number (&args, NULL, 1); + t1 = get_tracepoint_by_number (&args, NULL); if (t1) trace_pass_set_count (t1, count, from_tty); } @@ -15393,7 +15667,7 @@ trace_pass_command (char *args, int from_tty) init_number_or_range (&state, args); while (!state.finished) { - t1 = get_tracepoint_by_number (&args, &state, 1); + t1 = get_tracepoint_by_number (&args, &state); if (t1) trace_pass_set_count (t1, count, from_tty); } @@ -15434,12 +15708,12 @@ get_tracepoint_by_number_on_target (int num) /* Utility: parse a tracepoint number and look it up in the list. If STATE is not NULL, use, get_number_or_range_state and ignore ARG. - If OPTIONAL_P is true, then if the argument is missing, the most - recent tracepoint (tracepoint_count) is returned. */ + If the argument is missing, the most recent tracepoint + (tracepoint_count) is returned. */ + struct tracepoint * get_tracepoint_by_number (char **arg, - struct get_number_or_range_state *state, - int optional_p) + struct get_number_or_range_state *state) { struct breakpoint *t; int tpnum; @@ -15451,12 +15725,7 @@ get_tracepoint_by_number (char **arg, tpnum = get_number_or_range (state); } else if (arg == NULL || *arg == NULL || ! **arg) - { - if (optional_p) - tpnum = tracepoint_count; - else - error_no_arg (_("tracepoint number")); - } + tpnum = tracepoint_count; else tpnum = get_number (arg); @@ -15466,8 +15735,7 @@ get_tracepoint_by_number (char **arg, printf_filtered (_("bad tracepoint number at or near '%s'\n"), instring); else - printf_filtered (_("Tracepoint argument missing " - "and no previous tracepoint\n")); + printf_filtered (_("No previous tracepoint\n")); return NULL; } @@ -15592,7 +15860,7 @@ save_breakpoints (char *filename, int from_tty, } if (tp->enable_state == bp_disabled) - fprintf_unfiltered (fp, "disable\n"); + fprintf_unfiltered (fp, "disable $bpnum\n"); /* If this is a multi-location breakpoint, check if the locations should be individually disabled. Watchpoint locations are @@ -15681,8 +15949,7 @@ static struct cmd_list_element *tcatch_cmdlist; void add_catch_command (char *name, char *docstring, - void (*sfunc) (char *args, int from_tty, - struct cmd_list_element *command), + cmd_sfunc_ftype *sfunc, completer_ftype *completer, void *user_data_catch, void *user_data_tcatch) @@ -15718,7 +15985,7 @@ save_command (char *arg, int from_tty) { printf_unfiltered (_("\"save\" must be followed by " "the name of a save subcommand.\n")); - help_list (save_cmdlist, "save ", -1, gdb_stdout); + help_list (save_cmdlist, "save ", all_commands, gdb_stdout); } struct breakpoint * @@ -15784,7 +16051,7 @@ breakpoint_free_objfile (struct objfile *objfile) struct bp_location **locp, *loc; ALL_BP_LOCATIONS (loc, locp) - if (loc->symtab != NULL && loc->symtab->objfile == objfile) + if (loc->symtab != NULL && SYMTAB_OBJFILE (loc->symtab) == objfile) loc->symtab = NULL; } @@ -15981,6 +16248,7 @@ initialize_breakpoint_ops (void) ops->print_mention = bkpt_print_mention; ops->print_recreate = dprintf_print_recreate; ops->after_condition_true = dprintf_after_condition_true; + ops->breakpoint_hit = dprintf_breakpoint_hit; } /* Chain containing all defined "enable breakpoint" subcommands. */ @@ -15995,6 +16263,7 @@ _initialize_breakpoint (void) initialize_breakpoint_ops (); observer_attach_solib_unloaded (disable_breakpoints_in_unloaded_shlib); + observer_attach_free_objfile (disable_breakpoints_in_freed_objfile); observer_attach_inferior_exit (clear_syscall_counts); observer_attach_memory_changed (invalidate_bp_value_on_memory_change); @@ -16507,18 +16776,15 @@ a warning will be emitted for such breakpoints."), &breakpoint_set_cmdlist, &breakpoint_show_cmdlist); - add_setshow_auto_boolean_cmd ("always-inserted", class_support, - &always_inserted_mode, _("\ + add_setshow_boolean_cmd ("always-inserted", class_support, + &always_inserted_mode, _("\ Set mode for inserting breakpoints."), _("\ Show mode for inserting breakpoints."), _("\ -When this mode is off, breakpoints are inserted in inferior when it is\n\ -resumed, and removed when execution stops. When this mode is on,\n\ -breakpoints are inserted immediately and removed only when the user\n\ -deletes the breakpoint. When this mode is auto (which is the default),\n\ -the behaviour depends on the non-stop setting (see help set non-stop).\n\ -In this case, if gdb is controlling the inferior in non-stop mode, gdb\n\ -behaves as if always-inserted mode is on; if gdb is controlling the\n\ -inferior in all-stop mode, gdb behaves as if always-inserted mode is off."), +When this mode is on, breakpoints are inserted immediately as soon as\n\ +they're created, kept inserted even when execution stops, and removed\n\ +only when the user deletes them. When this mode is off (the default),\n\ +breakpoints are inserted only when execution continues, and removed\n\ +when execution stops."), NULL, &show_always_inserted_mode, &breakpoint_set_cmdlist,