diff options
Diffstat (limited to 'lldb')
23 files changed, 160 insertions, 46 deletions
diff --git a/lldb/bindings/CMakeLists.txt b/lldb/bindings/CMakeLists.txt index b44ed59..296eae1 100644 --- a/lldb/bindings/CMakeLists.txt +++ b/lldb/bindings/CMakeLists.txt @@ -23,7 +23,11 @@ endif() set(SWIG_COMMON_FLAGS -c++ - -w361,362 # Ignore warnings about ignored operator overloads + # Ignored warnings: + # 361: operator! ignored. + # 362: operator= ignored. + # 509: Overloaded method declaration effectively ignored, shadowed by previous declaration. + -w361,362,509 -features autodoc -I${LLDB_SOURCE_DIR}/include -I${CMAKE_CURRENT_SOURCE_DIR} diff --git a/lldb/cmake/modules/LLDBConfig.cmake b/lldb/cmake/modules/LLDBConfig.cmake index a758261..93c8ffe 100644 --- a/lldb/cmake/modules/LLDBConfig.cmake +++ b/lldb/cmake/modules/LLDBConfig.cmake @@ -67,6 +67,8 @@ option(LLDB_SKIP_STRIP "Whether to skip stripping of binaries when installing ll option(LLDB_SKIP_DSYM "Whether to skip generating a dSYM when installing lldb." OFF) option(LLDB_ENFORCE_STRICT_TEST_REQUIREMENTS "Fail to configure if certain requirements are not met for testing." OFF) +option(LLDB_TEST_USE_VENDOR_PACKAGES + "Use packages from lldb/third_party/Python/module instead of system deps." ON) set(LLDB_GLOBAL_INIT_DIRECTORY "" CACHE STRING "Path to the global lldbinit directory. Relative paths are resolved relative to the diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 4526557..b2346c2 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -3376,15 +3376,19 @@ protected: case 'r': { size_t ref_count = 0; + char in_shared_cache = 'Y'; + ModuleSP module_sp(module->shared_from_this()); + if (!ModuleList::ModuleIsInCache(module)) + in_shared_cache = 'N'; if (module_sp) { // Take one away to make sure we don't count our local "module_sp" ref_count = module_sp.use_count() - 1; } if (width) - strm.Printf("{%*" PRIu64 "}", width, (uint64_t)ref_count); + strm.Printf("{%c %*" PRIu64 "}", in_shared_cache, width, (uint64_t)ref_count); else - strm.Printf("{%" PRIu64 "}", (uint64_t)ref_count); + strm.Printf("{%c %" PRIu64 "}", in_shared_cache, (uint64_t)ref_count); } break; case 's': diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index ad4321d9..91d5eea 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -936,8 +936,8 @@ let Command = "target modules list" in { OptionalArg<"Width">, Desc<"Display the modification time with optional " "width of the module.">; def target_modules_list_ref_count : Option<"ref-count", "r">, Group<1>, - OptionalArg<"Width">, Desc<"Display the reference count if the module is " - "still in the shared module cache.">; + OptionalArg<"Width">, Desc<"Display whether the module is still in the " + "the shared module cache (Y/N), and its shared pointer use_count.">; def target_modules_list_pointer : Option<"pointer", "p">, Group<1>, OptionalArg<"None">, Desc<"Display the module pointer.">; def target_modules_list_global : Option<"global", "g">, Group<1>, diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index a1ad3f5..ce52f35 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -1417,7 +1417,7 @@ bool ScriptInterpreterPythonImpl::GenerateScriptAliasFunction( sstr.Printf("def %s (debugger, args, exe_ctx, result, internal_dict):", auto_generated_function_name.c_str()); - if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/true) + if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/false) .Success()) return false; diff --git a/lldb/source/Symbol/Variable.cpp b/lldb/source/Symbol/Variable.cpp index 2bb2ff7..a33c343 100644 --- a/lldb/source/Symbol/Variable.cpp +++ b/lldb/source/Symbol/Variable.cpp @@ -509,15 +509,17 @@ static void PrivateAutoCompleteMembers( CompilerType member_compiler_type = compiler_type.GetFieldAtIndex( i, member_name, nullptr, nullptr, nullptr); - if (partial_member_name.empty() || - llvm::StringRef(member_name).starts_with(partial_member_name)) { + if (partial_member_name.empty()) { + request.AddCompletion((prefix_path + member_name).str()); + } else if (llvm::StringRef(member_name) + .starts_with(partial_member_name)) { if (member_name == partial_member_name) { PrivateAutoComplete( frame, partial_path, prefix_path + member_name, // Anything that has been resolved // already will be in here member_compiler_type.GetCanonicalType(), request); - } else { + } else if (partial_path.empty()) { request.AddCompletion((prefix_path + member_name).str()); } } diff --git a/lldb/test/API/commands/command/script/TestCommandScript.py b/lldb/test/API/commands/command/script/TestCommandScript.py index 8505520..fdd5216 100644 --- a/lldb/test/API/commands/command/script/TestCommandScript.py +++ b/lldb/test/API/commands/command/script/TestCommandScript.py @@ -216,3 +216,17 @@ class CmdPythonTestCase(TestBase): # The result object will be replaced by an empty result object (in the # "Started" state). self.expect("script str(persistence.result_copy)", substrs=["Started"]) + + def test_interactive(self): + """ + Test that we can add multiple lines interactively. + """ + interp = self.dbg.GetCommandInterpreter() + cmd_file = self.getSourcePath("cmd_file.lldb") + result = lldb.SBCommandReturnObject() + interp.HandleCommand(f"command source {cmd_file}", result) + self.assertCommandReturn(result, "Sourcing the command should cause no errors.") + self.assertTrue(interp.UserCommandExists("my_cmd"), "Command defined.") + interp.HandleCommand("my_cmd", result) + self.assertCommandReturn(result, "Running the command succeeds") + self.assertIn("My Command Result", result.GetOutput(), "Command was correct") diff --git a/lldb/test/API/commands/command/script/cmd_file.lldb b/lldb/test/API/commands/command/script/cmd_file.lldb new file mode 100644 index 0000000..1589a7c --- /dev/null +++ b/lldb/test/API/commands/command/script/cmd_file.lldb @@ -0,0 +1,4 @@ +command script add my_cmd +result.PutCString("My Command Result") +result.SetStatus(lldb.eReturnStatusSuccessFinishResult) +DONE diff --git a/lldb/test/API/functionalities/completion/TestCompletion.py b/lldb/test/API/functionalities/completion/TestCompletion.py index f71bc73..0d6907e 100644 --- a/lldb/test/API/functionalities/completion/TestCompletion.py +++ b/lldb/test/API/functionalities/completion/TestCompletion.py @@ -60,10 +60,12 @@ class CommandLineCompletionTestCase(TestBase): def do_test_variable_completion(self, command): self.complete_from_to(f"{command} fo", f"{command} fooo") - self.complete_from_to(f"{command} fooo.", f"{command} fooo.") + self.complete_from_to(f"{command} fooo.", f"{command} fooo.t") + self.complete_from_to(f"{command} fooo.t.", f"{command} fooo.t.x") self.complete_from_to(f"{command} fooo.dd", f"{command} fooo.dd") - self.complete_from_to(f"{command} ptr_fooo->", f"{command} ptr_fooo->") + self.complete_from_to(f"{command} ptr_fooo->", f"{command} ptr_fooo->t") + self.complete_from_to(f"{command} ptr_fooo->t.", f"{command} ptr_fooo->t.x") self.complete_from_to(f"{command} ptr_fooo->dd", f"{command} ptr_fooo->dd") self.complete_from_to(f"{command} cont", f"{command} container") diff --git a/lldb/test/API/functionalities/completion/main.cpp b/lldb/test/API/functionalities/completion/main.cpp index 06ff577..f925c1d 100644 --- a/lldb/test/API/functionalities/completion/main.cpp +++ b/lldb/test/API/functionalities/completion/main.cpp @@ -1,12 +1,17 @@ #include <iostream> +class Baz { +public: + int x; +}; + class Foo { public: - int Bar(int x, int y) - { - return x + y; - } + Baz t; + int temp; + + int Bar(int x, int y) { return x + y; } }; namespace { int Quux (void) { return 0; } } diff --git a/lldb/test/API/lit.cfg.py b/lldb/test/API/lit.cfg.py index 12675ed..f9497b6 100644 --- a/lldb/test/API/lit.cfg.py +++ b/lldb/test/API/lit.cfg.py @@ -309,3 +309,6 @@ if "FREEBSD_LEGACY_PLUGIN" in os.environ: # Propagate XDG_CACHE_HOME if "XDG_CACHE_HOME" in os.environ: config.environment["XDG_CACHE_HOME"] = os.environ["XDG_CACHE_HOME"] + +if is_configured("use_vendor_packages"): + config.environment["LLDB_TEST_USE_VENDOR_PACKAGES"] = "1" diff --git a/lldb/test/API/lit.site.cfg.py.in b/lldb/test/API/lit.site.cfg.py.in index 053331d..c2602ac 100644 --- a/lldb/test/API/lit.site.cfg.py.in +++ b/lldb/test/API/lit.site.cfg.py.in @@ -38,6 +38,7 @@ config.libcxx_include_target_dir = "@LIBCXX_GENERATED_INCLUDE_TARGET_DIR@" # The API tests use their own module caches. config.lldb_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_LLDB@", "lldb-api") config.clang_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_CLANG@", "lldb-api") +config.use_vendor_packages = @LLDB_TEST_USE_VENDOR_PACKAGES@ # Plugins lldb_build_intel_pt = '@LLDB_BUILD_INTEL_PT@' diff --git a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py index 17cdad8..52c0bbf 100644 --- a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py +++ b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py @@ -14,6 +14,51 @@ class TestDAP_setDataBreakpoints(lldbdap_testcase.DAPTestCaseBase): @skipIfWindows @skipIfRemote + def test_duplicate_start_addresses(self): + """Test setDataBreakpoints with multiple watchpoints starting at the same addresses.""" + 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) + # The first one should be overwritten by the third one as they start at + # the same address. This is indicated by returning {verified: False} for + # the first one. + dataBreakpoints = [ + {"dataId": response_x["body"]["dataId"], "accessType": "read"}, + {"dataId": response_arr_2["body"]["dataId"], "accessType": "write"}, + {"dataId": response_x["body"]["dataId"], "accessType": "write"}, + ] + set_response = self.dap_server.request_setDataBreakpoint(dataBreakpoints) + self.assertEquals( + set_response["body"]["breakpoints"], + [{"verified": False}, {"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_expression(self): """Tests setting data breakpoints on expression.""" program = self.getBuildArtifact("a.out") diff --git a/lldb/test/CMakeLists.txt b/lldb/test/CMakeLists.txt index 1aa8843..7c31fd4 100644 --- a/lldb/test/CMakeLists.txt +++ b/lldb/test/CMakeLists.txt @@ -26,6 +26,21 @@ if(LLDB_ENFORCE_STRICT_TEST_REQUIREMENTS) endforeach() endif() +# The "pexpect" package should come from the system environment, not from the +# LLDB tree. However, we delay the deletion of it from the tree in case +# users/buildbots don't have the package yet and need some time to install it. +if (NOT LLDB_TEST_USE_VENDOR_PACKAGES) + unset(PY_pexpect_FOUND CACHE) + lldb_find_python_module(pexpect) + if (NOT PY_pexpect_FOUND) + message(FATAL_ERROR + "Python module 'pexpect' not found. Please install it via pip or via " + "your operating system's package manager. For a temporary workaround, " + "use a version from the LLDB tree with " + "`LLDB_TEST_USE_VENDOR_PACKAGES=ON`") + endif() +endif() + if(LLDB_BUILT_STANDALONE) # In order to run check-lldb-* we need the correct map_config directives in # llvm-lit. Because this is a standalone build, LLVM doesn't know about LLDB, @@ -240,7 +255,8 @@ llvm_canonicalize_cmake_booleans( LLDB_HAS_LIBCXX LLDB_TOOL_LLDB_SERVER_BUILD LLDB_USE_SYSTEM_DEBUGSERVER - LLDB_IS_64_BITS) + LLDB_IS_64_BITS + LLDB_TEST_USE_VENDOR_PACKAGES) # Configure the individual test suites. add_subdirectory(API) diff --git a/lldb/test/Shell/Driver/TestHelp.test b/lldb/test/Shell/Driver/TestHelp.test index 0f73fdf..2521b31 100644 --- a/lldb/test/Shell/Driver/TestHelp.test +++ b/lldb/test/Shell/Driver/TestHelp.test @@ -37,8 +37,6 @@ CHECK: --arch CHECK: -a CHECK: --core CHECK: -c -CHECK: --debug -CHECK: -d CHECK: --editor CHECK: -e CHECK: --file diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index c63ff0f..9286abb 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -188,7 +188,6 @@ SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) { if (args.hasArg(OPT_no_use_colors)) { m_debugger.SetUseColor(false); WithColor::setAutoDetectFunction(disable_color); - m_option_data.m_debug_mode = true; } if (args.hasArg(OPT_version)) { @@ -455,16 +454,7 @@ int Driver::MainLoop() { // Process lldbinit files before handling any options from the command line. SBCommandReturnObject result; sb_interpreter.SourceInitFileInGlobalDirectory(result); - if (m_option_data.m_debug_mode) { - result.PutError(m_debugger.GetErrorFile()); - result.PutOutput(m_debugger.GetOutputFile()); - } - sb_interpreter.SourceInitFileInHomeDirectory(result, m_option_data.m_repl); - if (m_option_data.m_debug_mode) { - result.PutError(m_debugger.GetErrorFile()); - result.PutOutput(m_debugger.GetOutputFile()); - } // Source the local .lldbinit file if it exists and we're allowed to source. // Here we want to always print the return object because it contains the @@ -536,11 +526,6 @@ int Driver::MainLoop() { "or -s) are ignored in REPL mode.\n"; } - if (m_option_data.m_debug_mode) { - result.PutError(m_debugger.GetErrorFile()); - result.PutOutput(m_debugger.GetOutputFile()); - } - const bool handle_events = true; const bool spawn_thread = false; diff --git a/lldb/tools/driver/Driver.h b/lldb/tools/driver/Driver.h index d5779b3..83e0d8a 100644 --- a/lldb/tools/driver/Driver.h +++ b/lldb/tools/driver/Driver.h @@ -75,7 +75,6 @@ public: std::vector<InitialCmdEntry> m_after_file_commands; std::vector<InitialCmdEntry> m_after_crash_commands; - bool m_debug_mode = false; bool m_source_quietly = false; bool m_print_version = false; bool m_print_python_path = false; diff --git a/lldb/tools/lldb-dap/Watchpoint.cpp b/lldb/tools/lldb-dap/Watchpoint.cpp index 2f176e0..2176550 100644 --- a/lldb/tools/lldb-dap/Watchpoint.cpp +++ b/lldb/tools/lldb-dap/Watchpoint.cpp @@ -16,17 +16,11 @@ 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()); } @@ -38,11 +32,20 @@ void Watchpoint::SetHitCondition() { } void Watchpoint::CreateJsonObject(llvm::json::Object &object) { - if (error.Success()) { - object.try_emplace("verified", true); - } else { + if (!error.IsValid() || error.Fail()) { object.try_emplace("verified", false); - EmplaceSafeString(object, "message", error.GetCString()); + if (error.Fail()) + EmplaceSafeString(object, "message", error.GetCString()); + } else { + object.try_emplace("verified", true); } } + +void Watchpoint::SetWatchpoint() { + wp = g_dap.target.WatchpointCreateByAddress(addr, size, options, error); + if (!condition.empty()) + SetCondition(); + if (!hitCondition.empty()) + SetHitCondition(); +} } // namespace lldb_dap diff --git a/lldb/tools/lldb-dap/Watchpoint.h b/lldb/tools/lldb-dap/Watchpoint.h index 026b07d..4d2e58e 100644 --- a/lldb/tools/lldb-dap/Watchpoint.h +++ b/lldb/tools/lldb-dap/Watchpoint.h @@ -17,6 +17,9 @@ namespace lldb_dap { struct Watchpoint : public BreakpointBase { + lldb::addr_t addr; + size_t size; + lldb::SBWatchpointOptions options; // The LLDB breakpoint associated wit this watchpoint. lldb::SBWatchpoint wp; lldb::SBError error; @@ -28,6 +31,8 @@ struct Watchpoint : public BreakpointBase { void SetCondition() override; void SetHitCondition() override; void CreateJsonObject(llvm::json::Object &object) override; + + void SetWatchpoint(); }; } // namespace lldb_dap diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp index c6a275b..55f8c92 100644 --- a/lldb/tools/lldb-dap/lldb-dap.cpp +++ b/lldb/tools/lldb-dap/lldb-dap.cpp @@ -2880,15 +2880,29 @@ void request_setDataBreakpoints(const llvm::json::Object &request) { const auto *breakpoints = arguments->getArray("breakpoints"); llvm::json::Array response_breakpoints; g_dap.target.DeleteAllWatchpoints(); + std::vector<Watchpoint> watchpoints; if (breakpoints) { for (const auto &bp : *breakpoints) { const auto *bp_obj = bp.getAsObject(); if (bp_obj) { Watchpoint wp(*bp_obj); - AppendBreakpoint(&wp, response_breakpoints); + watchpoints.push_back(wp); } } } + // If two watchpoints start at the same address, the latter overwrite the + // former. So, we only enable those at first-seen addresses when iterating + // backward. + std::set<lldb::addr_t> addresses; + for (auto iter = watchpoints.rbegin(); iter != watchpoints.rend(); ++iter) { + if (addresses.count(iter->addr) == 0) { + iter->SetWatchpoint(); + addresses.insert(iter->addr); + } + } + for (auto wp : watchpoints) + AppendBreakpoint(&wp, response_breakpoints); + llvm::json::Object body; body.try_emplace("breakpoints", std::move(response_breakpoints)); response.try_emplace("body", std::move(body)); diff --git a/lldb/use_lldb_suite_root.py b/lldb/use_lldb_suite_root.py index fd42f63..b8f8acf 100644 --- a/lldb/use_lldb_suite_root.py +++ b/lldb/use_lldb_suite_root.py @@ -21,5 +21,7 @@ def add_lldbsuite_packages_dir(lldb_root): lldb_root = os.path.dirname(inspect.getfile(inspect.currentframe())) -add_third_party_module_dirs(lldb_root) +# Use environment variables to avoid plumbing flags, lit configs, etc. +if os.getenv("LLDB_TEST_USE_VENDOR_PACKAGES"): + add_third_party_module_dirs(lldb_root) add_lldbsuite_packages_dir(lldb_root) diff --git a/lldb/utils/lldb-dotest/CMakeLists.txt b/lldb/utils/lldb-dotest/CMakeLists.txt index 09f41db..2ba40f0 100644 --- a/lldb/utils/lldb-dotest/CMakeLists.txt +++ b/lldb/utils/lldb-dotest/CMakeLists.txt @@ -10,6 +10,7 @@ set(LLDB_LIBS_DIR "${LLVM_LIBRARY_OUTPUT_INTDIR}") llvm_canonicalize_cmake_booleans( LLDB_BUILD_INTEL_PT LLDB_HAS_LIBCXX + LLDB_TEST_USE_VENDOR_PACKAGES ) if ("libcxx" IN_LIST LLVM_ENABLE_RUNTIMES) diff --git a/lldb/utils/lldb-dotest/lldb-dotest.in b/lldb/utils/lldb-dotest/lldb-dotest.in index 5cd49d2..9291f59 100755 --- a/lldb/utils/lldb-dotest/lldb-dotest.in +++ b/lldb/utils/lldb-dotest/lldb-dotest.in @@ -1,4 +1,5 @@ #!@Python3_EXECUTABLE@ +import os import subprocess import sys @@ -17,8 +18,12 @@ has_libcxx = @LLDB_HAS_LIBCXX@ libcxx_libs_dir = "@LIBCXX_LIBRARY_DIR@" libcxx_include_dir = "@LIBCXX_GENERATED_INCLUDE_DIR@" libcxx_include_target_dir = "@LIBCXX_GENERATED_INCLUDE_TARGET_DIR@" +use_vendor_packages = @LLDB_TEST_USE_VENDOR_PACKAGES@ if __name__ == '__main__': + if use_vendor_packages: + os.putenv("LLDB_TEST_USE_VENDOR_PACKAGES", "1") + wrapper_args = sys.argv[1:] dotest_args = [] # split on an empty string will produce [''] and if you |