X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fbreakpoint.c;h=4e6c627d913abcb4e7108f71b8787b3c81832df2;hb=41fac0cf495b84994046901e3293d54e8eef3534;hp=f4f9325ab6477efa6b614b3e9e6fe30fc9965257;hpb=58ce7251e876ad5b6569e3ee72dfe6c4c5697ca8;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index f4f9325ab6..4e6c627d91 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,11 @@ #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 #include "gdb-demangle.h" #include "filenames.h" #include "annotate.h" @@ -66,7 +67,6 @@ #include "continuations.h" #include "stack.h" #include "skip.h" -#include "gdb_regex.h" #include "ax-gdb.h" #include "dummy-frame.h" @@ -80,7 +80,7 @@ #undef savestring #include "mi/mi-common.h" -#include "python/python.h" +#include "extension.h" /* Enums for exception-handling support. */ enum exception_event_kind @@ -119,7 +119,6 @@ static void create_sals_from_address_default (char **, static void create_breakpoints_sal_default (struct gdbarch *, struct linespec_result *, - struct linespec_sals *, char *, char *, enum bptype, enum bpdisp, int, int, int, @@ -167,11 +166,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); @@ -235,9 +229,6 @@ 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); @@ -301,7 +292,13 @@ struct breakpoint_ops bkpt_breakpoint_ops; static struct breakpoint_ops bkpt_probe_breakpoint_ops; /* Dynamic printf class type. */ -static struct breakpoint_ops dprintf_breakpoint_ops; +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; @@ -1049,14 +1046,18 @@ 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)) @@ -1415,6 +1416,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 placed_address = target_info->placed_address; + int placed_size = target_info->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, &placed_address, &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. @@ -1441,6 +1536,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 @@ -1514,74 +1610,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 @@ -1796,11 +1845,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) { @@ -1808,7 +1865,7 @@ update_watchpoint (struct watchpoint *b, int reparse) struct value *val_chain, *v, *result, *next; struct program_space *frame_pspace; - fetch_subexp_value (b->exp, &pc, &v, &result, &val_chain); + fetch_subexp_value (b->exp, &pc, &v, &result, &val_chain, 0); /* Avoid setting b->val if it's already set. The meaning of b->val is 'the last value' user saw, and we should update @@ -1940,8 +1997,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; @@ -2018,6 +2081,14 @@ 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)) + return 0; + return 1; } @@ -2083,6 +2154,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 @@ -2248,6 +2322,8 @@ parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd) fpieces, nargs, argvec); } + do_cleanups (old_cleanups); + if (ex.reason < 0) { /* If we got here, it means the command could not be parsed to a valid @@ -2256,8 +2332,6 @@ parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd) return NULL; } - do_cleanups (old_cleanups); - /* We have a valid agent expression, return it. */ return aexpr; } @@ -2274,14 +2348,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 @@ -2376,9 +2465,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; @@ -2477,12 +2566,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 @@ -2504,9 +2597,24 @@ insert_bp_location (struct bp_location *bl, /* 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) + + /* 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", @@ -2519,12 +2627,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 @@ -2535,13 +2647,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) + || userloaded_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) @@ -2556,38 +2680,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 @@ -2595,6 +2732,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); @@ -2638,6 +2777,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); @@ -2929,6 +3070,30 @@ remove_breakpoints (void) return val; } +/* When a thread exits, remove breakpoints that are related to + that thread. */ + +static void +remove_threaded_breakpoints (struct thread_info *tp, int silent) +{ + struct breakpoint *b, *b_tmp; + + ALL_BREAKPOINTS_SAFE (b, b_tmp) + { + if (b->thread == tp->num && user_breakpoint_p (b)) + { + b->disposition = disp_del_at_next_stop; + + printf_filtered (_("\ +Thread-specific breakpoint %d deleted - thread %d no longer in the thread list.\n"), + b->number, tp->num); + + /* Hide it from the user. */ + b->number = 0; + } + } +} + /* Remove breakpoints of process PID. */ int @@ -3050,10 +3215,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; @@ -3062,10 +3227,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; @@ -3130,24 +3295,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); @@ -3188,15 +3353,28 @@ 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); if (!bp_objfile_data->longjmp_searched) { - bp_objfile_data->longjmp_probes - = find_probes_in_objfile (objfile, "libc", "longjmp"); + VEC (probe_p) *ret; + + ret = find_probes_in_objfile (objfile, "libc", "longjmp"); + if (ret != NULL) + { + /* We are only interested in checking one element. */ + struct probe *p = VEC_index (probe_p, ret, 0); + + if (!can_evaluate_probe_arguments (p)) + { + /* We cannot use the probe interface here, because it does + not know how to evaluate arguments. */ + VEC_free (probe_p, ret); + ret = NULL; + } + } + bp_objfile_data->longjmp_probes = ret; bp_objfile_data->longjmp_searched = 1; } @@ -3214,7 +3392,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"); @@ -3224,31 +3404,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); @@ -3285,25 +3468,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); @@ -3337,8 +3520,24 @@ create_exception_master_breakpoint (void) /* We prefer the SystemTap probe point if it exists. */ if (!bp_objfile_data->exception_searched) { - bp_objfile_data->exception_probes - = find_probes_in_objfile (objfile, "libgcc", "unwind"); + VEC (probe_p) *ret; + + ret = find_probes_in_objfile (objfile, "libgcc", "unwind"); + + if (ret != NULL) + { + /* We are only interested in checking one element. */ + struct probe *p = VEC_index (probe_p, ret, 0); + + if (!can_evaluate_probe_arguments (p)) + { + /* We cannot use the probe interface here, because it does + not know how to evaluate arguments. */ + VEC_free (probe_p, ret); + ret = NULL; + } + } + bp_objfile_data->exception_probes = ret; bp_objfile_data->exception_searched = 1; } @@ -3356,7 +3555,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"); @@ -3368,26 +3569,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, @@ -3527,7 +3728,7 @@ detach_breakpoints (ptid_t ptid) struct cleanup *old_chain = save_inferior_ptid (); struct inferior *inf = current_inferior (); - if (PIDGET (ptid) == PIDGET (inferior_ptid)) + if (ptid_get_pid (ptid) == ptid_get_pid (inferior_ptid)) error (_("Cannot detach breakpoints of inferior_ptid")); /* Set inferior_ptid; remove_breakpoint_1 uses this global. */ @@ -3537,6 +3738,15 @@ detach_breakpoints (ptid_t ptid) if (bl->pspace != inf->pspace) continue; + /* This function must physically remove breakpoints locations + from the specified ptid, without modifying the breakpoint + package's state. Locations of type bp_loc_other are only + maintained at GDB side. So, there is no need to remove + these bp_loc_other locations. Moreover, removing these + would modify the breakpoint package's state. */ + if (bl->loc_type == bp_loc_other) + continue; + if (bl->inserted) val |= remove_breakpoint_1 (bl, mark_inserted); } @@ -3583,7 +3793,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 + OBJF_USERLOADED 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 { @@ -3628,10 +3862,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) + || userloaded_objfile_contains_address_p (bl->pspace, + bl->address)))) val = 0; if (val) @@ -4143,25 +4388,27 @@ bpstat_find_breakpoint (bpstat bsp, struct breakpoint *breakpoint) /* See breakpoint.h. */ -enum bpstat_signal_value -bpstat_explains_signal (bpstat bsp) +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 = BPSTAT_SIGNAL_HIDE; - - if (bsp->breakpoint_at != NULL) - newval = bsp->breakpoint_at->ops->explains_signal (bsp->breakpoint_at); - - if (newval > result) - result = newval; + if (bsp->breakpoint_at == NULL) + { + /* A moribund location can never explain a signal other than + GDB_SIGNAL_TRAP. */ + if (sig == GDB_SIGNAL_TRAP) + return 1; + } + else + { + 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 @@ -4560,10 +4807,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) @@ -4633,7 +4882,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 @@ -4773,7 +5022,7 @@ watchpoint_check (void *p) return WP_VALUE_CHANGED; mark = value_mark (); - fetch_subexp_value (b->exp, &pc, &new_val, NULL, NULL); + fetch_subexp_value (b->exp, &pc, &new_val, NULL, NULL, 0); /* We use value_equal_contents instead of value_equal because the latter coerces an array to a pointer, thus comparing just @@ -5010,17 +5259,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; @@ -5034,109 +5286,113 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) 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) { - int value_is_zero = 0; - struct expression *cond; + 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); + /* 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))) - if (is_watchpoint (b)) - { - struct watchpoint *w = (struct watchpoint *) b; + { + bs->stop = 0; + return; + } - cond = w->cond_exp; - } + /* 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 (cond && b->disposition != disp_del_at_next_stop) + { + 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 - 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; + 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 - 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); - 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); + } } @@ -5290,6 +5546,8 @@ bpstat_stop_status (struct address_space *aspace, if (command_line_is_silent (bs->commands ? bs->commands->commands : NULL)) bs->print = 0; + + b->ops->after_condition_true (bs); } } @@ -5343,21 +5601,6 @@ handle_jit_event (void) target_terminal_inferior (); } -/* Handle an solib event by calling solib_add. */ - -void -handle_solib_event (void) -{ - clear_program_space_solib_cache (current_inferior ()->pspace); - - /* Check for any newly added shared libraries if we're supposed to - be adding them automatically. Switch terminal for any messages - produced by breakpoint_re_set. */ - target_terminal_ours_for_output (); - solib_add (NULL, 0, ¤t_target, auto_solib_add); - target_terminal_inferior (); -} - /* Prepare WHAT final decision for infrun. */ /* Decide what infrun needs to do with this bpstat. */ @@ -5794,8 +6037,6 @@ bptype_string (enum bptype type) return bptypes[(int) type].description; } -DEF_VEC_I(int); - /* For MI, output a field named 'thread-groups' with a list as the value. For CLI, prefix the list with the string 'inf'. */ @@ -5805,8 +6046,7 @@ output_thread_groups (struct ui_out *uiout, VEC(int) *inf_num, int mi_only) { - struct cleanup *back_to = make_cleanup_ui_out_list_begin_end (uiout, - field_name); + struct cleanup *back_to; int is_mi = ui_out_is_mi_like_p (uiout); int inf; int i; @@ -5816,6 +6056,8 @@ output_thread_groups (struct ui_out *uiout, if (!is_mi && mi_only) return; + back_to = make_cleanup_ui_out_list_begin_end (uiout, field_name); + for (i = 0; VEC_iterate (int, inf_num, i, inf); ++i) { if (is_mi) @@ -6654,12 +6896,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) { @@ -7408,9 +7647,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) @@ -7462,6 +7701,78 @@ 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_USERLOADED 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 OBJF_USERLOADED 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_USERLOADED (nor OBJF_SHARED) as those aren't considered + dynamic objects (e.g. the main objfile). */ + if ((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 @@ -7487,7 +7798,7 @@ struct fork_catchpoint static int insert_catch_fork (struct bp_location *bl) { - return target_insert_fork_catchpoint (PIDGET (inferior_ptid)); + return target_insert_fork_catchpoint (ptid_get_pid (inferior_ptid)); } /* Implement the "remove" breakpoint_ops method for fork @@ -7496,7 +7807,7 @@ insert_catch_fork (struct bp_location *bl) static int remove_catch_fork (struct bp_location *bl) { - return target_remove_fork_catchpoint (PIDGET (inferior_ptid)); + return target_remove_fork_catchpoint (ptid_get_pid (inferior_ptid)); } /* Implement the "breakpoint_hit" breakpoint_ops method for fork @@ -7604,7 +7915,7 @@ static struct breakpoint_ops catch_fork_breakpoint_ops; static int insert_catch_vfork (struct bp_location *bl) { - return target_insert_vfork_catchpoint (PIDGET (inferior_ptid)); + return target_insert_vfork_catchpoint (ptid_get_pid (inferior_ptid)); } /* Implement the "remove" breakpoint_ops method for vfork @@ -7613,7 +7924,7 @@ insert_catch_vfork (struct bp_location *bl) static int remove_catch_vfork (struct bp_location *bl) { - return target_remove_vfork_catchpoint (PIDGET (inferior_ptid)); + return target_remove_vfork_catchpoint (ptid_get_pid (inferior_ptid)); } /* Implement the "breakpoint_hit" breakpoint_ops method for vfork @@ -8050,7 +8361,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); } @@ -8106,7 +8417,7 @@ insert_catch_syscall (struct bp_location *bl) } } - return target_set_syscall_catchpoint (PIDGET (inferior_ptid), + return target_set_syscall_catchpoint (ptid_get_pid (inferior_ptid), inf_data->total_syscalls_count != 0, inf_data->any_syscall_count, VEC_length (int, @@ -8146,7 +8457,7 @@ remove_catch_syscall (struct bp_location *bl) } } - return target_set_syscall_catchpoint (PIDGET (inferior_ptid), + return target_set_syscall_catchpoint (ptid_get_pid (inferior_ptid), inf_data->total_syscalls_count != 0, inf_data->any_syscall_count, VEC_length (int, @@ -8185,10 +8496,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; @@ -8469,13 +8779,13 @@ dtor_catch_exec (struct breakpoint *b) static int insert_catch_exec (struct bp_location *bl) { - return target_insert_exec_catchpoint (PIDGET (inferior_ptid)); + return target_insert_exec_catchpoint (ptid_get_pid (inferior_ptid)); } static int remove_catch_exec (struct bp_location *bl) { - return target_remove_exec_catchpoint (PIDGET (inferior_ptid)); + return target_remove_exec_catchpoint (ptid_get_pid (inferior_ptid)); } static int @@ -8830,7 +9140,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; @@ -8939,25 +9250,16 @@ update_dprintf_command_list (struct breakpoint *b) _("Invalid dprintf style.")); gdb_assert (printf_line != NULL); - /* Manufacture a printf/continue sequence. */ + /* Manufacture a printf sequence. */ { - struct command_line *printf_cmd_line, *cont_cmd_line = NULL; - - if (strcmp (dprintf_style, dprintf_style_agent) != 0) - { - cont_cmd_line = xmalloc (sizeof (struct command_line)); - cont_cmd_line->control_type = simple_control; - cont_cmd_line->body_count = 0; - cont_cmd_line->body_list = NULL; - cont_cmd_line->next = NULL; - cont_cmd_line->line = xstrdup ("continue"); - } + struct command_line *printf_cmd_line + = xmalloc (sizeof (struct command_line)); printf_cmd_line = xmalloc (sizeof (struct command_line)); printf_cmd_line->control_type = simple_control; printf_cmd_line->body_count = 0; printf_cmd_line->body_list = NULL; - printf_cmd_line->next = cont_cmd_line; + printf_cmd_line->next = NULL; printf_cmd_line->line = printf_line; breakpoint_set_commands (b, printf_cmd_line); @@ -9615,47 +9917,47 @@ create_breakpoint (struct gdbarch *gdbarch, breakpoint. */ if (!pending) { - struct linespec_sals *lsal; - - lsal = VEC_index (linespec_sals, canonical.sals, 0); - if (parse_arg) { - char *rest; - /* Here we only parse 'arg' to separate condition - from thread number, so parsing in context of first - sal is OK. When setting the breakpoint we'll - re-parse it in context of each sal. */ - - find_condition_and_thread (arg, lsal->sals.sals[0].pc, &cond_string, - &thread, &task, &rest); - if (cond_string) - make_cleanup (xfree, cond_string); - if (rest) - make_cleanup (xfree, rest); - if (rest) - extra_string = rest; + char *rest; + struct linespec_sals *lsal; + + lsal = VEC_index (linespec_sals, canonical.sals, 0); + + /* Here we only parse 'arg' to separate condition + from thread number, so parsing in context of first + sal is OK. When setting the breakpoint we'll + re-parse it in context of each sal. */ + + find_condition_and_thread (arg, lsal->sals.sals[0].pc, &cond_string, + &thread, &task, &rest); + if (cond_string) + make_cleanup (xfree, cond_string); + if (rest) + make_cleanup (xfree, rest); + if (rest) + extra_string = rest; } else { - if (*arg != '\0') - error (_("Garbage '%s' at end of location"), arg); - - /* Create a private copy of condition string. */ - if (cond_string) - { - cond_string = xstrdup (cond_string); - make_cleanup (xfree, cond_string); - } - /* Create a private copy of any extra string. */ - if (extra_string) - { - extra_string = xstrdup (extra_string); - make_cleanup (xfree, extra_string); - } + if (*arg != '\0') + error (_("Garbage '%s' at end of location"), arg); + + /* Create a private copy of condition string. */ + if (cond_string) + { + cond_string = xstrdup (cond_string); + make_cleanup (xfree, cond_string); + } + /* Create a private copy of any extra string. */ + if (extra_string) + { + extra_string = xstrdup (extra_string); + make_cleanup (xfree, extra_string); + } } - ops->create_breakpoints_sal (gdbarch, &canonical, lsal, + ops->create_breakpoints_sal (gdbarch, &canonical, cond_string, extra_string, type_wanted, tempflag ? disp_del : disp_donttouch, thread, task, ignore_count, ops, @@ -9808,7 +10110,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); } @@ -10635,6 +10937,20 @@ print_recreate_watchpoint (struct breakpoint *b, struct ui_file *fp) print_recreate_thread (b, fp); } +/* Implement the "explains_signal" breakpoint_ops method for + watchpoints. */ + +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 0; + + return 1; +} + /* The breakpoint_ops structure to be used in hardware watchpoints. */ static struct breakpoint_ops watchpoint_breakpoint_ops; @@ -10970,7 +11286,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty, exp_valid_block = innermost_block; mark = value_mark (); - fetch_subexp_value (exp, &pc, &val, &result, NULL); + fetch_subexp_value (exp, &pc, &val, &result, NULL, just_location); if (just_location) { @@ -11016,13 +11332,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" @@ -11059,7 +11368,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; @@ -11556,6 +11875,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) @@ -11578,7 +11898,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; @@ -12591,6 +12911,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 = @@ -12714,7 +13037,6 @@ base_breakpoint_create_sals_from_address (char **arg, static void base_breakpoint_create_breakpoints_sal (struct gdbarch *gdbarch, struct linespec_result *c, - struct linespec_sals *lsal, char *cond_string, char *extra_string, enum bptype type_wanted, @@ -12737,10 +13059,18 @@ base_breakpoint_decode_linespec (struct breakpoint *b, char **s, /* The default 'explains_signal' method. */ -static enum bpstat_signal_value -base_breakpoint_explains_signal (struct breakpoint *b) +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. */ + +static void +base_breakpoint_after_condition_true (struct bpstats *bs) +{ + /* Nothing to do. */ } struct breakpoint_ops base_breakpoint_ops = @@ -12762,7 +13092,8 @@ struct breakpoint_ops base_breakpoint_ops = base_breakpoint_create_sals_from_address, base_breakpoint_create_breakpoints_sal, base_breakpoint_decode_linespec, - base_breakpoint_explains_signal + base_breakpoint_explains_signal, + base_breakpoint_after_condition_true, }; /* Default breakpoint_ops methods. */ @@ -12822,6 +13153,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) { @@ -12927,7 +13275,6 @@ bkpt_create_sals_from_address (char **arg, static void bkpt_create_breakpoints_sal (struct gdbarch *gdbarch, struct linespec_result *canonical, - struct linespec_sals *lsal, char *cond_string, char *extra_string, enum bptype type_wanted, @@ -12938,7 +13285,7 @@ bkpt_create_breakpoints_sal (struct gdbarch *gdbarch, int from_tty, int enabled, int internal, unsigned flags) { - create_breakpoints_sal_default (gdbarch, canonical, lsal, + create_breakpoints_sal_default (gdbarch, canonical, cond_string, extra_string, type_wanted, disposition, thread, task, @@ -13128,7 +13475,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; @@ -13138,7 +13487,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); } @@ -13265,7 +13616,6 @@ tracepoint_create_sals_from_address (char **arg, static void tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch, struct linespec_result *canonical, - struct linespec_sals *lsal, char *cond_string, char *extra_string, enum bptype type_wanted, @@ -13276,7 +13626,7 @@ tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch, int from_tty, int enabled, int internal, unsigned flags) { - create_breakpoints_sal_default (gdbarch, canonical, lsal, + create_breakpoints_sal_default (gdbarch, canonical, cond_string, extra_string, type_wanted, disposition, thread, task, @@ -13356,6 +13706,44 @@ dprintf_print_recreate (struct breakpoint *tp, struct ui_file *fp) print_recreate_thread (tp, fp); } +/* Implement the "after_condition_true" breakpoint_ops method for + dprintf. + + dprintf's are implemented with regular commands in their command + list, but we run the commands here instead of before presenting the + stop to the user, as dprintf's don't actually cause a stop. This + also makes it so that the commands of multiple dprintfs at the same + address are all handled. */ + +static void +dprintf_after_condition_true (struct bpstats *bs) +{ + struct cleanup *old_chain; + struct bpstats tmp_bs = { NULL }; + struct bpstats *tmp_bs_p = &tmp_bs; + + /* dprintf's never cause a stop. This wasn't set in the + check_status hook instead because that would make the dprintf's + condition not be evaluated. */ + bs->stop = 0; + + /* Run the command list here. Take ownership of it instead of + copying. We never want these commands to run later in + bpstat_do_actions, if a breakpoint that causes a stop happens to + be set at same address as this dprintf, or even if running the + commands here throws. */ + tmp_bs.commands = bs->commands; + bs->commands = NULL; + old_chain = make_cleanup_decref_counted_command_line (&tmp_bs.commands); + + bpstat_do_actions_1 (&tmp_bs_p); + + /* 'tmp_bs.commands' will usually be NULL by now, but + bpstat_do_actions_1 may return early without processing the whole + list. */ + do_cleanups (old_chain); +} + /* The breakpoint_ops structure to be used on static tracepoints with markers (`-m'). */ @@ -13379,7 +13767,6 @@ strace_marker_create_sals_from_address (char **arg, static void strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch, struct linespec_result *canonical, - struct linespec_sals *lsal, char *cond_string, char *extra_string, enum bptype type_wanted, @@ -13391,6 +13778,8 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch, int internal, unsigned flags) { int i; + struct linespec_sals *lsal = VEC_index (linespec_sals, + canonical->sals, 0); /* If the user is creating a static tracepoint by marker id (strace -m MARKER_ID), then store the sals index, so that @@ -14112,7 +14501,6 @@ create_sals_from_address_default (char **arg, static void create_breakpoints_sal_default (struct gdbarch *gdbarch, struct linespec_result *canonical, - struct linespec_sals *lsal, char *cond_string, char *extra_string, enum bptype type_wanted, @@ -14469,25 +14857,35 @@ disable_command (char *args, int from_tty) if (user_breakpoint_p (bpt)) disable_breakpoint (bpt); } - else if (strchr (args, '.')) + else { - struct bp_location *loc = find_location_by_number (args); - if (loc) + char *num = extract_arg (&args); + + while (num) { - if (loc->enabled) + if (strchr (num, '.')) { - loc->enabled = 0; - mark_breakpoint_location_modified (loc); + struct bp_location *loc = find_location_by_number (num); + + if (loc) + { + if (loc->enabled) + { + loc->enabled = 0; + mark_breakpoint_location_modified (loc); + } + if (target_supports_enable_disable_tracepoint () + && current_trace_status ()->running && loc->owner + && is_tracepoint (loc->owner)) + target_disable_tracepoint (loc); + } + update_global_location_list (0); } - if (target_supports_enable_disable_tracepoint () - && current_trace_status ()->running && loc->owner - && is_tracepoint (loc->owner)) - target_disable_tracepoint (loc); + else + map_breakpoint_numbers (num, do_map_disable_breakpoint, NULL); + num = extract_arg (&args); } - update_global_location_list (0); } - else - map_breakpoint_numbers (args, do_map_disable_breakpoint, NULL); } static void @@ -14593,25 +14991,35 @@ enable_command (char *args, int from_tty) if (user_breakpoint_p (bpt)) enable_breakpoint (bpt); } - else if (strchr (args, '.')) + else { - struct bp_location *loc = find_location_by_number (args); - if (loc) + char *num = extract_arg (&args); + + while (num) { - if (!loc->enabled) + if (strchr (num, '.')) { - loc->enabled = 1; - mark_breakpoint_location_modified (loc); + struct bp_location *loc = find_location_by_number (num); + + if (loc) + { + if (!loc->enabled) + { + loc->enabled = 1; + mark_breakpoint_location_modified (loc); + } + if (target_supports_enable_disable_tracepoint () + && current_trace_status ()->running && loc->owner + && is_tracepoint (loc->owner)) + target_enable_tracepoint (loc); + } + update_global_location_list (1); } - if (target_supports_enable_disable_tracepoint () - && current_trace_status ()->running && loc->owner - && is_tracepoint (loc->owner)) - target_enable_tracepoint (loc); + else + map_breakpoint_numbers (num, do_map_enable_breakpoint, NULL); + num = extract_arg (&args); } - update_global_location_list (1); } - else - map_breakpoint_numbers (args, do_map_enable_breakpoint, NULL); } /* This struct packages up disposition data for application to multiple @@ -14731,7 +15139,7 @@ deprecated_insert_raw_breakpoint (struct gdbarch *gdbarch, { struct bp_target_info *bp_tgt; - 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; @@ -14761,12 +15169,6 @@ deprecated_remove_raw_breakpoint (struct gdbarch *gdbarch, void *bp) 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 @@ -14870,7 +15272,7 @@ detach_single_step_breakpoints (void) /* Check whether a software single-step breakpoint is inserted at PC. */ -static int +int single_step_breakpoint_inserted_here_p (struct address_space *aspace, CORE_ADDR pc) { @@ -15254,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); } @@ -15265,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); } @@ -15306,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; @@ -15323,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); @@ -15338,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; } @@ -15376,7 +15772,6 @@ save_breakpoints (char *filename, int from_tty, { struct breakpoint *tp; int any = 0; - char *pathname; struct cleanup *cleanup; struct ui_file *fp; int extra_trace_bits = 0; @@ -15412,9 +15807,9 @@ save_breakpoints (char *filename, int from_tty, return; } - pathname = tilde_expand (filename); - cleanup = make_cleanup (xfree, pathname); - fp = gdb_fopen (pathname, "w"); + filename = tilde_expand (filename); + cleanup = make_cleanup (xfree, filename); + fp = gdb_fopen (filename, "w"); if (!fp) error (_("Unable to open file '%s' for saving (%s)"), filename, safe_strerror (errno)); @@ -15484,9 +15879,9 @@ save_breakpoints (char *filename, int from_tty, if (extra_trace_bits && *default_collect) fprintf_unfiltered (fp, "set default-collect %s\n", default_collect); - do_cleanups (cleanup); if (from_tty) printf_filtered (_("Saved to file '%s'.\n"), filename); + do_cleanups (cleanup); } /* The `save breakpoints' command. */ @@ -15748,6 +16143,7 @@ initialize_breakpoint_ops (void) ops->print_it = print_it_watchpoint; ops->print_mention = print_mention_watchpoint; ops->print_recreate = print_recreate_watchpoint; + ops->explains_signal = explains_signal_watchpoint; /* Masked watchpoints. */ ops = &masked_watchpoint_breakpoint_ops; @@ -15852,6 +16248,8 @@ initialize_breakpoint_ops (void) ops->print_it = bkpt_print_it; 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. */ @@ -15866,6 +16264,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); @@ -16433,8 +16832,7 @@ Set a dynamic printf at specified line or function.\n\ dprintf location,format string,arg1,arg2,...\n\ location may be a line number, function name, or \"*\" and an address.\n\ If a line number is specified, break at start of code for that line.\n\ -If a function is specified, break at start of code for that function.\n\ -")); +If a function is specified, break at start of code for that function.")); set_cmd_completer (c, location_completer); add_setshow_enum_cmd ("dprintf-style", class_support, @@ -16483,4 +16881,5 @@ agent-printf \"printf format string\", arg1, arg2, arg3, ..., argn\n\ automatic_hardware_breakpoints = 1; observer_attach_about_to_proceed (breakpoint_about_to_proceed); + observer_attach_thread_exit (remove_threaded_breakpoints); }