aboutsummaryrefslogtreecommitdiff
path: root/lldb
diff options
context:
space:
mode:
Diffstat (limited to 'lldb')
-rw-r--r--lldb/docs/resources/test.rst8
-rw-r--r--lldb/docs/testsuite/a-detailed-walkthrough.txt9
-rw-r--r--lldb/include/lldb/Interpreter/OptionValueSInt64.h4
-rw-r--r--lldb/include/lldb/Interpreter/OptionValueUInt64.h26
-rw-r--r--lldb/include/lldb/Interpreter/Options.h33
-rw-r--r--lldb/packages/Python/lldbsuite/test/README-TestSuite14
-rw-r--r--lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py47
-rw-r--r--lldb/source/Commands/CommandObjectBreakpoint.cpp37
-rw-r--r--lldb/source/Core/CoreProperties.td2
-rw-r--r--lldb/source/Core/Debugger.cpp6
-rw-r--r--lldb/source/Interpreter/OptionValueUInt64.cpp13
-rw-r--r--lldb/source/Interpreter/Options.cpp13
-rw-r--r--lldb/source/Target/Process.cpp11
-rw-r--r--lldb/test/API/commands/expression/call-throws/TestCallThatThrows.py2
-rw-r--r--lldb/test/API/commands/expression/dont_allow_jit/TestAllowJIT.py8
-rw-r--r--lldb/test/API/commands/settings/TestSettings.py15
-rw-r--r--lldb/test/API/commands/statistics/basic/TestStats.py34
-rw-r--r--lldb/test/API/commands/trace/TestTraceSave.py8
-rw-r--r--lldb/test/API/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py2
-rw-r--r--lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py12
-rw-r--r--lldb/test/API/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py20
-rw-r--r--lldb/test/API/functionalities/gdb_remote_client/TestJLink6Armv7RegisterDefinition.py2
-rw-r--r--lldb/test/API/functionalities/module_cache/simple_exe/TestModuleCacheSimple.py13
-rw-r--r--lldb/test/API/functionalities/progress_reporting/TestTrimmedProgressReporting.py3
-rw-r--r--lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py48
-rw-r--r--lldb/test/API/functionalities/thread/backtrace_limit/TestBacktraceLimit.py2
-rw-r--r--lldb/test/API/macosx/arm-corefile-regctx/TestArmMachoCorefileRegctx.py4
-rw-r--r--lldb/test/API/macosx/lc-note/addrable-bits/TestAddrableBitsCorefile.py2
-rw-r--r--lldb/test/API/macosx/lc-note/firmware-corefile/TestFirmwareCorefiles.py14
-rw-r--r--lldb/test/API/macosx/lc-note/kern-ver-str/TestKernVerStrLCNOTE.py2
-rw-r--r--lldb/test/API/macosx/lc-note/multiple-binary-corefile/TestMultipleBinaryCorefile.py2
-rw-r--r--lldb/test/API/macosx/queues/TestQueues.py3
-rw-r--r--lldb/test/API/macosx/safe-to-func-call/TestSafeFuncCalls.py3
-rw-r--r--lldb/test/API/python_api/interpreter/TestRunCommandInterpreterAPI.py28
-rw-r--r--lldb/test/API/tools/lldb-dap/databreakpoint/Makefile3
-rw-r--r--lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py131
-rw-r--r--lldb/test/API/tools/lldb-dap/databreakpoint/main.cpp17
-rw-r--r--lldb/tools/lldb-dap/CMakeLists.txt1
-rw-r--r--lldb/tools/lldb-dap/DAPForward.h2
-rw-r--r--lldb/tools/lldb-dap/Watchpoint.cpp48
-rw-r--r--lldb/tools/lldb-dap/Watchpoint.h34
-rw-r--r--lldb/tools/lldb-dap/lldb-dap.cpp341
-rw-r--r--lldb/unittests/Interpreter/CMakeLists.txt1
-rw-r--r--lldb/unittests/Interpreter/TestOptions.cpp29
-rw-r--r--lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp10
45 files changed, 853 insertions, 214 deletions
diff --git a/lldb/docs/resources/test.rst b/lldb/docs/resources/test.rst
index 5275786..2b0e901 100644
--- a/lldb/docs/resources/test.rst
+++ b/lldb/docs/resources/test.rst
@@ -17,8 +17,8 @@ The LLDB test suite consists of three different kinds of test:
the output.
* **API tests**: Integration tests that interact with the debugger through the
SB API. These are written in Python and use LLDB's ``dotest.py`` testing
- framework on top of Python's `unittest2
- <https://docs.python.org/2/library/unittest.html>`_.
+ framework on top of Python's `unittest
+ <https://docs.python.org/3/library/unittest.html>`_.
All three test suites use ``lit`` (`LLVM Integrated Tester
<https://llvm.org/docs/CommandGuide/lit.html>`_ ) as the test driver. The test
@@ -94,7 +94,7 @@ programs from source, run them, and debug the processes.
As mentioned before, ``dotest.py`` is LLDB's testing framework. The
implementation is located under ``lldb/packages/Python/lldbsuite``. We have
several extensions and custom test primitives on top of what's offered by
-`unittest2 <https://docs.python.org/2/library/unittest.html>`_. Those can be
+`unittest <https://docs.python.org/3/library/unittest.html>`_. Those can be
found in
`lldbtest.py <https://github.com/llvm/llvm-project/blob/main/lldb/packages/Python/lldbsuite/test/lldbtest.py>`_.
@@ -146,7 +146,7 @@ the test should be run or not.
::
- @expectedFailure(checking_function_name)
+ @skipTestIfFn(checking_function_name)
In addition to providing a lot more flexibility when it comes to writing the
test, the API test also allow for much more complex scenarios when it comes to
diff --git a/lldb/docs/testsuite/a-detailed-walkthrough.txt b/lldb/docs/testsuite/a-detailed-walkthrough.txt
index 57c9dbc..8a70437 100644
--- a/lldb/docs/testsuite/a-detailed-walkthrough.txt
+++ b/lldb/docs/testsuite/a-detailed-walkthrough.txt
@@ -58,16 +58,15 @@ display their output. For brevity, the '-t' output is not included here.
Notice the 'expected failures=1' message at the end of the run. This is because
of a bug currently in lldb such that setting target.process.output-path to
'stdout.txt' does not have any effect on the redirection of the standard output
-of the subsequent launched process. We are using unittest2 (a backport of new
-unittest features for Python 2.4-2.6) to decorate (mark) the particular test
-method as such:
+of the subsequent launched process. We are using unittest to decorate (mark)
+the particular test method as such:
- @unittest2.expectedFailure
+ @unittest.expectedFailure
# rdar://problem/8435794
# settings set target.process.output-path does not seem to work
def test_set_output_path(self):
-See http://pypi.python.org/pypi/unittest2 for more details.
+See http://docs.python.org/library/unittest.html for more details.
Now let's look inside the test method:
diff --git a/lldb/include/lldb/Interpreter/OptionValueSInt64.h b/lldb/include/lldb/Interpreter/OptionValueSInt64.h
index 5efae62..3cf41d3 100644
--- a/lldb/include/lldb/Interpreter/OptionValueSInt64.h
+++ b/lldb/include/lldb/Interpreter/OptionValueSInt64.h
@@ -86,8 +86,8 @@ public:
protected:
int64_t m_current_value = 0;
int64_t m_default_value = 0;
- int64_t m_min_value = INT64_MIN;
- int64_t m_max_value = INT64_MAX;
+ int64_t m_min_value = std::numeric_limits<int64_t>::min();
+ int64_t m_max_value = std::numeric_limits<int64_t>::max();
};
} // namespace lldb_private
diff --git a/lldb/include/lldb/Interpreter/OptionValueUInt64.h b/lldb/include/lldb/Interpreter/OptionValueUInt64.h
index 30c27bf..0707607 100644
--- a/lldb/include/lldb/Interpreter/OptionValueUInt64.h
+++ b/lldb/include/lldb/Interpreter/OptionValueUInt64.h
@@ -64,13 +64,35 @@ public:
uint64_t GetDefaultValue() const { return m_default_value; }
- void SetCurrentValue(uint64_t value) { m_current_value = value; }
+ bool SetCurrentValue(uint64_t value) {
+ if (value >= m_min_value && value <= m_max_value) {
+ m_current_value = value;
+ return true;
+ }
+ return false;
+ }
+
+ bool SetDefaultValue(uint64_t value) {
+ if (value >= m_min_value && value <= m_max_value) {
+ m_default_value = value;
+ return true;
+ }
+ return false;
+ }
+
+ void SetMinimumValue(int64_t v) { m_min_value = v; }
+
+ uint64_t GetMinimumValue() const { return m_min_value; }
+
+ void SetMaximumValue(int64_t v) { m_max_value = v; }
- void SetDefaultValue(uint64_t value) { m_default_value = value; }
+ uint64_t GetMaximumValue() const { return m_max_value; }
protected:
uint64_t m_current_value = 0;
uint64_t m_default_value = 0;
+ uint64_t m_min_value = std::numeric_limits<uint64_t>::min();
+ uint64_t m_max_value = std::numeric_limits<uint64_t>::max();
};
} // namespace lldb_private
diff --git a/lldb/include/lldb/Interpreter/Options.h b/lldb/include/lldb/Interpreter/Options.h
index bf74927..18a87e4 100644
--- a/lldb/include/lldb/Interpreter/Options.h
+++ b/lldb/include/lldb/Interpreter/Options.h
@@ -336,6 +336,39 @@ public:
bool m_did_finalize = false;
};
+/// Creates an error that represents the failure to parse an command line option
+/// argument. This creates an error containing all information needed to show
+/// the developer what went wrong when parsing their command. It is recommended
+/// to use this instead of writing an error by hand.
+///
+/// \param[in] option_arg
+/// The argument that was attempted to be parsed.
+///
+/// \param[in] short_option
+/// The short form of the option. For example, if the flag is -f, the short
+/// option is "f".
+///
+/// \param[in] long_option
+/// The long form of the option. This field is optional. If the flag is
+/// --force, then the long option is "force".
+///
+/// \param[in] additional_context
+/// This is extra context that will get included in the error. This field is
+/// optional.
+///
+/// \return
+/// An llvm::Error that contains a standardized format for what went wrong
+/// when parsing and why.
+llvm::Error CreateOptionParsingError(llvm::StringRef option_arg,
+ const char short_option,
+ llvm::StringRef long_option = {},
+ llvm::StringRef additional_context = {});
+
+static constexpr llvm::StringLiteral g_bool_parsing_error_message =
+ "Failed to parse as boolean";
+static constexpr llvm::StringLiteral g_int_parsing_error_message =
+ "Failed to parse as integer";
+
} // namespace lldb_private
#endif // LLDB_INTERPRETER_OPTIONS_H
diff --git a/lldb/packages/Python/lldbsuite/test/README-TestSuite b/lldb/packages/Python/lldbsuite/test/README-TestSuite
index f76e836..388f94d 100644
--- a/lldb/packages/Python/lldbsuite/test/README-TestSuite
+++ b/lldb/packages/Python/lldbsuite/test/README-TestSuite
@@ -91,20 +91,6 @@ to the Python test suite under the current 'test' directory.
Contains platform specific plugin to build binaries with dsym/dwarf debugging
info. Other platform specific functionalities may be added in the future.
-- unittest2 directory
-
- Many new features were added to unittest in Python 2.7, including test
- discovery. unittest2 allows you to use these features with earlier versions of
- Python.
-
- It currently has unittest2 0.5.1 from http://pypi.python.org/pypi/unittest2.
- Version 0.5.1 of unittest2 has feature parity with unittest in Python 2.7
- final. If you want to ensure that your tests run identically under unittest2
- and unittest in Python 2.7 you should use unittest2 0.5.1.
-
- Later versions of unittest2 include changes in unittest made in Python 3.2 and
- onwards after the release of Python 2.7.
-
- Profiling dotest.py runs
I used the following command line thingy to do the profiling on a SnowLeopard
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
index bb863bb..27a76a6 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
@@ -501,6 +501,18 @@ class DebugCommunication(object):
return variable["value"]
return None
+ def get_local_variable_child(self, name, child_name, frameIndex=0, threadId=None):
+ local = self.get_local_variable(name, frameIndex, threadId)
+ if local["variablesReference"] == 0:
+ return None
+ children = self.request_variables(local["variablesReference"])["body"][
+ "variables"
+ ]
+ for child in children:
+ if child["name"] == child_name:
+ return child
+ return None
+
def replay_packets(self, replay_file_path):
f = open(replay_file_path, "r")
mode = "invalid"
@@ -895,6 +907,41 @@ class DebugCommunication(object):
}
return self.send_recv(command_dict)
+ def request_dataBreakpointInfo(
+ self, variablesReference, name, frameIndex=0, threadId=None
+ ):
+ stackFrame = self.get_stackFrame(frameIndex=frameIndex, threadId=threadId)
+ if stackFrame is None:
+ return []
+ args_dict = {
+ "variablesReference": variablesReference,
+ "name": name,
+ "frameId": stackFrame["id"],
+ }
+ command_dict = {
+ "command": "dataBreakpointInfo",
+ "type": "request",
+ "arguments": args_dict,
+ }
+ return self.send_recv(command_dict)
+
+ def request_setDataBreakpoint(self, dataBreakpoints):
+ """dataBreakpoints is a list of dictionary with following fields:
+ {
+ dataId: (address in hex)/(size in bytes)
+ accessType: read/write/readWrite
+ [condition]: string
+ [hitCondition]: string
+ }
+ """
+ args_dict = {"breakpoints": dataBreakpoints}
+ command_dict = {
+ "command": "setDataBreakpoints",
+ "type": "request",
+ "arguments": args_dict,
+ }
+ return self.send_recv(command_dict)
+
def request_compileUnits(self, moduleId):
args_dict = {"moduleId": moduleId}
command_dict = {
diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp
index 3fdf5cd..fc22176 100644
--- a/lldb/source/Commands/CommandObjectBreakpoint.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp
@@ -64,6 +64,8 @@ public:
Status error;
const int short_option =
g_breakpoint_modify_options[option_idx].short_option;
+ const char *long_option =
+ g_breakpoint_modify_options[option_idx].long_option;
switch (short_option) {
case 'c':
@@ -84,18 +86,17 @@ public:
case 'G': {
bool value, success;
value = OptionArgParser::ToBoolean(option_arg, false, &success);
- if (success) {
+ if (success)
m_bp_opts.SetAutoContinue(value);
- } else
- error.SetErrorStringWithFormat(
- "invalid boolean value '%s' passed for -G option",
- option_arg.str().c_str());
+ else
+ error = CreateOptionParsingError(option_arg, short_option, long_option,
+ g_bool_parsing_error_message);
} break;
case 'i': {
uint32_t ignore_count;
if (option_arg.getAsInteger(0, ignore_count))
- error.SetErrorStringWithFormat("invalid ignore count '%s'",
- option_arg.str().c_str());
+ error = CreateOptionParsingError(option_arg, short_option, long_option,
+ g_int_parsing_error_message);
else
m_bp_opts.SetIgnoreCount(ignore_count);
} break;
@@ -105,27 +106,29 @@ public:
if (success) {
m_bp_opts.SetOneShot(value);
} else
- error.SetErrorStringWithFormat(
- "invalid boolean value '%s' passed for -o option",
- option_arg.str().c_str());
+ error = CreateOptionParsingError(option_arg, short_option, long_option,
+ g_bool_parsing_error_message);
} break;
case 't': {
lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
if (option_arg == "current") {
if (!execution_context) {
- error.SetErrorStringWithFormat("No context to determine current "
- "thread");
+ error = CreateOptionParsingError(
+ option_arg, short_option, long_option,
+ "No context to determine current thread");
} else {
ThreadSP ctx_thread_sp = execution_context->GetThreadSP();
if (!ctx_thread_sp || !ctx_thread_sp->IsValid()) {
- error.SetErrorStringWithFormat("No currently selected thread");
+ error =
+ CreateOptionParsingError(option_arg, short_option, long_option,
+ "No currently selected thread");
} else {
thread_id = ctx_thread_sp->GetID();
}
}
} else if (option_arg.getAsInteger(0, thread_id)) {
- error.SetErrorStringWithFormat("invalid thread id string '%s'",
- option_arg.str().c_str());
+ error = CreateOptionParsingError(option_arg, short_option, long_option,
+ g_int_parsing_error_message);
}
if (thread_id != LLDB_INVALID_THREAD_ID)
m_bp_opts.SetThreadID(thread_id);
@@ -139,8 +142,8 @@ public:
case 'x': {
uint32_t thread_index = UINT32_MAX;
if (option_arg.getAsInteger(0, thread_index)) {
- error.SetErrorStringWithFormat("invalid thread index string '%s'",
- option_arg.str().c_str());
+ error = CreateOptionParsingError(option_arg, short_option, long_option,
+ g_int_parsing_error_message);
} else {
m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
}
diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td
index 4cfff80..a6cb951 100644
--- a/lldb/source/Core/CoreProperties.td
+++ b/lldb/source/Core/CoreProperties.td
@@ -132,7 +132,7 @@ let Definition = "debugger" in {
Global,
DefaultStringValue<"${ansi.normal}">,
Desc<"When displaying the line marker in a color-enabled terminal, use the ANSI terminal code specified in this format immediately after the line to be marked.">;
- def TerminalWidth: Property<"term-width", "SInt64">,
+ def TerminalWidth: Property<"term-width", "UInt64">,
Global,
DefaultUnsignedValue<80>,
Desc<"The maximum number of columns to use for displaying text.">;
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 97311b4..c3e603d 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -365,7 +365,7 @@ bool Debugger::SetREPLLanguage(lldb::LanguageType repl_lang) {
uint64_t Debugger::GetTerminalWidth() const {
const uint32_t idx = ePropertyTerminalWidth;
- return GetPropertyAtIndexAs<int64_t>(
+ return GetPropertyAtIndexAs<uint64_t>(
idx, g_debugger_properties[idx].default_uint_value);
}
@@ -886,8 +886,8 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
}
assert(m_dummy_target_sp.get() && "Couldn't construct dummy target?");
- OptionValueSInt64 *term_width =
- m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64(
+ OptionValueUInt64 *term_width =
+ m_collection_sp->GetPropertyAtIndexAsOptionValueUInt64(
ePropertyTerminalWidth);
term_width->SetMinimumValue(10);
term_width->SetMaximumValue(1024);
diff --git a/lldb/source/Interpreter/OptionValueUInt64.cpp b/lldb/source/Interpreter/OptionValueUInt64.cpp
index 1999c63..2e69c16 100644
--- a/lldb/source/Interpreter/OptionValueUInt64.cpp
+++ b/lldb/source/Interpreter/OptionValueUInt64.cpp
@@ -47,9 +47,16 @@ Status OptionValueUInt64::SetValueFromString(llvm::StringRef value_ref,
llvm::StringRef value_trimmed = value_ref.trim();
uint64_t value;
if (llvm::to_integer(value_trimmed, value)) {
- m_value_was_set = true;
- m_current_value = value;
- NotifyValueChanged();
+ if (value >= m_min_value && value <= m_max_value) {
+ m_value_was_set = true;
+ m_current_value = value;
+ NotifyValueChanged();
+ } else {
+ error.SetErrorStringWithFormat(
+ "%" PRIu64 " is out of range, valid values must be between %" PRIu64
+ " and %" PRIu64 ".",
+ value, m_min_value, m_max_value);
+ }
} else {
error.SetErrorStringWithFormat("invalid uint64_t string value: '%s'",
value_ref.str().c_str());
diff --git a/lldb/source/Interpreter/Options.cpp b/lldb/source/Interpreter/Options.cpp
index 89fe690..51b7e6b 100644
--- a/lldb/source/Interpreter/Options.cpp
+++ b/lldb/source/Interpreter/Options.cpp
@@ -1365,3 +1365,16 @@ llvm::Expected<Args> Options::Parse(const Args &args,
argv.erase(argv.begin(), argv.begin() + OptionParser::GetOptionIndex());
return ReconstituteArgsAfterParsing(argv, args);
}
+
+llvm::Error lldb_private::CreateOptionParsingError(
+ llvm::StringRef option_arg, const char short_option,
+ llvm::StringRef long_option, llvm::StringRef additional_context) {
+ std::string buffer;
+ llvm::raw_string_ostream stream(buffer);
+ stream << "Invalid value ('" << option_arg << "') for -" << short_option;
+ if (!long_option.empty())
+ stream << " (" << long_option << ")";
+ if (!additional_context.empty())
+ stream << ": " << additional_context;
+ return llvm::createStringError(llvm::inconvertibleErrorCode(), buffer);
+}
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 23a8a66..137795c 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -2937,14 +2937,11 @@ void Process::CompleteAttach() {
DidAttach(process_arch);
if (process_arch.IsValid()) {
+ LLDB_LOG(log,
+ "Process::{0} replacing process architecture with DidAttach() "
+ "architecture: \"{1}\"",
+ __FUNCTION__, process_arch.GetTriple().getTriple());
GetTarget().SetArchitecture(process_arch);
- if (log) {
- const char *triple_str = process_arch.GetTriple().getTriple().c_str();
- LLDB_LOGF(log,
- "Process::%s replacing process architecture with DidAttach() "
- "architecture: %s",
- __FUNCTION__, triple_str ? triple_str : "<null>");
- }
}
// We just attached. If we have a platform, ask it for the process
diff --git a/lldb/test/API/commands/expression/call-throws/TestCallThatThrows.py b/lldb/test/API/commands/expression/call-throws/TestCallThatThrows.py
index 2868ec5..b8cc87c 100644
--- a/lldb/test/API/commands/expression/call-throws/TestCallThatThrows.py
+++ b/lldb/test/API/commands/expression/call-throws/TestCallThatThrows.py
@@ -46,7 +46,7 @@ class ExprCommandWithThrowTestCase(TestBase):
value = frame.EvaluateExpression("[my_class callMeIThrow]", options)
self.assertTrue(value.IsValid())
- self.assertEqual(value.GetError().Success(), False)
+ self.assertFalse(value.GetError().Success())
self.check_after_call()
diff --git a/lldb/test/API/commands/expression/dont_allow_jit/TestAllowJIT.py b/lldb/test/API/commands/expression/dont_allow_jit/TestAllowJIT.py
index 307d452..eb812f1 100644
--- a/lldb/test/API/commands/expression/dont_allow_jit/TestAllowJIT.py
+++ b/lldb/test/API/commands/expression/dont_allow_jit/TestAllowJIT.py
@@ -54,7 +54,7 @@ class TestAllowJIT(TestBase):
# First make sure we can call the function with the default option set.
options = lldb.SBExpressionOptions()
# Check that the default is to allow JIT:
- self.assertEqual(options.GetAllowJIT(), True, "Default is true")
+ self.assertTrue(options.GetAllowJIT(), "Default is true")
# Now use the options:
result = frame.EvaluateExpression("call_me(10)", options)
@@ -64,9 +64,7 @@ class TestAllowJIT(TestBase):
# Now disallow JIT and make sure it fails:
options.SetAllowJIT(False)
# Check that we got the right value:
- self.assertEqual(
- options.GetAllowJIT(), False, "Got False after setting to False"
- )
+ self.assertFalse(options.GetAllowJIT(), "Got False after setting to False")
# Again use it and ensure we fail:
result = frame.EvaluateExpression("call_me(10)", options)
@@ -79,7 +77,7 @@ class TestAllowJIT(TestBase):
# Finally set the allow JIT value back to true and make sure that works:
options.SetAllowJIT(True)
- self.assertEqual(options.GetAllowJIT(), True, "Set back to True correctly")
+ self.assertTrue(options.GetAllowJIT(), "Set back to True correctly")
# And again, make sure this works:
result = frame.EvaluateExpression("call_me(10)", options)
diff --git a/lldb/test/API/commands/settings/TestSettings.py b/lldb/test/API/commands/settings/TestSettings.py
index a2d8454..104a9f0 100644
--- a/lldb/test/API/commands/settings/TestSettings.py
+++ b/lldb/test/API/commands/settings/TestSettings.py
@@ -2,7 +2,6 @@
Test lldb settings command.
"""
-
import json
import os
import re
@@ -151,14 +150,22 @@ class SettingsCommandTestCase(TestBase):
self.expect(
"settings show term-width",
SETTING_MSG("term-width"),
- startstr="term-width (int) = 70",
+ startstr="term-width (unsigned) = 70",
)
# The overall display should also reflect the new setting.
self.expect(
"settings show",
SETTING_MSG("term-width"),
- substrs=["term-width (int) = 70"],
+ substrs=["term-width (unsigned) = 70"],
+ )
+
+ self.dbg.SetTerminalWidth(60)
+
+ self.expect(
+ "settings show",
+ SETTING_MSG("term-width"),
+ substrs=["term-width (unsigned) = 60"],
)
# rdar://problem/10712130
@@ -593,7 +600,7 @@ class SettingsCommandTestCase(TestBase):
self.expect(
"settings show term-width",
SETTING_MSG("term-width"),
- startstr="term-width (int) = 60",
+ startstr="term-width (unsigned) = 60",
)
self.runCmd("settings clear term-width", check=False)
# string
diff --git a/lldb/test/API/commands/statistics/basic/TestStats.py b/lldb/test/API/commands/statistics/basic/TestStats.py
index 6f08322..fb6fc07 100644
--- a/lldb/test/API/commands/statistics/basic/TestStats.py
+++ b/lldb/test/API/commands/statistics/basic/TestStats.py
@@ -35,17 +35,13 @@ class TestCase(TestBase):
)
def verify_key_in_dict(self, key, d, description):
- self.assertEqual(
- key in d,
- True,
- 'make sure key "%s" is in dictionary %s' % (key, description),
+ self.assertIn(
+ key, d, 'make sure key "%s" is in dictionary %s' % (key, description)
)
def verify_key_not_in_dict(self, key, d, description):
- self.assertEqual(
- key in d,
- False,
- 'make sure key "%s" is in dictionary %s' % (key, description),
+ self.assertNotIn(
+ key, d, 'make sure key "%s" is in dictionary %s' % (key, description)
)
def verify_keys(self, dict, description, keys_exist, keys_missing=None):
@@ -120,9 +116,7 @@ class TestCase(TestBase):
self.verify_success_fail_count(stats, "frameVariable", 1, 0)
# Test that "stopCount" is available when the process has run
- self.assertEqual(
- "stopCount" in stats, True, 'ensure "stopCount" is in target JSON'
- )
+ self.assertIn("stopCount", stats, 'ensure "stopCount" is in target JSON')
self.assertGreater(
stats["stopCount"], 0, 'make sure "stopCount" is greater than zero'
)
@@ -484,9 +478,9 @@ class TestCase(TestBase):
exe = self.getBuildArtifact(exe_name)
dsym = self.getBuildArtifact(exe_name + ".dSYM")
# Make sure the executable file exists after building.
- self.assertEqual(os.path.exists(exe), True)
+ self.assertTrue(os.path.exists(exe))
# Make sure the dSYM file exists after building.
- self.assertEqual(os.path.isdir(dsym), True)
+ self.assertTrue(os.path.isdir(dsym))
# Create the target
target = self.createTestTarget(file_path=exe)
@@ -532,9 +526,9 @@ class TestCase(TestBase):
exe = self.getBuildArtifact(exe_name)
dsym = self.getBuildArtifact(exe_name + ".dSYM")
# Make sure the executable file exists after building.
- self.assertEqual(os.path.exists(exe), True)
+ self.assertTrue(os.path.exists(exe))
# Make sure the dSYM file doesn't exist after building.
- self.assertEqual(os.path.isdir(dsym), False)
+ self.assertFalse(os.path.isdir(dsym))
# Create the target
target = self.createTestTarget(file_path=exe)
@@ -585,11 +579,11 @@ class TestCase(TestBase):
dsym = self.getBuildArtifact(exe_name + ".dSYM")
main_obj = self.getBuildArtifact("main.o")
# Make sure the executable file exists after building.
- self.assertEqual(os.path.exists(exe), True)
+ self.assertTrue(os.path.exists(exe))
# Make sure the dSYM file doesn't exist after building.
- self.assertEqual(os.path.isdir(dsym), False)
+ self.assertFalse(os.path.isdir(dsym))
# Make sure the main.o object file exists after building.
- self.assertEqual(os.path.exists(main_obj), True)
+ self.assertTrue(os.path.exists(main_obj))
# Delete the main.o file that contains the debug info so we force an
# error when we run to main and try to get variables
@@ -604,7 +598,7 @@ class TestCase(TestBase):
# Make sure we have "debugInfoHadVariableErrors" variable that is set to
# false before failing to get local variables due to missing .o file.
- self.assertEqual(exe_stats["debugInfoHadVariableErrors"], False)
+ self.assertFalse(exe_stats["debugInfoHadVariableErrors"])
# Verify that the top level statistic that aggregates the number of
# modules with debugInfoHadVariableErrors is zero
@@ -624,7 +618,7 @@ class TestCase(TestBase):
# Make sure we have "hadFrameVariableErrors" variable that is set to
# true after failing to get local variables due to missing .o file.
- self.assertEqual(exe_stats["debugInfoHadVariableErrors"], True)
+ self.assertTrue(exe_stats["debugInfoHadVariableErrors"])
# Verify that the top level statistic that aggregates the number of
# modules with debugInfoHadVariableErrors is greater than zero
diff --git a/lldb/test/API/commands/trace/TestTraceSave.py b/lldb/test/API/commands/trace/TestTraceSave.py
index ef1ab2f..af38669 100644
--- a/lldb/test/API/commands/trace/TestTraceSave.py
+++ b/lldb/test/API/commands/trace/TestTraceSave.py
@@ -179,11 +179,11 @@ class TestTraceSave(TraceIntelPTTestCaseBase):
res = lldb.SBCommandReturnObject()
ci.HandleCommand("thread trace dump instructions -c 10 --forwards", res)
- self.assertEqual(res.Succeeded(), True)
+ self.assertTrue(res.Succeeded())
first_ten_instructions = res.GetOutput()
ci.HandleCommand("thread trace dump instructions -c 10", res)
- self.assertEqual(res.Succeeded(), True)
+ self.assertTrue(res.Succeeded())
last_ten_instructions = res.GetOutput()
# Now, save the trace to <trace_copy_dir>
@@ -203,11 +203,11 @@ class TestTraceSave(TraceIntelPTTestCaseBase):
# Compare with instructions saved at the first time
ci.HandleCommand("thread trace dump instructions -c 10 --forwards", res)
- self.assertEqual(res.Succeeded(), True)
+ self.assertTrue(res.Succeeded())
self.assertEqual(res.GetOutput(), first_ten_instructions)
ci.HandleCommand("thread trace dump instructions -c 10", res)
- self.assertEqual(res.Succeeded(), True)
+ self.assertTrue(res.Succeeded())
self.assertEqual(res.GetOutput(), last_ten_instructions)
def testSaveKernelTrace(self):
diff --git a/lldb/test/API/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py b/lldb/test/API/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py
index 0ab11a4..d120692 100644
--- a/lldb/test/API/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py
+++ b/lldb/test/API/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py
@@ -40,7 +40,7 @@ class BadAddressBreakpointTestCase(TestBase):
bkpt = target.BreakpointCreateByAddress(illegal_address)
# Verify that breakpoint is not resolved.
for bp_loc in bkpt:
- self.assertEqual(bp_loc.IsResolved(), False)
+ self.assertFalse(bp_loc.IsResolved())
else:
self.fail(
"Could not find an illegal address at which to set a bad breakpoint."
diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py b/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
index 620f648..ea24295 100644
--- a/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
+++ b/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
@@ -572,9 +572,9 @@ class BreakpointCommandTestCase(TestBase):
res = target.GetStatistics().GetAsJSON(stream)
self.assertTrue(res.Success())
debug_stats = json.loads(stream.GetData())
- self.assertEqual(
- "targets" in debug_stats,
- True,
+ self.assertIn(
+ "targets",
+ debug_stats,
'Make sure the "targets" key in in target.GetStatistics()',
)
target_stats = debug_stats["targets"][0]
@@ -659,9 +659,9 @@ class BreakpointCommandTestCase(TestBase):
res = target.GetStatistics().GetAsJSON(stream)
self.assertTrue(res.Success())
debug_stats = json.loads(stream.GetData())
- self.assertEqual(
- "targets" in debug_stats,
- True,
+ self.assertIn(
+ "targets",
+ debug_stats,
'Make sure the "targets" key in in target.GetStatistics()',
)
target_stats = debug_stats["targets"][0]
diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py b/lldb/test/API/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py
index 330f916..0f9510c 100644
--- a/lldb/test/API/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py
+++ b/lldb/test/API/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py
@@ -389,7 +389,7 @@ class BreakpointNames(TestBase):
)
def check_permission_results(self, bp_name):
- self.assertEqual(bp_name.GetAllowDelete(), False, "Didn't set allow delete.")
+ self.assertFalse(bp_name.GetAllowDelete(), "Didn't set allow delete.")
protected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)
protected_id = protected_bkpt.GetID()
@@ -402,14 +402,11 @@ class BreakpointNames(TestBase):
self.assertSuccess(success, "Couldn't add this name to the breakpoint")
self.target.DisableAllBreakpoints()
- self.assertEqual(
- protected_bkpt.IsEnabled(),
- True,
- "Didnt' keep breakpoint from being disabled",
+ self.assertTrue(
+ protected_bkpt.IsEnabled(), "Didnt' keep breakpoint from being disabled"
)
- self.assertEqual(
+ self.assertFalse(
unprotected_bkpt.IsEnabled(),
- False,
"Protected too many breakpoints from disabling.",
)
@@ -418,14 +415,11 @@ class BreakpointNames(TestBase):
result = lldb.SBCommandReturnObject()
self.dbg.GetCommandInterpreter().HandleCommand("break disable", result)
self.assertTrue(result.Succeeded())
- self.assertEqual(
- protected_bkpt.IsEnabled(),
- True,
- "Didnt' keep breakpoint from being disabled",
+ self.assertTrue(
+ protected_bkpt.IsEnabled(), "Didnt' keep breakpoint from being disabled"
)
- self.assertEqual(
+ self.assertFalse(
unprotected_bkpt.IsEnabled(),
- False,
"Protected too many breakpoints from disabling.",
)
diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestJLink6Armv7RegisterDefinition.py b/lldb/test/API/functionalities/gdb_remote_client/TestJLink6Armv7RegisterDefinition.py
index eb7c036..3a42662 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/TestJLink6Armv7RegisterDefinition.py
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestJLink6Armv7RegisterDefinition.py
@@ -198,7 +198,7 @@ class TestJLink6Armv7RegisterDefinition(GDBRemoteTestBase):
error = lldb.SBError()
data = lldb.SBData()
data.SetData(error, val, lldb.eByteOrderBig, 4)
- self.assertEqual(r1_valobj.SetData(data, error), True)
+ self.assertTrue(r1_valobj.SetData(data, error))
self.assertSuccess(error)
r1_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex(0).FindRegister("r1")
diff --git a/lldb/test/API/functionalities/module_cache/simple_exe/TestModuleCacheSimple.py b/lldb/test/API/functionalities/module_cache/simple_exe/TestModuleCacheSimple.py
index 4214bd1..abf4cf3 100644
--- a/lldb/test/API/functionalities/module_cache/simple_exe/TestModuleCacheSimple.py
+++ b/lldb/test/API/functionalities/module_cache/simple_exe/TestModuleCacheSimple.py
@@ -66,18 +66,16 @@ class ModuleCacheTestcaseSimple(TestBase):
# get a different creation and modification time for the file since some
# OSs store the modification time in seconds since Jan 1, 1970.
os.remove(exe)
- self.assertEqual(
- os.path.exists(exe),
- False,
- "make sure we were able to remove the executable",
+ self.assertFalse(
+ os.path.exists(exe), "make sure we were able to remove the executable"
)
time.sleep(2)
# Now rebuild the binary so it has a different content which should
# update the UUID to make the cache miss when it tries to load the
# symbol table from the binary at the same path.
self.build(dictionary={"CFLAGS_EXTRAS": "-DEXTRA_FUNCTION"})
- self.assertEqual(
- os.path.exists(exe), True, "make sure executable exists after rebuild"
+ self.assertTrue(
+ os.path.exists(exe), "make sure executable exists after rebuild"
)
# Make sure the modification time has changed or this test will fail.
exe_mtime_2 = os.path.getmtime(exe)
@@ -99,9 +97,8 @@ class ModuleCacheTestcaseSimple(TestBase):
main_module = target.GetModuleAtIndex(0)
self.assertTrue(main_module.IsValid())
main_module.GetNumSymbols()
- self.assertEqual(
+ self.assertTrue(
os.path.exists(symtab_cache_path),
- True,
'make sure "symtab" cache files exists after cache is updated',
)
symtab_mtime_2 = os.path.getmtime(symtab_cache_path)
diff --git a/lldb/test/API/functionalities/progress_reporting/TestTrimmedProgressReporting.py b/lldb/test/API/functionalities/progress_reporting/TestTrimmedProgressReporting.py
index 357999b..ee35dbd 100644
--- a/lldb/test/API/functionalities/progress_reporting/TestTrimmedProgressReporting.py
+++ b/lldb/test/API/functionalities/progress_reporting/TestTrimmedProgressReporting.py
@@ -24,7 +24,8 @@ class TestTrimmedProgressReporting(PExpectTest):
)
self.expect("set set term-width " + str(term_width))
self.expect(
- "set show term-width", substrs=["term-width (int) = " + str(term_width)]
+ "set show term-width",
+ substrs=["term-width (unsigned) = " + str(term_width)],
)
self.child.send("file " + self.getBuildArtifact("a.out") + "\n")
diff --git a/lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py b/lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py
index eee91bf..851097b 100644
--- a/lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py
+++ b/lldb/test/API/functionalities/stats_api/TestStatisticsAPI.py
@@ -33,47 +33,47 @@ class TestStatsAPI(TestBase):
stream = lldb.SBStream()
res = stats.GetAsJSON(stream)
debug_stats = json.loads(stream.GetData())
- self.assertEqual(
- "targets" in debug_stats,
- True,
+ self.assertIn(
+ "targets",
+ debug_stats,
'Make sure the "targets" key in in target.GetStatistics()',
)
- self.assertEqual(
- "modules" in debug_stats,
- True,
+ self.assertIn(
+ "modules",
+ debug_stats,
'Make sure the "modules" key in in target.GetStatistics()',
)
stats_json = debug_stats["targets"][0]
- self.assertEqual(
- "expressionEvaluation" in stats_json,
- True,
+ self.assertIn(
+ "expressionEvaluation",
+ stats_json,
'Make sure the "expressionEvaluation" key in in target.GetStatistics()["targets"][0]',
)
- self.assertEqual(
- "frameVariable" in stats_json,
- True,
+ self.assertIn(
+ "frameVariable",
+ stats_json,
'Make sure the "frameVariable" key in in target.GetStatistics()["targets"][0]',
)
expressionEvaluation = stats_json["expressionEvaluation"]
- self.assertEqual(
- "successes" in expressionEvaluation,
- True,
+ self.assertIn(
+ "successes",
+ expressionEvaluation,
'Make sure the "successes" key in in "expressionEvaluation" dictionary"',
)
- self.assertEqual(
- "failures" in expressionEvaluation,
- True,
+ self.assertIn(
+ "failures",
+ expressionEvaluation,
'Make sure the "failures" key in in "expressionEvaluation" dictionary"',
)
frameVariable = stats_json["frameVariable"]
- self.assertEqual(
- "successes" in frameVariable,
- True,
+ self.assertIn(
+ "successes",
+ frameVariable,
'Make sure the "successes" key in in "frameVariable" dictionary"',
)
- self.assertEqual(
- "failures" in frameVariable,
- True,
+ self.assertIn(
+ "failures",
+ frameVariable,
'Make sure the "failures" key in in "frameVariable" dictionary"',
)
diff --git a/lldb/test/API/functionalities/thread/backtrace_limit/TestBacktraceLimit.py b/lldb/test/API/functionalities/thread/backtrace_limit/TestBacktraceLimit.py
index 98baea4..fded504 100644
--- a/lldb/test/API/functionalities/thread/backtrace_limit/TestBacktraceLimit.py
+++ b/lldb/test/API/functionalities/thread/backtrace_limit/TestBacktraceLimit.py
@@ -23,5 +23,5 @@ class BacktraceLimitSettingTest(TestBase):
interp.HandleCommand(
"settings set target.process.thread.max-backtrace-depth 30", result
)
- self.assertEqual(True, result.Succeeded())
+ self.assertTrue(result.Succeeded())
self.assertEqual(30, thread.GetNumFrames())
diff --git a/lldb/test/API/macosx/arm-corefile-regctx/TestArmMachoCorefileRegctx.py b/lldb/test/API/macosx/arm-corefile-regctx/TestArmMachoCorefileRegctx.py
index 1ecb0f4..4190ea3 100644
--- a/lldb/test/API/macosx/arm-corefile-regctx/TestArmMachoCorefileRegctx.py
+++ b/lldb/test/API/macosx/arm-corefile-regctx/TestArmMachoCorefileRegctx.py
@@ -28,7 +28,7 @@ class TestArmMachoCorefileRegctx(TestBase):
target = self.dbg.CreateTarget("")
err = lldb.SBError()
process = target.LoadCore(self.corefile)
- self.assertEqual(process.IsValid(), True)
+ self.assertTrue(process.IsValid())
thread = process.GetSelectedThread()
frame = thread.GetSelectedFrame()
@@ -51,7 +51,7 @@ class TestArmMachoCorefileRegctx(TestBase):
target = self.dbg.CreateTarget("")
err = lldb.SBError()
process = target.LoadCore(self.corefile)
- self.assertEqual(process.IsValid(), True)
+ self.assertTrue(process.IsValid())
thread = process.GetSelectedThread()
frame = thread.GetSelectedFrame()
diff --git a/lldb/test/API/macosx/lc-note/addrable-bits/TestAddrableBitsCorefile.py b/lldb/test/API/macosx/lc-note/addrable-bits/TestAddrableBitsCorefile.py
index 221fe62..e56ecfc 100644
--- a/lldb/test/API/macosx/lc-note/addrable-bits/TestAddrableBitsCorefile.py
+++ b/lldb/test/API/macosx/lc-note/addrable-bits/TestAddrableBitsCorefile.py
@@ -29,7 +29,7 @@ class TestAddrableBitsCorefile(TestBase):
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
self, "break here", lldb.SBFileSpec("main.c")
)
- self.assertEqual(process.IsValid(), True)
+ self.assertTrue(process.IsValid())
found_main = False
for f in thread.frames:
diff --git a/lldb/test/API/macosx/lc-note/firmware-corefile/TestFirmwareCorefiles.py b/lldb/test/API/macosx/lc-note/firmware-corefile/TestFirmwareCorefiles.py
index b9d2055..db3074d 100644
--- a/lldb/test/API/macosx/lc-note/firmware-corefile/TestFirmwareCorefiles.py
+++ b/lldb/test/API/macosx/lc-note/firmware-corefile/TestFirmwareCorefiles.py
@@ -73,7 +73,7 @@ class TestFirmwareCorefiles(TestBase):
if self.TraceOn():
self.runCmd("script print('loading corefile %s')" % verstr_corefile)
process = target.LoadCore(verstr_corefile)
- self.assertEqual(process.IsValid(), True)
+ self.assertTrue(process.IsValid())
if self.TraceOn():
self.runCmd("image list")
self.runCmd("target mod dump sections")
@@ -91,7 +91,7 @@ class TestFirmwareCorefiles(TestBase):
"script print('loading corefile %s')" % verstr_corefile_invalid_ident
)
process = target.LoadCore(verstr_corefile_invalid_ident)
- self.assertEqual(process.IsValid(), True)
+ self.assertTrue(process.IsValid())
# Third, try the "kern ver str" corefile where it loads at an address
target = self.dbg.CreateTarget("")
@@ -99,7 +99,7 @@ class TestFirmwareCorefiles(TestBase):
if self.TraceOn():
self.runCmd("script print('loading corefile %s')" % verstr_corefile_addr)
process = target.LoadCore(verstr_corefile_addr)
- self.assertEqual(process.IsValid(), True)
+ self.assertTrue(process.IsValid())
if self.TraceOn():
self.runCmd("image list")
self.runCmd("target mod dump sections")
@@ -178,7 +178,7 @@ class TestFirmwareCorefiles(TestBase):
if self.TraceOn():
self.runCmd("script print('loading corefile %s')" % binspec_corefile)
process = target.LoadCore(binspec_corefile)
- self.assertEqual(process.IsValid(), True)
+ self.assertTrue(process.IsValid())
if self.TraceOn():
self.runCmd("image list")
self.runCmd("target mod dump sections")
@@ -192,7 +192,7 @@ class TestFirmwareCorefiles(TestBase):
if self.TraceOn():
self.runCmd("script print('loading corefile %s')" % binspec_corefile_addr)
process = target.LoadCore(binspec_corefile_addr)
- self.assertEqual(process.IsValid(), True)
+ self.assertTrue(process.IsValid())
if self.TraceOn():
self.runCmd("image list")
self.runCmd("target mod dump sections")
@@ -212,7 +212,7 @@ class TestFirmwareCorefiles(TestBase):
"script print('loading corefile %s')" % binspec_corefile_slideonly
)
process = target.LoadCore(binspec_corefile_slideonly)
- self.assertEqual(process.IsValid(), True)
+ self.assertTrue(process.IsValid())
if self.TraceOn():
self.runCmd("image list")
self.runCmd("target mod dump sections")
@@ -352,7 +352,7 @@ class TestFirmwareCorefiles(TestBase):
)
process = target.LoadCore(binspec_corefile_addr)
- self.assertEqual(process.IsValid(), True)
+ self.assertTrue(process.IsValid())
if self.TraceOn():
self.runCmd("image list")
self.runCmd("target mod dump sections")
diff --git a/lldb/test/API/macosx/lc-note/kern-ver-str/TestKernVerStrLCNOTE.py b/lldb/test/API/macosx/lc-note/kern-ver-str/TestKernVerStrLCNOTE.py
index 9713c4a..d436619 100644
--- a/lldb/test/API/macosx/lc-note/kern-ver-str/TestKernVerStrLCNOTE.py
+++ b/lldb/test/API/macosx/lc-note/kern-ver-str/TestKernVerStrLCNOTE.py
@@ -94,7 +94,7 @@ class TestKernVerStrLCNOTE(TestBase):
self.target = self.dbg.CreateTarget("")
err = lldb.SBError()
self.process = self.target.LoadCore(self.corefile)
- self.assertEqual(self.process.IsValid(), True)
+ self.assertTrue(self.process.IsValid())
if self.TraceOn():
self.runCmd("image list")
self.assertEqual(self.target.GetNumModules(), 1)
diff --git a/lldb/test/API/macosx/lc-note/multiple-binary-corefile/TestMultipleBinaryCorefile.py b/lldb/test/API/macosx/lc-note/multiple-binary-corefile/TestMultipleBinaryCorefile.py
index 0a0bc68..897eab2 100644
--- a/lldb/test/API/macosx/lc-note/multiple-binary-corefile/TestMultipleBinaryCorefile.py
+++ b/lldb/test/API/macosx/lc-note/multiple-binary-corefile/TestMultipleBinaryCorefile.py
@@ -45,7 +45,7 @@ class TestMultipleBinaryCorefile(TestBase):
if self.TraceOn():
print("loading corefile %s" % self.corefile)
process = target.LoadCore(self.corefile)
- self.assertEqual(process.IsValid(), True)
+ self.assertTrue(process.IsValid())
if self.TraceOn():
print("image list after loading corefile:")
self.runCmd("image list")
diff --git a/lldb/test/API/macosx/queues/TestQueues.py b/lldb/test/API/macosx/queues/TestQueues.py
index f2d15bb..45b52af 100644
--- a/lldb/test/API/macosx/queues/TestQueues.py
+++ b/lldb/test/API/macosx/queues/TestQueues.py
@@ -457,9 +457,8 @@ class TestQueues(TestBase):
"doing_the_work_2",
"queue 2's pending item #0 should be doing_the_work_2",
)
- self.assertEqual(
+ self.assertFalse(
queue_performer_2.GetPendingItemAtIndex(9999).IsValid(),
- False,
"queue 2's pending item #9999 is invalid",
)
diff --git a/lldb/test/API/macosx/safe-to-func-call/TestSafeFuncCalls.py b/lldb/test/API/macosx/safe-to-func-call/TestSafeFuncCalls.py
index 6a37b25..551cab1 100644
--- a/lldb/test/API/macosx/safe-to-func-call/TestSafeFuncCalls.py
+++ b/lldb/test/API/macosx/safe-to-func-call/TestSafeFuncCalls.py
@@ -49,8 +49,7 @@ class TestSafeFuncCalls(TestBase):
main_thread.SafeToCallFunctions(),
"It is safe to call functions on the main thread",
)
- self.assertEqual(
+ self.assertFalse(
select_thread.SafeToCallFunctions(),
- False,
"It is not safe to call functions on the select thread",
)
diff --git a/lldb/test/API/python_api/interpreter/TestRunCommandInterpreterAPI.py b/lldb/test/API/python_api/interpreter/TestRunCommandInterpreterAPI.py
index 64e0770..af97493 100644
--- a/lldb/test/API/python_api/interpreter/TestRunCommandInterpreterAPI.py
+++ b/lldb/test/API/python_api/interpreter/TestRunCommandInterpreterAPI.py
@@ -79,13 +79,13 @@ class SBCommandInterpreterRunOptionsCase(TestBase):
opts = lldb.SBCommandInterpreterRunOptions()
# Check getters with default values
- self.assertEqual(opts.GetStopOnContinue(), False)
- self.assertEqual(opts.GetStopOnError(), False)
- self.assertEqual(opts.GetStopOnCrash(), False)
- self.assertEqual(opts.GetEchoCommands(), True)
- self.assertEqual(opts.GetPrintResults(), True)
- self.assertEqual(opts.GetPrintErrors(), True)
- self.assertEqual(opts.GetAddToHistory(), True)
+ self.assertFalse(opts.GetStopOnContinue())
+ self.assertFalse(opts.GetStopOnError())
+ self.assertFalse(opts.GetStopOnCrash())
+ self.assertTrue(opts.GetEchoCommands())
+ self.assertTrue(opts.GetPrintResults())
+ self.assertTrue(opts.GetPrintErrors())
+ self.assertTrue(opts.GetAddToHistory())
# Invert values
opts.SetStopOnContinue(not opts.GetStopOnContinue())
@@ -97,10 +97,10 @@ class SBCommandInterpreterRunOptionsCase(TestBase):
opts.SetAddToHistory(not opts.GetAddToHistory())
# Check the value changed
- self.assertEqual(opts.GetStopOnContinue(), True)
- self.assertEqual(opts.GetStopOnError(), True)
- self.assertEqual(opts.GetStopOnCrash(), True)
- self.assertEqual(opts.GetEchoCommands(), False)
- self.assertEqual(opts.GetPrintResults(), False)
- self.assertEqual(opts.GetPrintErrors(), False)
- self.assertEqual(opts.GetAddToHistory(), False)
+ self.assertTrue(opts.GetStopOnContinue())
+ self.assertTrue(opts.GetStopOnError())
+ self.assertTrue(opts.GetStopOnCrash())
+ self.assertFalse(opts.GetEchoCommands())
+ self.assertFalse(opts.GetPrintResults())
+ self.assertFalse(opts.GetPrintErrors())
+ self.assertFalse(opts.GetAddToHistory())
diff --git a/lldb/test/API/tools/lldb-dap/databreakpoint/Makefile b/lldb/test/API/tools/lldb-dap/databreakpoint/Makefile
new file mode 100644
index 0000000..99998b2
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/databreakpoint/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
new file mode 100644
index 0000000..17cdad8
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
@@ -0,0 +1,131 @@
+"""
+Test lldb-dap dataBreakpointInfo and setDataBreakpoints requests
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+import lldbdap_testcase
+
+
+class TestDAP_setDataBreakpoints(lldbdap_testcase.DAPTestCaseBase):
+ def setUp(self):
+ lldbdap_testcase.DAPTestCaseBase.setUp(self)
+ self.accessTypes = ["read", "write", "readWrite"]
+
+ @skipIfWindows
+ @skipIfRemote
+ def test_expression(self):
+ """Tests setting data breakpoints on expression."""
+ program = self.getBuildArtifact("a.out")
+ self.build_and_launch(program)
+ source = "main.cpp"
+ first_loop_break_line = line_number(source, "// first loop breakpoint")
+ self.set_source_breakpoints(source, [first_loop_break_line])
+ self.continue_to_next_stop()
+ self.dap_server.get_stackFrame()
+ # Test setting write watchpoint using expressions: &x, arr+2
+ response_x = self.dap_server.request_dataBreakpointInfo(0, "&x")
+ response_arr_2 = self.dap_server.request_dataBreakpointInfo(0, "arr+2")
+ # Test response from dataBreakpointInfo request.
+ self.assertEquals(response_x["body"]["dataId"].split("/")[1], "4")
+ self.assertEquals(response_x["body"]["accessTypes"], self.accessTypes)
+ self.assertEquals(response_arr_2["body"]["dataId"].split("/")[1], "4")
+ self.assertEquals(response_arr_2["body"]["accessTypes"], self.accessTypes)
+ dataBreakpoints = [
+ {"dataId": response_x["body"]["dataId"], "accessType": "write"},
+ {"dataId": response_arr_2["body"]["dataId"], "accessType": "write"},
+ ]
+ set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints)
+ self.assertEquals(
+ set_response["body"]["breakpoints"],
+ [{"verified": True}, {"verified": True}],
+ )
+
+ self.continue_to_next_stop()
+ x_val = self.dap_server.get_local_variable_value("x")
+ i_val = self.dap_server.get_local_variable_value("i")
+ self.assertEquals(x_val, "2")
+ self.assertEquals(i_val, "1")
+
+ self.continue_to_next_stop()
+ arr_2 = self.dap_server.get_local_variable_child("arr", "[2]")
+ i_val = self.dap_server.get_local_variable_value("i")
+ self.assertEquals(arr_2["value"], "42")
+ self.assertEquals(i_val, "2")
+
+ @skipIfWindows
+ @skipIfRemote
+ def test_functionality(self):
+ """Tests setting data breakpoints on variable."""
+ program = self.getBuildArtifact("a.out")
+ self.build_and_launch(program)
+ source = "main.cpp"
+ first_loop_break_line = line_number(source, "// first loop breakpoint")
+ self.set_source_breakpoints(source, [first_loop_break_line])
+ self.continue_to_next_stop()
+ self.dap_server.get_local_variables()
+ # Test write watchpoints on x, arr[2]
+ response_x = self.dap_server.request_dataBreakpointInfo(1, "x")
+ arr = self.dap_server.get_local_variable("arr")
+ response_arr_2 = self.dap_server.request_dataBreakpointInfo(
+ arr["variablesReference"], "[2]"
+ )
+
+ # Test response from dataBreakpointInfo request.
+ self.assertEquals(response_x["body"]["dataId"].split("/")[1], "4")
+ self.assertEquals(response_x["body"]["accessTypes"], self.accessTypes)
+ self.assertEquals(response_arr_2["body"]["dataId"].split("/")[1], "4")
+ self.assertEquals(response_arr_2["body"]["accessTypes"], self.accessTypes)
+ dataBreakpoints = [
+ {"dataId": response_x["body"]["dataId"], "accessType": "write"},
+ {"dataId": response_arr_2["body"]["dataId"], "accessType": "write"},
+ ]
+ set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints)
+ self.assertEquals(
+ set_response["body"]["breakpoints"],
+ [{"verified": True}, {"verified": True}],
+ )
+
+ self.continue_to_next_stop()
+ x_val = self.dap_server.get_local_variable_value("x")
+ i_val = self.dap_server.get_local_variable_value("i")
+ self.assertEquals(x_val, "2")
+ self.assertEquals(i_val, "1")
+
+ self.continue_to_next_stop()
+ arr_2 = self.dap_server.get_local_variable_child("arr", "[2]")
+ i_val = self.dap_server.get_local_variable_value("i")
+ self.assertEquals(arr_2["value"], "42")
+ self.assertEquals(i_val, "2")
+ self.dap_server.request_setDataBreakpoint([])
+
+ # Test hit condition
+ second_loop_break_line = line_number(source, "// second loop breakpoint")
+ breakpoint_ids = self.set_source_breakpoints(source, [second_loop_break_line])
+ self.continue_to_breakpoints(breakpoint_ids)
+ dataBreakpoints = [
+ {
+ "dataId": response_x["body"]["dataId"],
+ "accessType": "write",
+ "hitCondition": "2",
+ }
+ ]
+ set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints)
+ self.assertEquals(set_response["body"]["breakpoints"], [{"verified": True}])
+ self.continue_to_next_stop()
+ x_val = self.dap_server.get_local_variable_value("x")
+ self.assertEquals(x_val, "3")
+
+ # Test condition
+ dataBreakpoints = [
+ {
+ "dataId": response_x["body"]["dataId"],
+ "accessType": "write",
+ "condition": "x==10",
+ }
+ ]
+ set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints)
+ self.assertEquals(set_response["body"]["breakpoints"], [{"verified": True}])
+ self.continue_to_next_stop()
+ x_val = self.dap_server.get_local_variable_value("x")
+ self.assertEquals(x_val, "10")
diff --git a/lldb/test/API/tools/lldb-dap/databreakpoint/main.cpp b/lldb/test/API/tools/lldb-dap/databreakpoint/main.cpp
new file mode 100644
index 0000000..bef09c2
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/databreakpoint/main.cpp
@@ -0,0 +1,17 @@
+int main(int argc, char const *argv[]) {
+ // Test for data breakpoint
+ int x = 0;
+ int arr[4] = {1, 2, 3, 4};
+ for (int i = 0; i < 5; ++i) { // first loop breakpoint
+ if (i == 1) {
+ x = i + 1;
+ } else if (i == 2) {
+ arr[i] = 42;
+ }
+ }
+
+ x = 1;
+ for (int i = 0; i < 10; ++i) { // second loop breakpoint
+ ++x;
+ }
+}
diff --git a/lldb/tools/lldb-dap/CMakeLists.txt b/lldb/tools/lldb-dap/CMakeLists.txt
index f8c0e4e..f8f0d86 100644
--- a/lldb/tools/lldb-dap/CMakeLists.txt
+++ b/lldb/tools/lldb-dap/CMakeLists.txt
@@ -37,6 +37,7 @@ add_lldb_tool(lldb-dap
RunInTerminal.cpp
SourceBreakpoint.cpp
DAP.cpp
+ Watchpoint.cpp
LINK_LIBS
liblldb
diff --git a/lldb/tools/lldb-dap/DAPForward.h b/lldb/tools/lldb-dap/DAPForward.h
index fffff1e..8c79488 100644
--- a/lldb/tools/lldb-dap/DAPForward.h
+++ b/lldb/tools/lldb-dap/DAPForward.h
@@ -14,6 +14,7 @@ struct BreakpointBase;
struct ExceptionBreakpoint;
struct FunctionBreakpoint;
struct SourceBreakpoint;
+struct Watchpoint;
} // namespace lldb_dap
namespace lldb {
@@ -39,6 +40,7 @@ class SBStringList;
class SBTarget;
class SBThread;
class SBValue;
+class SBWatchpoint;
} // namespace lldb
#endif
diff --git a/lldb/tools/lldb-dap/Watchpoint.cpp b/lldb/tools/lldb-dap/Watchpoint.cpp
new file mode 100644
index 0000000..2f176e0
--- /dev/null
+++ b/lldb/tools/lldb-dap/Watchpoint.cpp
@@ -0,0 +1,48 @@
+//===-- Watchpoint.cpp ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Watchpoint.h"
+#include "DAP.h"
+#include "JSONUtils.h"
+#include "llvm/ADT/StringExtras.h"
+
+namespace lldb_dap {
+Watchpoint::Watchpoint(const llvm::json::Object &obj) : BreakpointBase(obj) {
+ llvm::StringRef dataId = GetString(obj, "dataId");
+ std::string accessType = GetString(obj, "accessType").str();
+ auto [addr_str, size_str] = dataId.split('/');
+ lldb::addr_t addr;
+ size_t size;
+ llvm::to_integer(addr_str, addr, 16);
+ llvm::to_integer(size_str, size);
+ lldb::SBWatchpointOptions options;
+ options.SetWatchpointTypeRead(accessType != "write");
+ if (accessType != "read")
+ options.SetWatchpointTypeWrite(lldb::eWatchpointWriteTypeOnModify);
+ wp = g_dap.target.WatchpointCreateByAddress(addr, size, options, error);
+ SetCondition();
+ SetHitCondition();
+}
+
+void Watchpoint::SetCondition() { wp.SetCondition(condition.c_str()); }
+
+void Watchpoint::SetHitCondition() {
+ uint64_t hitCount = 0;
+ if (llvm::to_integer(hitCondition, hitCount))
+ wp.SetIgnoreCount(hitCount - 1);
+}
+
+void Watchpoint::CreateJsonObject(llvm::json::Object &object) {
+ if (error.Success()) {
+ object.try_emplace("verified", true);
+ } else {
+ object.try_emplace("verified", false);
+ EmplaceSafeString(object, "message", error.GetCString());
+ }
+}
+} // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/Watchpoint.h b/lldb/tools/lldb-dap/Watchpoint.h
new file mode 100644
index 0000000..026b07d
--- /dev/null
+++ b/lldb/tools/lldb-dap/Watchpoint.h
@@ -0,0 +1,34 @@
+//===-- Watchpoint.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_TOOLS_LLDB_DAP_WATCHPOINT_H
+#define LLDB_TOOLS_LLDB_DAP_WATCHPOINT_H
+
+#include "BreakpointBase.h"
+#include "lldb/API/SBError.h"
+#include "lldb/API/SBWatchpoint.h"
+#include "lldb/API/SBWatchpointOptions.h"
+
+namespace lldb_dap {
+
+struct Watchpoint : public BreakpointBase {
+ // The LLDB breakpoint associated wit this watchpoint.
+ lldb::SBWatchpoint wp;
+ lldb::SBError error;
+
+ Watchpoint() = default;
+ Watchpoint(const llvm::json::Object &obj);
+ Watchpoint(lldb::SBWatchpoint wp) : wp(wp) {}
+
+ void SetCondition() override;
+ void SetHitCondition() override;
+ void CreateJsonObject(llvm::json::Object &object) override;
+};
+} // namespace lldb_dap
+
+#endif
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index 78b0b40..c6a275b 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//
#include "DAP.h"
+#include "Watchpoint.h"
+#include "lldb/API/SBMemoryRegionInfo.h"
#include <cassert>
#include <climits>
@@ -560,6 +562,46 @@ void EventThreadFunction() {
}
}
+lldb::SBValue FindVariable(uint64_t variablesReference, llvm::StringRef name) {
+ lldb::SBValue variable;
+ if (lldb::SBValueList *top_scope = GetTopLevelScope(variablesReference)) {
+ bool is_duplicated_variable_name = name.contains(" @");
+ // variablesReference is one of our scopes, not an actual variable it is
+ // asking for a variable in locals or globals or registers
+ int64_t end_idx = top_scope->GetSize();
+ // Searching backward so that we choose the variable in closest scope
+ // among variables of the same name.
+ for (int64_t i = end_idx - 1; i >= 0; --i) {
+ lldb::SBValue curr_variable = top_scope->GetValueAtIndex(i);
+ std::string variable_name = CreateUniqueVariableNameForDisplay(
+ curr_variable, is_duplicated_variable_name);
+ if (variable_name == name) {
+ variable = curr_variable;
+ break;
+ }
+ }
+ } else {
+ // This is not under the globals or locals scope, so there are no duplicated
+ // names.
+
+ // We have a named item within an actual variable so we need to find it
+ // withing the container variable by name.
+ lldb::SBValue container = g_dap.variables.GetVariable(variablesReference);
+ variable = container.GetChildMemberWithName(name.data());
+ if (!variable.IsValid()) {
+ if (name.starts_with("[")) {
+ llvm::StringRef index_str(name.drop_front(1));
+ uint64_t index = 0;
+ if (!index_str.consumeInteger(0, index)) {
+ if (index_str == "]")
+ variable = container.GetChildAtIndex(index);
+ }
+ }
+ }
+ }
+ return variable;
+}
+
// Both attach and launch take a either a sourcePath or sourceMap
// argument (or neither), from which we need to set the target.source-map.
void SetSourceMapFromArguments(const llvm::json::Object &arguments) {
@@ -1647,6 +1689,8 @@ void request_initialize(const llvm::json::Object &request) {
body.try_emplace("supportsProgressReporting", true);
// The debug adapter supports 'logMessage' in breakpoint.
body.try_emplace("supportsLogPoints", true);
+ // The debug adapter supports data watchpoints.
+ body.try_emplace("supportsDataBreakpoints", true);
response.try_emplace("body", std::move(body));
g_dap.SendJSON(llvm::json::Value(std::move(response)));
@@ -2593,6 +2637,264 @@ void request_setFunctionBreakpoints(const llvm::json::Object &request) {
g_dap.SendJSON(llvm::json::Value(std::move(response)));
}
+// "DataBreakpointInfoRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "Obtains information on a possible data breakpoint that
+// could be set on an expression or variable.\nClients should only call this
+// request if the corresponding capability `supportsDataBreakpoints` is
+// true.", "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "dataBreakpointInfo" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/DataBreakpointInfoArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "DataBreakpointInfoArguments": {
+// "type": "object",
+// "description": "Arguments for `dataBreakpointInfo` request.",
+// "properties": {
+// "variablesReference": {
+// "type": "integer",
+// "description": "Reference to the variable container if the data
+// breakpoint is requested for a child of the container. The
+// `variablesReference` must have been obtained in the current suspended
+// state. See 'Lifetime of Object References' in the Overview section for
+// details."
+// },
+// "name": {
+// "type": "string",
+// "description": "The name of the variable's child to obtain data
+// breakpoint information for.\nIf `variablesReference` isn't specified,
+// this can be an expression."
+// },
+// "frameId": {
+// "type": "integer",
+// "description": "When `name` is an expression, evaluate it in the scope
+// of this stack frame. If not specified, the expression is evaluated in
+// the global scope. When `variablesReference` is specified, this property
+// has no effect."
+// }
+// },
+// "required": [ "name" ]
+// },
+// "DataBreakpointInfoResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to `dataBreakpointInfo` request.",
+// "properties": {
+// "body": {
+// "type": "object",
+// "properties": {
+// "dataId": {
+// "type": [ "string", "null" ],
+// "description": "An identifier for the data on which a data
+// breakpoint can be registered with the `setDataBreakpoints`
+// request or null if no data breakpoint is available. If a
+// `variablesReference` or `frameId` is passed, the `dataId` is
+// valid in the current suspended state, otherwise it's valid
+// indefinitely. See 'Lifetime of Object References' in the Overview
+// section for details. Breakpoints set using the `dataId` in the
+// `setDataBreakpoints` request may outlive the lifetime of the
+// associated `dataId`."
+// },
+// "description": {
+// "type": "string",
+// "description": "UI string that describes on what data the
+// breakpoint is set on or why a data breakpoint is not available."
+// },
+// "accessTypes": {
+// "type": "array",
+// "items": {
+// "$ref": "#/definitions/DataBreakpointAccessType"
+// },
+// "description": "Attribute lists the available access types for a
+// potential data breakpoint. A UI client could surface this
+// information."
+// },
+// "canPersist": {
+// "type": "boolean",
+// "description": "Attribute indicates that a potential data
+// breakpoint could be persisted across sessions."
+// }
+// },
+// "required": [ "dataId", "description" ]
+// }
+// },
+// "required": [ "body" ]
+// }]
+// }
+void request_dataBreakpointInfo(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ FillResponse(request, response);
+ llvm::json::Object body;
+ lldb::SBError error;
+ llvm::json::Array accessTypes{"read", "write", "readWrite"};
+ const auto *arguments = request.getObject("arguments");
+ const auto variablesReference =
+ GetUnsigned(arguments, "variablesReference", 0);
+ llvm::StringRef name = GetString(arguments, "name");
+ lldb::SBFrame frame = g_dap.GetLLDBFrame(*arguments);
+ lldb::SBValue variable = FindVariable(variablesReference, name);
+ std::string addr, size;
+
+ if (variable.IsValid()) {
+ lldb::addr_t load_addr = variable.GetLoadAddress();
+ size_t byte_size = variable.GetByteSize();
+ if (load_addr == LLDB_INVALID_ADDRESS) {
+ body.try_emplace("dataId", nullptr);
+ body.try_emplace("description",
+ "does not exist in memory, its location is " +
+ std::string(variable.GetLocation()));
+ } else if (byte_size == 0) {
+ body.try_emplace("dataId", nullptr);
+ body.try_emplace("description", "variable size is 0");
+ } else {
+ addr = llvm::utohexstr(load_addr);
+ size = llvm::utostr(byte_size);
+ }
+ } else if (variablesReference == 0 && frame.IsValid()) {
+ lldb::SBValue value = frame.EvaluateExpression(name.data());
+ if (value.GetError().Fail()) {
+ lldb::SBError error = value.GetError();
+ const char *error_cstr = error.GetCString();
+ body.try_emplace("dataId", nullptr);
+ body.try_emplace("description", error_cstr && error_cstr[0]
+ ? std::string(error_cstr)
+ : "evaluation failed");
+ } else {
+ uint64_t load_addr = value.GetValueAsUnsigned();
+ addr = llvm::utohexstr(load_addr);
+ lldb::SBMemoryRegionInfo region;
+ lldb::SBError err =
+ g_dap.target.GetProcess().GetMemoryRegionInfo(load_addr, region);
+ if (err.Success()) {
+ if (!(region.IsReadable() || region.IsWritable())) {
+ body.try_emplace("dataId", nullptr);
+ body.try_emplace("description",
+ "memory region for address " + addr +
+ " has no read or write permissions");
+ } else {
+ lldb::SBData data = value.GetPointeeData();
+ if (data.IsValid())
+ size = llvm::utostr(data.GetByteSize());
+ else {
+ body.try_emplace("dataId", nullptr);
+ body.try_emplace("description",
+ "unable to get byte size for expression: " +
+ name.str());
+ }
+ }
+ } else {
+ body.try_emplace("dataId", nullptr);
+ body.try_emplace("description",
+ "unable to get memory region info for address " +
+ addr);
+ }
+ }
+ } else {
+ body.try_emplace("dataId", nullptr);
+ body.try_emplace("description", "variable not found: " + name.str());
+ }
+
+ if (!body.getObject("dataId")) {
+ body.try_emplace("dataId", addr + "/" + size);
+ body.try_emplace("accessTypes", std::move(accessTypes));
+ body.try_emplace("description",
+ size + " bytes at " + addr + " " + name.str());
+ }
+ response.try_emplace("body", std::move(body));
+ g_dap.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+// "SetDataBreakpointsRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "Replaces all existing data breakpoints with new data
+// breakpoints.\nTo clear all data breakpoints, specify an empty
+// array.\nWhen a data breakpoint is hit, a `stopped` event (with reason
+// `data breakpoint`) is generated.\nClients should only call this request
+// if the corresponding capability `supportsDataBreakpoints` is true.",
+// "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "setDataBreakpoints" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/SetDataBreakpointsArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "SetDataBreakpointsArguments": {
+// "type": "object",
+// "description": "Arguments for `setDataBreakpoints` request.",
+// "properties": {
+// "breakpoints": {
+// "type": "array",
+// "items": {
+// "$ref": "#/definitions/DataBreakpoint"
+// },
+// "description": "The contents of this array replaces all existing data
+// breakpoints. An empty array clears all data breakpoints."
+// }
+// },
+// "required": [ "breakpoints" ]
+// },
+// "SetDataBreakpointsResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to `setDataBreakpoints` request.\nReturned is
+// information about each breakpoint created by this request.",
+// "properties": {
+// "body": {
+// "type": "object",
+// "properties": {
+// "breakpoints": {
+// "type": "array",
+// "items": {
+// "$ref": "#/definitions/Breakpoint"
+// },
+// "description": "Information about the data breakpoints. The array
+// elements correspond to the elements of the input argument
+// `breakpoints` array."
+// }
+// },
+// "required": [ "breakpoints" ]
+// }
+// },
+// "required": [ "body" ]
+// }]
+// }
+void request_setDataBreakpoints(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ lldb::SBError error;
+ FillResponse(request, response);
+ const auto *arguments = request.getObject("arguments");
+ const auto *breakpoints = arguments->getArray("breakpoints");
+ llvm::json::Array response_breakpoints;
+ g_dap.target.DeleteAllWatchpoints();
+ if (breakpoints) {
+ for (const auto &bp : *breakpoints) {
+ const auto *bp_obj = bp.getAsObject();
+ if (bp_obj) {
+ Watchpoint wp(*bp_obj);
+ AppendBreakpoint(&wp, response_breakpoints);
+ }
+ }
+ }
+ llvm::json::Object body;
+ body.try_emplace("breakpoints", std::move(response_breakpoints));
+ response.try_emplace("body", std::move(body));
+ g_dap.SendJSON(llvm::json::Value(std::move(response)));
+}
+
// "SourceRequest": {
// "allOf": [ { "$ref": "#/definitions/Request" }, {
// "type": "object",
@@ -3076,7 +3378,6 @@ void request_setVariable(const llvm::json::Object &request) {
const auto variablesReference =
GetUnsigned(arguments, "variablesReference", 0);
llvm::StringRef name = GetString(arguments, "name");
- bool is_duplicated_variable_name = name.contains(" @");
const auto value = GetString(arguments, "value");
// Set success to false just in case we don't find the variable by name
@@ -3097,40 +3398,8 @@ void request_setVariable(const llvm::json::Object &request) {
const auto id_value = GetUnsigned(arguments, "id", UINT64_MAX);
if (id_value != UINT64_MAX) {
variable = g_dap.variables.GetVariable(id_value);
- } else if (lldb::SBValueList *top_scope =
- GetTopLevelScope(variablesReference)) {
- // variablesReference is one of our scopes, not an actual variable it is
- // asking for a variable in locals or globals or registers
- int64_t end_idx = top_scope->GetSize();
- // Searching backward so that we choose the variable in closest scope
- // among variables of the same name.
- for (int64_t i = end_idx - 1; i >= 0; --i) {
- lldb::SBValue curr_variable = top_scope->GetValueAtIndex(i);
- std::string variable_name = CreateUniqueVariableNameForDisplay(
- curr_variable, is_duplicated_variable_name);
- if (variable_name == name) {
- variable = curr_variable;
- break;
- }
- }
} else {
- // This is not under the globals or locals scope, so there are no duplicated
- // names.
-
- // We have a named item within an actual variable so we need to find it
- // withing the container variable by name.
- lldb::SBValue container = g_dap.variables.GetVariable(variablesReference);
- variable = container.GetChildMemberWithName(name.data());
- if (!variable.IsValid()) {
- if (name.starts_with("[")) {
- llvm::StringRef index_str(name.drop_front(1));
- uint64_t index = 0;
- if (!index_str.consumeInteger(0, index)) {
- if (index_str == "]")
- variable = container.GetChildAtIndex(index);
- }
- }
- }
+ variable = FindVariable(variablesReference, name);
}
if (variable.IsValid()) {
@@ -3613,6 +3882,10 @@ void RegisterRequestCallbacks() {
request_setExceptionBreakpoints);
g_dap.RegisterRequestCallback("setFunctionBreakpoints",
request_setFunctionBreakpoints);
+ g_dap.RegisterRequestCallback("dataBreakpointInfo",
+ request_dataBreakpointInfo);
+ g_dap.RegisterRequestCallback("setDataBreakpoints",
+ request_setDataBreakpoints);
g_dap.RegisterRequestCallback("setVariable", request_setVariable);
g_dap.RegisterRequestCallback("source", request_source);
g_dap.RegisterRequestCallback("stackTrace", request_stackTrace);
diff --git a/lldb/unittests/Interpreter/CMakeLists.txt b/lldb/unittests/Interpreter/CMakeLists.txt
index 5b5268f..54cea99 100644
--- a/lldb/unittests/Interpreter/CMakeLists.txt
+++ b/lldb/unittests/Interpreter/CMakeLists.txt
@@ -2,6 +2,7 @@ add_lldb_unittest(InterpreterTests
TestCommandPaths.cpp
TestCompletion.cpp
TestOptionArgParser.cpp
+ TestOptions.cpp
TestOptionValue.cpp
TestOptionValueFileColonLine.cpp
TestRegexCommand.cpp
diff --git a/lldb/unittests/Interpreter/TestOptions.cpp b/lldb/unittests/Interpreter/TestOptions.cpp
new file mode 100644
index 0000000..93474e3
--- /dev/null
+++ b/lldb/unittests/Interpreter/TestOptions.cpp
@@ -0,0 +1,29 @@
+//===-- TestOptions.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Interpreter/Options.h"
+#include "gtest/gtest.h"
+
+#include "llvm/Testing/Support/Error.h"
+
+using namespace lldb_private;
+
+TEST(OptionsTest, CreateOptionParsingError) {
+ ASSERT_THAT_ERROR(
+ CreateOptionParsingError("yippee", 'f', "fun",
+ "unable to convert 'yippee' to boolean"),
+ llvm::FailedWithMessage("Invalid value ('yippee') for -f (fun): unable "
+ "to convert 'yippee' to boolean"));
+
+ ASSERT_THAT_ERROR(
+ CreateOptionParsingError("52", 'b', "bean-count"),
+ llvm::FailedWithMessage("Invalid value ('52') for -b (bean-count)"));
+
+ ASSERT_THAT_ERROR(CreateOptionParsingError("c", 'm'),
+ llvm::FailedWithMessage("Invalid value ('c') for -m"));
+}
diff --git a/lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
index a4db4627f..b90fbb7 100644
--- a/lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
+++ b/lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
@@ -11,6 +11,7 @@
#include "Plugins/ScriptInterpreter/Python/PythonDataObjects.h"
#include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h"
+#include "TestingSupport/SubsystemRAII.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
@@ -26,6 +27,8 @@ using namespace lldb_private::python;
using llvm::Expected;
class PythonDataObjectsTest : public PythonTestSuite {
+ SubsystemRAII<FileSystem> subsystems;
+
public:
void SetUp() override {
PythonTestSuite::SetUp();
@@ -209,8 +212,8 @@ TEST_F(PythonDataObjectsTest, TestPythonBoolean) {
};
// Test PythonBoolean constructed from long integer values.
- test_from_long(0); // Test 'false' value.
- test_from_long(1); // Test 'true' value.
+ test_from_long(0); // Test 'false' value.
+ test_from_long(1); // Test 'true' value.
test_from_long(~0); // Any value != 0 is 'true'.
}
@@ -811,7 +814,8 @@ main = foo
testing::ContainsRegex("line 7, in baz"),
testing::ContainsRegex("ZeroDivisionError")))));
-#if !((defined(_WIN32) || defined(_WIN64)) && (defined(__aarch64__) || defined(_M_ARM64)))
+#if !((defined(_WIN32) || defined(_WIN64)) && \
+ (defined(__aarch64__) || defined(_M_ARM64)))
static const char script2[] = R"(
class MyError(Exception):