X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gdb%2Fbreakpoint.c;h=a144a7e96a941b05c6dbd880cf785febad9f2f66;hb=6144afba18bc86c04804bfc7df535e778e3c4e31;hp=114762dd5685d380c0c281e60d1818407ed1f9ed;hpb=ecd75fc8eed3bde86036141228074a20e55dcfc9;p=platform%2Fupstream%2Fbinutils.git diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 114762d..a144a7e 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -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 #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); @@ -234,8 +227,8 @@ 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 int find_single_step_breakpoint (struct address_space *aspace, + CORE_ADDR pc); static void free_bp_location (struct bp_location *loc); static void incref_bp_location (struct bp_location *loc); @@ -243,9 +236,44 @@ 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); @@ -302,6 +330,12 @@ static struct breakpoint_ops bkpt_probe_breakpoint_ops; /* Dynamic printf class type. */ struct breakpoint_ops dprintf_breakpoint_ops; +/* One (or perhaps two) breakpoints used for software single + stepping. */ + +static void *single_step_breakpoints[2]; +static struct gdbarch *single_step_gdbarch[2]; + /* The style in which to perform a dynamic printf. This is a user option because different output options have different tradeoffs; if GDB does the printing, there is better error handling if there @@ -421,34 +455,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 +883,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 +1096,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 +1466,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 +1586,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 +1660,27 @@ 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; + one_breakpoint_xfer_memory (readbuf, writebuf, writebuf_org, + memaddr, len, &bl->target_info, bl->gdbarch); + } - /* 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; - } + /* Now process single-step breakpoints. These are not found in the + bp_location array. */ + for (i = 0; i < 2; i++) + { + struct bp_target_info *bp_tgt = single_step_breakpoints[i]; - if (bp_addr + bp_size > memaddr + len) - { - /* Only copy the first part of the breakpoint. */ - bp_size -= (bp_addr + bp_size) - (memaddr + len); - } + if (bp_tgt != NULL) + { + struct gdbarch *gdbarch = single_step_gdbarch[i]; - 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, bp_tgt, gdbarch); + } + } } + /* Return true if BPT is either a software breakpoint or a hardware @@ -1651,6 +1751,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 @@ -1825,6 +1948,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; } @@ -1854,8 +1983,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; @@ -1870,7 +2022,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; } } @@ -2031,6 +2191,23 @@ 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; + } + return 1; } @@ -2293,14 +2470,26 @@ build_target_command_list (struct bp_location *bl) /* Release commands left over from a previous insert. */ VEC_free (agent_expr_p, bl->target_info.tcommands); - /* For now, limit to agent-style dprintf breakpoints. */ - if (bl->owner->type != bp_dprintf - || strcmp (dprintf_style, dprintf_style_agent) != 0) + if (!target_can_run_breakpoint_commands ()) return; - if (!target_can_run_breakpoint_commands ()) + /* 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 @@ -2395,9 +2584,9 @@ insert_bp_location (struct bp_location *bl, int *hw_breakpoint_error, int *hw_bp_error_explained_already) { - int val = 0; - const 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; @@ -2411,7 +2600,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; @@ -2452,7 +2641,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) { @@ -2481,10 +2670,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; + } } } @@ -2496,12 +2691,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 = e.message; + bp_err = e.error; + bp_err_message = e.message; } } else @@ -2522,10 +2721,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", @@ -2538,12 +2752,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 = e.message; + bp_err = e.error; + bp_err_message = e.message; } } else @@ -2554,13 +2772,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) @@ -2575,39 +2805,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 { - 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); + 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 @@ -2615,6 +2857,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); @@ -2658,6 +2902,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); @@ -2725,7 +2971,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. @@ -2745,13 +2991,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. */ @@ -3094,10 +3337,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; @@ -3106,10 +3349,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; @@ -3174,24 +3417,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); @@ -3208,7 +3451,7 @@ create_overlay_event_breakpoint (void) overlay_events_enabled = 0; } } - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); } static void @@ -3271,7 +3514,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"); @@ -3290,25 +3535,25 @@ create_longjmp_master_breakpoint (void) 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); @@ -3316,7 +3561,7 @@ create_longjmp_master_breakpoint (void) } } } - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); do_cleanups (old_chain); } @@ -3345,25 +3590,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); @@ -3372,7 +3617,7 @@ create_std_terminate_master_breakpoint (void) } } - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); do_cleanups (old_chain); } @@ -3432,7 +3677,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"); @@ -3444,26 +3691,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, @@ -3472,7 +3719,7 @@ create_exception_master_breakpoint (void) b->enable_state = bp_disabled; } - update_global_location_list (1); + update_global_location_list (UGLL_MAY_INSERT); } void @@ -3588,11 +3835,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 @@ -3668,7 +3910,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 { @@ -3713,10 +3979,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) @@ -4005,12 +4282,12 @@ breakpoint_inserted_here_p (struct address_space *aspace, CORE_ADDR pc) return 0; } -/* This function returns non-zero iff there is a software breakpoint - inserted at PC. */ +/* Ignoring deprecated raw breakpoints, return non-zero iff there is a + software breakpoint inserted at PC. */ -int -software_breakpoint_inserted_here_p (struct address_space *aspace, - CORE_ADDR pc) +static struct bp_location * +find_non_raw_software_breakpoint_inserted_here (struct address_space *aspace, + CORE_ADDR pc) { struct bp_location *bl, **blp_tmp; @@ -4028,10 +4305,23 @@ software_breakpoint_inserted_here_p (struct address_space *aspace, && !section_is_mapped (bl->section)) continue; /* unmapped overlay -- can't be a match */ else - return 1; + return bl; } } + return NULL; +} + +/* This function returns non-zero iff there is a software breakpoint + inserted at PC. */ + +int +software_breakpoint_inserted_here_p (struct address_space *aspace, + CORE_ADDR pc) +{ + if (find_non_raw_software_breakpoint_inserted_here (aspace, pc) != NULL) + return 1; + /* Also check for software single-step breakpoints. */ if (single_step_breakpoint_inserted_here_p (aspace, pc)) return 1; @@ -4864,6 +5154,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 @@ -5107,7 +5400,6 @@ bpstat_check_watchpoint (bpstat bs) 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; @@ -5132,17 +5424,20 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) return; } - /* If this is a thread-specific breakpoint, don't waste cpu evaluating the - condition if this isn't the specified thread. */ - if (b->thread != -1 && b->thread != thread_id) + /* 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 Python breakpoints that have a "stop" method implemented. */ - if (b->py_bp_object) - bs->stop = gdbpy_should_stop (b->py_bp_object); + /* Evaluate extension language breakpoints that have a "stop" method + implemented. */ + bs->stop = breakpoint_ext_lang_cond_says_stop (b); if (is_watchpoint (b)) { @@ -5414,9 +5709,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; } @@ -6734,12 +7029,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) { @@ -7215,7 +7507,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; } @@ -7265,7 +7557,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. */ @@ -7283,7 +7576,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 @@ -7291,12 +7584,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; @@ -7306,7 +7599,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) { @@ -7327,7 +7620,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; } } @@ -7341,7 +7634,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; } } @@ -7358,7 +7651,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); } } @@ -7386,7 +7679,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; } @@ -7417,7 +7710,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; } @@ -7445,14 +7738,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; } @@ -7554,10 +7889,19 @@ disable_breakpoints_in_freed_objfile (struct objfile *objfile) if (objfile == NULL) return; - /* If the file is a shared library not loaded by the user then - solib_unloaded was notified and disable_breakpoints_in_unloaded_shlib - was called. In that case there is no need to take action again. */ - if ((objfile->flags & OBJF_SHARED) && !(objfile->flags & OBJF_USERLOADED)) + /* 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) @@ -7589,7 +7933,11 @@ disable_breakpoints_in_freed_objfile (struct objfile *objfile) if (is_addr_in_objfile (loc_addr, objfile)) { loc->shlib_disabled = 1; - loc->inserted = 0; + /* 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); @@ -8190,7 +8538,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); } @@ -8556,7 +8904,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 @@ -8798,7 +9146,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); } } } @@ -8813,7 +9161,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); } } } @@ -8822,7 +9170,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 @@ -8858,19 +9206,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; @@ -8886,6 +9235,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; @@ -8894,7 +9244,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; } @@ -8908,7 +9258,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 * @@ -8969,7 +9319,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; @@ -9848,7 +10199,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; } @@ -9911,8 +10262,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); @@ -9938,7 +10289,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); } @@ -10360,7 +10711,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 @@ -10409,8 +10760,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: @@ -10983,6 +11332,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; @@ -11116,6 +11466,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; @@ -11251,6 +11607,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; } @@ -11477,7 +11835,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. */ @@ -12256,24 +12614,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; @@ -12608,23 +12958,23 @@ update_global_location_list (int should_insert) "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); @@ -12646,12 +12996,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. */ @@ -12940,6 +13290,20 @@ bkpt_re_set (struct breakpoint *b) breakpoint_re_set_default (b); } +/* Copy SRC's shadow buffer and whatever else we'd set if we actually + inserted DEST, so we can remove it later, in case SRC is removed + first. */ + +static void +bp_target_info_copy_insertion_state (struct bp_target_info *dest, + const struct bp_target_info *src) +{ + dest->shadow_len = src->shadow_len; + memcpy (dest->shadow_contents, src->shadow_contents, src->shadow_len); + dest->placed_address = src->placed_address; + dest->placed_size = src->placed_size; +} + static int bkpt_insert_location (struct bp_location *bl) { @@ -12947,8 +13311,25 @@ bkpt_insert_location (struct bp_location *bl) return target_insert_hw_breakpoint (bl->gdbarch, &bl->target_info); else - return target_insert_breakpoint (bl->gdbarch, - &bl->target_info); + { + struct bp_target_info *bp_tgt = &bl->target_info; + int ret; + int sss_slot; + + /* There is no need to insert a breakpoint if an unconditional + raw/sss breakpoint is already inserted at that location. */ + sss_slot = find_single_step_breakpoint (bp_tgt->placed_address_space, + bp_tgt->reqstd_address); + if (sss_slot >= 0) + { + struct bp_target_info *sss_bp_tgt = single_step_breakpoints[sss_slot]; + + bp_target_info_copy_insertion_state (bp_tgt, sss_bp_tgt); + return 0; + } + + return target_insert_breakpoint (bl->gdbarch, bp_tgt); + } } static int @@ -12957,7 +13338,19 @@ bkpt_remove_location (struct bp_location *bl) if (bl->loc_type == bp_loc_hardware_breakpoint) return target_remove_hw_breakpoint (bl->gdbarch, &bl->target_info); else - return target_remove_breakpoint (bl->gdbarch, &bl->target_info); + { + struct bp_target_info *bp_tgt = &bl->target_info; + struct address_space *aspace = bp_tgt->placed_address_space; + CORE_ADDR address = bp_tgt->reqstd_address; + + /* Only remove the breakpoint if there is no raw/sss breakpoint + still inserted at this location. Otherwise, we would be + effectively disabling the raw/sss breakpoint. */ + if (single_step_breakpoint_inserted_here_p (aspace, address)) + return 0; + + return target_remove_breakpoint (bl->gdbarch, bp_tgt); + } } static int @@ -12982,6 +13375,23 @@ bkpt_breakpoint_hit (const struct bp_location *bl, } 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) { gdb_assert (bl->owner->type == bp_hardware_breakpoint); @@ -13286,7 +13696,9 @@ 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); + bl->probe.probe->pops->set_semaphore (bl->probe.probe, + bl->probe.objfile, + bl->gdbarch); } return v; @@ -13296,7 +13708,9 @@ 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); + bl->probe.probe->pops->clear_semaphore (bl->probe.probe, + bl->probe.objfile, + bl->gdbarch); return bkpt_remove_location (bl); } @@ -13741,7 +14155,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 @@ -14070,7 +14484,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); @@ -14173,7 +14587,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. @@ -14534,7 +14948,7 @@ map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *, while (!state.finished) { - char *p = state.string; + const char *p = state.string; match = 0; @@ -14631,7 +15045,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); } @@ -14686,7 +15100,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); @@ -14756,7 +15170,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); } @@ -14820,7 +15234,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); @@ -14945,11 +15359,29 @@ deprecated_insert_raw_breakpoint (struct gdbarch *gdbarch, struct address_space *aspace, CORE_ADDR pc) { struct bp_target_info *bp_tgt; + struct bp_location *bl; - bp_tgt = XZALLOC (struct bp_target_info); + bp_tgt = XCNEW (struct bp_target_info); bp_tgt->placed_address_space = aspace; - bp_tgt->placed_address = pc; + bp_tgt->reqstd_address = pc; + + /* If an unconditional non-raw breakpoint is already inserted at + that location, there's no need to insert another. However, with + target-side evaluation of breakpoint conditions, if the + breakpoint that is currently inserted on the target is + conditional, we need to make it unconditional. Note that a + breakpoint with target-side commands is not reported even if + unconditional, so we need to remove the commands from the target + as well. */ + bl = find_non_raw_software_breakpoint_inserted_here (aspace, pc); + if (bl != NULL + && VEC_empty (agent_expr_p, bl->target_info.conditions) + && VEC_empty (agent_expr_p, bl->target_info.tcommands)) + { + bp_target_info_copy_insertion_state (bp_tgt, &bl->target_info); + return bp_tgt; + } if (target_insert_breakpoint (gdbarch, bp_tgt) != 0) { @@ -14968,20 +15400,35 @@ int deprecated_remove_raw_breakpoint (struct gdbarch *gdbarch, void *bp) { struct bp_target_info *bp_tgt = bp; + struct address_space *aspace = bp_tgt->placed_address_space; + CORE_ADDR address = bp_tgt->reqstd_address; + struct bp_location *bl; int ret; - ret = target_remove_breakpoint (gdbarch, bp_tgt); + bl = find_non_raw_software_breakpoint_inserted_here (aspace, address); + + /* Only remove the raw breakpoint if there are no other non-raw + breakpoints still inserted at this location. Otherwise, we would + be effectively disabling those breakpoints. */ + if (bl == NULL) + ret = target_remove_breakpoint (gdbarch, bp_tgt); + else if (!VEC_empty (agent_expr_p, bl->target_info.conditions) + || !VEC_empty (agent_expr_p, bl->target_info.tcommands)) + { + /* The target is evaluating conditions, and when we inserted the + software single-step breakpoint, we had made the breakpoint + unconditional and command-less on the target side. Reinsert + to restore the conditions/commands. */ + ret = target_insert_breakpoint (bl->gdbarch, &bl->target_info); + } + else + ret = 0; + 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 @@ -15082,12 +15529,12 @@ detach_single_step_breakpoints (void) single_step_breakpoints[i]); } -/* Check whether a software single-step breakpoint is inserted at - PC. */ +/* Find the software single-step breakpoint that inserted at PC. + Returns its slot if found, and -1 if not found. */ static int -single_step_breakpoint_inserted_here_p (struct address_space *aspace, - CORE_ADDR pc) +find_single_step_breakpoint (struct address_space *aspace, + CORE_ADDR pc) { int i; @@ -15096,12 +15543,22 @@ single_step_breakpoint_inserted_here_p (struct address_space *aspace, 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, + bp_tgt->reqstd_address, aspace, pc)) - return 1; + return i; } - return 0; + return -1; +} + +/* Check whether a software single-step breakpoint is inserted at + PC. */ + +int +single_step_breakpoint_inserted_here_p (struct address_space *aspace, + CORE_ADDR pc) +{ + return find_single_step_breakpoint (aspace, pc) >= 0; } /* Returns 0 if 'bp' is NOT a syscall catchpoint, @@ -15469,7 +15926,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); } @@ -15480,7 +15937,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); } @@ -15521,12 +15978,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; @@ -15538,12 +15995,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); @@ -15553,8 +16005,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; } @@ -15679,7 +16130,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 @@ -15768,8 +16219,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) @@ -15805,7 +16255,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 * @@ -16068,6 +16518,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. */ @@ -16595,18 +17046,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,