Consider the following chain of events:
* GDB is performing an inferior call, and
* the inferior calls longjmp, and
* GDB detects that the longjmp has completed, stops, and enters
check_longjmp_breakpoint_for_call_dummy (in breakpoint.c), and
* GDB tries to unwind the stack in order to check that the dummy
frame (setup for the inferior call) is still on the stack, but
* The unwind fails, possibly due to missing debug information, so
* GDB incorrectly concludes that the inferior has longjmp'd past the
dummy frame, and so deletes the dummy frame, including the dummy
frame breakpoint, but then
* The inferior continues, and eventually returns to the dummy frame,
which is usually (always?) on the stack, the inferior starts
trying to execute the random contents of the stack, this results
in undefined behaviour.
This situation is already warned about in the comment on the function
check_longjmp_breakpoint_for_call_dummy where we say:
You should call this function only at places where it is safe to currently
unwind the whole stack. Failed stack unwind would discard live dummy
frames.
The warning here is fine, the problem is that, even though we call the
function from a location within GDB where we hope to be able to
unwind, sometime the state of the inferior means that the unwind will
not succeed.
This commit tries to improve the situation by adding the following
additional check; when GDB fails to find the dummy frame on the stack,
instead of just assuming that the dummy frame can be garbage
collected, first find the stop_reason for the last frame on the stack.
If this stop_reason indicates that the stack unwinding may have failed
then we assume that the dummy frame is still in use. However, if the
last frame's stop_reason indicates that the stack unwind completed
successfully then we can be confident that the dummy frame is no
longer in use, and we garbage collect it.
Tested on x86-64 GNU/Linux.
gdb/ChangeLog:
* breakpoint.c (check_longjmp_breakpoint_for_call_dummy): Add
check for why the backtrace stopped.
gdb/testsuite/ChangeLog:
* gdb.base/premature-dummy-frame-removal.c: New file.
* gdb.base/premature-dummy-frame-removal.exp: New file.
* gdb.base/premature-dummy-frame-removal.py: New file.
Change-Id: I8f330cfe0f3f33beb3a52a36994094c4abada07e
I spotted some indentation issues where we had some spaces followed by
tabs at beginning of line, that I wanted to fix. So while at it, I did
a quick grep to find and fix all I could find.
gdb/ChangeLog:
* Fix tab after space indentation issues throughout.
Change-Id: I1acb414dd9c593b474ae2b8667496584df4316fd
I wrote a small script to spot a pattern of indentation mistakes I saw
happened in breakpoint.c. And while at it I ran it on all files and
fixed what I found. No behavior changes intended, just indentation and
addition / removal of curly braces.
gdb/ChangeLog:
* Fix some indentation mistakes throughout.
gdbserver/ChangeLog:
* Fix some indentation mistakes throughout.
Change-Id: Ia01990c26c38e83a243d8f33da1d494f16315c6e
Remove it, change users (well, a single one) to use all_bp_locations.
This requires moving all_bp_locations to breakpoint.h to expose it.
gdb/ChangeLog:
* breakpoint.h (iterate_over_bp_locations): Remove. Update
users to use all_bp_locations.
(all_bp_locations): New.
* breakpoint.c (all_bp_locations): Make non-static.
(iterate_over_bp_locations): Remove.
Change-Id: Iaf1f716d6c2c5b2975579b3dc113a86f5d0975be
Now that we have range functions that let us use ranged for loops, we
can remove iterate_over_breakpoints in favor of those, which are easier
to read and write. This requires exposing the declaration of
all_breakpoints and all_breakpoints_safe in breakpoint.h, as well as the
supporting types.
Change some users of iterate_over_breakpoints to use all_breakpoints,
when they don't need to delete the breakpoint, and all_breakpoints_safe
otherwise.
gdb/ChangeLog:
* breakpoint.h (iterate_over_breakpoints): Remove. Update
callers to use all_breakpoints or all_breakpoints_safe.
(breakpoint_range, all_breakpoints, breakpoint_safe_range,
all_breakpoints_safe): Move here.
* breakpoint.c (all_breakpoints, all_breakpoints_safe): Make
non-static.
(iterate_over_breakpoints): Remove.
* python/py-finishbreakpoint.c (bpfinishpy_detect_out_scope_cb):
Return void.
* python/py-breakpoint.c (build_bp_list): Add comment, reverse
return value logic.
* guile/scm-breakpoint.c (bpscm_build_bp_list): Return void.
Change-Id: Idde764a1f577de0423e4f2444a7d5cdb01ba5e48
Add the all_bp_locations_at_addr function, which returns a range of all
breakpoint locations at exactly the given address. This lets us
replace:
bp_location *loc, **loc2p, *locp;
ALL_BP_LOCATIONS_AT_ADDR (loc2p, locp, address)
{
loc = *loc2p;
// use loc
}
with
for (bp_location *loc : all_bp_locations_at_addr (address))
{
// use loc
}
The all_bp_locations_at_addr returns a bp_locations_at_addr_range
object, which is really just a wrapper around two std::vector iterators
representing the beginning and end of the interesting range. These
iterators are found when constructing the bp_locations_at_addr_range
object using std::equal_range, which seems a perfect fit for this use
case.
One thing I noticed about the current ALL_BP_LOCATIONS_AT_ADDR is that
if you call it with a NULL start variable, that variable gets filled in
and can be re-used for subsequent iterations. This avoids the cost of
finding the start of the interesting range again for the subsequent
iterations. This happens in build_target_command_list, for example.
The same effect can be achieved by storing the range in a local
variable, it can be iterated on multiple times.
Note that the original comment over ALL_BP_LOCATIONS_AT_ADDR says:
Iterates through locations with address ADDRESS for the currently
selected program space.
I don't see anything restricting the iteration to a given program space,
as we iterate over all bp_locations, which as far as I know contains all
breakpoint locations, regardless of the program space. So I just
dropped that part of the comment.
gdb/ChangeLog:
* breakpoint.c (get_first_locp_gte_addr): Remove.
(ALL_BP_LOCATIONS_AT_ADDR): Remove. Replace all uses with
all_bp_locations_at_addr.
(struct bp_locations_at_addr_range): New.
(all_bp_locations_at_addr): New.
(bp_locations_compare_addrs): New.
Change-Id: Icc8c92302045c47a48f507b7f1872bdd31d4ba59
Add the all_bp_locations function to replace the ALL_BP_LOCATIONS macro.
For simplicity, all_bp_locations simply returns a const reference to the
bp_locations vector. But the callers just treat it as a range to
iterate on, so if we ever change the breakpoint location storage, we can
change the all_bp_locations function to return some other range type,
and the callers won't need to be changed.
gdb/ChangeLog:
* breakpoint.c (ALL_BP_LOCATIONS): Remove, update users to use
all_bp_locations.
(all_bp_locations): New.
Change-Id: Iae71a1ba135c1a5bcdb4658bf3cf9793f0e9f81c
Change the type of the global location list, bp_locations, to be an
std::vector.
Adjust the users to deal with that, mostly in an obvious way by using
.data() and .size(). The user where it's slightly less obvious is
update_global_location_list. There, we std::move the old location list
out of the global vector into a local variable. The code to fill the
new location list gets simpler, as it's now simply using .push_back(),
no need to count the locations beforehand.
In the rest of update_global_location_list, the code is adjusted to work
with indices instead of `bp_location **`, to iterate on the location
list. I believe it's a bit easier to understand this way. But more
importantly, when we build with _GLIBCXX_DEBUG, the operator[] of the
vector does bound checking, so we will know if we ever access past a
vector size (which we won't if we access by raw pointer). I think that
work can further be done to make that function easier to understand,
notably find better names than "loc" and "loc2" for variables, but
that's work for later.
gdb/ChangeLog:
* breakpoint.c (bp_locations): Change to std::vector, update all
users.
(bp_locations_count): Remove.
(update_global_location_list): Change to work with indices
rather than bp_location**.
Change-Id: I193ce40f84d5dc930fbab8867cf946e78ff0df0b
Add the breakpoint::locations method, which returns a range that can be
used to iterate over a breakpoint's locations. This shortens
for (bp_location *loc = b->loc; loc != nullptr; loc = loc->next)
into
for (bp_location *loc : b->locations ())
Change all the places that I found that could use it.
gdb/ChangeLog:
* breakpoint.h (bp_locations_range): New.
(struct breakpoint) <locations>: New. Use where possible.
Change-Id: I1ba2f7d93d57e544e1f8609124587dcf2e1da037
Same idea as the previous patches, but to replace the ALL_TRACEPOINTS
macro. Define a new filtered_iterator that only keeps the breakpoints
for which is_tracepoint returns true (just like the macro did).
I would have like to make it so tracepoint_range yields some
`tracepoint *` instead of some `breakpoint *`, that would help simplify
the callers, who wouldn't have to do the cast themselves. But I didn't
find an obvious way to do it. It can always be added later.
It turns out there is already an all_tracepoints function, which returns
a vector containing all the breakpoints that are tracepoint. Remove it,
most users will just work seamlessly with the new function. The
exception is start_tracing, which iterated multiple times on the vector.
Adapt this one so it iterates multiple times on the returned range.
Since the existing users of all_tracepoints are outside of breakpoint.c,
this requires defining all_tracepoints and a few supporting types in
breakpoint.h. So, move breakpoint_iterator from breakpoint.c to
breakpoint.h.
gdb/ChangeLog:
* breakpoint.h (all_tracepoints): Remove.
(breakpoint_iterator): Move here.
(struct tracepoint_filter): New.
(tracepoint_iterator): New.
(tracepoint_range): New.
(all_tracepoints): New.
* breakpoint.c (ALL_TRACEPOINTS): Remove, replace all users with
all_tracepoints.
(breakpoint_iterator): Move to header.
(all_tracepoints): New.
* tracepoint.c (start_tracing): Adjust.
Change-Id: I76b1bba4215dbec7a03846c568368aeef7f1e05a
Same as the previous patch, but intended to replace the
ALL_BREAKPOINTS_SAFE macro, which allows deleting the current breakpoint
while iterating. The new range type simply wraps the range added by the
previous patch with basic_safe_range.
I didn't remove the ALL_BREAKPOINTS_SAFE macro, because there is one
spot where it's more tricky to remove, in the
check_longjmp_breakpoint_for_call_dummy function. More thought it
needed for this one.
gdb/ChangeLog:
* breakpoint.c (breakpoint_safe_range): New.
(all_breakpoints_safe): New. Use instead of
ALL_BREAKPOINTS_SAFE where possible.
Change-Id: Ifccab29f135e1f85700e3697ed60f0b643c7682f
Introduce the all_breakpoints function, which returns a range that can
be used to iterate on breakpoints. Replace all uses of the
ALL_BREAKPOINTS macro with this.
In one instance, I could replace the breakpoint iteration with a call to
get_breakpoint.
gdb/ChangeLog:
* breakpoint.c (ALL_BREAKPOINTS): Remove, replace all uses with
all_breakpoints.
(breakpoint_iterator): New.
(breakpoint_range): New.
(all_breakpoints): New.
Change-Id: I229595bddad7c9100b179a9dd56b04b8c206e86c
Same idea as previous patch, but for add_alias_cmd. Remove the overload
that accepts the target command as a string (the target command name),
leaving only the one that takes the cmd_list_element.
gdb/ChangeLog:
* command.h (add_alias_cmd): Accept target as
cmd_list_element. Update callers.
Change-Id: I546311f411e9e7da9302322d6ffad4e6c56df266
Same idea as previous patch, but for add_info_alias.
gdb/ChangeLog:
* command.h (add_info_alias): Accept target as
cmd_list_element. Update callers.
Change-Id: If830d423364bf42d7bea5ac4dd3a81adcfce6f7a
The alias creation functions currently accept a name to specify the
target command. They pass this to add_alias_cmd, which needs to lookup
the target command by name.
Given that:
- We don't support creating an alias for a command before that command
exists.
- We always use add_info_alias just after creating that target command,
and therefore have access to the target command's cmd_list_element.
... change add_com_alias to accept the target command as a
cmd_list_element (other functions are done in subsequent patches). This
ensures we don't create the alias before the target command, because you
need to get the cmd_list_element from somewhere when you call the alias
creation function. And it avoids an unecessary command lookup. So it
seems better to me in every aspect.
gdb/ChangeLog:
* command.h (add_com_alias): Accept target as
cmd_list_element. Update callers.
Change-Id: I24bed7da57221cc77606034de3023fedac015150
Previously, the prefixname field of struct cmd_list_element was manually
set for prefix commands. This seems verbose and error prone as it
required every single call to functions adding prefix commands to
specify the prefix name while the same information can be easily
generated.
Historically, this was not possible as the prefix field was null for
many commands, but this was fixed in commit
3f4d92ebdf by Philippe Waroquiers, so
we can rely on the prefix field being set when generating the prefix
name.
This commit also fixes a use after free in this scenario:
* A command gets created via Python (using the gdb.Command class).
The prefix name member is dynamically allocated.
* An alias to the new command is created. The alias's prefixname is set
to point to the prefixname for the original command with a direct
assignment.
* A new command with the same name as the Python command is created.
* The object for the original Python command gets freed and its
prefixname gets freed as well.
* The alias is updated to point to the new command, but its prefixname
is not updated so it keeps pointing to the freed one.
gdb/ChangeLog:
* command.h (add_prefix_cmd): Remove the prefixname argument as
it can now be generated automatically. Update all callers.
(add_basic_prefix_cmd): Ditto.
(add_show_prefix_cmd): Ditto.
(add_prefix_cmd_suppress_notification): Ditto.
(add_abbrev_prefix_cmd): Ditto.
* cli/cli-decode.c (add_prefix_cmd): Ditto.
(add_basic_prefix_cmd): Ditto.
(add_show_prefix_cmd): Ditto.
(add_prefix_cmd_suppress_notification): Ditto.
(add_prefix_cmd_suppress_notification): Ditto.
(add_abbrev_prefix_cmd): Ditto.
* cli/cli-decode.h (struct cmd_list_element): Replace the
prefixname member variable with a method which generates the
prefix name at runtime. Update all code reading the prefix
name to use the method, and remove all code setting it.
* python/py-cmd.c (cmdpy_destroyer): Remove code to free the
prefixname member as it's now a method.
(cmdpy_function): Determine if the command is a prefix by
looking at prefixlist, not prefixname.
Now that libiberty includes htab_eq_string, we can remove the
identical function from gdb.
gdb/ChangeLog
2021-05-07 Tom Tromey <tom@tromey.com>
* breakpoint.c (ambiguous_names_p): Use htab_eq_string.
* utils.c (streq_hash): Remove.
* utils.h (streq_hash): Don't declare.
* completer.c (completion_tracker::discard_completions): Update
comment.
* ada-lang.c (_initialize_ada_language): Use htab_eq_string.
Add a '--force' flag to the '-break-condition' command to be
able to force conditions.
gdb/ChangeLog:
2021-05-06 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* mi/mi-cmd-break.c (mi_cmd_break_condition): New function.
* mi/mi-cmds.c: Change the binding of "-break-condition" to
mi_cmd_break_condition.
* mi/mi-cmds.h (mi_cmd_break_condition): Declare.
* breakpoint.h (set_breakpoint_condition): Declare a new
overload.
* breakpoint.c (set_breakpoint_condition): New overloaded function
extracted out from ...
(condition_command): ... this.
* NEWS: Mention the change.
gdb/testsuite/ChangeLog:
2021-05-06 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* gdb.mi/mi-break.exp (test_forced_conditions): Add a test
for the -break-condition command's "--force" flag.
gdb/doc/ChangeLog:
2021-05-06 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* gdb.texinfo (GDB/MI Breakpoint Commands): Mention the
'--force' flag of the '-break-condition' command.
Give a name to each observer, this will help produce more meaningful
debug message.
gdbsupport/ChangeLog:
* observable.h (class observable) <struct observer> <observer>:
Add name parameter.
<name>: New field.
<attach>: Add name parameter, update all callers.
Change-Id: Ie0cc4664925215b8d2b09e026011b7803549fba0
Use a function_view instead of function pointer + data. Actually,
nothing uses the data anyway, but that makes iterate_over_bp_locations
more like iterate_over_breakpoints.
gdb/ChangeLog:
* breakpoint.c (iterate_over_bp_locations): Change callback to
function view, remove data parameter.
* breakpoint.h (iterate_over_bp_locations): Likewise.
* record-full.c (record_full_sync_record_breakpoints): Remove
data parameter.
Change-Id: I66cdc94a505f67bc640bcc66865fb535ee939a57
The 'create_breakpoint' function takes a 'parse_extra' argument that
determines whether the condition, thread, and force-condition
specifiers should be parsed from the extra string or be used from the
function arguments. However, for the case when 'parse_extra' is
false, there is no way to pass the force-condition specifier. This
patch adds it as a new argument.
Also, in the case when parse_extra is false, the current behavior is
as if the condition is being forced. This is a bug. The default
behavior should reject the breakpoint. See below for a demo of this
incorrect behavior. (The MI command '-break-insert' uses the
'create_breakpoint' function with parse_extra=0.)
$ gdb -q --interpreter=mi3 /tmp/simple
=thread-group-added,id="i1"
=cmd-param-changed,param="history save",value="on"
=cmd-param-changed,param="auto-load safe-path",value="/"
~"Reading symbols from /tmp/simple...\n"
(gdb)
-break-insert -c junk -f main
&"warning: failed to validate condition at location 1, disabling:\n "
&"No symbol \"junk\" in current context.\n"
^done,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="<MULTIPLE>",cond="junk",times="0",original-location="main",locations=[{number="1.1",enabled="N",addr="0x000000000000114e",func="main",file="/tmp/simple.c",fullname="/tmp/simple.c",line="2",thread-groups=["i1"]}]}
(gdb)
break main if junk
&"break main if junk\n"
&"No symbol \"junk\" in current context.\n"
^error,msg="No symbol \"junk\" in current context."
(gdb)
break main -force-condition if junk
&"break main -force-condition if junk\n"
~"Note: breakpoint 1 also set at pc 0x114e.\n"
&"warning: failed to validate condition at location 1, disabling:\n "
&"No symbol \"junk\" in current context.\n"
~"Breakpoint 2 at 0x114e: file /tmp/simple.c, line 2.\n"
=breakpoint-created,bkpt={number="2",type="breakpoint",disp="keep",enabled="y",addr="<MULTIPLE>",cond="junk",times="0",original-location="main",locations=[{number="2.1",enabled="N",addr="0x000000000000114e",func="main",file="/tmp/simple.c",fullname="/tmp/simple.c",line="2",thread-groups=["i1"]}]}
^done
(gdb)
After applying this patch, we get the behavior below:
(gdb)
-break-insert -c junk -f main
^error,msg="No symbol \"junk\" in current context."
This restores the behavior that is present in the existing releases.
gdb/ChangeLog:
2021-04-21 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* breakpoint.h (create_breakpoint): Add a new parameter,
'force_condition'.
* breakpoint.c (create_breakpoint): Use the 'force_condition'
argument when 'parse_extra' is false to check if the condition
is invalid at all of the breakpoint locations.
Update the users below.
(break_command_1)
(dprintf_command)
(trace_command)
(ftrace_command)
(strace_command)
(create_tracepoint_from_upload): Update.
* guile/scm-breakpoint.c (gdbscm_register_breakpoint_x): Update.
* mi/mi-cmd-break.c (mi_cmd_break_insert_1): Update.
* python/py-breakpoint.c (bppy_init): Update.
* python/py-finishbreakpoint.c (bpfinishpy_init): Update.
gdb/testsuite/ChangeLog:
2021-04-21 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* gdb.mi/mi-break.exp: Extend with checks for invalid breakpoint
conditions.
For breakpoint locations that are disabled because of an invalid
condition, CLI displays "N*" in the 'enabled' field, where '*' refers
to the footnote below the table:
(*): Breakpoint condition is invalid at this location.
This is not necessary for MI, where we shall simply print "N" without
the footnote.
Update the document to mention the "N" value for the MI. Also remove
the line about the 'enable' field, because there is no such field for
locations.
gdb/ChangeLog:
2021-04-21 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* breakpoint.c (print_one_breakpoint_location): Display "N" for
disabled-by-condition locations on MI-like output.
(breakpoint_1): Do not display the disabled-by-condition footnote
if the output is MI-like.
gdb/doc/ChangeLog:
2021-04-21 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* gdb.texinfo (GDB/MI Breakpoint Information): Update the
description for the 'enabled' field of breakpoint locations.
The current_top_target function is a hidden dependency on the current
inferior. Since I'd like to slowly move towards reducing our dependency
on the global current state, remove this function and make callers use
current_inferior ()->top_target ()
There is no expected change in behavior, but this one step towards
making those callers use the inferior from their context, rather than
refer to the global current inferior.
gdb/ChangeLog:
* target.h (current_top_target): Remove, make callers use the
current inferior instead.
* target.c (current_top_target): Remove.
Change-Id: Iccd457036f84466cdaa3865aa3f9339a24ea001d
This adds an expr::operation_up to struct expression, and then
modifies various parts of GDB to use this member when it is non-null.
The list of such spots was a bit surprising to me, and found only
after writing most of the code and then noticing what no longer
compiled.
In a few spots, new accessor methods are added to operation
subclasses, so that code that dissects an expression will work with
the new scheme.
After this change, code that constructs an expression can be switched
to the new form without breaking.
gdb/ChangeLog
2021-03-08 Tom Tromey <tom@tromey.com>
* ada-exp.h (class ada_var_value_operation) <get_symbol>: Remove;
now in superclass.
* value.h (fetch_subexp_value): Add "op" parameter.
* value.c (init_if_undefined_command): Update.
* tracepoint.c (validate_actionline, encode_actions_1): Update.
* stap-probe.c (stap_probe::compile_to_ax): Update.
* printcmd.c (set_command): Update.
* ppc-linux-nat.c (ppc_linux_nat_target::check_condition):
Update.
* parser-defs.h (struct expr_builder) <set_operation>: New
method.
* parse.c (parse_exp_in_context, exp_uses_objfile): Update.
* expression.h (struct expression) <first_opcode>: Update.
<op>: New member.
* expprint.c (dump_raw_expression, dump_prefix_expression):
Update.
* expop.h (class var_value_operation) <get_symbol>: New method.
(class register_operation) <get_name>: New method.
(class equal_operation): No longer a typedef, now a subclass.
(class unop_memval_operation) <get_type>: New method.
(class assign_operation) <get_lhs>: New method.
(class unop_cast_operation) <get_type>: New method.
* eval.c (evaluate_expression, evaluate_type)
(evaluate_subexpression_type): Update.
(fetch_subexp_value): Add "op" parameter.
(parse_and_eval_type): Update.
* dtrace-probe.c (dtrace_probe::compile_to_ax): Update.
* breakpoint.c (update_watchpoint, watchpoint_check)
(watchpoint_exp_is_const, watch_command_1): Update.
* ax-gdb.c (gen_trace_for_expr, gen_eval_for_expr, gen_printf):
Update.
Add a new obj_section function to bound_minimal_symbol, this just
calls obj_section on the contained minimal_symbol passing in the
contained objfile.
This allows some minor code simplification in a few places.
There should be no user visible changes after this commit.
gdb/ChangeLog:
* breakpoint.c (resolve_sal_pc): Make use of
bound_minimal_symbol::obj_section.
* maint.c (maintenance_translate_address): Likewise.
* minsyms.c (minimal_symbol_upper_bound): Likewise.
* minsyms.h (struct bound_minimal_symbol) <obj_section>: New
member function.
* printcmd.c (info_address_command): Make use of
bound_minimal_symbol::obj_section.
The test-case nextoverthrow.exp is failing on targets with unstripped libc.
This is a regression since commit 1940319c0e "[gdb] Fix internal-error in
process_event_stop_test".
The problem is that this code in create_exception_master_breakpoint:
...
for (objfile *sepdebug = obj->separate_debug_objfile;
sepdebug != nullptr; sepdebug = sepdebug->separate_debug_objfile)
if (create_exception_master_breakpoint_hook (sepdebug))
...
iterates over all the separate debug object files, but fails to handle the
case that obj itself has the debug info we're looking for.
Fix this by using the separate_debug_objfiles () range instead, which does
iterate both over obj and the obj->separate_debug_objfile chain.
Tested on x86_64-linux.
gdb/ChangeLog:
2021-02-05 Tom de Vries <tdevries@suse.de>
PR breakpoints/27330
* breakpoint.c (create_exception_master_breakpoint): Handle case that
glibc object file has debug info.
When running test-case gdb.base/longjmp.exp with target board unix/-m32, we
run into:
...
(gdb) next^M
Warning:^M
Cannot insert breakpoint 0.^M
Cannot access memory at address 0x7dbf7353^M
^M
__libc_siglongjmp (env=0x804a040 <env>, val=1) at longjmp.c:28^M
28 longjmps++;^M
(gdb) FAIL: gdb.base/longjmp.exp: next over longjmp(1)
...
The failure to access memory happens in i386_get_longjmp_target and is due to
glibc having pointer encryption (aka "pointer mangling" or "pointer guard") of
the long jump buffer. This is a known problem.
In create_longjmp_master_breakpoint (which attempts to install a master
longjmp breakpoint) a preference scheme is present, which installs a
probe breakpoint if a libc:longjmp probe is present, and otherwise falls back
to setting breakpoints at the names in the longjmp_names array.
But in fact, both the probe breakpoint and the longjmp_names breakpoints are
set. The latter ones are set when processing libc.so.debug, and the former
one when processing libc.so. In other words, this is the longjmp variant of
PR26881, which describes the same problem for master exception breakpoints.
This problem only triggers when the glibc debug info package is installed,
which is not due to the debug info itself in libc.so.debug, but due to the
minimal symbols (because create_longjmp_master_breakpoint uses minimal symbols
to translate the longjmp_names to addresses).
The problem doesn't trigger for -m64, because there tdep->jb_pc_offset is not
set.
Fix this similar to commit 1940319c0e (the fix for PR26881): only install
longjmp_names breakpoints in libc.so/libc.so.debug if installing the
libc:longjmp probe in libc.so failed.
Tested on x86_64-linux.
gdb/ChangeLog:
2021-01-28 Tom de Vries <tdevries@suse.de>
PR breakpoints/27205
* breakpoint.c (create_longjmp_master_breakpoint_probe)
(create_longjmp_master_breakpoint_names): New function, factored out
of ...
(create_longjmp_master_breakpoint): ... here. Only try to install
longjmp_names breakpoints in libc.so/libc.so.debug if installing probe
breakpoint in libc.so failed.
The function create_exception_master_breakpoint in gdb/breakpoint.c attempts
to set a master exception breakpoint in each objfile. It tries this using
a libgcc/unwind probe, and if that fails then using the
_Unwind_DebugHook symbol:
...
for (objfile *objfile : current_program_space->objfiles ())
{
/* Try using probes. */
if (/* successful */)
continue;
/* Try using _Unwind_DebugHook */
}
...
The preference scheme works ok both if the objfile has debug info, and if it's
stripped.
But it doesn't work when the objfile has a .gnu_debuglink to a .debug file
(and the .debug file is present). What happens is that:
- we first encounter objfile libgcc.debug
- we try using probes, and this fails
- so we try _Unwind_DebugHook, which succeeds
- next we encounter objfile libgcc
- we try using probes, and this succeeds.
So, we end up with a master exception breakpoint in both libgcc (using probes)
and libgcc.debug (using _Unwind_DebugHook).
This eventually causes:
...
(gdb) PASS: gdb.cp/nextoverthrow.exp: post-check - next over a throw 3
next^M
src/gdb/infrun.c:6384: internal-error: \
void process_event_stop_test(execution_control_state*): \
Assertion `ecs->event_thread->control.exception_resume_breakpoint != NULL' \
failed.^M
A problem internal to GDB has been detected,^M
further debugging may prove unreliable.^M
Quit this debugging session? (y or n) FAIL: gdb.cp/nextoverthrow.exp: next
past catch (GDB internal error)
...
To trigger this internal-error, we need to use gcc-10 or later to compile the
test-case, such that it contains the fix for gcc PR97774 - "Incorrect line
info for try/catch".
Fix this by only trying to install the master exception breakpoint in
libgcc.debug using the _Unwind_DebugHook method, if the install using probes
in libgcc failed.
Tested on x86_64-linux.
gdb/ChangeLog:
2021-01-08 Tom de Vries <tdevries@suse.de>
PR gdb/26881
* breakpoint.c (create_exception_master_breakpoint_probe)
(create_exception_master_breakpoint_hook): Factor out
of ...
(create_exception_master_breakpoint): ... here. Only try to install
the master exception breakpoint in objfile.debug using the
_Unwind_DebugHook method, if the install using probes in objfile
failed.
This commits the result of running gdb/copyright.py as per our Start
of New Year procedure...
gdb/ChangeLog
Update copyright year range in copyright header of all GDB files.
This changes bp_location to derive from refcounted_object, introduces
a ref_ptr specialization for this type, and then changes
bpstats::bp_location_at to use that specialization. This removes some
manual reference counting and simplifies the code.
gdb/ChangeLog
2020-12-11 Tom Tromey <tom@tromey.com>
* inline-frame.c (stopped_by_user_bp_inline_frame): Update.
* ada-lang.c (check_status_exception): Update.
* breakpoint.c (free_bp_location): Remove.
(decref_bp_location): Use bp_location_ref_policy.
(bpstats::bpstats): Don't call incref_bp_location.
(bpstats::~bpstats): Remove.
(bpstats::bpstats): Update.
(bpstat_check_watchpoint, bpstat_check_breakpoint_conditions)
(bp_location::bp_location): Update.
(incref_bp_location): Remove.
(bkpt_print_it): Update.
* breakpoint.h (class bp_location): Derive from
refcounted_object.
(struct bpstats): Remove destructor.
<bp_location_at>: Now a bp_location_ref_ptr.
<refc>: Remove.
(bp_location_ref_ptr): New typedef.
(struct bp_location_ref_policy): New.
I noticed a spurious newline on infrun debugging output. The following patch
fixes that. I'll push as obvious.
gdb/ChangeLog:
2020-12-10 Luis Machado <luis.machado@linaro.org>
* breakpoint.c (should_be_inserted): Don't output newline.
The break command's "-force-condition" flag is currently required to
be followed by the "if" keyword. This prevents flexibility when using
other keywords, e.g. "thread":
(gdb) break main -force-condition thread 1 if foo
Function "main -force-condition" not defined.
Make breakpoint pending on future shared library load? (y or [n]) n
Remove the requirement that "-force-condition" is always followed by
an "if", so that more flexibility is obtained when positioning
keywords.
gdb/ChangeLog:
2020-12-07 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* linespec.c (linespec_lexer_lex_keyword): The "-force-condition"
keyword may be followed by any keyword.
* breakpoint.c (find_condition_and_thread): Advance 'tok' by
'toklen' in the case for "-force-condition".
gdb/testsuite/ChangeLog:
2020-12-07 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* gdb.linespec/keywords.exp: Add tests to check positional
flexibility of "-force-condition".
I noticed that watchpoint_exp_is_const should return bool; this patch
implements this change.
gdb/ChangeLog
2020-11-21 Tom Tromey <tom@tromey.com>
* breakpoint.c (watchpoint_exp_is_const): Return bool.
Switch over to using new option processing mechanism for watch,
awatch, and rwatch commands. Add command completion function.
This means that expression completion now works correctly when the
-location flag is used. So previously:
(gdb) watch var.<TAB><TAB>
.... list fields of var ....
But,
(gdb) watch -location var.<TAB><TAB>
.... list all symbols ....
After this commit only the fields of 'var' are listed even when
'-location' is passed.
Another benefit of this change is that '-location' will now complete.
One thing to note is that previous these commands accepted both
'-location' or '-l' (these being synonyms). The new option scheme
doesn't really allow for official short form flags, however, it does
allow for non-ambiguous sub-strings to be used. What this means is
that currently (as these commands only have the '-location' flag) the
user can still use '-l', so there's no change there.
The interactive help text for these commands now emphasises
'-location' as the real option, but does mention that '-l' can also be
used.
gdb/ChangeLog:
* breakpoint.c (struct watch_options): New struct.
(watch_option_defs): New static global.
(make_watch_options_def_group): New function.
(watch_maybe_just_location): Convert option parsing.
(watch_command_completer): New function.
(_initialize_breakpoint): Build help text using options mechanism.
gdb/testsuite/ChangeLog:
* gdb.base/completion.exp: Add new completion tests.
A little int to bool conversion around the 'watch' type commands.
There should be no user visible changes after this commit.
gdb/ChangeLog:
* breakpoint.c (update_watchpoint): Pass 'false' not '0'.
(watch_command_1): Update parameter types. Convert locals to
bool.
(watch_command_wrapper): Change parameter type.
(watch_maybe_just_location): Change locals to bool.
(rwatch_command_wrapper): Update parameter type.
(awatch_command_wrapper): Update parameter type.
* breakpoint.h (watch_command_wrapper): Change parameter type.
(rwatch_command_wrapper): Update parameter type.
(awatch_command_wrapper): Update parameter type.
* eval.c (fetch_subexp_value): Change parameter type.
* ppc-linux-nat.c (ppc_linux_nat_target::check_condition): Pass
'false' not '0'.
* value.h (fetch_subexp_value): Change parameter type in
declaration.
Use the gdb::option framework for the '-force' flag of the 'condition'
command. This gives tab-completion ability for the flag.
gdb/ChangeLog:
2020-10-27 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* breakpoint.c (struct condition_command_opts): New struct.
(condition_command_option_defs): New static global.
(make_condition_command_options_def_group): New function.
(condition_completer): Update to consider the '-force' flag.
(condition_command): Use gdb::option for the '-force' flag.
gdb/testsuite/ChangeLog:
2020-10-27 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* gdb.base/condbreak.exp: Update the completion tests to
consider the '-force' flag.
The previous patch made it possible to define a condition if it's
valid at some locations. If the condition is invalid at all of the
locations, it's rejected. However, there may be cases where the user
knows the condition *will* be valid at a location in the future,
e.g. due to a shared library load.
To make it possible that such condition can be defined, this patch
adds an optional '-force' flag to the 'condition' command, and,
respectively, a '-force-condition' flag to the 'break'command. When
the force flag is passed, the condition is not rejected even when it
is invalid for all the current locations (note that all the locations
would be internally disabled in this case).
For instance:
(gdb) break test.c:5
Breakpoint 1 at 0x1155: file test.c, line 5.
(gdb) cond 1 foo == 42
No symbol "foo" in current context.
Defining the condition was not possible because 'foo' is not
available. The user can override this behavior with the '-force'
flag:
(gdb) cond -force 1 foo == 42
warning: failed to validate condition at location 1.1, disabling:
No symbol "foo" in current context.
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y <MULTIPLE>
stop only if foo == 42
1.1 N 0x0000000000001155 in main at test.c:5
Now the condition is accepted, but the location is automatically
disabled. If a future location has a context in which 'foo' is
available, that location would be enabled.
For the 'break' command, -force-condition has the same result:
(gdb) break test.c:5 -force-condition if foo == 42
warning: failed to validate condition at location 0x1169, disabling:
No symbol "foo" in current context.
Breakpoint 1 at 0x1169: file test.c, line 5.
gdb/ChangeLog:
2020-10-27 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* breakpoint.h (set_breakpoint_condition): Add a new bool parameter.
* breakpoint.c: Update the help text of the 'condition' and 'break'
commands.
(set_breakpoint_condition): Take a new bool parameter
to control whether condition definition should be forced even when
the condition expression is invalid in all of the current locations.
(condition_command): Update the call to 'set_breakpoint_condition'.
(find_condition_and_thread): Take the "-force-condition" flag into
account.
* linespec.c (linespec_keywords): Add "-force-condition" as an
element.
(FORCE_KEYWORD_INDEX): New #define.
(linespec_lexer_lex_keyword): Update to consider "-force-condition"
as a keyword.
* ada-lang.c (create_ada_exception_catchpoint): Ditto.
* guile/scm-breakpoint.c (gdbscm_set_breakpoint_condition_x): Ditto.
* python/py-breakpoint.c (bppy_set_condition): Ditto.
* NEWS: Mention the changes to the 'break' and 'condition' commands.
gdb/testsuite/ChangeLog:
2020-10-27 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* gdb.base/condbreak-multi-context.exp: Expand to test forcing
the condition.
* gdb.linespec/cpcompletion.exp: Update to consider the
'-force-condition' keyword.
* gdb.linespec/explicit.exp: Ditto.
* lib/completion-support.exp: Ditto.
gdb/doc/ChangeLog:
2020-10-27 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* gdb.texinfo (Set Breaks): Document the '-force-condition' flag
of the 'break'command.
* gdb.texinfo (Conditions): Document the '-force' flag of the
'condition' command.
Currently, for a conditional breakpoint, GDB checks if the condition
can be evaluated in the context of the first symtab and line (SAL).
In case of an error, defining the conditional breakpoint is aborted.
This prevents having a conditional breakpoint whose condition may
actually be meaningful for some of the location contexts. This patch
makes it possible to define conditional BPs by checking all location
contexts. If the condition is meaningful for even one context, the
breakpoint is defined. The locations for which the condition gives
errors are disabled.
The bp_location struct is introduced a new field, 'disabled_by_cond'.
This field denotes whether the location is disabled automatically
because the condition was non-evaluatable. Disabled-by-cond locations
cannot be enabled by the user. But locations that are not
disabled-by-cond can be enabled/disabled by the user manually as
before.
For a concrete example, consider 3 contexts of a function 'func'.
class Base
{
public:
int b = 20;
void func () {}
};
class A : public Base
{
public:
int a = 10;
void func () {}
};
class C : public Base
{
public:
int c = 30;
void func () {}
};
Note that
* the variable 'a' is defined only in the context of A::func.
* the variable 'c' is defined only in the context of C::func.
* the variable 'b' is defined in all the three contexts.
With the existing GDB, it's not possible to define a conditional
breakpoint at 'func' if the condition refers to 'a' or 'c':
(gdb) break func if a == 10
No symbol "a" in current context.
(gdb) break func if c == 30
No symbol "c" in current context.
(gdb) info breakpoints
No breakpoints or watchpoints.
With this patch, it becomes possible:
(gdb) break func if a == 10
warning: failed to validate condition at location 1, disabling:
No symbol "a" in current context.
warning: failed to validate condition at location 3, disabling:
No symbol "a" in current context.
Breakpoint 1 at 0x11b6: func. (3 locations)
(gdb) break func if c == 30
Note: breakpoint 1 also set at pc 0x11ce.
Note: breakpoint 1 also set at pc 0x11c2.
Note: breakpoint 1 also set at pc 0x11b6.
warning: failed to validate condition at location 1, disabling:
No symbol "c" in current context.
warning: failed to validate condition at location 2, disabling:
No symbol "c" in current context.
Breakpoint 2 at 0x11b6: func. (3 locations)
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y <MULTIPLE>
stop only if a == 10
1.1 N* 0x00000000000011b6 in Base::func() at condbreak-multi-context.cc:23
1.2 y 0x00000000000011c2 in A::func() at condbreak-multi-context.cc:31
1.3 N* 0x00000000000011ce in C::func() at condbreak-multi-context.cc:39
2 breakpoint keep y <MULTIPLE>
stop only if c == 30
2.1 N* 0x00000000000011b6 in Base::func() at condbreak-multi-context.cc:23
2.2 N* 0x00000000000011c2 in A::func() at condbreak-multi-context.cc:31
2.3 y 0x00000000000011ce in C::func() at condbreak-multi-context.cc:39
(*): Breakpoint condition is invalid at this location.
Here, uppercase 'N' denotes that the location is disabled because of
the invalid condition, as mentioned with a footnote in the legend of
the table. Locations that are disabled by the user are still denoted
with lowercase 'n'. Executing the code hits the breakpoints 1.2 and
2.3 as expected.
Defining a condition on an unconditional breakpoint gives the same
behavior above:
(gdb) break func
Breakpoint 1 at 0x11b6: func. (3 locations)
(gdb) cond 1 a == 10
warning: failed to validate condition at location 1.1, disabling:
No symbol "a" in current context.
warning: failed to validate condition at location 1.3, disabling:
No symbol "a" in current context.
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y <MULTIPLE>
stop only if a == 10
1.1 N* 0x00000000000011b6 in Base::func() at condbreak-multi-context.cc:23
1.2 y 0x00000000000011c2 in A::func() at condbreak-multi-context.cc:31
1.3 N* 0x00000000000011ce in C::func() at condbreak-multi-context.cc:39
(*): Breakpoint condition is invalid at this location.
Locations that are disabled because of a condition cannot be enabled
by the user:
...
(gdb) enable 1.1
Breakpoint 1's condition is invalid at location 1, cannot enable.
Resetting the condition enables the locations back:
...
(gdb) cond 1
Breakpoint 1's condition is now valid at location 1, enabling.
Breakpoint 1's condition is now valid at location 3, enabling.
Breakpoint 1 now unconditional.
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y <MULTIPLE>
1.1 y 0x00000000000011b6 in Base::func() at condbreak-multi-context.cc:23
1.2 y 0x00000000000011c2 in A::func() at condbreak-multi-context.cc:31
1.3 y 0x00000000000011ce in C::func() at condbreak-multi-context.cc:39
If a location is disabled by the user, a condition can still be defined
but the location will remain disabled even if the condition is meaningful
for the disabled location:
...
(gdb) disable 1.2
(gdb) cond 1 a == 10
warning: failed to validate condition at location 1.1, disabling:
No symbol "a" in current context.
warning: failed to validate condition at location 1.3, disabling:
No symbol "a" in current context.
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y <MULTIPLE>
stop only if a == 10
1.1 N* 0x00000000000011b6 in Base::func() at condbreak-multi-context.cc:23
1.2 n 0x00000000000011c2 in A::func() at condbreak-multi-context.cc:31
1.3 N* 0x00000000000011ce in C::func() at condbreak-multi-context.cc:39
(*): Breakpoint condition is invalid at this location.
The condition of a breakpoint can be changed. Locations'
enable/disable states are updated accordingly.
...
(gdb) cond 1 c == 30
warning: failed to validate condition at location 1.1, disabling:
No symbol "c" in current context.
Breakpoint 1's condition is now valid at location 3, enabling.
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y <MULTIPLE>
stop only if c == 30
1.1 N* 0x00000000000011b6 in Base::func() at condbreak-multi-context.cc:23
1.2 N* 0x00000000000011c2 in A::func() at condbreak-multi-context.cc:31
1.3 y 0x00000000000011ce in C::func() at condbreak-multi-context.cc:39
(*): Breakpoint condition is invalid at this location.
(gdb) cond 1 b == 20
Breakpoint 1's condition is now valid at location 1, enabling.
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y <MULTIPLE>
stop only if b == 20
1.1 y 0x00000000000011b6 in Base::func() at condbreak-multi-context.cc:23
1.2 n 0x00000000000011c2 in A::func() at condbreak-multi-context.cc:31
1.3 y 0x00000000000011ce in C::func() at condbreak-multi-context.cc:39
# Note that location 1.2 was disabled by the user previously.
If the condition expression is bad for all the locations, it will be
rejected.
(gdb) cond 1 garbage
No symbol "garbage" in current context.
For conditions that are invalid or valid for all the locations of a
breakpoint, the existing behavior is preserved.
Regression-tested on X86_64 Linux.
gdb/ChangeLog:
2020-10-27 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* breakpoint.h (class bp_location) <disabled_by_cond>: New field.
* breakpoint.c (set_breakpoint_location_condition): New function.
(set_breakpoint_condition): Disable a breakpoint location if parsing
the condition string gives an error.
(should_be_inserted): Update to consider the 'disabled_by_cond' field.
(build_target_condition_list): Ditto.
(build_target_command_list): Ditto.
(build_bpstat_chain): Ditto.
(print_one_breakpoint_location): Ditto.
(print_one_breakpoint): Ditto.
(breakpoint_1): Ditto.
(bp_location::bp_location): Ditto.
(locations_are_equal): Ditto.
(update_breakpoint_locations): Ditto.
(enable_disable_bp_num_loc): Ditto.
(init_breakpoint_sal): Use set_breakpoint_location_condition.
(find_condition_and_thread_for_sals): New static function.
(create_breakpoint): Call find_condition_and_thread_for_sals.
(location_to_sals): Call find_condition_and_thread_for_sals instead
of find_condition_and_thread.
gdb/testsuite/ChangeLog:
2020-10-27 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* gdb.base/condbreak-multi-context.cc: New file.
* gdb.base/condbreak-multi-context.exp: New file.
gdb/doc/ChangeLog:
2020-10-27 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* gdb.texinfo (Set Breaks): Document disabling of breakpoint
locations for which the breakpoint condition is invalid.
This fixes a regression introduced by the following commit:
fe053b9e85 gdb/jit: pass the jiter objfile as an argument to jit_event_handler
In the refactoring `handle_jit_event` function was changed to pass a matching
objfile pointer to the `jit_event_handler` explicitly, rather using internal
storage:
```
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5448,8 +5448,9 @@ handle_jit_event (void)
frame = get_current_frame ();
gdbarch = get_frame_arch (frame);
+ objfile *jiter = symbol_objfile (get_frame_function (frame));
- jit_event_handler (gdbarch);
+ jit_event_handler (gdbarch, jiter);
```
This was needed to add support for multiple jiters. However it has also
introduced a regression, because `get_frame_function (frame)` here may
return `nullptr`, resulting in a crash.
A more resilient way would be to use an approach mirroring
`jit_breakpoint_re_set` - to find a minimal symbol matching the
breakpoint location and use its object file. We know that this
breakpoint event comes from a breakpoint set by `jit_breakpoint_re_set`,
thus using the reverse approach should be reliable enough.
gdb/Changelog:
2020-10-14 Mihails Strasuns <mihails.strasuns@intel.com>
* breakpoint.c (handle_jit_event): Add an argument, change how
`jit_event_handler` is called.
This changes breakpoint.c to use htab_up rather than an explicit
htab_delete. This simplifies the code somewhat.
gdb/ChangeLog
2020-09-17 Tom Tromey <tom@tromey.com>
* breakpoint.c (ambiguous_names_p): Use htab_up.
Use bool instead of int in struct solib_catchpoint and in init_catchpoint &
related functions.
gdb/ChangeLog:
* breakpoint.h (init_catchpoint): Change int parameter to bool.
(add_solib_catchpoint): Likewise.
* breakpoint.c (struct solib_catchpoint) <is_load>: Change type
to bool.
(add_solib_catchpoint): Change int parameter/variable to bool.
(catch_load_or_unload): Likewise.
(init_catchpoint): Likewise.
(create_fork_vfork_event_catchpoint): Likewise.
(catch_fork_command_1): Likewise.
(catch_exec_command_1): Likewise.
Change-Id: I1faf4506e9109f3ccdd7229ba766dc7d77aa7aa0
When GDB reads commands from the input, its internal buffer is re-used
for each line. This is usually just fine because commands are
executed in order; by the time we read the next line, we are already
done with the current line. However, a problematic case is breakpoint
commands that are input from a script. The header (e.g. commands 1 2)
is overwritten with the next line before the breakpoint numbers are
processed completely.
For example, suppose we have the following script:
break main
break main
commands 1 2
print 100123
end
and source this script:
(gdb) source script.gdb
Breakpoint 1 at 0x1245: file main.cpp, line 27.
Breakpoint 2 at 0x1245: file main.cpp, line 27.
No breakpoint number 123.
Note the "No breakpoint number 123." error message. This happens
because GDB first reads "commands 1 2" into its internal buffer
buffer -> "commands 1 2"
and then starts parsing the breakpoint numbers. After parsing the first
token, the "next token" pointer is as below:
buffer -> "commands 1 2"
next-token -----------^
So, if we continue parsing, we would tokenize "2" correctly. However,
before parsing the next number, GDB reads the commands to attach them
to breakpoint 1. Reading the commands causes the buffer to be
overwritten:
buffer -> " print 100123"
next-token -----------^
So, the next time we parse the breakpoint number, we read "123".
To fix, simply create a copy of the arguments of the header.
gdb/ChangeLog:
2020-09-16 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* breakpoint.c (commands_command_1): Make a copy of the 'arg'
argument.
gdb/testsuite/ChangeLog:
2020-09-16 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* gdb.base/bp-cmds-sourced-script.c: New file.
* gdb.base/bp-cmds-sourced-script.exp: New test.
* gdb.base/bp-cmds-sourced-script.gdb: New file.
The options for the "breakpoint condition-evaluation" setting are
"host", "target", and "auto". The help message mentions the option
"gdb" at one point instead of "host". Fix this typo. Also add a period.
gdb/ChangeLog:
2020-09-11 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com>
* breakpoint.c: Fix typo in the help message of the
"set breakpoint condition-evaluation" command.
Consider test-case test.c:
...
$ cat test.c
int main (void) {
return 0;
L1:
(void)0;
}
...
Compiled with debug info:
...
$ gcc test.c -g
...
When attempting to set a breakpoint at L1, which is a label without address:
...
<1><f4>: Abbrev Number: 2 (DW_TAG_subprogram)
<f5> DW_AT_name : main
<2><115>: Abbrev Number: 3 (DW_TAG_label)
<116> DW_AT_name : L1
<119> DW_AT_decl_file : 1
<11a> DW_AT_decl_line : 5
<2><11b>: Abbrev Number: 0
...
we run into an internal-error:
...
$ gdb -batch a.out -ex "b main:L1"
linespec.c:3233: internal-error: void \
decode_line_full(const event_location*, int, program_space*, symtab*, \
int, linespec_result*, const char*, const char*): \
Assertion `result.size () == 1 || canonical->pre_expanded' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
...
Fix this by detecting the error condition in decode_line_full instead, and
throwing an error, such that we have instead:
...
(gdb) b main:L1
Location main:L1 not available
(gdb)
...
Unfortunately, to call event_location_to_string, which is used to get the
location name in the error message, we need to pass a non-const struct
event_location, because the call may cache the string in the struct (See
EL_STRING). So, we change the prototype of decode_line_full accordingly, and
everywhere this propages to.
Tested on x86_64-linux.
gdb/ChangeLog:
2020-08-28 Tom de Vries <tdevries@suse.de>
PR breakpoint/26544
* breakpoint.c (parse_breakpoint_sals): Remove const from struct
event_location.
(create_breakpoint): Same.
(base_breakpoint_decode_location): Same.
(bkpt_create_sals_from_location): Same.
(bkpt_decode_location): Same.
(bkpt_probe_create_sals_from_location): Same.
(bkpt_probe_decode_location): Same.
(tracepoint_create_sals_from_location): Same.
(tracepoint_decode_location): Same.
(tracepoint_probe_decode_location): Same.
(strace_marker_create_sals_from_location): Same.
(strace_marker_decode_location): Same.
(create_sals_from_location_default): Same.
(decode_location_default): Same.
* breakpoint.h (struct breakpoint_ops): Same.
(create_breakpoint): Same.
* linespec.h (decode_line_full): Same.
* linespec.c (decode_line_full): Same. Throw error if
result.size () == 0.
gdb/testsuite/ChangeLog:
2020-08-28 Tom de Vries <tdevries@suse.de>
* gdb.base/label-without-address.c: New test.
* gdb.base/label-without-address.exp: New file.
If you do "advance LINESPEC", and LINESPEC expands to more than one
location, GDB just errors out:
if (sals.size () != 1)
error (_("Couldn't get information on specified line."));
For example, advancing to a line in an inlined function, inlined three
times:
(gdb) b 21
Breakpoint 1 at 0x55555555516f: advance.cc:21. (3 locations)
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y <MULTIPLE>
1.1 y 0x000055555555516f in inline_func at advance.cc:21
1.2 y 0x000055555555517e in inline_func at advance.cc:21
1.3 y 0x000055555555518d in inline_func at advance.cc:21
(gdb) advance 21
Couldn't get information on specified line.
(gdb)
Similar issue with the "until" command, as it shares the
implementation with "advance".
Since, as the comment in gdb.base/advance.exp says, "advance <location>"
is really just syntactic sugar for "tbreak <location>;continue",
fix this by making GDB insert a breakpoint at all the resolved
locations.
A new testcase is included, which exercises both "advance" and
"until", in two different cases expanding to multiple locations:
- inlined functions
- C++ overloads
This also exercises the inline frames issue fixed by the previous
patch.
gdb/ChangeLog:
PR gdb/26524
* breakpoint.c (until_break_fsm) <location_breakpoint,
caller_breakpoint>: Delete fields.
<breakpoints>: New field.
<until_break_fsm>: Adjust to save a breakpoint vector instead of
two individual breakpoints.
(until_break_fsm::should_stop): Loop over breakpoints in the
breakpoint vector.
(until_break_fsm::clean_up): Adjust to clear the breakpoints
vector.
(until_break_command): Handle location expanding into multiple
sals.
gdb/testsuite/ChangeLog:
PR gdb/26523
PR gdb/26524
* gdb.base/advance-until-multiple-locations.cc: New.
* gdb.base/advance-until-multiple-locations.exp: New.