CommandObjectBreakpointAddPattern is a raw command. I was adjusting the
patch for changes to handle the dummy target changes done while the
patch was in review, and I copied the lines to the beginning of the
DoExecute, but in the case of raw commands, you have to do the option
parsing by hand, and this was before the parsing was done so the state
wasn't determined yet.
Someone came up with a clever idea for a new breakpoint type, but we
couldn't figure out how to add it in an ergonomic way because
`breakpoint set` has used up all the short-option characters. And even
if they did find a way to add it, the help for `break set` is so
confusing - because of the way it is implemented - that very few people
would detect the addition.
The basic problem is that `break set` distinguishes amongst the
fundamental breakpoint types it offers by which "required option" you
provide. If you pass a `-a` you are setting an address breakpoint, if
`-n`, `-F`, etc. a symbol name based breakpoint. And so forth. That is
however pretty hard to discern from the option grouping printing from
`help break set`. `break set` also suffers from the problem that it uses
common options in different ways depending on which "required" option is
present, which makes documenting the various behaviors difficult. And as
we run out of single letters it makes extending it difficult to
impossible.
This PR fixes that situation by adding a new command for adding
breakpoints - `break add`. The new command specifies the "breakpoint
types" as subcommands of `break add` rather than distinguishing them by
their being one of the "required" options the way `break set` does. That
both makes it much clearer what the breakpoint types actually are, and
means that the option set can be dedicated to that particular breakpoint
type, and so the help for each is less cluttered, and can be documented
properly for each usage.
Instead of trying to parse the meaning of:
```
(lldb) help break set
Sets a breakpoint or set of breakpoints in the executable.
Syntax: breakpoint set <cmd-options>
Command Options Usage:
breakpoint set [-DHd] -l <linenum> [-G <boolean>] [-C <command>] [-c <expr>] [-Y <source-language>] [-i <count>] [-o <boolean>] [-q <queue-name>] [-t <thread-id>] [-x <thread-index>] [-T <thread-name>] [-R <address>] [-N <breakpoint-name>] [-u <column>] [-f <filename>] [-m <boolean>] [-s <shlib-name>] [-K <boolean>]
breakpoint set [-DHd] -a <address-expression> [-G <boolean>] [-C <command>] [-c <expr>] [-Y <source-language>] [-i <count>] [-o <boolean>] [-q <queue-name>] [-t <thread-id>] [-x <thread-index>] [-T <thread-name>] [-N <breakpoint-name>] [-s <shlib-name>]
breakpoint set [-DHd] -n <function-name> [-G <boolean>] [-C <command>] [-c <expr>] [-Y <source-language>] [-i <count>] [-o <boolean>] [-q <queue-name>] [-t <thread-id>] [-x <thread-index>] [-T <thread-name>] [-R <address>] [-N <breakpoint-name>] [-f <filename>] [-L <source-language>] [-s <shlib-name>] [-K <boolean>]
breakpoint set [-DHd] -F <fullname> [-G <boolean>] [-C <command>] [-c <expr>] [-Y <source-language>] [-i <count>] [-o <boolean>] [-q <queue-name>] [-t <thread-id>] [-x <thread-index>] [-T <thread-name>] [-R <address>] [-N <breakpoint-name>] [-f <filename>] [-L <source-language>] [-s <shlib-name>] [-K <boolean>]
breakpoint set [-DHd] -S <selector> [-G <boolean>] [-C <command>] [-c <expr>] [-Y <source-language>] [-i <count>] [-o <boolean>] [-q <queue-name>] [-t <thread-id>] [-x <thread-index>] [-T <thread-name>] [-R <address>] [-N <breakpoint-name>] [-f <filename>] [-L <source-language>] [-s <shlib-name>] [-K <boolean>]
breakpoint set [-DHd] -M <method> [-G <boolean>] [-C <command>] [-c <expr>] [-Y <source-language>] [-i <count>] [-o <boolean>] [-q <queue-name>] [-t <thread-id>] [-x <thread-index>] [-T <thread-name>] [-R <address>] [-N <breakpoint-name>] [-f <filename>] [-L <source-language>] [-s <shlib-name>] [-K <boolean>]
breakpoint set [-DHd] -r <regular-expression> [-G <boolean>] [-C <command>] [-c <expr>] [-Y <source-language>] [-i <count>] [-o <boolean>] [-q <queue-name>] [-t <thread-id>] [-x <thread-index>] [-T <thread-name>] [-R <address>] [-N <breakpoint-name>] [-f <filename>] [-L <source-language>] [-s <shlib-name>] [-K <boolean>]
breakpoint set [-DHd] -b <function-name> [-G <boolean>] [-C <command>] [-c <expr>] [-Y <source-language>] [-i <count>] [-o <boolean>] [-q <queue-name>] [-t <thread-id>] [-x <thread-index>] [-T <thread-name>] [-R <address>] [-N <breakpoint-name>] [-f <filename>] [-L <source-language>] [-s <shlib-name>] [-K <boolean>]
breakpoint set [-ADHd] -p <regular-expression> [-G <boolean>] [-C <command>] [-c <expr>] [-Y <source-language>] [-i <count>] [-o <boolean>] [-q <queue-name>] [-t <thread-id>] [-x <thread-index>] [-T <thread-name>] [-N <breakpoint-name>] [-f <filename>] [-m <boolean>] [-s <shlib-name>] [-X <function-name>]
breakpoint set [-DHd] -E <source-language> [-G <boolean>] [-C <command>] [-c <expr>] [-Y <source-language>] [-i <count>] [-o <boolean>] [-q <queue-name>] [-t <thread-id>] [-x <thread-index>] [-T <thread-name>] [-N <breakpoint-name>] [-h <boolean>] [-w <boolean>]
breakpoint set [-DHd] -P <python-class> [-k <none>] [-v <none>] [-G <boolean>] [-C <command>] [-c <expr>] [-Y <source-language>] [-i <count>] [-o <boolean>] [-q <queue-name>] [-t <thread-id>] [-x <thread-index>] [-T <thread-name>] [-N <breakpoint-name>] [-f <filename>] [-s <shlib-name>]
breakpoint set [-DHd] -y <linespec> [-G <boolean>] [-C <command>] [-c <expr>] [-Y <source-language>] [-i <count>] [-o <boolean>] [-q <queue-name>] [-t <thread-id>] [-x <thread-index>] [-T <thread-name>] [-R <address>] [-N <breakpoint-name>] [-m <boolean>] [-s <shlib-name>] [-K <boolean>]
```
We instead offer:
```
(lldb) help break add
Commands to add breakpoints of various types
Syntax: breakpoint add
Access the breakpoint search kernels built into lldb. Along with specifying the
search kernel, each breakpoint add operation can specify a common set of
"reaction" options for each breakpoint. The reaction options can also be
modified after breakpoint creation using the "breakpoint modify" command.
The following subcommands are supported:
address -- Add breakpoints by raw address
exception -- Add breakpoints on language exceptions. If no language is specified, break on exceptions for all supported languages
file -- Add breakpoints on lines in specified source files
name -- Add breakpoints matching function or symbol names
pattern -- Add breakpoints matching patterns in the source text Expects 'raw' input (see 'help raw-input'.)
scripted -- Add breakpoints using a scripted breakpoint resolver.
For more help on any particular subcommand, type 'help <command> <subcommand>'.
```
The individual subcommand helps are also easier to read. They are still
a little too verbose because they all repeat the options for the
`reactions`. A general fix for our help system would be when a command
incorporates an OptionGroup whole into the command options, help would
show the option group name - which you could separately look up. But
even without that:
```
(lldb) help br a a
Add breakpoints by raw address
Syntax: breakpoint add address <cmd-options> <address> [<address> [...]]
Command Options Usage:
breakpoint add address [-DHde] [-G <boolean>] [-C <command>] [-c <expr>] [-Y <source-language>] [-i <count>] [-o <boolean>] [-q <queue-name>] [-t <thread-id>] [-x <thread-index>] [-T <thread-name>] [-N <breakpoint-name>] [-s <shlib-name>] <address> [<address> [...]]
-C <command> ( --command <command> )
A command to run when the breakpoint is hit, can be provided more than once, the commands will be run in left-to-right order.
-D ( --dummy-breakpoints )
Act on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets.
-G <boolean> ( --auto-continue <boolean> )
The breakpoint will auto-continue after running its commands.
-H ( --hardware )
Require the breakpoint to use hardware breakpoints.
-N <breakpoint-name> ( --breakpoint-name <breakpoint-name> )
Adds this name to the list of names for this breakpoint. Can be specified more than once.
-T <thread-name> ( --thread-name <thread-name> )
The breakpoint stops only for the thread whose thread name matches this argument.
-Y <source-language> ( --condition-language <source-language> )
Specifies the Language to use when executing the breakpoint's condition expression.
-c <expr> ( --condition <expr> )
The breakpoint stops only if this condition expression evaluates to true.
-d ( --disable )
Disable the breakpoint.
-e ( --enable )
Enable the breakpoint.
-i <count> ( --ignore-count <count> )
Set the number of times this breakpoint is skipped before stopping.
-o <boolean> ( --one-shot <boolean> )
The breakpoint is deleted the first time it stop causes a stop.
-q <queue-name> ( --queue-name <queue-name> )
The breakpoint stops only for threads in the queue whose name is given by this argument.
-s <shlib-name> ( --shlib <shlib-name> )
Set the breakpoint at an address relative to sections in this shared library.
-t <thread-id> ( --thread-id <thread-id> )
The breakpoint stops only for the thread whose TID matches this argument. The token 'current' resolves to the current thread's ID.
-x <thread-index> ( --thread-index <thread-index> )
The breakpoint stops only for the thread whose index matches this argument.
This command takes options and free-form arguments. If your arguments resemble option specifiers (i.e., they start with a - or --), you must use ' --
' between the end of the command options and the beginning of the arguments.
```
is pretty readable.
This patch fixes and eliminates the possibility of SupportFileSP ever
being nullptr. The support file was originally treated like a value
type, but became a polymorphic type and therefore has to be stored and
passed around as a pointer.
To avoid having all the callers check the validity of the pointer, I
introduced the invariant that SupportFileSP is never null and always
default constructed. However, without enforcement at the type level,
that's fragile and indeed, we already identified two crashes where
someone accidentally broke that invariant.
This PR introduces a NonNullSharedPtr to prevent that. NonNullSharedPtr
is a smart pointer wrapper around std::shared_ptr that guarantees the
pointer is never null. If default-constructed, it creates a
default-constructed instance of the contained type. Note that I'm using
private inheritance because you shouldn't inherit from standard library
classes due to the lack of virtual destructor. So while the new
abstraction looks like a `std::shared_ptr`, it is in fact **not** a
shared pointer. Given that our destructor is trivial, we could use
public inheritance, but currently there's no need for it.
rdar://164989579
Introduce the concept of internal stop hooks.
These are similar to LLDB's internal breakpoints:
LLDB itself will add them and users of LLDB will
not be able to add or remove them.
This change adds the following 3
independently-useful concepts:
* Maintain a list of internal stop hooks that will be populated by LLDB
and cannot be added to or removed from by users. They are managed in a
separate list in `Target::m_internal_stop_hooks`.
* `StopHookKind:CodeBased` and `StopHookCoded` represent a stop hook
defined by a C++ code callback (instead of command line expressions or a
Python class).
* Stop hooks that do not print any output can now also suppress the
printing of their header and description when they are hit via
`StopHook::GetSuppressOutput`.
Combining these 3 concepts we can model "internal
stop hooks" which serve the same function as
LLDB's internal breakpoints: executing built-in,
LLDB-defined behavior, leveraging the existing
mechanism of stop hooks.
This change also simplifies
`Target::RunStopHooks`. We already have to
materialize a new list for combining internal and
user stop hooks. Filter and only add active hooks to this list to avoid
the need for "isActive?"
checks later on.
The LLVM Style Guide says the following about error and warning messages
[1]:
> [T]o match error message styles commonly produced by other tools,
> start the first sentence with a lowercase letter, and finish the last
> sentence without a period, if it would end in one otherwise.
I often provide this feedback during code review, but we still have a
bunch of places where we have inconsistent error message, which bothers
me as a user. This PR identifies a handful of those places and updates
the messages to be consistent.
[1] https://llvm.org/docs/CodingStandards.html#error-and-warning-messages
LLDB breakpoint conditions take an expression that's evaluated using the
language of the code where the breakpoint is located. Users have asked
to have an option to tell it to evaluate the expression in a specific
language.
This is feature is especially helpful for Swift, for example for a
condition based on the value in memory at an offset from a register.
Such a condition is pretty difficult to write in Swift, but easy in C.
This PR adds a new argument (-Y) to specify the language of the
condition expression. We can't reuse the current -L option, since you
might want to break on only Swift symbols, but run a C expression there
as per the example above.
rdar://146119507
This RP changes some Breakpoint-related interfaces to return errors. On
its own these improvements are small, but they encourage better error
handling going forward. There are a bunch of other candidates, but these
were the functions that I touched while working on #146602.
It was assuming that for any location M.N, N was always less than the
number of breakpoint locations. But if you rebuild the target and rerun
multiple times, when the section backing one of the locations is no
longer valid, we remove the location, but we don't reuse the ID. So you
can have a breakpoint that only has location 1.3. The num_locations
check would say that was an invalid location.
Currently, CommandObjects are obtaining a target in a variety of ways.
Often the command incorrectly operates on the selected target. As an
example, when a breakpoint command is running, the current target is
passed into the command but the target that hit the breakpoint is not
the selected target. In other places we use the CommandObject's
execution context, which is frozen during the execution of the command,
and comes with its own limitations. Finally, we often want to fall back
to the dummy target if no real target is available.
Instead of having to guess how to get the target, this patch introduces
one helper function in CommandObject to get the most relevant target. In
order of priority, that's the target from the command object's execution
context, from the interpreter's execution context, the selected target
or the dummy target.
rdar://110846511
As a minor follow up for https://github.com/llvm/llvm-project/pull/97675, I'm renaming `SupportsExceptionBreakpoints` to `SupportsExceptionBreakpointsOnThrow` and adding a `SupportsExceptionBreakpointsOnCatch` to have a bit of more granularity.
CommandObjectBreakpoint has a harcoded list of languages for which
exception breakpoints can be enabled. I'm making this a bit more generic
so that my Mojo plugin can get this feature.
Basically, I'm adding a new overridable method
`Language::SupportsExceptionBreakpoints` that can be used by language
plugins to determine whether they support this feature or not. This
method is used in addition to the hardcoded list and, as an example, I'm
using it for the ObjC language support.
Another route is simply to avoid doing the check that it's being done
right now and simply try to the create the exception breakpoint for
whatever language that is not in the hardcoded list. I'm happy to do
that if the reviewers think it's a good idea.
As a note, the other possible place for adding this
`SupportsExceptionBreakpoints` method is in `LanguageRuntime`. However,
accessing it requires having a process, which is not always the case
when invoking the `breakpoint set -E` command. The process might not be
alive yet, so `Language` is a good second place for this.
And as a final note, I don't want to make this
`SupportsExceptionBreakpoints` complicated. I'm keeping it as simple as
possible because it can easily evolve as it's not part of the public
API.
This is another step towards supporting DWARF5 checksums and inline
source code in LLDB. This is a reland of #85468 but without the
functional change of storing the support file from the line table (yet).
Partly, there's just a lot of unnecessary boiler plate. It's also
possible to define combinations of arguments that make no sense (e.g.
eArgRepeatPlus followed by eArgRepeatPlain...) but these are never
checked since we just push_back directly into the argument definitions.
This commit is step 1 of this cleanup - do the obvious stuff. In it, all
the simple homogenous argument lists and the breakpoint/watchpoint
ID/Range types, are set with common functions. This is an NFC change, it
just centralizes boiler plate. There's no checking yet because you can't
get a single argument wrong.
The end goal is that all argument definition goes through functions and
m_arguments is hidden so that you can't define inconsistent argument
sets.
This updates the remaining SetOptionValue methods in
CommandObjectBreakpoint to use CreateOptionParsingError.
I found a few minor bugs that were fixed during this refactor (e.g.
using the wrong flag in an error message). That is one of the benefits
of centralizing error message creation.
I also found some option parsing code that is written incorrectly. I do
not make an attempt to update those here because this PR is primarily
about changing existing error handling code, not adding new error
handling code.
I have been looking to simplify parsing logic and improve the interfaces
so that they are both easier to use and harder to abuse. To be specific,
I am referring to functions such as `OptionArgParser::ToBoolean`: I
would like to go from its current interface to something more like
`llvm::Error<bool> ToBoolean(llvm::StringRef option_arg)`.
Through working on that, I encountered 2 inconveniences:
1. Option parsing code is not uniform. Every function writes a slightly
different error message, so incorporating an error message from the
`ToBoolean` implementation is going to be laborious as I figure out what
exactly needs to change or stay the same.
2. Changing the interface of `ToBoolean` would require a global atomic
change across all of the Command code. This would be quite frustrating
to do because of the non-uniformity of our existing code.
To address these frustrations, I think it would be easiest to first
standardize the error reporting mechanism when parsing options in
commands. I do so by introducing `CreateOptionParsingError` which will
create an error message of the shape:
Invalid value ('${option_arg}') for -${short_value} ('${long_value}'):
${additional_context}
Concretely, it would look something like this:
(lldb) breakpoint set -n main -G yay
error: Invalid value ('yay') for -G (auto-continue): Failed to parse as
boolean
After this, updating the interfaces for parsing the values themselves
should become simpler. Because this can be adopted incrementally, this
should be able to done over the course of time instead of all at once as
a giant difficult-to-review change. I've changed exactly one function
where this function would be used as an illustration of what I am
proposing.
`FindBreakpointID` take a BreakpointID and a pointer to a size_t (so you
can get position information). It returns a bool to indicate whether the
id was found in the list or not.
There are 2 callers of this currently and neither one actually uses the
position information, so I removed it. After that, I renamed it to
Contains to more accurately reflect the intent. Additionally, I changed
the argument type from a reference to a value (because BreakpointID is
just a wrapper around 2 integers, copies are cheap).
BreakpointIDList does not need to know about CommandReturnObject.
BreakpointIDList::FindAndReplaceIDRanges is the last place that uses it
in BreakpointIDList.
Instead of passing in a CommandReturnObject, it now returns an
llvm::Error. The callsite uses the Error to populate the
CommandReturnObject as needed.
This abstraction is leaky and BreakpointIDList does not need to know
about CommandReturnObject.
Additionally, setting the CommandReturnObject inout param to a success
state does very little. The function returns immediately if the input
ArrayRef is empty, and reading
CommandObjectMultiwordBreakpoint::VerifyIDs more closely, the input is
always empty if the previous call to
BreakpointIDList::FindAndReplaceIDRanges failed. If the call was
successful, then the CommandReturnObject is already in a success state.
I have opted to remove the function altogether and inline the
functionality where it was used.
This patch changes the interface of
StructuredData::Array::GetItemAtIndexAsString to return a
`std::optional<llvm::StringRef>` instead of taking an out parameter.
More generally, this commit serves as proposal that we change all of the
sibling APIs (`GetItemAtIndexAs`) to do the same thing. The reason this
isn't one giant patch is because it is rather unwieldy changing just one
of these, so if this is approved, I will do all of the other ones as
individual follow-ups.
[lldb] Part 2 of 2 - Refactor `CommandObject::DoExecute(...)` to return
`void` instead of ~~`bool`~~
Justifications:
- The code doesn't ultimately apply the `true`/`false` return values.
- The methods already pass around a `CommandReturnObject`, typically
with a `result` parameter.
- Each command return object already contains:
- A more precise status
- The error code(s) that apply to that status
Part 1 refactors the `CommandObject::Execute(...)` method.
- See
[https://github.com/llvm/llvm-project/pull/69989](https://github.com/llvm/llvm-project/pull/69989)
rdar://117378957
This patch should allow the user to set specific auto-completion type
for their custom commands.
To do so, we had to hoist the `CompletionType` enum so the user can
access it and add a new completion type flag to the CommandScriptAdd
Command Object.
So now, the user can specify which completion type will be used with
their custom command, when they register it.
This also makes the `crashlog` custom commands use disk-file completion
type, to browse through the user file system and load the report.
Differential Revision: https://reviews.llvm.org/D152011
Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
Refactor OptionValue to return a std::optional instead of taking a fail
value. This allows the caller to handle situations where there's no
value, instead of being unable to distinguish between the absence of a
value and the value happening the match the fail value. When a fail
value is required, std::optional::value_or() provides the same
functionality.
Breakpoint option `-t` checks that `option_arg` is empty by checking `option_arg[0] == '\0'`. This is unnecessary: the next two checks for comparing against "current" and calling `getAsInteger` already gracefully handle an empty StringRef. If the `option_arg` string is empty, this crashes (or triggers an assertion failure with asserts enabled). Also, this sets the thread id to `LLDB_INVALID_THREAD_ID` if the thread id is invalid -- it should just not set the thread id.
Likewise of `-x` which checks `option_arg[0] == '\n'` unnecessarily.
I believe both of these bugs are unreachable via normal LLDB usage, and are only accessible via the fuzzer -- most likely some other CLI parsing is trimming whitespace and rejecting empty inputs. Still, it doesn't hurt to simplify this bit.
Refactor the command option enum values and the command argument table
to connect the two. This has two benefits:
- We guarantee that two options that use the same argument type have
the same accepted values.
- We can print the enum values and their description in the help
output. (D129707)
Differential revision: https://reviews.llvm.org/D129703
Applied modernize-use-equals-default clang-tidy check over LLDB.
This check is already present in the lldb/.clang-tidy config.
Differential Revision: https://reviews.llvm.org/D121844
This provides a convenient way to limit a breakpoint
to the current thread when setting it from the command line w/o
having to figure out what the current thread is.
Differential Revision: https://reviews.llvm.org/D107015
The code that figured out which breakpoints to delete was supposed
to set the result status if it found breakpoints, and then the code
that actually deleted them checked that the result's status was set.
The code for "break delete --disabled" failed to set the status if
no "protected" breakpoints were provided. This was a confusing way
to implement this, so I reworked it with early returns so it was less
error prone, and added a test case for the no arguments case.
Differential Revision: https://reviews.llvm.org/D106623
Replacing existing uses with AppendError.
SetError is also part of the SBI API. This remains
but instead of calling the underlying SetError it
will call AppendError.
Reviewed By: teemperor
Differential Revision: https://reviews.llvm.org/D104768
This is part 2, covering the commands source.
Some uses remain where it's tricky to see what the
logic is or they are not used with AppendError.
Reviewed By: teemperor
Differential Revision: https://reviews.llvm.org/D104448
This is an NFC cleanup.
Many of the API's that returned BreakpointOptions always returned valid ones.
Internally the BreakpointLocations usually have null BreakpointOptions, since they
use their owner's options until an option is set specifically on the location.
So the original code used pointers & unique_ptr everywhere for consistency.
But that made the code hard to reason about from the outside.
This patch changes the code so that everywhere an API is guaranteed to
return a non-null BreakpointOption, it returns it as a reference to make
that clear.
It also changes the Breakpoint to hold a BreakpointOption
member where it previously had a UP. Since we were always filling the UP
in the Breakpoint constructor, having the UP wasn't helping anything.
Differential Revision: https://reviews.llvm.org/D104162
This converts a default constructor's member initializers into C++11
default member initializers. This patch was automatically generated with
clang-tidy and the modernize-use-default-member-init check.
$ run-clang-tidy.py -header-filter='lldb' -checks='-*,modernize-use-default-member-init' -fix
This is a mass-refactoring patch and this commit will be added to
.git-blame-ignore-revs.
Differential revision: https://reviews.llvm.org/D103483
1. created a common completion for breakpoint names;
2. bound the breakpoint name common completion with eArgTypeBreakpointName;
3. implemented the dedicated completion for breakpoint read -N.
Reviewed By: JDevlieghere
Differential Revision: https://reviews.llvm.org/D80693