forked from OSchip/llvm-project
Fixed line wrapping for the "long help" content in LLDB commands. Content is now dynamically wrapped for the column width of the current terminal. Lines that begin with whitespace will be indented identically on subsequent lines to maintain formatting.
Existing commands supplying this type of help content have been reworked to take advantage of the changes. In addition to formatting changes, content was changes for accuracy and clarity purposes. <rdar://problem/21269977> llvm-svn: 242122
This commit is contained in:
parent
2ffb36e829
commit
ea671fbdff
|
@ -160,6 +160,9 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
FormatLongHelpText (Stream &output_strm, const char *long_help);
|
||||
|
||||
void
|
||||
GenerateHelpText (CommandReturnObject &result);
|
||||
|
||||
|
|
|
@ -23,10 +23,10 @@
|
|||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
|
@ -45,19 +45,23 @@
|
|||
isEnabled = "YES">
|
||||
</EnvironmentVariable>
|
||||
</EnvironmentVariables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
displayScaleIsEnabled = "NO"
|
||||
displayScale = "1.00"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable>
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "26F5C26910F3D9A4009D5894"
|
||||
|
@ -79,10 +83,10 @@
|
|||
<ProfileAction
|
||||
displayScaleIsEnabled = "NO"
|
||||
displayScale = "1.00"
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
<EnvironmentVariables>
|
||||
<EnvironmentVariable
|
||||
|
|
|
@ -1249,25 +1249,25 @@ public:
|
|||
CommandObjectBreakpointDisable (CommandInterpreter &interpreter) :
|
||||
CommandObjectParsed (interpreter,
|
||||
"breakpoint disable",
|
||||
"Disable the specified breakpoint(s) without removing it/them. If no breakpoints are specified, disable them all.",
|
||||
"Disable the specified breakpoint(s) without removing them. If none are specified, disable all breakpoints.",
|
||||
NULL)
|
||||
{
|
||||
SetHelpLong(
|
||||
"Disable the specified breakpoint(s) without removing it/them. \n\
|
||||
If no breakpoints are specified, disable them all.\n\
|
||||
\n\
|
||||
Note: disabling a breakpoint will cause none of its locations to be hit\n\
|
||||
regardless of whether they are enabled or disabled. So the sequence: \n\
|
||||
\n\
|
||||
(lldb) break disable 1\n\
|
||||
(lldb) break enable 1.1\n\
|
||||
\n\
|
||||
will NOT cause location 1.1 to get hit. To achieve that, do:\n\
|
||||
\n\
|
||||
(lldb) break disable 1.*\n\
|
||||
(lldb) break enable 1.1\n\
|
||||
\n\
|
||||
The first command disables all the locations of breakpoint 1, \n\
|
||||
"Disable the specified breakpoint(s) without removing them. \
|
||||
If none are specified, disable all breakpoints." R"(
|
||||
|
||||
)" "Note: disabling a breakpoint will cause none of its locations to be hit \
|
||||
regardless of whether they are enabled or disabled. After the sequence:" R"(
|
||||
|
||||
(lldb) break disable 1
|
||||
(lldb) break enable 1.1
|
||||
|
||||
execution will NOT stop at location 1.1. To achieve that, type:
|
||||
|
||||
(lldb) break disable 1.*
|
||||
(lldb) break enable 1.1
|
||||
|
||||
)" "The first command disables all the locations of breakpoint 1, \
|
||||
the second re-enables the first location."
|
||||
);
|
||||
|
||||
|
|
|
@ -49,143 +49,120 @@ public:
|
|||
m_options (interpreter)
|
||||
{
|
||||
SetHelpLong (
|
||||
"\nGeneral information about entering breakpoint commands\n\
|
||||
------------------------------------------------------\n\
|
||||
\n\
|
||||
This command will cause you to be prompted to enter the command or set of\n\
|
||||
commands you wish to be executed when the specified breakpoint is hit. You\n\
|
||||
will be told to enter your command(s), and will see a '> 'prompt. Because\n\
|
||||
you can enter one or many commands to be executed when a breakpoint is hit,\n\
|
||||
you will continue to be prompted after each new-line that you enter, until you\n\
|
||||
enter the word 'DONE', which will cause the commands you have entered to be\n\
|
||||
stored with the breakpoint and executed when the breakpoint is hit.\n\
|
||||
\n\
|
||||
Syntax checking is not necessarily done when breakpoint commands are entered.\n\
|
||||
An improperly written breakpoint command will attempt to get executed when the\n\
|
||||
breakpoint gets hit, and usually silently fail. If your breakpoint command does\n\
|
||||
not appear to be getting executed, go back and check your syntax.\n\
|
||||
\n\
|
||||
Special information about PYTHON breakpoint commands\n\
|
||||
----------------------------------------------------\n\
|
||||
\n\
|
||||
You may enter either one line of Python, multiple lines of Python (including\n\
|
||||
function definitions), or specify a Python function in a module that has already,\n\
|
||||
or will be imported. If you enter a single line of Python, that will be passed\n\
|
||||
to the Python interpreter 'as is' when the breakpoint gets hit. If you enter\n\
|
||||
function definitions, they will be passed to the Python interpreter as soon as\n\
|
||||
you finish entering the breakpoint command, and they can be called later (don't\n\
|
||||
forget to add calls to them, if you want them called when the breakpoint is\n\
|
||||
hit). If you enter multiple lines of Python that are not function definitions,\n\
|
||||
they will be collected into a new, automatically generated Python function, and\n\
|
||||
a call to the newly generated function will be attached to the breakpoint.\n\
|
||||
\n\
|
||||
\n\
|
||||
This auto-generated function is passed in three arguments:\n\
|
||||
\n\
|
||||
frame: a lldb.SBFrame object for the frame which hit breakpoint.\n\
|
||||
bp_loc: a lldb.SBBreakpointLocation object that represents the breakpoint\n\
|
||||
location that was hit.\n\
|
||||
dict: the python session dictionary hit.\n\
|
||||
\n\
|
||||
When specifying a python function with the --python-function option, you need\n\
|
||||
to supply the function name prepended by the module name. So if you import a\n\
|
||||
module named 'myutils' that contains a 'breakpoint_callback' function, you would\n\
|
||||
specify the option as:\n\
|
||||
\n\
|
||||
--python-function myutils.breakpoint_callback\n\
|
||||
\n\
|
||||
The function itself must have the following prototype:\n\
|
||||
\n\
|
||||
def breakpoint_callback(frame, bp_loc, dict):\n\
|
||||
# Your code goes here\n\
|
||||
\n\
|
||||
The arguments are the same as the 3 auto generation function arguments listed\n\
|
||||
above. Note that the global variable 'lldb.frame' will NOT be setup when this\n\
|
||||
function is called, so be sure to use the 'frame' argument. The 'frame' argument\n\
|
||||
can get you to the thread (frame.GetThread()), the thread can get you to the\n\
|
||||
process (thread.GetProcess()), and the process can get you back to the target\n\
|
||||
(process.GetTarget()).\n\
|
||||
\n\
|
||||
Important Note: Because loose Python code gets collected into functions, if you\n\
|
||||
want to access global variables in the 'loose' code, you need to specify that\n\
|
||||
they are global, using the 'global' keyword. Be sure to use correct Python\n\
|
||||
syntax, including indentation, when entering Python breakpoint commands.\n\
|
||||
\n\
|
||||
As a third option, you can pass the name of an already existing Python function\n\
|
||||
and that function will be attached to the breakpoint. It will get passed the\n\
|
||||
frame and bp_loc arguments mentioned above.\n\
|
||||
\n\
|
||||
Example Python one-line breakpoint command:\n\
|
||||
\n\
|
||||
(lldb) breakpoint command add -s python 1\n\
|
||||
Enter your Python command(s). Type 'DONE' to end.\n\
|
||||
> print \"Hit this breakpoint!\"\n\
|
||||
> DONE\n\
|
||||
\n\
|
||||
As a convenience, this also works for a short Python one-liner:\n\
|
||||
(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\"\n\
|
||||
(lldb) run\n\
|
||||
Launching '.../a.out' (x86_64)\n\
|
||||
(lldb) Fri Sep 10 12:17:45 2010\n\
|
||||
Process 21778 Stopped\n\
|
||||
* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread\n\
|
||||
36 \n\
|
||||
37 int c(int val)\n\
|
||||
38 {\n\
|
||||
39 -> return val + 3;\n\
|
||||
40 }\n\
|
||||
41 \n\
|
||||
42 int main (int argc, char const *argv[])\n\
|
||||
(lldb)\n\
|
||||
\n\
|
||||
Example multiple line Python breakpoint command, using function definition:\n\
|
||||
\n\
|
||||
(lldb) breakpoint command add -s python 1\n\
|
||||
Enter your Python command(s). Type 'DONE' to end.\n\
|
||||
> def breakpoint_output (bp_no):\n\
|
||||
> out_string = \"Hit breakpoint number \" + repr (bp_no)\n\
|
||||
> print out_string\n\
|
||||
> return True\n\
|
||||
> breakpoint_output (1)\n\
|
||||
> DONE\n\
|
||||
\n\
|
||||
\n\
|
||||
Example multiple line Python breakpoint command, using 'loose' Python:\n\
|
||||
\n\
|
||||
(lldb) breakpoint command add -s p 1\n\
|
||||
Enter your Python command(s). Type 'DONE' to end.\n\
|
||||
> global bp_count\n\
|
||||
> bp_count = bp_count + 1\n\
|
||||
> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\"\n\
|
||||
> DONE\n\
|
||||
\n\
|
||||
In this case, since there is a reference to a global variable,\n\
|
||||
'bp_count', you will also need to make sure 'bp_count' exists and is\n\
|
||||
initialized:\n\
|
||||
\n\
|
||||
(lldb) script\n\
|
||||
>>> bp_count = 0\n\
|
||||
>>> quit()\n\
|
||||
\n\
|
||||
(lldb)\n\
|
||||
\n\
|
||||
\n\
|
||||
Your Python code, however organized, can optionally return a value.\n\
|
||||
If the returned value is False, that tells LLDB not to stop at the breakpoint\n\
|
||||
to which the code is associated. Returning anything other than False, or even\n\
|
||||
returning None, or even omitting a return statement entirely, will cause\n\
|
||||
LLDB to stop.\n\
|
||||
\n\
|
||||
Final Note: If you get a warning that no breakpoint command was generated, but\n\
|
||||
you did not get any syntax errors, you probably forgot to add a call to your\n\
|
||||
functions.\n\
|
||||
\n\
|
||||
Special information about debugger command breakpoint commands\n\
|
||||
--------------------------------------------------------------\n\
|
||||
\n\
|
||||
You may enter any debugger command, exactly as you would at the debugger prompt.\n\
|
||||
You may enter as many debugger commands as you like, but do NOT enter more than\n\
|
||||
one command per line.\n" );
|
||||
R"(
|
||||
General information about entering breakpoint commands
|
||||
------------------------------------------------------
|
||||
|
||||
)" "This command will prompt for commands to be executed when the specified \
|
||||
breakpoint is hit. Each command is typed on its own line following the '> ' \
|
||||
prompt until 'DONE' is entered." R"(
|
||||
|
||||
)" "Syntactic errors may not be detected when initially entered, and many \
|
||||
malformed commands can silently fail when executed. If your breakpoint commands \
|
||||
do not appear to be executing, double-check the command syntax." R"(
|
||||
|
||||
)" "Note: You may enter any debugger command exactly as you would at the debugger \
|
||||
prompt. There is no limit to the number of commands supplied, but do NOT enter \
|
||||
more than one command per line." R"(
|
||||
|
||||
Special information about PYTHON breakpoint commands
|
||||
----------------------------------------------------
|
||||
|
||||
)" "You may enter either one or more lines of Python, including function \
|
||||
definitions or calls to functions that will have been imported by the time \
|
||||
the code executes. Single line breakpoint commands will be interpreted 'as is' \
|
||||
when the breakpoint is hit. Multiple lines of Python will be wrapped in a \
|
||||
generated function, and a call to the function will be attached to the breakpoint." R"(
|
||||
|
||||
This auto-generated function is passed in three arguments:
|
||||
|
||||
frame: an lldb.SBFrame object for the frame which hit breakpoint.
|
||||
|
||||
bp_loc: an lldb.SBBreakpointLocation object that represents the breakpoint location that was hit.
|
||||
|
||||
dict: the python session dictionary hit.
|
||||
|
||||
)" "When specifying a python function with the --python-function option, you need \
|
||||
to supply the function name prepended by the module name:" R"(
|
||||
|
||||
--python-function myutils.breakpoint_callback
|
||||
|
||||
The function itself must have the following prototype:
|
||||
|
||||
def breakpoint_callback(frame, bp_loc, dict):
|
||||
# Your code goes here
|
||||
|
||||
)" "The arguments are the same as the arguments passed to generated functions as \
|
||||
described above. Note that the global variable 'lldb.frame' will NOT be updated when \
|
||||
this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
|
||||
can get you to the thread via frame.GetThread(), the thread can get you to the \
|
||||
process via thread.GetProcess(), and the process can get you back to the target \
|
||||
via process.GetTarget()." R"(
|
||||
|
||||
)" "Important Note: As Python code gets collected into functions, access to global \
|
||||
variables requires explicit scoping using the 'global' keyword. Be sure to use correct \
|
||||
Python syntax, including indentation, when entering Python breakpoint commands." R"(
|
||||
|
||||
Example Python one-line breakpoint command:
|
||||
|
||||
(lldb) breakpoint command add -s python 1
|
||||
Enter your Python command(s). Type 'DONE' to end.
|
||||
> print "Hit this breakpoint!"
|
||||
> DONE
|
||||
|
||||
As a convenience, this also works for a short Python one-liner:
|
||||
|
||||
(lldb) breakpoint command add -s python 1 -o 'import time; print time.asctime()'
|
||||
(lldb) run
|
||||
Launching '.../a.out' (x86_64)
|
||||
(lldb) Fri Sep 10 12:17:45 2010
|
||||
Process 21778 Stopped
|
||||
* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
|
||||
36
|
||||
37 int c(int val)
|
||||
38 {
|
||||
39 -> return val + 3;
|
||||
40 }
|
||||
41
|
||||
42 int main (int argc, char const *argv[])
|
||||
|
||||
Example multiple line Python breakpoint command:
|
||||
|
||||
(lldb) breakpoint command add -s p 1
|
||||
Enter your Python command(s). Type 'DONE' to end.
|
||||
> global bp_count
|
||||
> bp_count = bp_count + 1
|
||||
> print "Hit this breakpoint " + repr(bp_count) + " times!"
|
||||
> DONE
|
||||
|
||||
Example multiple line Python breakpoint command, using function definition:
|
||||
|
||||
(lldb) breakpoint command add -s python 1
|
||||
Enter your Python command(s). Type 'DONE' to end.
|
||||
> def breakpoint_output (bp_no):
|
||||
> out_string = "Hit breakpoint number " + repr (bp_no)
|
||||
> print out_string
|
||||
> return True
|
||||
> breakpoint_output (1)
|
||||
> DONE
|
||||
|
||||
)" "In this case, since there is a reference to a global variable, \
|
||||
'bp_count', you will also need to make sure 'bp_count' exists and is \
|
||||
initialized:" R"(
|
||||
|
||||
(lldb) script
|
||||
>>> bp_count = 0
|
||||
>>> quit()
|
||||
|
||||
)" "Your Python code, however organized, can optionally return a value. \
|
||||
If the returned value is False, that tells LLDB not to stop at the breakpoint \
|
||||
to which the code is associated. Returning anything other than False, or even \
|
||||
returning None, or even omitting a return statement entirely, will cause \
|
||||
LLDB to stop." R"(
|
||||
|
||||
)" "Final Note: A warning that no breakpoint command was generated when there \
|
||||
are no syntax errors may indicate that a function was declared but never called."
|
||||
);
|
||||
|
||||
CommandArgumentEntry arg;
|
||||
CommandArgumentData bp_id_arg;
|
||||
|
|
|
@ -450,60 +450,74 @@ public:
|
|||
NULL)
|
||||
{
|
||||
SetHelpLong(
|
||||
"'alias' allows the user to create a short-cut or abbreviation for long \n\
|
||||
commands, multi-word commands, and commands that take particular options. \n\
|
||||
Below are some simple examples of how one might use the 'alias' command: \n\
|
||||
\n 'command alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\
|
||||
// command. \n\
|
||||
'command alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\
|
||||
// command. Since breakpoint commands are two-word \n\
|
||||
// commands, the user will still need to enter the \n\
|
||||
// second word after 'bp', e.g. 'bp enable' or \n\
|
||||
// 'bp delete'. \n\
|
||||
'command alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
|
||||
// two-word command 'breakpoint list'. \n\
|
||||
\nAn alias can include some options for the command, with the values either \n\
|
||||
filled in at the time the alias is created, or specified as positional \n\
|
||||
arguments, to be filled in when the alias is invoked. The following example \n\
|
||||
shows how to create aliases with options: \n\
|
||||
\n\
|
||||
'command alias bfl breakpoint set -f %1 -l %2' \n\
|
||||
\nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
|
||||
options already part of the alias. So if the user wants to set a breakpoint \n\
|
||||
by file and line without explicitly having to use the -f and -l options, the \n\
|
||||
user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \n\
|
||||
for the actual arguments that will be passed when the alias command is used. \n\
|
||||
The number in the placeholder refers to the position/order the actual value \n\
|
||||
occupies when the alias is used. All the occurrences of '%1' in the alias \n\
|
||||
will be replaced with the first argument, all the occurrences of '%2' in the \n\
|
||||
alias will be replaced with the second argument, and so on. This also allows \n\
|
||||
actual arguments to be used multiple times within an alias (see 'process \n\
|
||||
launch' example below). \n\
|
||||
Note: the positional arguments must substitute as whole words in the resultant\n\
|
||||
command, so you can't at present do something like:\n\
|
||||
\n\
|
||||
command alias bcppfl breakpoint set -f %1.cpp -l %2\n\
|
||||
\n\
|
||||
to get the file extension \".cpp\" automatically appended. For more complex\n\
|
||||
aliasing, use the \"command regex\" command instead.\n\
|
||||
\nSo in the 'bfl' case, the actual file value will be \n\
|
||||
filled in with the first argument following 'bfl' and the actual line number \n\
|
||||
value will be filled in with the second argument. The user would use this \n\
|
||||
alias as follows: \n\
|
||||
\n (lldb) command alias bfl breakpoint set -f %1 -l %2 \n\
|
||||
<... some time later ...> \n\
|
||||
(lldb) bfl my-file.c 137 \n\
|
||||
\nThis would be the same as if the user had entered \n\
|
||||
'breakpoint set -f my-file.c -l 137'. \n\
|
||||
\nAnother example: \n\
|
||||
\n (lldb) command alias pltty process launch -s -o %1 -e %1 \n\
|
||||
(lldb) pltty /dev/tty0 \n\
|
||||
// becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
|
||||
\nIf the user always wanted to pass the same value to a particular option, the \n\
|
||||
alias could be defined with that value directly in the alias as a constant, \n\
|
||||
rather than using a positional placeholder: \n\
|
||||
\n command alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\
|
||||
// 3 of whatever file is indicated. \n");
|
||||
"'alias' allows the user to create a short-cut or abbreviation for long \
|
||||
commands, multi-word commands, and commands that take particular options. \
|
||||
Below are some simple examples of how one might use the 'alias' command:" R"(
|
||||
|
||||
(lldb) command alias sc script
|
||||
|
||||
Creates the abbreviation 'sc' for the 'script' command.
|
||||
|
||||
(lldb) command alias bp breakpoint
|
||||
|
||||
)" " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \
|
||||
breakpoint commands are two-word commands, the user would still need to \
|
||||
enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." R"(
|
||||
|
||||
(lldb) command alias bpl breakpoint list
|
||||
|
||||
Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
|
||||
|
||||
)" "An alias can include some options for the command, with the values either \
|
||||
filled in at the time the alias is created, or specified as positional \
|
||||
arguments, to be filled in when the alias is invoked. The following example \
|
||||
shows how to create aliases with options:" R"(
|
||||
|
||||
(lldb) command alias bfl breakpoint set -f %1 -l %2
|
||||
|
||||
)" " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
|
||||
options already part of the alias. So if the user wants to set a breakpoint \
|
||||
by file and line without explicitly having to use the -f and -l options, the \
|
||||
user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \
|
||||
for the actual arguments that will be passed when the alias command is used. \
|
||||
The number in the placeholder refers to the position/order the actual value \
|
||||
occupies when the alias is used. All the occurrences of '%1' in the alias \
|
||||
will be replaced with the first argument, all the occurrences of '%2' in the \
|
||||
alias will be replaced with the second argument, and so on. This also allows \
|
||||
actual arguments to be used multiple times within an alias (see 'process \
|
||||
launch' example below)." R"(
|
||||
|
||||
)" "Note: the positional arguments must substitute as whole words in the resultant \
|
||||
command, so you can't at present do something like this to append the file extension \
|
||||
\".cpp\":" R"(
|
||||
|
||||
(lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
|
||||
|
||||
)" "For more complex aliasing, use the \"command regex\" command instead. In the \
|
||||
'bfl' case above, the actual file value will be filled in with the first argument \
|
||||
following 'bfl' and the actual line number value will be filled in with the second \
|
||||
argument. The user would use this alias as follows:" R"(
|
||||
|
||||
(lldb) command alias bfl breakpoint set -f %1 -l %2
|
||||
(lldb) bfl my-file.c 137
|
||||
|
||||
This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
|
||||
|
||||
Another example:
|
||||
|
||||
(lldb) command alias pltty process launch -s -o %1 -e %1
|
||||
(lldb) pltty /dev/tty0
|
||||
|
||||
Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
|
||||
|
||||
)" "If the user always wanted to pass the same value to a particular option, the \
|
||||
alias could be defined with that value directly in the alias as a constant, \
|
||||
rather than using a positional placeholder:" R"(
|
||||
|
||||
(lldb) command alias bl3 breakpoint set -f %1 -l 3
|
||||
|
||||
Always sets a breakpoint on line 3 of whatever file is indicated.)"
|
||||
);
|
||||
|
||||
CommandArgumentEntry arg1;
|
||||
CommandArgumentEntry arg2;
|
||||
|
@ -960,30 +974,29 @@ public:
|
|||
IOHandlerDelegateMultiline ("", IOHandlerDelegate::Completion::LLDBCommand),
|
||||
m_options (interpreter)
|
||||
{
|
||||
SetHelpLong(
|
||||
"This command allows the user to create powerful regular expression commands\n"
|
||||
"with substitutions. The regular expressions and substitutions are specified\n"
|
||||
"using the regular expression substitution format of:\n"
|
||||
"\n"
|
||||
" s/<regex>/<subst>/\n"
|
||||
"\n"
|
||||
"<regex> is a regular expression that can use parenthesis to capture regular\n"
|
||||
"expression input and substitute the captured matches in the output using %1\n"
|
||||
"for the first match, %2 for the second, and so on.\n"
|
||||
"\n"
|
||||
"The regular expressions can all be specified on the command line if more than\n"
|
||||
"one argument is provided. If just the command name is provided on the command\n"
|
||||
"line, then the regular expressions and substitutions can be entered on separate\n"
|
||||
" lines, followed by an empty line to terminate the command definition.\n"
|
||||
"\n"
|
||||
"EXAMPLES\n"
|
||||
"\n"
|
||||
"The following example will define a regular expression command named 'f' that\n"
|
||||
"will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n"
|
||||
"a number follows 'f':\n"
|
||||
"\n"
|
||||
" (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n"
|
||||
"\n"
|
||||
SetHelpLong(R"(
|
||||
)" "This command allows the user to create powerful regular expression commands \
|
||||
with substitutions. The regular expressions and substitutions are specified \
|
||||
using the regular expression substitution format of:" R"(
|
||||
|
||||
s/<regex>/<subst>/
|
||||
|
||||
)" "<regex> is a regular expression that can use parenthesis to capture regular \
|
||||
expression input and substitute the captured matches in the output using %1 \
|
||||
for the first match, %2 for the second, and so on." R"(
|
||||
|
||||
)" "The regular expressions can all be specified on the command line if more than \
|
||||
one argument is provided. If just the command name is provided on the command \
|
||||
line, then the regular expressions and substitutions can be entered on separate \
|
||||
lines, followed by an empty line to terminate the command definition." R"(
|
||||
|
||||
EXAMPLES
|
||||
|
||||
)" "The following example will define a regular expression command named 'f' that \
|
||||
will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
|
||||
a number follows 'f':" R"(
|
||||
|
||||
(lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -203,34 +203,38 @@ CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interprete
|
|||
m_expr_lines ()
|
||||
{
|
||||
SetHelpLong(
|
||||
"Timeouts:\n\
|
||||
If the expression can be evaluated statically (without running code) then it will be.\n\
|
||||
Otherwise, by default the expression will run on the current thread with a short timeout:\n\
|
||||
currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted\n\
|
||||
and resumed with all threads running. You can use the -a option to disable retrying on all\n\
|
||||
threads. You can use the -t option to set a shorter timeout.\n\
|
||||
\n\
|
||||
User defined variables:\n\
|
||||
You can define your own variables for convenience or to be used in subsequent expressions.\n\
|
||||
You define them the same way you would define variables in C. If the first character of \n\
|
||||
your user defined variable is a $, then the variable's value will be available in future\n\
|
||||
expressions, otherwise it will just be available in the current expression.\n\
|
||||
\n\
|
||||
\n\
|
||||
Continuing evaluation after a breakpoint:\n\
|
||||
If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once\n\
|
||||
you are done with your investigation, you can either remove the expression execution frames\n\
|
||||
from the stack with \"thread return -x\" or if you are still interested in the expression result\n\
|
||||
you can issue the \"continue\" command and the expression evaluation will complete and the\n\
|
||||
expression result will be available using the \"thread.completed-expression\" key in the thread\n\
|
||||
format.\n\
|
||||
\n\
|
||||
Examples: \n\
|
||||
\n\
|
||||
expr my_struct->a = my_array[3] \n\
|
||||
expr -f bin -- (index * 8) + 5 \n\
|
||||
expr unsigned int $foo = 5\n\
|
||||
expr char c[] = \"foo\"; c[0]\n");
|
||||
R"(
|
||||
Timeouts:
|
||||
|
||||
)" " If the expression can be evaluated statically (without running code) then it will be. \
|
||||
Otherwise, by default the expression will run on the current thread with a short timeout: \
|
||||
currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted \
|
||||
and resumed with all threads running. You can use the -a option to disable retrying on all \
|
||||
threads. You can use the -t option to set a shorter timeout." R"(
|
||||
|
||||
User defined variables:
|
||||
|
||||
)" " You can define your own variables for convenience or to be used in subsequent expressions. \
|
||||
You define them the same way you would define variables in C. If the first character of \
|
||||
your user defined variable is a $, then the variable's value will be available in future \
|
||||
expressions, otherwise it will just be available in the current expression." R"(
|
||||
|
||||
Continuing evaluation after a breakpoint:
|
||||
|
||||
)" " If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once \
|
||||
you are done with your investigation, you can either remove the expression execution frames \
|
||||
from the stack with \"thread return -x\" or if you are still interested in the expression result \
|
||||
you can issue the \"continue\" command and the expression evaluation will complete and the \
|
||||
expression result will be available using the \"thread.completed-expression\" key in the thread \
|
||||
format." R"(
|
||||
|
||||
Examples:
|
||||
|
||||
expr my_struct->a = my_array[3]
|
||||
expr -f bin -- (index * 8) + 5
|
||||
expr unsigned int $foo = 5
|
||||
expr char c[] = \"foo\"; c[0])"
|
||||
);
|
||||
|
||||
CommandArgumentEntry arg;
|
||||
CommandArgumentData expression_arg;
|
||||
|
|
|
@ -1067,10 +1067,12 @@ public:
|
|||
0)
|
||||
{
|
||||
SetHelpLong(
|
||||
"Examples: \n\
|
||||
\n\
|
||||
platform get-file /the/remote/file/path /the/local/file/path\n\
|
||||
# Transfer a file from the remote end with file path /the/remote/file/path to the local host.\n");
|
||||
R"(Examples:
|
||||
|
||||
(lldb) platform get-file /the/remote/file/path /the/local/file/path
|
||||
|
||||
Transfer a file from the remote end with file path /the/remote/file/path to the local host.)"
|
||||
);
|
||||
|
||||
CommandArgumentEntry arg1, arg2;
|
||||
CommandArgumentData file_arg_remote, file_arg_host;
|
||||
|
@ -1150,10 +1152,12 @@ public:
|
|||
0)
|
||||
{
|
||||
SetHelpLong(
|
||||
"Examples: \n\
|
||||
\n\
|
||||
platform get-size /the/remote/file/path\n\
|
||||
# Get the file size from the remote end with path /the/remote/file/path.\n");
|
||||
R"(Examples:
|
||||
|
||||
(lldb) platform get-size /the/remote/file/path
|
||||
|
||||
Get the file size from the remote end with path /the/remote/file/path.)"
|
||||
);
|
||||
|
||||
CommandArgumentEntry arg1;
|
||||
CommandArgumentData file_arg_remote;
|
||||
|
|
|
@ -1681,7 +1681,8 @@ public:
|
|||
NULL),
|
||||
m_options (interpreter)
|
||||
{
|
||||
SetHelpLong ("If no signals are specified, update them all. If no update option is specified, list the current values.\n");
|
||||
SetHelpLong ("\nIf no signals are specified, update them all. If no update "
|
||||
"option is specified, list the current values.");
|
||||
CommandArgumentEntry arg;
|
||||
CommandArgumentData signal_arg;
|
||||
|
||||
|
|
|
@ -60,24 +60,25 @@ public:
|
|||
m_arguments.push_back (arg2);
|
||||
|
||||
SetHelpLong (
|
||||
"When setting a dictionary or array variable, you can set multiple entries \n\
|
||||
at once by giving the values to the set command. For example: \n\
|
||||
\n\
|
||||
(lldb) settings set target.run-args value1 value2 value3 \n\
|
||||
(lldb) settings set target.env-vars MYPATH=~/.:/usr/bin SOME_ENV_VAR=12345 \n\
|
||||
\n\
|
||||
(lldb) settings show target.run-args \n\
|
||||
[0]: 'value1' \n\
|
||||
[1]: 'value2' \n\
|
||||
[3]: 'value3' \n\
|
||||
(lldb) settings show target.env-vars \n\
|
||||
'MYPATH=~/.:/usr/bin'\n\
|
||||
'SOME_ENV_VAR=12345' \n\
|
||||
\n\
|
||||
Warning: The 'set' command re-sets the entire array or dictionary. If you \n\
|
||||
just want to add, remove or update individual values (or add something to \n\
|
||||
the end), use one of the other settings sub-commands: append, replace, \n\
|
||||
insert-before or insert-after.\n");
|
||||
"\nWhen setting a dictionary or array variable, you can set multiple entries \
|
||||
at once by giving the values to the set command. For example:" R"(
|
||||
|
||||
(lldb) settings set target.run-args value1 value2 value3
|
||||
(lldb) settings set target.env-vars MYPATH=~/.:/usr/bin SOME_ENV_VAR=12345
|
||||
|
||||
(lldb) settings show target.run-args
|
||||
[0]: 'value1'
|
||||
[1]: 'value2'
|
||||
[3]: 'value3'
|
||||
(lldb) settings show target.env-vars
|
||||
'MYPATH=~/.:/usr/bin'
|
||||
'SOME_ENV_VAR=12345'
|
||||
|
||||
)" "Warning: The 'set' command re-sets the entire array or dictionary. If you \
|
||||
just want to add, remove or update individual values (or add something to \
|
||||
the end), use one of the other settings sub-commands: append, replace, \
|
||||
insert-before or insert-after."
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -764,31 +764,39 @@ public:
|
|||
m_arguments.push_back (type_arg);
|
||||
|
||||
SetHelpLong(
|
||||
"Some examples of using this command.\n"
|
||||
"We use as reference the following snippet of code:\n"
|
||||
"\n"
|
||||
"typedef int Aint;\n"
|
||||
"typedef float Afloat;\n"
|
||||
"typedef Aint Bint;\n"
|
||||
"typedef Afloat Bfloat;\n"
|
||||
"\n"
|
||||
"Aint ix = 5;\n"
|
||||
"Bint iy = 5;\n"
|
||||
"\n"
|
||||
"Afloat fx = 3.14;\n"
|
||||
"BFloat fy = 3.14;\n"
|
||||
"\n"
|
||||
"Typing:\n"
|
||||
"type format add -f hex AInt\n"
|
||||
"frame variable iy\n"
|
||||
"will produce an hex display of iy, because no formatter is available for Bint and the one for Aint is used instead\n"
|
||||
"To prevent this type\n"
|
||||
"type format add -f hex -C no AInt\n"
|
||||
"\n"
|
||||
"A similar reasoning applies to\n"
|
||||
"type format add -f hex -C no float -p\n"
|
||||
"which now prints all floats and float&s as hexadecimal, but does not format float*s\n"
|
||||
"and does not change the default display for Afloat and Bfloat objects.\n"
|
||||
R"(
|
||||
The following examples of 'type format add' refer to this code snippet for context:
|
||||
|
||||
typedef int Aint;
|
||||
typedef float Afloat;
|
||||
typedef Aint Bint;
|
||||
typedef Afloat Bfloat;
|
||||
|
||||
Aint ix = 5;
|
||||
Bint iy = 5;
|
||||
|
||||
Afloat fx = 3.14;
|
||||
BFloat fy = 3.14;
|
||||
|
||||
Adding default formatting:
|
||||
|
||||
(lldb) type format add -f hex AInt
|
||||
(lldb) frame variable iy
|
||||
|
||||
)" " Produces hexidecimal display of iy, because no formatter is available for Bint and \
|
||||
the one for Aint is used instead." R"(
|
||||
|
||||
To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains:
|
||||
|
||||
|
||||
(lldb) type format add -f hex -C no AInt
|
||||
|
||||
Similar reasoning applies to this:
|
||||
|
||||
(lldb) type format add -f hex -C no float -p
|
||||
|
||||
)" " All float values and float references are now formatted as hexadecimal, but not \
|
||||
pointers to floats. Nor will it change the default display for Afloat and Bfloat objects."
|
||||
);
|
||||
|
||||
// Add the "--format" to all options groups
|
||||
|
@ -1736,68 +1744,85 @@ CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &in
|
|||
m_arguments.push_back (type_arg);
|
||||
|
||||
SetHelpLong(
|
||||
"Some examples of using this command.\n"
|
||||
"We use as reference the following snippet of code:\n"
|
||||
"struct JustADemo\n"
|
||||
"{\n"
|
||||
"int* ptr;\n"
|
||||
"float value;\n"
|
||||
"JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}\n"
|
||||
"};\n"
|
||||
"JustADemo object(42,3.14);\n"
|
||||
"struct AnotherDemo : public JustADemo\n"
|
||||
"{\n"
|
||||
"uint8_t byte;\n"
|
||||
"AnotherDemo(uint8_t b = 'E', int p = 1, float v = 0.1) : JustADemo(p,v), byte(b) {}\n"
|
||||
"};\n"
|
||||
"AnotherDemo *another_object = new AnotherDemo('E',42,3.14);\n"
|
||||
"\n"
|
||||
"type summary add --summary-string \"the answer is ${*var.ptr}\" JustADemo\n"
|
||||
"when typing frame variable object you will get \"the answer is 42\"\n"
|
||||
"type summary add --summary-string \"the answer is ${*var.ptr}, and the question is ${var.value}\" JustADemo\n"
|
||||
"when typing frame variable object you will get \"the answer is 42 and the question is 3.14\"\n"
|
||||
"\n"
|
||||
"Alternatively, you could also say\n"
|
||||
"type summary add --summary-string \"${var%V} -> ${*var}\" \"int *\"\n"
|
||||
"and replace the above summary string with\n"
|
||||
"type summary add --summary-string \"the answer is ${var.ptr}, and the question is ${var.value}\" JustADemo\n"
|
||||
"to obtain a similar result\n"
|
||||
"\n"
|
||||
"To add a summary valid for both JustADemo and AnotherDemo you can use the scoping operator, as in:\n"
|
||||
"type summary add --summary-string \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes\n"
|
||||
"\n"
|
||||
"This will be used for both variables of type JustADemo and AnotherDemo. To prevent this, change the -C to read -C no\n"
|
||||
"If you do not want pointers to be shown using that summary, you can use the -p option, as in:\n"
|
||||
"type summary add --summary-string \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes -p\n"
|
||||
"A similar option -r exists for references.\n"
|
||||
"\n"
|
||||
"If you simply want a one-line summary of the content of your variable, without typing an explicit string to that effect\n"
|
||||
"you can use the -c option, without giving any summary string:\n"
|
||||
"type summary add -c JustADemo\n"
|
||||
"frame variable object\n"
|
||||
"the output being similar to (ptr=0xsomeaddress, value=3.14)\n"
|
||||
"\n"
|
||||
"If you want to display some summary text, but also expand the structure of your object, you can add the -e option, as in:\n"
|
||||
"type summary add -e --summary-string \"*ptr = ${*var.ptr}\" JustADemo\n"
|
||||
"Here the value of the int* is displayed, followed by the standard LLDB sequence of children objects, one per line.\n"
|
||||
"to get an output like:\n"
|
||||
"\n"
|
||||
"*ptr = 42 {\n"
|
||||
" ptr = 0xsomeaddress\n"
|
||||
" value = 3.14\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"You can also add Python summaries, in which case you will use lldb public API to gather information from your variables"
|
||||
"and elaborate them to a meaningful summary inside a script written in Python. The variable object will be passed to your"
|
||||
"script as an SBValue object. The following example might help you when starting to use the Python summaries feature:\n"
|
||||
"type summary add JustADemo -o \"value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();\"\n"
|
||||
"If you prefer to type your scripts on multiple lines, you will use the -P option and then type your script, ending it with "
|
||||
"the word DONE on a line by itself to mark you're finished editing your code:\n"
|
||||
"(lldb)type summary add JustADemo -P\n"
|
||||
" value = valobj.GetChildMemberWithName('value');\n"
|
||||
" return 'My value is ' + value.GetValue();\n"
|
||||
"DONE\n"
|
||||
"(lldb) <-- type further LLDB commands here\n"
|
||||
R"(
|
||||
The following examples of 'type summary add' refer to this code snippet for context:
|
||||
|
||||
struct JustADemo
|
||||
{
|
||||
int* ptr;
|
||||
float value;
|
||||
JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
|
||||
};
|
||||
JustADemo demo_instance(42, 3.14);
|
||||
|
||||
typedef JustADemo NewDemo;
|
||||
NewDemo new_demo_instance(42, 3.14);
|
||||
|
||||
(lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo
|
||||
|
||||
Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"
|
||||
|
||||
(lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo
|
||||
|
||||
Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"
|
||||
|
||||
)" "Alternatively, you could define formatting for all pointers to integers and \
|
||||
rely on that when formatting JustADemo to obtain the same result:" R"(
|
||||
|
||||
(lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
|
||||
(lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo
|
||||
|
||||
)" "Type summaries are automatically applied to derived typedefs, so the examples \
|
||||
above apply to both JustADemo and NewDemo. The cascade option can be used to \
|
||||
suppress this behavior:" R"(
|
||||
|
||||
(lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no
|
||||
|
||||
The summary will now be used for values of JustADemo but not NewDemo.
|
||||
|
||||
)" "By default summaries are shown for pointers and references to values of the \
|
||||
specified type. To suppress formatting for pointers use the -p option, or apply \
|
||||
the corresponding -r option to suppress formatting for references:" R"(
|
||||
|
||||
(lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo
|
||||
|
||||
)" "One-line summaries including all fields in a type can be inferred without supplying an \
|
||||
explicit summary string by passing the -c option:" R"(
|
||||
|
||||
(lldb) type summary add -c JustADemo
|
||||
(lldb) frame variable demo_instance
|
||||
(ptr=<address>, value=3.14)
|
||||
|
||||
)" "Type summaries normally suppress the nested display of individual fields. To \
|
||||
supply a summary to supplement the default structure add the -e option:" R"(
|
||||
|
||||
(lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo
|
||||
|
||||
)" "Now when displaying JustADemo values the int* is displayed, followed by the \
|
||||
standard LLDB sequence of children, one per line:" R"(
|
||||
|
||||
*ptr = 42 {
|
||||
ptr = <address>
|
||||
value = 3.14
|
||||
}
|
||||
|
||||
)" "You can also add summaries written in Python. These scripts use lldb public API to \
|
||||
gather information from your variables and produce a meaningful summary. To start a \
|
||||
multi-line script use the -P option. The function declaration will be displayed along with \
|
||||
a comment describing the two arguments. End your script with the word 'DONE' on a line by \
|
||||
itself:" R"(
|
||||
|
||||
(lldb) type summary add JustADemo -P
|
||||
def function (valobj,internal_dict):
|
||||
"""valobj: an SBValue which you want to provide a summary for
|
||||
internal_dict: an LLDB support object not to be used"""
|
||||
value = valobj.GetChildMemberWithName('value');
|
||||
return 'My value is ' + value.GetValue();
|
||||
DONE
|
||||
|
||||
Alternatively, the -o option can be used when providing a simple one-line Python script:
|
||||
|
||||
(lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")"
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4117,30 +4142,36 @@ public:
|
|||
m_arguments.push_back (type_arg);
|
||||
|
||||
SetHelpLong(
|
||||
"Some examples of using this command.\n"
|
||||
"We use as reference the following snippet of code:\n"
|
||||
"\n"
|
||||
"class Foo {;\n"
|
||||
" int a;\n"
|
||||
" int b;\n"
|
||||
" int c;\n"
|
||||
" int d;\n"
|
||||
" int e;\n"
|
||||
" int f;\n"
|
||||
" int g;\n"
|
||||
" int h;\n"
|
||||
" int i;\n"
|
||||
"} \n"
|
||||
"Typing:\n"
|
||||
"type filter add --child a --child g Foo\n"
|
||||
"frame variable a_foo\n"
|
||||
"will produce an output where only a and g are displayed\n"
|
||||
"Other children of a_foo (b,c,d,e,f,h and i) are available by asking for them, as in:\n"
|
||||
"frame variable a_foo.b a_foo.c ... a_foo.i\n"
|
||||
"\n"
|
||||
"Use option --raw to frame variable prevails on the filter\n"
|
||||
"frame variable a_foo --raw\n"
|
||||
"shows all the children of a_foo (a thru i) as if no filter was defined\n"
|
||||
R"(
|
||||
The following examples of 'type filter add' refer to this code snippet for context:
|
||||
|
||||
class Foo {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
int d;
|
||||
int e;
|
||||
int f;
|
||||
int g;
|
||||
int h;
|
||||
int i;
|
||||
}
|
||||
Foo my_foo;
|
||||
|
||||
Adding a simple filter:
|
||||
|
||||
(lldb) type filter add --child a --child g Foo
|
||||
(lldb) frame variable my_foo
|
||||
|
||||
)" "Produces output where only a and g are displayed. Other children of my_foo \
|
||||
(b, c, d, e, f, h and i) are available by asking for them explicitly:" R"(
|
||||
|
||||
(lldb) frame variable my_foo.b my_foo.c my_foo.i
|
||||
|
||||
)" "The formatting option --raw on frame variable bypasses the filter, showing \
|
||||
all children of my_foo as if no filter was defined:" R"(
|
||||
|
||||
(lldb) frame variable my_foo --raw)"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -931,10 +931,14 @@ public:
|
|||
m_option_watchpoint ()
|
||||
{
|
||||
SetHelpLong(
|
||||
"Examples: \n\
|
||||
\n\
|
||||
watchpoint set variable -w read_write my_global_var \n\
|
||||
# Watch my_global_var for read/write access, with the region to watch corresponding to the byte size of the data type.\n");
|
||||
R"(
|
||||
Examples:
|
||||
|
||||
(lldb) watchpoint set variable -w read_write my_global_var
|
||||
|
||||
)" " Watches my_global_var for read/write access, with the region to watch \
|
||||
corresponding to the byte size of the data type."
|
||||
);
|
||||
|
||||
CommandArgumentEntry arg;
|
||||
CommandArgumentData var_name_arg;
|
||||
|
@ -1138,10 +1142,13 @@ public:
|
|||
m_option_watchpoint ()
|
||||
{
|
||||
SetHelpLong(
|
||||
"Examples: \n\
|
||||
\n\
|
||||
watchpoint set expression -w write -x 1 -- foo + 32\n\
|
||||
# Watch write access for the 1-byte region pointed to by the address 'foo + 32'.\n");
|
||||
R"(
|
||||
Examples:
|
||||
|
||||
(lldb) watchpoint set expression -w write -x 1 -- foo + 32
|
||||
|
||||
Watches write access for the 1-byte region pointed to by the address 'foo + 32')"
|
||||
);
|
||||
|
||||
CommandArgumentEntry arg;
|
||||
CommandArgumentData expression_arg;
|
||||
|
|
|
@ -48,121 +48,112 @@ public:
|
|||
m_options (interpreter)
|
||||
{
|
||||
SetHelpLong (
|
||||
"\nGeneral information about entering watchpoint commands \n\
|
||||
------------------------------------------------------ \n\
|
||||
\n\
|
||||
This command will cause you to be prompted to enter the command or set \n\
|
||||
of commands you wish to be executed when the specified watchpoint is \n\
|
||||
hit. You will be told to enter your command(s), and will see a '> ' \n\
|
||||
prompt. Because you can enter one or many commands to be executed when \n\
|
||||
a watchpoint is hit, you will continue to be prompted after each \n\
|
||||
new-line that you enter, until you enter the word 'DONE', which will \n\
|
||||
cause the commands you have entered to be stored with the watchpoint \n\
|
||||
and executed when the watchpoint is hit. \n\
|
||||
\n\
|
||||
Syntax checking is not necessarily done when watchpoint commands are \n\
|
||||
entered. An improperly written watchpoint command will attempt to get \n\
|
||||
executed when the watchpoint gets hit, and usually silently fail. If \n\
|
||||
your watchpoint command does not appear to be getting executed, go \n\
|
||||
back and check your syntax. \n\
|
||||
\n\
|
||||
\n\
|
||||
Special information about PYTHON watchpoint commands \n\
|
||||
---------------------------------------------------- \n\
|
||||
\n\
|
||||
You may enter either one line of Python or multiple lines of Python \n\
|
||||
(including defining whole functions, if desired). If you enter a \n\
|
||||
single line of Python, that will be passed to the Python interpreter \n\
|
||||
'as is' when the watchpoint gets hit. If you enter function \n\
|
||||
definitions, they will be passed to the Python interpreter as soon as \n\
|
||||
you finish entering the watchpoint command, and they can be called \n\
|
||||
later (don't forget to add calls to them, if you want them called when \n\
|
||||
the watchpoint is hit). If you enter multiple lines of Python that \n\
|
||||
are not function definitions, they will be collected into a new, \n\
|
||||
automatically generated Python function, and a call to the newly \n\
|
||||
generated function will be attached to the watchpoint. \n\
|
||||
\n\
|
||||
This auto-generated function is passed in two arguments: \n\
|
||||
\n\
|
||||
frame: an SBFrame object representing the frame which hit the watchpoint. \n\
|
||||
From the frame you can get back to the thread and process. \n\
|
||||
wp: the watchpoint that was hit. \n\
|
||||
\n\
|
||||
Important Note: Because loose Python code gets collected into functions, \n\
|
||||
if you want to access global variables in the 'loose' code, you need to \n\
|
||||
specify that they are global, using the 'global' keyword. Be sure to \n\
|
||||
use correct Python syntax, including indentation, when entering Python \n\
|
||||
watchpoint commands. \n\
|
||||
\n\
|
||||
As a third option, you can pass the name of an already existing Python function \n\
|
||||
and that function will be attached to the watchpoint. It will get passed the \n\
|
||||
frame and wp_loc arguments mentioned above. \n\
|
||||
\n\
|
||||
Example Python one-line watchpoint command: \n\
|
||||
\n\
|
||||
(lldb) watchpoint command add -s python 1 \n\
|
||||
Enter your Python command(s). Type 'DONE' to end. \n\
|
||||
> print \"Hit this watchpoint!\" \n\
|
||||
> DONE \n\
|
||||
\n\
|
||||
As a convenience, this also works for a short Python one-liner: \n\
|
||||
(lldb) watchpoint command add -s python 1 -o \"import time; print time.asctime()\" \n\
|
||||
(lldb) run \n\
|
||||
Launching '.../a.out' (x86_64) \n\
|
||||
(lldb) Fri Sep 10 12:17:45 2010 \n\
|
||||
Process 21778 Stopped \n\
|
||||
* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = watchpoint 1.1, queue = com.apple.main-thread \n\
|
||||
36 \n\
|
||||
37 int c(int val)\n\
|
||||
38 {\n\
|
||||
39 -> return val + 3;\n\
|
||||
40 }\n\
|
||||
41 \n\
|
||||
42 int main (int argc, char const *argv[])\n\
|
||||
(lldb) \n\
|
||||
\n\
|
||||
Example multiple line Python watchpoint command, using function definition: \n\
|
||||
\n\
|
||||
(lldb) watchpoint command add -s python 1 \n\
|
||||
Enter your Python command(s). Type 'DONE' to end. \n\
|
||||
> def watchpoint_output (wp_no): \n\
|
||||
> out_string = \"Hit watchpoint number \" + repr (wp_no) \n\
|
||||
> print out_string \n\
|
||||
> return True \n\
|
||||
> watchpoint_output (1) \n\
|
||||
> DONE \n\
|
||||
\n\
|
||||
\n\
|
||||
Example multiple line Python watchpoint command, using 'loose' Python: \n\
|
||||
\n\
|
||||
(lldb) watchpoint command add -s p 1 \n\
|
||||
Enter your Python command(s). Type 'DONE' to end. \n\
|
||||
> global wp_count \n\
|
||||
> wp_count = wp_count + 1 \n\
|
||||
> print \"Hit this watchpoint \" + repr(wp_count) + \" times!\" \n\
|
||||
> DONE \n\
|
||||
\n\
|
||||
In this case, since there is a reference to a global variable, \n\
|
||||
'wp_count', you will also need to make sure 'wp_count' exists and is \n\
|
||||
initialized: \n\
|
||||
\n\
|
||||
(lldb) script \n\
|
||||
>>> wp_count = 0 \n\
|
||||
>>> quit() \n\
|
||||
\n\
|
||||
(lldb) \n\
|
||||
\n\
|
||||
\n\
|
||||
Final Note: If you get a warning that no watchpoint command was generated, \n\
|
||||
but you did not get any syntax errors, you probably forgot to add a call \n\
|
||||
to your functions. \n\
|
||||
\n\
|
||||
Special information about debugger command watchpoint commands \n\
|
||||
-------------------------------------------------------------- \n\
|
||||
\n\
|
||||
You may enter any debugger command, exactly as you would at the \n\
|
||||
debugger prompt. You may enter as many debugger commands as you like, \n\
|
||||
but do NOT enter more than one command per line. \n" );
|
||||
R"(
|
||||
General information about entering watchpoint commands
|
||||
------------------------------------------------------
|
||||
|
||||
)" "This command will prompt for commands to be executed when the specified \
|
||||
watchpoint is hit. Each command is typed on its own line following the '> ' \
|
||||
prompt until 'DONE' is entered." R"(
|
||||
|
||||
)" "Syntactic errors may not be detected when initially entered, and many \
|
||||
malformed commands can silently fail when executed. If your watchpoint commands \
|
||||
do not appear to be executing, double-check the command syntax." R"(
|
||||
|
||||
)" "Note: You may enter any debugger command exactly as you would at the debugger \
|
||||
prompt. There is no limit to the number of commands supplied, but do NOT enter \
|
||||
more than one command per line." R"(
|
||||
|
||||
Special information about PYTHON watchpoint commands
|
||||
----------------------------------------------------
|
||||
|
||||
)" "You may enter either one or more lines of Python, including function \
|
||||
definitions or calls to functions that will have been imported by the time \
|
||||
the code executes. Single line watchpoint commands will be interpreted 'as is' \
|
||||
when the watchpoint is hit. Multiple lines of Python will be wrapped in a \
|
||||
generated function, and a call to the function will be attached to the watchpoint." R"(
|
||||
|
||||
This auto-generated function is passed in three arguments:
|
||||
|
||||
frame: an lldb.SBFrame object for the frame which hit the watchpoint.
|
||||
|
||||
wp: the watchpoint that was hit.
|
||||
|
||||
)" "When specifying a python function with the --python-function option, you need \
|
||||
to supply the function name prepended by the module name:" R"(
|
||||
|
||||
--python-function myutils.watchpoint_callback
|
||||
|
||||
The function itself must have the following prototype:
|
||||
|
||||
def watchpoint_callback(frame, wp):
|
||||
# Your code goes here
|
||||
|
||||
)" "The arguments are the same as the arguments passed to generated functions as \
|
||||
described above. Note that the global variable 'lldb.frame' will NOT be updated when \
|
||||
this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
|
||||
can get you to the thread via frame.GetThread(), the thread can get you to the \
|
||||
process via thread.GetProcess(), and the process can get you back to the target \
|
||||
via process.GetTarget()." R"(
|
||||
|
||||
)" "Important Note: As Python code gets collected into functions, access to global \
|
||||
variables requires explicit scoping using the 'global' keyword. Be sure to use correct \
|
||||
Python syntax, including indentation, when entering Python watchpoint commands." R"(
|
||||
|
||||
Example Python one-line watchpoint command:
|
||||
|
||||
(lldb) watchpoint command add -s python 1
|
||||
Enter your Python command(s). Type 'DONE' to end.
|
||||
> print "Hit this watchpoint!"
|
||||
> DONE
|
||||
|
||||
As a convenience, this also works for a short Python one-liner:
|
||||
|
||||
(lldb) watchpoint command add -s python 1 -o 'import time; print time.asctime()'
|
||||
(lldb) run
|
||||
Launching '.../a.out' (x86_64)
|
||||
(lldb) Fri Sep 10 12:17:45 2010
|
||||
Process 21778 Stopped
|
||||
* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = watchpoint 1.1, queue = com.apple.main-thread
|
||||
36
|
||||
37 int c(int val)
|
||||
38 {
|
||||
39 -> return val + 3;
|
||||
40 }
|
||||
41
|
||||
42 int main (int argc, char const *argv[])
|
||||
|
||||
Example multiple line Python watchpoint command, using function definition:
|
||||
|
||||
(lldb) watchpoint command add -s python 1
|
||||
Enter your Python command(s). Type 'DONE' to end.
|
||||
> def watchpoint_output (wp_no):
|
||||
> out_string = "Hit watchpoint number " + repr (wp_no)
|
||||
> print out_string
|
||||
> return True
|
||||
> watchpoint_output (1)
|
||||
> DONE
|
||||
|
||||
Example multiple line Python watchpoint command, using 'loose' Python:
|
||||
|
||||
(lldb) watchpoint command add -s p 1
|
||||
Enter your Python command(s). Type 'DONE' to end.
|
||||
> global wp_count
|
||||
> wp_count = wp_count + 1
|
||||
> print "Hit this watchpoint " + repr(wp_count) + " times!"
|
||||
> DONE
|
||||
|
||||
)" "In this case, since there is a reference to a global variable, \
|
||||
'wp_count', you will also need to make sure 'wp_count' exists and is \
|
||||
initialized:" R"(
|
||||
|
||||
(lldb) script
|
||||
>>> wp_count = 0
|
||||
>>> quit()
|
||||
|
||||
)" "Final Note: A warning that no watchpoint command was generated when there \
|
||||
are no syntax errors may indicate that a function was declared but never called."
|
||||
);
|
||||
|
||||
CommandArgumentEntry arg;
|
||||
CommandArgumentData wp_id_arg;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "lldb/Interpreter/CommandObject.h"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
@ -920,6 +921,27 @@ ExprPathHelpTextCallback()
|
|||
" meaning of array slicing (taking elements n thru m inside the array or pointed-to memory).";
|
||||
}
|
||||
|
||||
void
|
||||
CommandObject::FormatLongHelpText (Stream &output_strm, const char *long_help)
|
||||
{
|
||||
CommandInterpreter& interpreter = GetCommandInterpreter();
|
||||
std::stringstream lineStream (long_help);
|
||||
std::string line;
|
||||
while (std::getline (lineStream, line)) {
|
||||
if (line.empty()) {
|
||||
output_strm << "\n";
|
||||
continue;
|
||||
}
|
||||
size_t result = line.find_first_not_of (" \t");
|
||||
if (result == std::string::npos) {
|
||||
result = 0;
|
||||
}
|
||||
std::string whitespace_prefix = line.substr (0, result);
|
||||
std::string remainder = line.substr (result);
|
||||
interpreter.OutputFormattedHelpText(output_strm, whitespace_prefix.c_str(), remainder.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CommandObject::GenerateHelpText (CommandReturnObject &result)
|
||||
{
|
||||
|
@ -947,7 +969,7 @@ CommandObject::GenerateHelpText (Stream &output_strm)
|
|||
const char *long_help = GetHelpLong();
|
||||
if ((long_help != nullptr)
|
||||
&& (strlen (long_help) > 0))
|
||||
output_strm.Printf ("\n%s", long_help);
|
||||
FormatLongHelpText (output_strm, long_help);
|
||||
if (WantsRawCommandString() && !WantsCompletion())
|
||||
{
|
||||
// Emit the message about using ' -- ' between the end of the command options and the raw input
|
||||
|
@ -984,7 +1006,7 @@ CommandObject::GenerateHelpText (Stream &output_strm)
|
|||
const char *long_help = GetHelpLong();
|
||||
if ((long_help != nullptr)
|
||||
&& (strlen (long_help) > 0))
|
||||
output_strm.Printf ("%s", long_help);
|
||||
FormatLongHelpText (output_strm, long_help);
|
||||
else if (WantsRawCommandString())
|
||||
{
|
||||
std::string help_text (GetHelp());
|
||||
|
|
Loading…
Reference in New Issue