[Lldb-commits] [lldb] [LLDB] Add Lexer (with tests) for DIL (Data Inspection Language). (PR #123521)
labath wrote: I agree with everything except for the last part. The current parser already threats `[]` [very specially](https://github.com/llvm/llvm-project/blob/89ca3e72ca03efbbfb5ae9b1c71d81f2d1753521/lldb/source/Target/StackFrame.cpp#L781). I think it has to do that so it can treat pointers as C arrays (and then it just special cases synthetic objects). I think that's a (mostly *) reasonable setup that we could replicate in the new DIL implementation, particularly as we would need special handling of `[]` to implement things like `[i+1]`. FWIW, I believe that the main source of keywords in Caroline's implementation is types (for casts). I think they could be handled generically (just ask the target whether the identifier names a type), were it not for the nasty C(++) habit of creating multiword types (`unsigned long long long long int`). Still, it feels there ought to be recognise these without making `unsigned` a full-fledged keyword. (*) I was recently made aware of an unfortunate difference in behavior of `frame var` and `expr` for map types: ``` (lldb) v m (std::map) m = size=3 { [0] = (first = -42, second = -47) [1] = (first = 0, second = 42) [2] = (first = 42, second = 47) } (lldb) v m[0] (std::__1::__value_type::value_type) m[0] = (first = -42, second = -47) (lldb) expr m[0] (std::map::mapped_type) $0 = 42 ``` I know that these are different languages, but this still seems like it could confuse some people. I don't have any specific ideas on how to fix/improve this though... https://github.com/llvm/llvm-project/pull/123521 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Fix Block::GetRangeIndexContainingAddress for discontinuous functions (PR #124931)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Pavel Labath (labath) Changes This is a followup to #122440, which changed function-relative calculations to use the function entry point rather than the lowest address of the function (but missed this usage). Like in #116777, the logic is changed to use file addresses instead of section offsets (as not all parts of the function have to be in the same section). --- Full diff: https://github.com/llvm/llvm-project/pull/124931.diff 2 Files Affected: - (modified) lldb/source/Symbol/Block.cpp (+19-32) - (modified) lldb/test/Shell/ScriptInterpreter/Python/sb_function_ranges.s (+24-13) ``diff diff --git a/lldb/source/Symbol/Block.cpp b/lldb/source/Symbol/Block.cpp index 139fa06d08fca5..bddb015333e09c 100644 --- a/lldb/source/Symbol/Block.cpp +++ b/lldb/source/Symbol/Block.cpp @@ -243,25 +243,15 @@ bool Block::GetRangeContainingAddress(const Address &addr, AddressRange &range) { Function *function = CalculateSymbolContextFunction(); if (function) { -const AddressRange &func_range = function->GetAddressRange(); -if (addr.GetModule() == func_range.GetBaseAddress().GetModule()) { - const addr_t file_addr = addr.GetFileAddress(); - const addr_t func_file_addr = - func_range.GetBaseAddress().GetFileAddress(); - if (file_addr >= func_file_addr && - file_addr < func_file_addr + func_range.GetByteSize()) { -addr_t offset = file_addr - func_file_addr; - -const Range *range_ptr = m_ranges.FindEntryThatContains(offset); - -if (range_ptr) { - range.GetBaseAddress() = - Address(func_file_addr + range_ptr->GetRangeBase(), - addr.GetModule()->GetSectionList()); - range.SetByteSize(range_ptr->GetByteSize()); - return true; -} - } +if (uint32_t idx = GetRangeIndexContainingAddress(addr); +idx != UINT32_MAX) { + const Range *range_ptr = m_ranges.GetEntryAtIndex(idx); + assert(range_ptr); + + range.GetBaseAddress() = function->GetAddress(); + range.GetBaseAddress().Slide(range_ptr->GetRangeBase()); + range.SetByteSize(range_ptr->GetByteSize()); + return true; } } range.Clear(); @@ -278,19 +268,16 @@ bool Block::GetRangeContainingLoadAddress(lldb::addr_t load_addr, uint32_t Block::GetRangeIndexContainingAddress(const Address &addr) { Function *function = CalculateSymbolContextFunction(); - if (function) { -const AddressRange &func_range = function->GetAddressRange(); -if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) { - const addr_t addr_offset = addr.GetOffset(); - const addr_t func_offset = func_range.GetBaseAddress().GetOffset(); - if (addr_offset >= func_offset && - addr_offset < func_offset + func_range.GetByteSize()) { -addr_t offset = addr_offset - func_offset; -return m_ranges.FindEntryIndexThatContains(offset); - } -} - } - return UINT32_MAX; + if (!function) +return UINT32_MAX; + + const Address &func_addr = function->GetAddress(); + if (addr.GetModule() != func_addr.GetModule()) +return UINT32_MAX; + + const addr_t file_addr = addr.GetFileAddress(); + const addr_t func_file_addr = func_addr.GetFileAddress(); + return m_ranges.FindEntryIndexThatContains(file_addr - func_file_addr); } bool Block::GetRangeAtIndex(uint32_t range_idx, AddressRange &range) { diff --git a/lldb/test/Shell/ScriptInterpreter/Python/sb_function_ranges.s b/lldb/test/Shell/ScriptInterpreter/Python/sb_function_ranges.s index 2e2bc52cd3ff99..4d42c50467da06 100644 --- a/lldb/test/Shell/ScriptInterpreter/Python/sb_function_ranges.s +++ b/lldb/test/Shell/ScriptInterpreter/Python/sb_function_ranges.s @@ -6,15 +6,22 @@ # CHECK: Found 1 function(s). # CHECK: foo: [input.o[0x0-0xe), input.o[0x14-0x1c)] -# CHECK-NEXT: input.o[0x0]: cmpl $0x0, %edi -# CHECK-NEXT: input.o[0x3]: je 0x14 -# CHECK-NEXT: input.o[0x5]: jmp0x7 -# CHECK-NEXT: input.o[0x7]: callq 0xe -# CHECK-NEXT: input.o[0xc]: jmp0x1b +# CHECK-NEXT: input.o[0x0]: callq 0xe +# CHECK-NEXT: input.o[0x5]: jmp0x1b +# CHECK-NEXT: input.o[0x7]: cmpl $0x0, %edi +# CHECK-NEXT: input.o[0xa]: je 0x14 +# CHECK-NEXT: input.o[0xc]: jmp0x0 # CHECK-EMPTY: # CHECK-NEXT: input.o[0x14]: callq 0x19 # CHECK-NEXT: input.o[0x19]: jmp0x1b # CHECK-NEXT: input.o[0x1b]: retq +# CHECK-NEXT: offset 0x00 => index 0 +# CHECK-NEXT: offset 0x0c => index 0 +# CHECK-NEXT: offset 0x0e => index +# CHECK-NEXT: offset 0x13 => index +# CHECK-NEXT: offset 0x14 => index 1 +# CHECK-NEXT: offset 0x1b => index 1 +# CHECK-NEXT: offset 0x1c => index #--- script.py @@ -28,6 +35,10 @@ def __lldb_init_module(debugger, internal_dict): fn = ctx.function print(f"{fn.name}: {fn.GetRanges()}") print(fn.GetInstructions(target)) +text = fn.addr.section +
[Lldb-commits] [lldb] [lldb] Fix Block::GetRangeIndexContainingAddress for discontinuous functions (PR #124931)
https://github.com/labath created https://github.com/llvm/llvm-project/pull/124931 This is a followup to #122440, which changed function-relative calculations to use the function entry point rather than the lowest address of the function (but missed this usage). Like in #116777, the logic is changed to use file addresses instead of section offsets (as not all parts of the function have to be in the same section). >From 7e4fa296561789ae95980ac0c1468573e80ef0cc Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Wed, 29 Jan 2025 16:15:44 +0100 Subject: [PATCH] [lldb] Fix Block::GetRangeIndexContainingAddress for discontinuous functions This is a followup to #122440, which changed function-relative calculations to use the function entry point rather than the lowest address of the function (but missed this usage). Like in #116777, the logic is changed to use file addresses instead of section offsets (as not all parts of the function have to be in the same section). --- lldb/source/Symbol/Block.cpp | 51 +++ .../Python/sb_function_ranges.s | 37 +- 2 files changed, 43 insertions(+), 45 deletions(-) diff --git a/lldb/source/Symbol/Block.cpp b/lldb/source/Symbol/Block.cpp index 139fa06d08fca5..bddb015333e09c 100644 --- a/lldb/source/Symbol/Block.cpp +++ b/lldb/source/Symbol/Block.cpp @@ -243,25 +243,15 @@ bool Block::GetRangeContainingAddress(const Address &addr, AddressRange &range) { Function *function = CalculateSymbolContextFunction(); if (function) { -const AddressRange &func_range = function->GetAddressRange(); -if (addr.GetModule() == func_range.GetBaseAddress().GetModule()) { - const addr_t file_addr = addr.GetFileAddress(); - const addr_t func_file_addr = - func_range.GetBaseAddress().GetFileAddress(); - if (file_addr >= func_file_addr && - file_addr < func_file_addr + func_range.GetByteSize()) { -addr_t offset = file_addr - func_file_addr; - -const Range *range_ptr = m_ranges.FindEntryThatContains(offset); - -if (range_ptr) { - range.GetBaseAddress() = - Address(func_file_addr + range_ptr->GetRangeBase(), - addr.GetModule()->GetSectionList()); - range.SetByteSize(range_ptr->GetByteSize()); - return true; -} - } +if (uint32_t idx = GetRangeIndexContainingAddress(addr); +idx != UINT32_MAX) { + const Range *range_ptr = m_ranges.GetEntryAtIndex(idx); + assert(range_ptr); + + range.GetBaseAddress() = function->GetAddress(); + range.GetBaseAddress().Slide(range_ptr->GetRangeBase()); + range.SetByteSize(range_ptr->GetByteSize()); + return true; } } range.Clear(); @@ -278,19 +268,16 @@ bool Block::GetRangeContainingLoadAddress(lldb::addr_t load_addr, uint32_t Block::GetRangeIndexContainingAddress(const Address &addr) { Function *function = CalculateSymbolContextFunction(); - if (function) { -const AddressRange &func_range = function->GetAddressRange(); -if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) { - const addr_t addr_offset = addr.GetOffset(); - const addr_t func_offset = func_range.GetBaseAddress().GetOffset(); - if (addr_offset >= func_offset && - addr_offset < func_offset + func_range.GetByteSize()) { -addr_t offset = addr_offset - func_offset; -return m_ranges.FindEntryIndexThatContains(offset); - } -} - } - return UINT32_MAX; + if (!function) +return UINT32_MAX; + + const Address &func_addr = function->GetAddress(); + if (addr.GetModule() != func_addr.GetModule()) +return UINT32_MAX; + + const addr_t file_addr = addr.GetFileAddress(); + const addr_t func_file_addr = func_addr.GetFileAddress(); + return m_ranges.FindEntryIndexThatContains(file_addr - func_file_addr); } bool Block::GetRangeAtIndex(uint32_t range_idx, AddressRange &range) { diff --git a/lldb/test/Shell/ScriptInterpreter/Python/sb_function_ranges.s b/lldb/test/Shell/ScriptInterpreter/Python/sb_function_ranges.s index 2e2bc52cd3ff99..4d42c50467da06 100644 --- a/lldb/test/Shell/ScriptInterpreter/Python/sb_function_ranges.s +++ b/lldb/test/Shell/ScriptInterpreter/Python/sb_function_ranges.s @@ -6,15 +6,22 @@ # CHECK: Found 1 function(s). # CHECK: foo: [input.o[0x0-0xe), input.o[0x14-0x1c)] -# CHECK-NEXT: input.o[0x0]: cmpl $0x0, %edi -# CHECK-NEXT: input.o[0x3]: je 0x14 -# CHECK-NEXT: input.o[0x5]: jmp0x7 -# CHECK-NEXT: input.o[0x7]: callq 0xe -# CHECK-NEXT: input.o[0xc]: jmp0x1b +# CHECK-NEXT: input.o[0x0]: callq 0xe +# CHECK-NEXT: input.o[0x5]: jmp0x1b +# CHECK-NEXT: input.o[0x7]: cmpl $0x0, %edi +# CHECK-NEXT: input.o[0xa]: je 0x14 +# CHECK-NEXT: input.o[0xc]: jmp0x0 # CHECK-EMPTY: # CHECK-NEXT: input.o[0x14]: callq 0x19 # CHECK-NEXT: input.o[0x19]: jmp0x1b # CHECK-NEXT: input.o[0x1b]: retq +
[Lldb-commits] [lldb] 9ea64dd - [lldb] Make Python >= 3.8 required for LLDB 21 (#124735)
Author: David Spickett Date: 2025-01-29T09:56:41Z New Revision: 9ea64dd8781328d831d7c69a586f0c84dece1c11 URL: https://github.com/llvm/llvm-project/commit/9ea64dd8781328d831d7c69a586f0c84dece1c11 DIFF: https://github.com/llvm/llvm-project/commit/9ea64dd8781328d831d7c69a586f0c84dece1c11.diff LOG: [lldb] Make Python >= 3.8 required for LLDB 21 (#124735) As decided on https://discourse.llvm.org/t/rfc-lets-document-and-enforce-a-minimum-python-version-for-lldb/82731. LLDB 20 recommended `>= 3.8` but did not remove support for anything earlier. Now we are in what will become LLDB 21, so I'm removing that support and making `>= 3.8` required. See https://docs.python.org/3/c-api/apiabiversion.html#c.PY_VERSION_HEX for the format of PY_VERSION_HEX. Added: Modified: lldb/docs/resources/build.rst lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp llvm/docs/ReleaseNotes.md Removed: diff --git a/lldb/docs/resources/build.rst b/lldb/docs/resources/build.rst index c0d3c580d631c1..214c5f63f2c73b 100644 --- a/lldb/docs/resources/build.rst +++ b/lldb/docs/resources/build.rst @@ -62,7 +62,7 @@ CMake configuration error. +---+--+--+ | Libxml2 | XML | ``LLDB_ENABLE_LIBXML2`` | +---+--+--+ -| Python| Python scripting. >= 3.0 is required, >= 3.8 is recommended. | ``LLDB_ENABLE_PYTHON`` | +| Python| Python scripting. >= 3.8 is required. | ``LLDB_ENABLE_PYTHON`` | +---+--+--+ | Lua | Lua scripting. Lua 5.3 and 5.4 are supported. | ``LLDB_ENABLE_LUA`` | +---+--+--+ diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index a0f8cf954f8040..1340425aade438 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -73,10 +73,8 @@ Expected python::As(Expected &&obj) { static bool python_is_finalizing() { #if PY_VERSION_HEX >= 0x030d return Py_IsFinalizing(); -#elif PY_VERSION_HEX >= 0x0307 - return _Py_IsFinalizing(); #else - return _Py_Finalizing != nullptr; + return _Py_IsFinalizing(); #endif } @@ -810,7 +808,6 @@ bool PythonCallable::Check(PyObject *py_obj) { return PyCallable_Check(py_obj); } -#if PY_VERSION_HEX >= 0x0303 static const char get_arg_info_script[] = R"( from inspect import signature, Parameter, ismethod from collections import namedtuple @@ -832,15 +829,12 @@ def main(f): raise Exception(f'unknown parameter kind: {kind}') return ArgInfo(count, varargs) )"; -#endif Expected PythonCallable::GetArgInfo() const { ArgInfo result = {}; if (!IsValid()) return nullDeref(); -#if PY_VERSION_HEX >= 0x0303 - // no need to synchronize access to this global, we already have the GIL static PythonScript get_arg_info(get_arg_info_script); Expected pyarginfo = get_arg_info(*this); @@ -852,57 +846,6 @@ Expected PythonCallable::GetArgInfo() const { cantFail(As(pyarginfo.get().GetAttribute("has_varargs"))); result.max_positional_args = has_varargs ? ArgInfo::UNBOUNDED : count; -#else - PyObject *py_func_obj; - bool is_bound_method = false; - bool is_class = false; - - if (PyType_Check(m_py_obj) || PyClass_Check(m_py_obj)) { -auto init = GetAttribute("__init__"); -if (!init) - return init.takeError(); -py_func_obj = init.get().get(); -is_class = true; - } else { -py_func_obj = m_py_obj; - } - - if (PyMethod_Check(py_func_obj)) { -py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); -PythonObject im_self = GetAttributeValue("im_self"); -if (im_self.IsValid() && !im_self.IsNone()) - is_bound_method = true; - } else { -// see if this is a callable object with an __call__ method -if (!PyFunction_Check(py_func_obj)) { - PythonObject __call__ = GetAttributeValue("__call__"); - if (__call__.IsValid()) { -auto __callable__ = __call__.AsType(); -if (__callable__.IsValid()) { - py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); - PythonObject im_self = __callable
[Lldb-commits] [lldb] [llvm] [lldb] Make Python >= 3.8 required for LLDB 21 (PR #124735)
https://github.com/DavidSpickett closed https://github.com/llvm/llvm-project/pull/124735 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -5028,48 +5021,128 @@ int main(int argc, char *argv[]) { #endif // Initialize LLDB first before we do anything. - lldb::SBDebugger::Initialize(); + lldb::SBError error = lldb::SBDebugger::InitializeWithErrorHandling(); + if (error.Fail()) { +llvm::errs() << "Failed to initialize LLDB: " << error.GetCString() << "\n"; +return EXIT_FAILURE; + } // Terminate the debugger before the C++ destructor chain kicks in. auto terminate_debugger = llvm::make_scope_exit([] { lldb::SBDebugger::Terminate(); }); - DAP dap = DAP(program_path.str(), default_repl_mode); + auto HandleClient = [=](int out_fd, int err_fd, StreamDescriptor input, + StreamDescriptor output) { +DAP dap = DAP(program_path, log, default_repl_mode, pre_init_commands); +dap.input.descriptor = std::move(input); +dap.output.descriptor = std::move(output); +RegisterRequestCallbacks(dap); + +if (auto Err = dap.ConfigureIO(out_fd, err_fd)) { + if (log) +*log << "configureIO failed: " << llvm::toStringWithoutConsuming(Err) + << "\n"; + std::cerr << "failed to configureIO: " << llvm::toString(std::move(Err)) labath wrote: That's good but beware `os << error` does not "consume" (set the ["checked" bit](https://llvm.org/docs/ProgrammersManual.html#recoverable-errors)), on the llvm::Error object (which means it will trigger an assert in debug mode). You need to consume it somehow, e.g., via toString, or `logAllUnhandledErrors` (the latter works best when the entire "main" function is wrapped in something returning an error object https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [lldb] Make Python >= 3.8 required for LLDB 21 (PR #124735)
https://github.com/DavidSpickett edited https://github.com/llvm/llvm-project/pull/124735 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] db567ea - [lldb][NFC] Format part of ScriptInterpreterPython.cpp
Author: David Spickett Date: 2025-01-29T09:59:34Z New Revision: db567eaca07133a374991153635a119d9eec066b URL: https://github.com/llvm/llvm-project/commit/db567eaca07133a374991153635a119d9eec066b DIFF: https://github.com/llvm/llvm-project/commit/db567eaca07133a374991153635a119d9eec066b.diff LOG: [lldb][NFC] Format part of ScriptInterpreterPython.cpp Was flagged in https://github.com/llvm/llvm-project/pull/124735 but done separately so it didn't get in the way of that. Added: Modified: lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp Removed: diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index e78e6068debb4f..f4efb00161f8b8 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -152,12 +152,14 @@ struct InitializePythonRAII { private: void InitializeThreadsPrivate() { -// Since Python 3.7 `Py_Initialize` calls `PyEval_InitThreads` inside itself, -// so there is no way to determine whether the embedded interpreter -// was already initialized by some external code. `PyEval_ThreadsInitialized` -// would always return `true` and `PyGILState_Ensure/Release` flow would be -// executed instead of unlocking GIL with `PyEval_SaveThread`. When -// an another thread calls `PyGILState_Ensure` it would get stuck in deadlock. +// Since Python 3.7 `Py_Initialize` calls `PyEval_InitThreads` inside +// itself, so there is no way to determine whether the embedded interpreter +// was already initialized by some external code. +// `PyEval_ThreadsInitialized` would always return `true` and +// `PyGILState_Ensure/Release` flow would be executed instead of unlocking +// GIL with `PyEval_SaveThread`. When an another thread calls +// `PyGILState_Ensure` it would get stuck in deadlock. + // The only case we should go further and acquire the GIL: it is unlocked. if (PyGILState_Check()) return; ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -5058,72 +5053,148 @@ int main(int argc, char *argv[]) { auto terminate_debugger = llvm::make_scope_exit([] { lldb::SBDebugger::Terminate(); }); - StreamDescriptor input; - StreamDescriptor output; - std::FILE *redirectOut = nullptr; - std::FILE *redirectErr = nullptr; - if (portno != -1) { -printf("Listening on port %i...\n", portno); -SOCKET socket_fd = AcceptConnection(log.get(), portno); -if (socket_fd < 0) - return EXIT_FAILURE; + std::vector pre_init_commands; + for (const std::string &arg : + input_args.getAllArgValues(OPT_pre_init_command)) { +pre_init_commands.push_back(arg); + } -input = StreamDescriptor::from_socket(socket_fd, true); -output = StreamDescriptor::from_socket(socket_fd, false); - } else { -#if defined(_WIN32) -// Windows opens stdout and stdin in text mode which converts \n to 13,10 -// while the value is just 10 on Darwin/Linux. Setting the file mode to -// binary fixes this. -int result = _setmode(fileno(stdout), _O_BINARY); -assert(result); -result = _setmode(fileno(stdin), _O_BINARY); -UNUSED_IF_ASSERT_DISABLED(result); -assert(result); -#endif + auto HandleClient = + [=, log = log.get()](std::string name, StreamDescriptor input, + StreamDescriptor output, std::FILE *redirectOut, + std::FILE *redirectErr) -> bool { +DAP dap = DAP(name, program_path.str(), log, default_repl_mode, + std::move(input), std::move(output)); -int stdout_fd = DuplicateFileDescriptor(fileno(stdout)); -if (stdout_fd == -1) { +// stdout/stderr redirection to the IDE's console +if (auto Err = dap.ConfigureIO(redirectOut, redirectErr)) { llvm::logAllUnhandledErrors( - llvm::errorCodeToError(llvm::errnoAsErrorCode()), llvm::errs(), - "Failed to configure stdout redirect: "); + std::move(Err), llvm::errs(), + "Failed to configure lldb-dap IO operations: "); return EXIT_FAILURE; } -redirectOut = stdout; -redirectErr = stderr; +RegisterRequestCallbacks(dap); -input = StreamDescriptor::from_file(fileno(stdin), false); -output = StreamDescriptor::from_file(stdout_fd, false); - } +dap.pre_init_commands = pre_init_commands; - DAP dap = DAP(program_path.str(), log.get(), default_repl_mode, -std::move(input), std::move(output)); +// used only by TestVSCode_redirection_to_console.py +if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) + redirection_test(); - // stdout/stderr redirection to the IDE's console - if (auto Err = dap.ConfigureIO(redirectOut, redirectErr)) { -llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), -"Failed to configure lldb-dap IO operations: "); -return EXIT_FAILURE; - } +if (auto Err = dap.Loop()) { + if (log) +*log << "Transport Error: " << llvm::toString(std::move(Err)) << "\n"; + return false; +} +return true; + }; - RegisterRequestCallbacks(dap); + if (!connection.empty()) { +auto maybeProtoclAndName = parseConnection(connection); +if (auto Err = maybeProtoclAndName.takeError()) { + llvm::errs() << "Invalid connection specification " << Err << "\n"; + return EXIT_FAILURE; +} - for (const std::string &arg : - input_args.getAllArgValues(OPT_pre_init_command)) { -dap.pre_init_commands.push_back(arg); - } +Socket::SocketProtocol protocol; +std::string name; +std::tie(protocol, name) = *maybeProtoclAndName; - // used only by TestVSCode_redirection_to_console.py - if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) -redirection_test(); +Status error; +std::unique_ptr listener = Socket::Create(protocol, error); +if (error.Fail()) { + llvm::errs() << "Failed to create listener for protocol " + << Socket::FindSchemeByProtocol(protocol) + << ", error: " << error.takeError() << "\n"; + return EXIT_FAILURE; +} - bool CleanExit = true; - if (auto Err = dap.Loop()) { +error = listener->Listen(name, /* backlog */ 5); +if (error.Fail()) { + llvm::errs() << "Failed to listen, error: " << error.takeError() << "\n"; + return EXIT_FAILURE; +} + +std::string address = +llvm::join(listener->GetListeningConnectionURI(), ", "); if (log) - *log << "Transport Error: " << llvm::toString(std::move(Err)) << "\n"; -CleanExit = false; + *log << "started with connection listeners " << address << "\n"; + +llvm::outs() << "Listening for: " << address << "\n"; +// Ensure listening address are flushed for calles to retrieve the resolve +// address. +llvm::outs().flush(); + +MainLoop mainloop; +mainloop.RegisterSignal( +SIGHUP, [](auto &RL) { RL.RequestTermination(); }, error); + +unsigne
[Lldb-commits] [lldb] [llvm] [lldb] Make Python >= 3.8 required for LLDB 21 (PR #124735)
https://github.com/DavidSpickett updated https://github.com/llvm/llvm-project/pull/124735 >From 08c47efd81fba63f252467bf7af48549ba4b62d5 Mon Sep 17 00:00:00 2001 From: David Spickett Date: Tue, 28 Jan 2025 10:58:34 + Subject: [PATCH] [lldb] Make Python >= 3.8 required for LLDB 21 As decided on https://discourse.llvm.org/t/rfc-lets-document-and-enforce-a-minimum-python-version-for-lldb/82731. LLDB 20 recommended >= 3.8 but did not remove support for anything earlier. Now we are in what will become LLDB 21, so I'm removing that support and making >= 3.8 required. See https://docs.python.org/3/c-api/apiabiversion.html#c.PY_VERSION_HEX for the format of PY_VERSION_HEX. --- lldb/docs/resources/build.rst | 2 +- .../Python/PythonDataObjects.cpp | 59 +-- .../Python/ScriptInterpreterPython.cpp| 27 + .../ScriptInterpreter/Python/lldb-python.h| 4 +- .../Python/PythonDataObjectsTests.cpp | 6 -- llvm/docs/ReleaseNotes.md | 3 + 6 files changed, 8 insertions(+), 93 deletions(-) diff --git a/lldb/docs/resources/build.rst b/lldb/docs/resources/build.rst index c0d3c580d631c1..214c5f63f2c73b 100644 --- a/lldb/docs/resources/build.rst +++ b/lldb/docs/resources/build.rst @@ -62,7 +62,7 @@ CMake configuration error. +---+--+--+ | Libxml2 | XML | ``LLDB_ENABLE_LIBXML2`` | +---+--+--+ -| Python| Python scripting. >= 3.0 is required, >= 3.8 is recommended. | ``LLDB_ENABLE_PYTHON`` | +| Python| Python scripting. >= 3.8 is required. | ``LLDB_ENABLE_PYTHON`` | +---+--+--+ | Lua | Lua scripting. Lua 5.3 and 5.4 are supported. | ``LLDB_ENABLE_LUA`` | +---+--+--+ diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index a0f8cf954f8040..1340425aade438 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -73,10 +73,8 @@ Expected python::As(Expected &&obj) { static bool python_is_finalizing() { #if PY_VERSION_HEX >= 0x030d return Py_IsFinalizing(); -#elif PY_VERSION_HEX >= 0x0307 - return _Py_IsFinalizing(); #else - return _Py_Finalizing != nullptr; + return _Py_IsFinalizing(); #endif } @@ -810,7 +808,6 @@ bool PythonCallable::Check(PyObject *py_obj) { return PyCallable_Check(py_obj); } -#if PY_VERSION_HEX >= 0x0303 static const char get_arg_info_script[] = R"( from inspect import signature, Parameter, ismethod from collections import namedtuple @@ -832,15 +829,12 @@ def main(f): raise Exception(f'unknown parameter kind: {kind}') return ArgInfo(count, varargs) )"; -#endif Expected PythonCallable::GetArgInfo() const { ArgInfo result = {}; if (!IsValid()) return nullDeref(); -#if PY_VERSION_HEX >= 0x0303 - // no need to synchronize access to this global, we already have the GIL static PythonScript get_arg_info(get_arg_info_script); Expected pyarginfo = get_arg_info(*this); @@ -852,57 +846,6 @@ Expected PythonCallable::GetArgInfo() const { cantFail(As(pyarginfo.get().GetAttribute("has_varargs"))); result.max_positional_args = has_varargs ? ArgInfo::UNBOUNDED : count; -#else - PyObject *py_func_obj; - bool is_bound_method = false; - bool is_class = false; - - if (PyType_Check(m_py_obj) || PyClass_Check(m_py_obj)) { -auto init = GetAttribute("__init__"); -if (!init) - return init.takeError(); -py_func_obj = init.get().get(); -is_class = true; - } else { -py_func_obj = m_py_obj; - } - - if (PyMethod_Check(py_func_obj)) { -py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); -PythonObject im_self = GetAttributeValue("im_self"); -if (im_self.IsValid() && !im_self.IsNone()) - is_bound_method = true; - } else { -// see if this is a callable object with an __call__ method -if (!PyFunction_Check(py_func_obj)) { - PythonObject __call__ = GetAttributeValue("__call__"); - if (__call__.IsValid()) { -auto __callable__ = __call__.AsType(); -if (__callable__.IsValid()) { - py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); - PythonObject im_self = __callable__.GetAttributeValue("im_self"); - if (im_self.IsValid() && !im_self.IsNone()) -is_bound_method = true; -} -
[Lldb-commits] [lldb] [llvm] [lldb] Make Python >= 3.8 required for LLDB 21 (PR #124735)
https://github.com/DavidSpickett edited https://github.com/llvm/llvm-project/pull/124735 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Remove some unused code in SymbolFileDWARF::ResolveFunction (PR #123206)
labath wrote: ping https://github.com/llvm/llvm-project/pull/123206 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Use Function::GetAddress in Module::FindFunctions (PR #124938)
https://github.com/labath created https://github.com/llvm/llvm-project/pull/124938 The original code resulted in a misfire in the symtab vs. debug info deduplication code, which caused us to return the same function twice when searching via a regex (for functions whose entry point is also not the lowest address). >From b67f966fb8ccac4bed71701136b95f73ff0d6394 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Wed, 29 Jan 2025 16:53:04 +0100 Subject: [PATCH] [lldb] Use Function::GetAddress in Module::FindFunctions The original code resulted in a misfire in the symtab vs. debug info deduplication code, which caused us to return the same function twice when searching via a regex (for functions whose entry point is also not the lowest address). --- lldb/source/Core/Module.cpp | 5 ++--- .../DWARF/x86/discontinuous-function.s| 20 +++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index 9601c834d9b8fec..33668c5d20dde41 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -919,9 +919,8 @@ void Module::FindFunctions(const RegularExpression ®ex, const SymbolContext &sc = sc_list[i]; if (sc.block) continue; - file_addr_to_index[sc.function->GetAddressRange() - .GetBaseAddress() - .GetFileAddress()] = i; + file_addr_to_index[sc.function->GetAddress().GetFileAddress()] = + i; } FileAddrToIndexMap::const_iterator end = file_addr_to_index.end(); diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/discontinuous-function.s b/lldb/test/Shell/SymbolFile/DWARF/x86/discontinuous-function.s index 93ea9f33e762df7..197ab9aa14910e7 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/x86/discontinuous-function.s +++ b/lldb/test/Shell/SymbolFile/DWARF/x86/discontinuous-function.s @@ -6,17 +6,29 @@ # The function bar has been placed "in the middle" of foo, and the function # entry point is deliberately not its lowest address. -# RUN: llvm-mc -triple x86_64-pc-linux -filetype=obj %s -o %t -# RUN: %lldb %t -o "image lookup -v -n foo" -o "expr -- &foo" -o exit | FileCheck %s +# RUN: split-file %s %t +# RUN: llvm-mc -triple x86_64-pc-linux -filetype=obj %t/input.s -o %t/input.o +# RUN: %lldb %t/input.o -s %t/commands -o exit | FileCheck %s -# CHECK-LABEL: image lookup +#--- commands + +image lookup -v -n foo +# CHECK-LABEL: image lookup -v -n foo +# CHECK: 1 match found in {{.*}} +# CHECK: Summary: input.o`foo +# CHECK: Function: id = {{.*}}, name = "foo", ranges = [0x-0x000e)[0x0014-0x001c) + +image lookup -v --regex -n '^foo$' +# CHECK-LABEL: image lookup -v --regex -n '^foo$' # CHECK: 1 match found in {{.*}} -# CHECK: Summary: {{.*}}`foo +# CHECK: Summary: input.o`foo # CHECK: Function: id = {{.*}}, name = "foo", ranges = [0x-0x000e)[0x0014-0x001c) +expr -- &foo # CHECK-LABEL: expr -- &foo # CHECK: (void (*)()) $0 = 0x0007 +#--- input.s .text foo.__part.1: ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Extended if conditions to support alias names for registers (PR #124475)
https://github.com/kper updated https://github.com/llvm/llvm-project/pull/124475 >From 096eb85718d70721cec1e539cfa4b05a96475c7a Mon Sep 17 00:00:00 2001 From: Kevin Per Date: Sun, 26 Jan 2025 17:34:17 + Subject: [PATCH 1/6] lldb: Extended if conditions to support alias names for registers --- .../Plugins/ABI/RISCV/ABISysV_riscv.cpp | 54 +++ 1 file changed, 54 insertions(+) diff --git a/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp b/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp index 8412991933d277..c463bd006b3db4 100644 --- a/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp +++ b/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp @@ -850,8 +850,62 @@ void ABISysV_riscv::AugmentRegisterInfo( it.value().alt_name.SetCString("x3"); else if (it.value().name == "fp") it.value().alt_name.SetCString("s0"); +else if (it.value().name == "tp") + it.value().alt_name.SetCString("x4"); else if (it.value().name == "s0") it.value().alt_name.SetCString("x8"); +else if (it.value().name == "s1") + it.value().alt_name.SetCString("x9"); +else if (it.value().name == "t0") + it.value().alt_name.SetCString("x5"); +else if (it.value().name == "t1") + it.value().alt_name.SetCString("x6"); +else if (it.value().name == "t2") + it.value().alt_name.SetCString("x7"); +else if (it.value().name == "a0") + it.value().alt_name.SetCString("x10"); +else if (it.value().name == "a1") + it.value().alt_name.SetCString("x11"); +else if (it.value().name == "a2") + it.value().alt_name.SetCString("x12"); +else if (it.value().name == "a3") + it.value().alt_name.SetCString("x13"); +else if (it.value().name == "a4") + it.value().alt_name.SetCString("x14"); +else if (it.value().name == "a5") + it.value().alt_name.SetCString("x15"); +else if (it.value().name == "a6") + it.value().alt_name.SetCString("x16"); +else if (it.value().name == "a7") + it.value().alt_name.SetCString("x17"); +else if (it.value().name == "s2") + it.value().alt_name.SetCString("x18"); +else if (it.value().name == "s3") + it.value().alt_name.SetCString("x19"); +else if (it.value().name == "s4") + it.value().alt_name.SetCString("x20"); +else if (it.value().name == "s5") + it.value().alt_name.SetCString("x21"); +else if (it.value().name == "s6") + it.value().alt_name.SetCString("x22"); +else if (it.value().name == "s7") + it.value().alt_name.SetCString("x23"); +else if (it.value().name == "s8") + it.value().alt_name.SetCString("x24"); +else if (it.value().name == "s9") + it.value().alt_name.SetCString("x25"); +else if (it.value().name == "s10") + it.value().alt_name.SetCString("x26"); +else if (it.value().name == "s11") + it.value().alt_name.SetCString("x27"); +else if (it.value().name == "t3") + it.value().alt_name.SetCString("x28"); +else if (it.value().name == "t4") + it.value().alt_name.SetCString("x29"); +else if (it.value().name == "t5") + it.value().alt_name.SetCString("x30"); +else if (it.value().name == "t6") + it.value().alt_name.SetCString("x31"); // Set generic regnum so lldb knows what the PC, etc is it.value().regnum_generic = GetGenericNum(it.value().name.GetStringRef()); >From ad3dfa270953a04f755773c402941fd10165a098 Mon Sep 17 00:00:00 2001 From: Kevin Per Date: Tue, 28 Jan 2025 15:23:54 + Subject: [PATCH 2/6] Added RISCV reg test for the ServerTargetXML --- .../TestGDBServerTargetXML.py | 149 ++ 1 file changed, 149 insertions(+) diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py b/lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py index 22f5553e40802d..c74726a88aa6ff 100644 --- a/lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py +++ b/lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py @@ -652,6 +652,155 @@ def haltReason(self): ) self.match("register read s31", ["s31 = 128"]) +@skipIfXmlSupportMissing +@skipIfRemote +@skipIfLLVMTargetMissing("RISCV") +def test_riscv64_regs(self): +"""Test grabbing various riscv64 registers from gdbserver.""" + +class MyResponder(MockGDBServerResponder): +reg_data = ( +( +"0102030405060708" # zero +"0102030405060708" # ra +"0102030405060708" # sp +"0102030405060708" # gp +"0102030405060708" # tp +"0102030405060708" # t0 +"0102030405060708" # t1 +"0102030405060708" # t2 +"0102030405060708" # fp +"0102030405060708" # s1 +"0102030405060708" # a0 +"01
[Lldb-commits] [lldb] [lldb] Remove PATH workaround for Android (PR #124682)
https://github.com/labath approved this pull request. https://github.com/llvm/llvm-project/pull/124682 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] 9326633 - [lldb] Remove PATH workaround for Android (#124682)
Author: Brad Smith Date: 2025-01-29T03:21:45-05:00 New Revision: 9326633abd0e59fc77072488ee8cded4fe83c8a1 URL: https://github.com/llvm/llvm-project/commit/9326633abd0e59fc77072488ee8cded4fe83c8a1 DIFF: https://github.com/llvm/llvm-project/commit/9326633abd0e59fc77072488ee8cded4fe83c8a1.diff LOG: [lldb] Remove PATH workaround for Android (#124682) Added: Modified: lldb/source/Host/posix/ProcessLauncherPosixFork.cpp Removed: diff --git a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp index 7d856954684c49..3e956290c3055a 100644 --- a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp +++ b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp @@ -230,16 +230,6 @@ MakeForkActions(const ProcessLaunchInfo &info) { return result; } -static Environment::Envp FixupEnvironment(Environment env) { -#ifdef __ANDROID__ - // If there is no PATH variable specified inside the environment then set the - // path to /system/bin. It is required because the default path used by - // execve() is wrong on android. - env.try_emplace("PATH", "/system/bin"); -#endif - return env.getEnvp(); -} - ForkLaunchInfo::ForkLaunchInfo(const ProcessLaunchInfo &info) : separate_process_group( info.GetFlags().Test(eLaunchFlagLaunchInSeparateProcessGroup)), @@ -247,8 +237,7 @@ ForkLaunchInfo::ForkLaunchInfo(const ProcessLaunchInfo &info) disable_aslr(info.GetFlags().Test(eLaunchFlagDisableASLR)), wd(info.GetWorkingDirectory().GetPath()), argv(info.GetArguments().GetConstArgumentVector()), - envp(FixupEnvironment(info.GetEnvironment())), - actions(MakeForkActions(info)) {} + envp(info.GetEnvironment().getEnvp()), actions(MakeForkActions(info)) {} HostProcess ProcessLauncherPosixFork::LaunchProcess(const ProcessLaunchInfo &launch_info, ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Remove PATH workaround for Android (PR #124682)
https://github.com/brad0 closed https://github.com/llvm/llvm-project/pull/124682 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -5058,72 +5053,148 @@ int main(int argc, char *argv[]) { auto terminate_debugger = llvm::make_scope_exit([] { lldb::SBDebugger::Terminate(); }); - StreamDescriptor input; - StreamDescriptor output; - std::FILE *redirectOut = nullptr; - std::FILE *redirectErr = nullptr; - if (portno != -1) { -printf("Listening on port %i...\n", portno); -SOCKET socket_fd = AcceptConnection(log.get(), portno); -if (socket_fd < 0) - return EXIT_FAILURE; + std::vector pre_init_commands; + for (const std::string &arg : + input_args.getAllArgValues(OPT_pre_init_command)) { +pre_init_commands.push_back(arg); + } -input = StreamDescriptor::from_socket(socket_fd, true); -output = StreamDescriptor::from_socket(socket_fd, false); - } else { -#if defined(_WIN32) -// Windows opens stdout and stdin in text mode which converts \n to 13,10 -// while the value is just 10 on Darwin/Linux. Setting the file mode to -// binary fixes this. -int result = _setmode(fileno(stdout), _O_BINARY); -assert(result); -result = _setmode(fileno(stdin), _O_BINARY); -UNUSED_IF_ASSERT_DISABLED(result); -assert(result); -#endif + auto HandleClient = + [=, log = log.get()](std::string name, StreamDescriptor input, + StreamDescriptor output, std::FILE *redirectOut, + std::FILE *redirectErr) -> bool { +DAP dap = DAP(name, program_path.str(), log, default_repl_mode, + std::move(input), std::move(output)); -int stdout_fd = DuplicateFileDescriptor(fileno(stdout)); -if (stdout_fd == -1) { +// stdout/stderr redirection to the IDE's console +if (auto Err = dap.ConfigureIO(redirectOut, redirectErr)) { llvm::logAllUnhandledErrors( - llvm::errorCodeToError(llvm::errnoAsErrorCode()), llvm::errs(), - "Failed to configure stdout redirect: "); + std::move(Err), llvm::errs(), + "Failed to configure lldb-dap IO operations: "); return EXIT_FAILURE; } -redirectOut = stdout; -redirectErr = stderr; +RegisterRequestCallbacks(dap); -input = StreamDescriptor::from_file(fileno(stdin), false); -output = StreamDescriptor::from_file(stdout_fd, false); - } +dap.pre_init_commands = pre_init_commands; - DAP dap = DAP(program_path.str(), log.get(), default_repl_mode, -std::move(input), std::move(output)); +// used only by TestVSCode_redirection_to_console.py +if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) + redirection_test(); - // stdout/stderr redirection to the IDE's console - if (auto Err = dap.ConfigureIO(redirectOut, redirectErr)) { -llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), -"Failed to configure lldb-dap IO operations: "); -return EXIT_FAILURE; - } +if (auto Err = dap.Loop()) { + if (log) +*log << "Transport Error: " << llvm::toString(std::move(Err)) << "\n"; + return false; +} +return true; + }; - RegisterRequestCallbacks(dap); + if (!connection.empty()) { +auto maybeProtoclAndName = parseConnection(connection); +if (auto Err = maybeProtoclAndName.takeError()) { + llvm::errs() << "Invalid connection specification " << Err << "\n"; + return EXIT_FAILURE; +} - for (const std::string &arg : - input_args.getAllArgValues(OPT_pre_init_command)) { -dap.pre_init_commands.push_back(arg); - } +Socket::SocketProtocol protocol; +std::string name; +std::tie(protocol, name) = *maybeProtoclAndName; - // used only by TestVSCode_redirection_to_console.py - if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) -redirection_test(); +Status error; +std::unique_ptr listener = Socket::Create(protocol, error); +if (error.Fail()) { + llvm::errs() << "Failed to create listener for protocol " + << Socket::FindSchemeByProtocol(protocol) + << ", error: " << error.takeError() << "\n"; + return EXIT_FAILURE; +} - bool CleanExit = true; - if (auto Err = dap.Loop()) { +error = listener->Listen(name, /* backlog */ 5); +if (error.Fail()) { + llvm::errs() << "Failed to listen, error: " << error.takeError() << "\n"; + return EXIT_FAILURE; +} + +std::string address = +llvm::join(listener->GetListeningConnectionURI(), ", "); if (log) - *log << "Transport Error: " << llvm::toString(std::move(Err)) << "\n"; -CleanExit = false; + *log << "started with connection listeners " << address << "\n"; + +llvm::outs() << "Listening for: " << address << "\n"; +// Ensure listening address are flushed for calles to retrieve the resolve +// address. +llvm::outs().flush(); + +MainLoop mainloop; +mainloop.RegisterSignal( +SIGHUP, [](auto &RL) { RL.RequestTermination(); }, error); --
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -5058,72 +5053,148 @@ int main(int argc, char *argv[]) { auto terminate_debugger = llvm::make_scope_exit([] { lldb::SBDebugger::Terminate(); }); - StreamDescriptor input; - StreamDescriptor output; - std::FILE *redirectOut = nullptr; - std::FILE *redirectErr = nullptr; - if (portno != -1) { -printf("Listening on port %i...\n", portno); -SOCKET socket_fd = AcceptConnection(log.get(), portno); -if (socket_fd < 0) - return EXIT_FAILURE; + std::vector pre_init_commands; + for (const std::string &arg : + input_args.getAllArgValues(OPT_pre_init_command)) { +pre_init_commands.push_back(arg); + } -input = StreamDescriptor::from_socket(socket_fd, true); -output = StreamDescriptor::from_socket(socket_fd, false); - } else { -#if defined(_WIN32) -// Windows opens stdout and stdin in text mode which converts \n to 13,10 -// while the value is just 10 on Darwin/Linux. Setting the file mode to -// binary fixes this. -int result = _setmode(fileno(stdout), _O_BINARY); -assert(result); -result = _setmode(fileno(stdin), _O_BINARY); -UNUSED_IF_ASSERT_DISABLED(result); -assert(result); -#endif + auto HandleClient = + [=, log = log.get()](std::string name, StreamDescriptor input, + StreamDescriptor output, std::FILE *redirectOut, + std::FILE *redirectErr) -> bool { +DAP dap = DAP(name, program_path.str(), log, default_repl_mode, + std::move(input), std::move(output)); -int stdout_fd = DuplicateFileDescriptor(fileno(stdout)); -if (stdout_fd == -1) { +// stdout/stderr redirection to the IDE's console +if (auto Err = dap.ConfigureIO(redirectOut, redirectErr)) { llvm::logAllUnhandledErrors( - llvm::errorCodeToError(llvm::errnoAsErrorCode()), llvm::errs(), - "Failed to configure stdout redirect: "); + std::move(Err), llvm::errs(), + "Failed to configure lldb-dap IO operations: "); return EXIT_FAILURE; } -redirectOut = stdout; -redirectErr = stderr; +RegisterRequestCallbacks(dap); -input = StreamDescriptor::from_file(fileno(stdin), false); -output = StreamDescriptor::from_file(stdout_fd, false); - } +dap.pre_init_commands = pre_init_commands; - DAP dap = DAP(program_path.str(), log.get(), default_repl_mode, -std::move(input), std::move(output)); +// used only by TestVSCode_redirection_to_console.py +if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) + redirection_test(); - // stdout/stderr redirection to the IDE's console - if (auto Err = dap.ConfigureIO(redirectOut, redirectErr)) { -llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), -"Failed to configure lldb-dap IO operations: "); -return EXIT_FAILURE; - } +if (auto Err = dap.Loop()) { + if (log) +*log << "Transport Error: " << llvm::toString(std::move(Err)) << "\n"; + return false; +} +return true; + }; - RegisterRequestCallbacks(dap); + if (!connection.empty()) { +auto maybeProtoclAndName = parseConnection(connection); +if (auto Err = maybeProtoclAndName.takeError()) { + llvm::errs() << "Invalid connection specification " << Err << "\n"; + return EXIT_FAILURE; +} - for (const std::string &arg : - input_args.getAllArgValues(OPT_pre_init_command)) { -dap.pre_init_commands.push_back(arg); - } +Socket::SocketProtocol protocol; +std::string name; +std::tie(protocol, name) = *maybeProtoclAndName; - // used only by TestVSCode_redirection_to_console.py - if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) -redirection_test(); +Status error; +std::unique_ptr listener = Socket::Create(protocol, error); +if (error.Fail()) { + llvm::errs() << "Failed to create listener for protocol " + << Socket::FindSchemeByProtocol(protocol) + << ", error: " << error.takeError() << "\n"; + return EXIT_FAILURE; +} - bool CleanExit = true; - if (auto Err = dap.Loop()) { +error = listener->Listen(name, /* backlog */ 5); +if (error.Fail()) { + llvm::errs() << "Failed to listen, error: " << error.takeError() << "\n"; + return EXIT_FAILURE; +} + +std::string address = +llvm::join(listener->GetListeningConnectionURI(), ", "); if (log) - *log << "Transport Error: " << llvm::toString(std::move(Err)) << "\n"; -CleanExit = false; + *log << "started with connection listeners " << address << "\n"; + +llvm::outs() << "Listening for: " << address << "\n"; +// Ensure listening address are flushed for calles to retrieve the resolve +// address. +llvm::outs().flush(); + +MainLoop mainloop; +mainloop.RegisterSignal( +SIGHUP, [](auto &RL) { RL.RequestTermination(); }, error); + +unsigne
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -5058,72 +5053,148 @@ int main(int argc, char *argv[]) { auto terminate_debugger = llvm::make_scope_exit([] { lldb::SBDebugger::Terminate(); }); - StreamDescriptor input; - StreamDescriptor output; - std::FILE *redirectOut = nullptr; - std::FILE *redirectErr = nullptr; - if (portno != -1) { -printf("Listening on port %i...\n", portno); -SOCKET socket_fd = AcceptConnection(log.get(), portno); -if (socket_fd < 0) - return EXIT_FAILURE; + std::vector pre_init_commands; + for (const std::string &arg : + input_args.getAllArgValues(OPT_pre_init_command)) { +pre_init_commands.push_back(arg); + } -input = StreamDescriptor::from_socket(socket_fd, true); -output = StreamDescriptor::from_socket(socket_fd, false); - } else { -#if defined(_WIN32) -// Windows opens stdout and stdin in text mode which converts \n to 13,10 -// while the value is just 10 on Darwin/Linux. Setting the file mode to -// binary fixes this. -int result = _setmode(fileno(stdout), _O_BINARY); -assert(result); -result = _setmode(fileno(stdin), _O_BINARY); -UNUSED_IF_ASSERT_DISABLED(result); -assert(result); -#endif + auto HandleClient = + [=, log = log.get()](std::string name, StreamDescriptor input, + StreamDescriptor output, std::FILE *redirectOut, + std::FILE *redirectErr) -> bool { +DAP dap = DAP(name, program_path.str(), log, default_repl_mode, + std::move(input), std::move(output)); -int stdout_fd = DuplicateFileDescriptor(fileno(stdout)); -if (stdout_fd == -1) { +// stdout/stderr redirection to the IDE's console +if (auto Err = dap.ConfigureIO(redirectOut, redirectErr)) { llvm::logAllUnhandledErrors( - llvm::errorCodeToError(llvm::errnoAsErrorCode()), llvm::errs(), - "Failed to configure stdout redirect: "); + std::move(Err), llvm::errs(), + "Failed to configure lldb-dap IO operations: "); return EXIT_FAILURE; } -redirectOut = stdout; -redirectErr = stderr; +RegisterRequestCallbacks(dap); -input = StreamDescriptor::from_file(fileno(stdin), false); -output = StreamDescriptor::from_file(stdout_fd, false); - } +dap.pre_init_commands = pre_init_commands; - DAP dap = DAP(program_path.str(), log.get(), default_repl_mode, -std::move(input), std::move(output)); +// used only by TestVSCode_redirection_to_console.py +if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) + redirection_test(); - // stdout/stderr redirection to the IDE's console - if (auto Err = dap.ConfigureIO(redirectOut, redirectErr)) { -llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), -"Failed to configure lldb-dap IO operations: "); -return EXIT_FAILURE; - } +if (auto Err = dap.Loop()) { + if (log) +*log << "Transport Error: " << llvm::toString(std::move(Err)) << "\n"; + return false; +} +return true; + }; - RegisterRequestCallbacks(dap); + if (!connection.empty()) { +auto maybeProtoclAndName = parseConnection(connection); +if (auto Err = maybeProtoclAndName.takeError()) { + llvm::errs() << "Invalid connection specification " << Err << "\n"; + return EXIT_FAILURE; +} - for (const std::string &arg : - input_args.getAllArgValues(OPT_pre_init_command)) { -dap.pre_init_commands.push_back(arg); - } +Socket::SocketProtocol protocol; +std::string name; +std::tie(protocol, name) = *maybeProtoclAndName; - // used only by TestVSCode_redirection_to_console.py - if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) -redirection_test(); +Status error; +std::unique_ptr listener = Socket::Create(protocol, error); +if (error.Fail()) { + llvm::errs() << "Failed to create listener for protocol " + << Socket::FindSchemeByProtocol(protocol) + << ", error: " << error.takeError() << "\n"; + return EXIT_FAILURE; +} - bool CleanExit = true; - if (auto Err = dap.Loop()) { +error = listener->Listen(name, /* backlog */ 5); +if (error.Fail()) { + llvm::errs() << "Failed to listen, error: " << error.takeError() << "\n"; + return EXIT_FAILURE; +} + +std::string address = +llvm::join(listener->GetListeningConnectionURI(), ", "); if (log) - *log << "Transport Error: " << llvm::toString(std::move(Err)) << "\n"; -CleanExit = false; + *log << "started with connection listeners " << address << "\n"; + +llvm::outs() << "Listening for: " << address << "\n"; +// Ensure listening address are flushed for calles to retrieve the resolve +// address. +llvm::outs().flush(); + +MainLoop mainloop; +mainloop.RegisterSignal( +SIGHUP, [](auto &RL) { RL.RequestTermination(); }, error); + +unsigne
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -1167,21 +1168,61 @@ def __init__( if log_file: adaptor_env["LLDBDAP_LOG"] = log_file +args = [executable] + +if connection is not None: +args.append("--connection") +args.append(connection) + self.process = subprocess.Popen( -[executable], +args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=adaptor_env, ) + +if connection is not None: +# If the process was also launched, parse the connection from the +# resolved connection. For example, if the connection +# `connection://localhost:0` was specified then the OS would pick a +# random port for listening and lldb-dap would print the listening +# port to stdout. +if self.process is not None: +# lldb-dap will print the listening address once the listener is +# made to stdout. The listener is formatted like +# `connection://host:port` or `unix-connection:///path`. +expected_prefix = "Listening for: " +out = self.process.stdout.readline().decode() +if not out.startswith(expected_prefix): +self.process.kill() +raise ValueError( +"lldb-dap failed to print listening address, expected '{}', got '{}'".format( +expected_prefix, out +) +) + +# If the listener expanded into multiple addresses, use the first. +connection = ( + out.removeprefix(expected_prefix).rstrip("\r\n").split(",", 1)[0] +) + +if connection.startswith("unix-connect://"): # unix-connect:///path labath wrote: How about something like: ```suggestion scheme, address = connection.split("://") if connection == "unix-connect": # unix-connect:///path # etc. ``` https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -4952,6 +4930,28 @@ static int DuplicateFileDescriptor(int fd) { #endif } +static llvm::Expected> +parseConnection(llvm::StringRef conn) { + if (conn.contains("://")) { labath wrote: It looks like this could use `lldb/Utility/URIParser.h` https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
https://github.com/labath edited https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
https://github.com/labath commented: I think this looks pretty good now. Just a couple of questions from my side. https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [lldb][Windows] WoA HW Watchpoint support in LLDB (PR #108072)
omjavaid wrote: > ### Known Issues (Just for documentation): > 1. I have updates the PR description the "Known Issues (Just for documentation):" part will be skipped in the final patch description. https://github.com/llvm/llvm-project/pull/108072 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [lldb][Windows] WoA HW Watchpoint support in LLDB (PR #108072)
https://github.com/omjavaid edited https://github.com/llvm/llvm-project/pull/108072 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [lldb] Change lldb's breakpoint detection behavior [WIP] (PR #105594)
https://github.com/jasonmolenda updated https://github.com/llvm/llvm-project/pull/105594 >From 56ca564185bdceea25162a1ce3b1e8c8fa2641e2 Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Fri, 19 Jul 2024 17:26:13 -0700 Subject: [PATCH 1/8] [lldb] Change lldb's breakpoint handling behavior (#96260) lldb today has two rules: When a thread stops at a BreakpointSite, we set the thread's StopReason to be "breakpoint hit" (regardless if we've actually hit the breakpoint, or if we've merely stopped *at* the breakpoint instruction/point and haven't tripped it yet). And second, when resuming a process, any thread sitting at a BreakpointSite is silently stepped over the BreakpointSite -- because we've already flagged the breakpoint hit when we stopped there originally. In this patch, I change lldb to only set a thread's stop reason to breakpoint-hit when we've actually executed the instruction/triggered the breakpoint. When we resume, we only silently step past a BreakpointSite that we've registered as hit. We preserve this state across inferior function calls that the user may do while stopped, etc. Also, when a user adds a new breakpoint at $pc while stopped, or changes $pc to be the address of a BreakpointSite, we will silently step past that breakpoint when the process resumes. This is purely a UX call, I don't think there's any person who wants to set a breakpoint at $pc and then hit it immediately on resuming. One non-intuitive UX from this change, but I'm convinced it is necessary: If you're stopped at a BreakpointSite that has not yet executed, you `stepi`, you will hit the breakpoint and the pc will not yet advance. This thread has not completed its stepi, and the thread plan is still on the stack. If you then `continue` the thread, lldb will now stop and say, "instruction step completed", one instruction past the BreakpointSite. You can continue a second time to resume execution. I discussed this with Jim, and trying to paper over this behavior will lead to more complicated scenarios behaving non-intuitively. And mostly it's the testsuite that was trying to instruction step past a breakpoint and getting thrown off -- and I changed those tests to expect the new behavior. The bugs driving this change are all from lldb dropping the real stop reason for a thread and setting it to breakpoint-hit when that was not the case. Jim hit one where we have an aarch64 watchpoint that triggers one instruction before a BreakpointSite. On this arch we are notified of the watchpoint hit after the instruction has been unrolled -- we disable the watchpoint, instruction step, re-enable the watchpoint and collect the new value. But now we're on a BreakpointSite so the watchpoint-hit stop reason is lost. Another was reported by ZequanWu in https://discourse.llvm.org/t/lldb-unable-to-break-at-start/78282 we attach to/launch a process with the pc at a BreakpointSite and misbehave. Caroline Tice mentioned it is also a problem they've had with putting a breakpoint on _dl_debug_state. The change to each Process plugin that does execution control is that 1. If we've stopped at a BreakpointSite that has not been executed yet, we will call Thread::SetThreadStoppedAtUnexecutedBP(pc) to record that. When the thread resumes, if the pc is still at the same site, we will continue, hit the breakpoint, and stop again. 2. When we've actually hit a breakpoint (enabled for this thread or not), the Process plugin should call Thread::SetThreadHitBreakpointSite(). When we go to resume the thread, we will push a step-over-breakpoint ThreadPlan before resuming. The biggest set of changes is to StopInfoMachException where we translate a Mach Exception into a stop reason. The Mach exception codes differ in a few places depending on the target (unambiguously), and I didn't want to duplicate the new code for each target so I've tested what mach exceptions we get for each action on each target, and reorganized StopInfoMachException::CreateStopReasonWithMachException to document these possible values, and handle them without specializing based on the target arch. rdar://123942164 --- lldb/include/lldb/Target/Thread.h | 24 ++ .../Process/Utility/StopInfoMachException.cpp | 322 -- .../Process/Windows/Common/ProcessWindows.cpp | 32 +- .../Process/gdb-remote/ProcessGDBRemote.cpp | 93 ++--- .../Process/scripted/ScriptedThread.cpp | 11 + lldb/source/Target/StopInfo.cpp | 2 + lldb/source/Target/Thread.cpp | 15 +- .../TestConsecutiveBreakpoints.py | 26 +- .../TestStepOverBreakpoint.py | 6 +- 9 files changed, 266 insertions(+), 265 deletions(-) diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index 38b65b2bc58490..22d452c7b4b8a3 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -131,6 +131,7 @@ class Thread : public std::enable_shared_from_this, register
[Lldb-commits] [lldb] Only include necessary files in the lldb-dap VSIX (PR #124986)
https://github.com/matthewbastien created https://github.com/llvm/llvm-project/pull/124986 The published VSIX for the LLDB DAP extension contains a bunch of unnecessary files: ``` ❯ tar tf llvm-vs-code-extensions.lldb-dap-0.2.8.vsix extension.vsixmanifest [Content_Types].xml extension/.github/workflows/auto_publish.yml extension/.github/workflows/integrate_llvmproject.yml extension/.gitignore extension/.vscode/launch.json extension/.vscode/tasks.json extension/LICENSE.TXT extension/out/debug-adapter-factory.js extension/out/debug-adapter-factory.js.map extension/out/disposable-context.js extension/out/disposable-context.js.map extension/out/extension.js extension/out/extension.js.map extension/out/types.js extension/out/types.js.map extension/package.json extension/README.md extension/src-ts/debug-adapter-factory.ts extension/src-ts/disposable-context.ts extension/src-ts/extension.ts extension/src-ts/types.ts extension/syntaxes/arm.disasm extension/syntaxes/arm64.disasm extension/syntaxes/disassembly.json extension/syntaxes/x86.disasm extension/tsconfig.json ``` All that's really needed is the package.json, license, README, syntaxes folder, and compiled sources. This PR adds a `.vscodeignore` file that requires files and directories to be explicitly added to the VSIX. >From d98d57a5f0df75aee5196e3e4046a7f68f4dc0d6 Mon Sep 17 00:00:00 2001 From: Matthew Bastien Date: Wed, 29 Jan 2025 16:02:11 -0500 Subject: [PATCH] only include necessary files in the lldb-dap VSIX --- lldb/tools/lldb-dap/.vscodeignore | 9 + 1 file changed, 9 insertions(+) create mode 100644 lldb/tools/lldb-dap/.vscodeignore diff --git a/lldb/tools/lldb-dap/.vscodeignore b/lldb/tools/lldb-dap/.vscodeignore new file mode 100644 index 00..0491ba879fc3f0 --- /dev/null +++ b/lldb/tools/lldb-dap/.vscodeignore @@ -0,0 +1,9 @@ +// Ignore everything by default +**/* + +// Only include specific files and directories +!LICENSE.TXT +!package.json +!README.md +!out/** +!syntaxes/** ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Only include necessary files in the lldb-dap VSIX (PR #124986)
github-actions[bot] wrote: Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using `@` followed by their GitHub username. If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the [LLVM GitHub User Guide](https://llvm.org/docs/GitHub.html). You can also ask questions in a comment on this PR, on the [LLVM Discord](https://discord.com/invite/xS7Z362) or on the [forums](https://discourse.llvm.org/). https://github.com/llvm/llvm-project/pull/124986 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [lldb][Windows] WoA HW Watchpoint support in LLDB (PR #108072)
@@ -110,8 +110,8 @@ NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows( NativeRegisterContextWindows_x86_64::NativeRegisterContextWindows_x86_64( const ArchSpec &target_arch, NativeThreadProtocol &native_thread) -: NativeRegisterContextWindows(native_thread, - CreateRegisterInfoInterface(target_arch)) {} +: NativeRegisterContextRegisterInfo( + native_thread, CreateRegisterInfoInterface(target_arch)) {} omjavaid wrote: Yes. Correct. NativeRegisterContextWindows_arm64 class now inherits from both NativeRegisterContextWindows and NativeRegisterContextDBReg_arm64 but both of these classes previously inherited from NativeRegisterContextRegisterInfo non-virtually. This caused multiple instances of NativeRegisterContextRegisterInfo in the hierarchy. I have now changed NativeRegisterContextWindows definition to inherit NativeRegisterContextRegisterInfo virtually which shifts the responsibility of initializing NativeRegisterContextRegisterInfo to the most derived class. Thats why this and other similar changes have been made. https://github.com/llvm/llvm-project/pull/108072 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [lldb] Change lldb's breakpoint detection behavior [WIP] (PR #105594)
https://github.com/jasonmolenda updated https://github.com/llvm/llvm-project/pull/105594 >From 56ca564185bdceea25162a1ce3b1e8c8fa2641e2 Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Fri, 19 Jul 2024 17:26:13 -0700 Subject: [PATCH 1/7] [lldb] Change lldb's breakpoint handling behavior (#96260) lldb today has two rules: When a thread stops at a BreakpointSite, we set the thread's StopReason to be "breakpoint hit" (regardless if we've actually hit the breakpoint, or if we've merely stopped *at* the breakpoint instruction/point and haven't tripped it yet). And second, when resuming a process, any thread sitting at a BreakpointSite is silently stepped over the BreakpointSite -- because we've already flagged the breakpoint hit when we stopped there originally. In this patch, I change lldb to only set a thread's stop reason to breakpoint-hit when we've actually executed the instruction/triggered the breakpoint. When we resume, we only silently step past a BreakpointSite that we've registered as hit. We preserve this state across inferior function calls that the user may do while stopped, etc. Also, when a user adds a new breakpoint at $pc while stopped, or changes $pc to be the address of a BreakpointSite, we will silently step past that breakpoint when the process resumes. This is purely a UX call, I don't think there's any person who wants to set a breakpoint at $pc and then hit it immediately on resuming. One non-intuitive UX from this change, but I'm convinced it is necessary: If you're stopped at a BreakpointSite that has not yet executed, you `stepi`, you will hit the breakpoint and the pc will not yet advance. This thread has not completed its stepi, and the thread plan is still on the stack. If you then `continue` the thread, lldb will now stop and say, "instruction step completed", one instruction past the BreakpointSite. You can continue a second time to resume execution. I discussed this with Jim, and trying to paper over this behavior will lead to more complicated scenarios behaving non-intuitively. And mostly it's the testsuite that was trying to instruction step past a breakpoint and getting thrown off -- and I changed those tests to expect the new behavior. The bugs driving this change are all from lldb dropping the real stop reason for a thread and setting it to breakpoint-hit when that was not the case. Jim hit one where we have an aarch64 watchpoint that triggers one instruction before a BreakpointSite. On this arch we are notified of the watchpoint hit after the instruction has been unrolled -- we disable the watchpoint, instruction step, re-enable the watchpoint and collect the new value. But now we're on a BreakpointSite so the watchpoint-hit stop reason is lost. Another was reported by ZequanWu in https://discourse.llvm.org/t/lldb-unable-to-break-at-start/78282 we attach to/launch a process with the pc at a BreakpointSite and misbehave. Caroline Tice mentioned it is also a problem they've had with putting a breakpoint on _dl_debug_state. The change to each Process plugin that does execution control is that 1. If we've stopped at a BreakpointSite that has not been executed yet, we will call Thread::SetThreadStoppedAtUnexecutedBP(pc) to record that. When the thread resumes, if the pc is still at the same site, we will continue, hit the breakpoint, and stop again. 2. When we've actually hit a breakpoint (enabled for this thread or not), the Process plugin should call Thread::SetThreadHitBreakpointSite(). When we go to resume the thread, we will push a step-over-breakpoint ThreadPlan before resuming. The biggest set of changes is to StopInfoMachException where we translate a Mach Exception into a stop reason. The Mach exception codes differ in a few places depending on the target (unambiguously), and I didn't want to duplicate the new code for each target so I've tested what mach exceptions we get for each action on each target, and reorganized StopInfoMachException::CreateStopReasonWithMachException to document these possible values, and handle them without specializing based on the target arch. rdar://123942164 --- lldb/include/lldb/Target/Thread.h | 24 ++ .../Process/Utility/StopInfoMachException.cpp | 322 -- .../Process/Windows/Common/ProcessWindows.cpp | 32 +- .../Process/gdb-remote/ProcessGDBRemote.cpp | 93 ++--- .../Process/scripted/ScriptedThread.cpp | 11 + lldb/source/Target/StopInfo.cpp | 2 + lldb/source/Target/Thread.cpp | 15 +- .../TestConsecutiveBreakpoints.py | 26 +- .../TestStepOverBreakpoint.py | 6 +- 9 files changed, 266 insertions(+), 265 deletions(-) diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index 38b65b2bc58490..22d452c7b4b8a3 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -131,6 +131,7 @@ class Thread : public std::enable_shared_from_this, register
[Lldb-commits] [lldb] [LLDB] Add Lexer (with tests) for DIL (Data Inspection Language). (PR #123521)
@@ -0,0 +1,189 @@ +//===-- DILLexer.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 +// +// This implements the recursive descent parser for the Data Inspection +// Language (DIL), and its helper functions, which will eventually underlie the +// 'frame variable' command. The language that this parser recognizes is +// described in lldb/docs/dil-expr-lang.ebnf +// +//===--===// + +#include "lldb/ValueObject/DILLexer.h" +#include "lldb/Utility/Status.h" +#include "llvm/ADT/StringSwitch.h" + +namespace lldb_private { + +namespace dil { + +llvm::StringRef Token::GetTokenName(Kind kind) { + switch (kind) { + case Kind::coloncolon: +return "coloncolon"; + case Kind::eof: +return "eof"; + case Kind::identifier: +return "identifier"; + case Kind::invalid: +return "invalid"; + case Kind::kw_namespace: +return "namespace"; + case Kind::l_paren: +return "l_paren"; + case Kind::none: +return "none"; + case Kind::r_paren: +return "r_paren"; + case Kind::unknown: +return "unknown"; + } +} + +static bool IsLetter(char c) { + return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); +} + +static bool IsDigit(char c) { return '0' <= c && c <= '9'; } + +// A word starts with a letter, underscore, or dollar sign, followed by +// letters ('a'..'z','A'..'Z'), digits ('0'..'9'), and/or underscores. +llvm::iterator_range DILLexer::IsWord() { + llvm::StringRef::iterator start = m_cur_pos; + bool dollar_start = false; + + // Must not start with a digit. + if (m_cur_pos == m_expr.end() || IsDigit(*m_cur_pos)) +return llvm::make_range(m_cur_pos, m_cur_pos); + + // First character *may* be a '$', for a register name or convenience + // variable. + if (*m_cur_pos == '$') { +dollar_start = true; +++m_cur_pos; + } + + // Contains only letters, digits or underscores + for (; m_cur_pos != m_expr.end(); ++m_cur_pos) { +char c = *m_cur_pos; +if (!IsLetter(c) && !IsDigit(c) && c != '_') + break; + } + + // If first char is '$', make sure there's at least one mare char, or it's + // invalid. + if (dollar_start && (m_cur_pos - start <= 1)) { +m_cur_pos = start; +return llvm::make_range(start, start); // Empty range + } + + return llvm::make_range(start, m_cur_pos); +} + +void DILLexer::UpdateLexedTokens(Token &result, Token::Kind tok_kind, + std::string tok_str, uint32_t tok_pos) { + Token new_token(tok_kind, tok_str, tok_pos); + result = new_token; + m_lexed_tokens.push_back(std::move(new_token)); +} + +llvm::Expected DILLexer::LexAll() { + bool done = false; + while (!done) { +auto tok_or_err = Lex(); +if (!tok_or_err) + return tok_or_err.takeError(); +Token token = *tok_or_err; +if (token.GetKind() == Token::eof) { + done = true; +} + } + return true; +} + +llvm::Expected DILLexer::Lex() { + Token result; + + // Skip over whitespace (spaces). + while (m_cur_pos != m_expr.end() && *m_cur_pos == ' ') +m_cur_pos++; + + // Check to see if we've reached the end of our input string. + if (m_cur_pos == m_expr.end()) { +UpdateLexedTokens(result, Token::eof, "", (uint32_t)m_expr.size()); +return result; + } + + uint32_t position = m_cur_pos - m_expr.begin(); + llvm::StringRef::iterator start = m_cur_pos; + llvm::iterator_range word_range = IsWord(); + if (!word_range.empty()) { +uint32_t length = word_range.end() - word_range.begin(); +llvm::StringRef word(m_expr.substr(position, length)); +// We will be adding more keywords here in the future... +Token::Kind kind = llvm::StringSwitch(word) + .Case("namespace", Token::kw_namespace) + .Default(Token::identifier); +UpdateLexedTokens(result, kind, word.str(), position); +return result; + } + + m_cur_pos = start; + llvm::StringRef remainder(m_expr.substr(position, m_expr.end() - m_cur_pos)); + std::vector> operators = { + {Token::l_paren, "("}, + {Token::r_paren, ")"}, + {Token::coloncolon, "::"}, + }; + for (auto [kind, str] : operators) { +if (remainder.consume_front(str)) { + m_cur_pos += strlen(str); + UpdateLexedTokens(result, kind, str, position); + return result; +} + } + + // Unrecognized character(s) in string; unable to lex it. + Status error("Unable to lex input string"); + return error.ToError(); +} + +const Token &DILLexer::LookAhead(uint32_t N) { + if (m_tokens_idx + N + 1 < m_lexed_tokens.size()) cmtice wrote: I think the "infinite" stream of eof tokens at the end is ok; I will give it a try. :-) https://github.com/llvm/llvm-project/pull/123521 __
[Lldb-commits] [lldb] [lldb] Remove some unused code in SymbolFileDWARF::ResolveFunction (PR #123206)
https://github.com/labath closed https://github.com/llvm/llvm-project/pull/123206 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] 3cf56b5 - [lldb] Remove some unused code in SymbolFileDWARF::ResolveFunction (#123206)
Author: Pavel Labath Date: 2025-01-30T08:24:40+01:00 New Revision: 3cf56b5f04cdec567cfab3975ac7b531422c1e2c URL: https://github.com/llvm/llvm-project/commit/3cf56b5f04cdec567cfab3975ac7b531422c1e2c DIFF: https://github.com/llvm/llvm-project/commit/3cf56b5f04cdec567cfab3975ac7b531422c1e2c.diff LOG: [lldb] Remove some unused code in SymbolFileDWARF::ResolveFunction (#123206) The purpose of this originally was to check for DWARF which refers to garbage-collected functions (by checking whether we're able to get a good address out of the function). The address check has been removed in https://reviews.llvm.org/D112310, so the code computing it is not doing anything. Added: Modified: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Removed: diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index afc37f517559ee4..a96757afabddf2e 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -2455,18 +2455,12 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, } assert(die && die.Tag() == DW_TAG_subprogram); if (GetFunction(die, sc)) { -Address addr; // Parse all blocks if needed if (inlined_die) { Block &function_block = sc.function->GetBlock(true); sc.block = function_block.FindBlockByID(inlined_die.GetID()); if (sc.block == nullptr) sc.block = function_block.FindBlockByID(inlined_die.GetOffset()); - if (sc.block == nullptr || !sc.block->GetStartAddress(addr)) -addr.Clear(); -} else { - sc.block = nullptr; - addr = sc.function->GetAddressRange().GetBaseAddress(); } sc_list.Append(sc); ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Remove some unused code in SymbolFileDWARF::ResolveFunction (PR #123206)
labath wrote: I tend to ignore those because people have very different definitions of NFC, but yeah, I guess this would fit most definitions. https://github.com/llvm/llvm-project/pull/123206 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Use Function::GetAddress in Module::FindFunctions (PR #124938)
labath wrote: There isn't a good reason for using GetAddressRange, and removing it is what I'm trying to do. But rather than trying to do it all at once, I'm doing it in pieces as some of the changes (particularly those that need to iterate over a set of ranges) are not trivial. This way I can also verify that each change does what it's supposed to do. I changed most of the trivial call sites when I introduced GetAddress (in #115836). In retrospect, this is probably trivial enough that it could have been a part of that, but I skipped it then because the mapping part looked scary. https://github.com/llvm/llvm-project/pull/124938 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Only include necessary files in the lldb-dap VSIX (PR #124986)
https://github.com/matthewbastien edited https://github.com/llvm/llvm-project/pull/124986 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Only include necessary files in the lldb-dap VSIX (PR #124986)
https://github.com/matthewbastien edited https://github.com/llvm/llvm-project/pull/124986 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Reland "[lldb] Implement basic support for reverse-continue" (#123906)" (PR #123945)
rocallahan wrote: @DavidSpickett can you apply that change to your branch since this is your PR now? @labath does this pass on x86-via-Rosetta Mac? Should we retry merging with this change? Thanks! https://github.com/llvm/llvm-project/pull/123945 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [lldb][Windows] WoA HW Watchpoint support in LLDB (PR #108072)
https://github.com/omjavaid updated https://github.com/llvm/llvm-project/pull/108072 >From 82ee1429a0fcf67aa36bf6ca7debb5518211d16c Mon Sep 17 00:00:00 2001 From: Muhammad Omair Javaid Date: Tue, 10 Sep 2024 18:03:29 +0500 Subject: [PATCH 1/7] WoA hardware breakpoint/watchpoint support --- .../Windows/Common/NativeProcessWindows.cpp | 52 --- .../Common/NativeRegisterContextWindows.cpp | 3 - .../Common/NativeRegisterContextWindows.h | 6 +- .../NativeRegisterContextWindows_WoW64.cpp| 4 +- .../NativeRegisterContextWindows_arm.cpp | 4 +- .../NativeRegisterContextWindows_arm64.cpp| 86 ++- .../NativeRegisterContextWindows_arm64.h | 32 ++- .../NativeRegisterContextWindows_i386.cpp | 4 +- .../NativeRegisterContextWindows_x86_64.cpp | 4 +- .../Windows/Common/NativeThreadWindows.cpp| 32 +++ 10 files changed, 135 insertions(+), 92 deletions(-) diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp index 9c330ff1186709..f38f6e32fcd90d 100644 --- a/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/NativeProcessWindows.cpp @@ -491,24 +491,47 @@ NativeProcessWindows::OnDebugException(bool first_chance, return ExceptionResult::MaskException; } case DWORD(STATUS_BREAKPOINT): - case STATUS_WX86_BREAKPOINT: -if (FindSoftwareBreakpoint(record.GetExceptionAddress())) { - LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.", - record.GetExceptionAddress()); - - StopThread(record.GetThreadID(), StopReason::eStopReasonBreakpoint); - - if (NativeThreadWindows *stop_thread = - GetThreadByID(record.GetThreadID())) { -auto ®ister_context = stop_thread->GetRegisterContext(); + case STATUS_WX86_BREAKPOINT: { +bool breakpoint_hit = false; +NativeThreadWindows *stop_thread = GetThreadByID(record.GetThreadID()); + +if (stop_thread) { + uint32_t hw_id = LLDB_INVALID_INDEX32; + auto ®_ctx = stop_thread->GetRegisterContext(); + reg_ctx.GetHardwareBreakHitIndex(hw_id, record.GetExceptionAddress()); + if (hw_id != LLDB_INVALID_INDEX32) { +breakpoint_hit = true; +LLDB_LOG(log, "Hit hardware breakpoint at address {0:x}.", + record.GetExceptionAddress()); + } else if (FindSoftwareBreakpoint(record.GetExceptionAddress())) { +breakpoint_hit = true; +LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.", + record.GetExceptionAddress()); uint32_t breakpoint_size = GetSoftwareBreakpointPCOffset(); // The current PC is AFTER the BP opcode, on all architectures. -uint64_t pc = register_context.GetPC() - breakpoint_size; -register_context.SetPC(pc); +uint64_t pc = reg_ctx.GetPC() - breakpoint_size; +reg_ctx.SetPC(pc); } - SetState(eStateStopped, true); - return ExceptionResult::MaskException; + if (breakpoint_hit) { +StopThread(record.GetThreadID(), StopReason::eStopReasonBreakpoint); +SetState(eStateStopped, true); +return ExceptionResult::MaskException; + } else { +const std::vector &args = record.GetExceptionArguments(); +if (args.size() >= 2) { + reg_ctx.GetWatchpointHitIndex(hw_id, args[1]); + if (hw_id != LLDB_INVALID_INDEX32) { +addr_t wp_pc = record.GetExceptionAddress(); +std::string desc = +formatv("{0} {1} {2}", args[1], hw_id, wp_pc).str(); +StopThread(record.GetThreadID(), StopReason::eStopReasonWatchpoint, + desc); +SetState(eStateStopped, true); +return ExceptionResult::MaskException; + } +} + } } if (!initial_stop) { @@ -531,6 +554,7 @@ NativeProcessWindows::OnDebugException(bool first_chance, // Hit the initial stop. Continue the application. return ExceptionResult::BreakInDebugger; } + } [[fallthrough]]; default: diff --git a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.cpp index 9128363eaa577a..95be1183abb759 100644 --- a/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows.cpp @@ -18,9 +18,6 @@ using namespace lldb; using namespace lldb_private; -NativeRegisterContextWindows::NativeRegisterContextWindows( -NativeThreadProtocol &thread, RegisterInfoInterface *reg_info_interface_p) -: NativeRegisterContextRegisterInfo(thread, reg_info_interface_p) {} lldb::thread_t NativeRegisterContextWindows::GetThreadHandle() const { auto wthread = static_cast(&m_thread); diff --git a/lldb/source/Plugins
[Lldb-commits] [lldb] [lldb] Support CommandInterpreter print callbacks (PR #125006)
https://github.com/JDevlieghere created https://github.com/llvm/llvm-project/pull/125006 Xcode uses a pseudoterminal for the debugger console. - The upside of this apporach is that it means that it can rely on LLDB's IOHandlers for multiline and script input. - The downside of this approach is that the command output is printed to the PTY and you don't get a SBCommandReturnObject. Adrian added support for inline diagnostics (#110901) and we'd like to access those from the IDE. This patch adds support for registering a callback in the command interpreter that gives access to the `(SB)CommandReturnObject` right before it will be printed. The callback implementation can choose whether it likes to handle printing the result or defer to lldb. If the callback indicated it handled the result, the command interpreter will skip printing the result. We considered a few other alternatives to solve this problem: - The most obvious one is using `HandleCommand`, which returns a `SBCommandReturnObject`. The problem with this approach is the multiline input mentioned above. We would need a way to tell the IDE that it should expect multiline input, which isn't known until LLDB starts handling the command. - To address the multiline issue,we considered exposing (some of the) IOHandler machinery through the SB API. To solve this particular issue, that would require reimplementing a ton of logic that already exists today in the CommandInterpeter. Furthermore that seems like overkill compared to the proposed solution. rdar://141254310 >From fdac9c0292cef848b880904cf84b2c0083065005 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Tue, 28 Jan 2025 15:43:31 -0800 Subject: [PATCH 1/3] [lldb] Fix CommandInterpreter formatting (NFC) --- .../lldb/Interpreter/CommandInterpreter.h| 16 +++- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/lldb/include/lldb/Interpreter/CommandInterpreter.h b/lldb/include/lldb/Interpreter/CommandInterpreter.h index 2bafc30cc8e23a..910c1d84303354 100644 --- a/lldb/include/lldb/Interpreter/CommandInterpreter.h +++ b/lldb/include/lldb/Interpreter/CommandInterpreter.h @@ -100,8 +100,7 @@ class CommandInterpreterRunOptions { LazyBool stop_on_error, LazyBool stop_on_crash, LazyBool echo_commands, LazyBool echo_comments, LazyBool print_results, LazyBool print_errors, - LazyBool add_to_history, - LazyBool handle_repeats) + LazyBool add_to_history, LazyBool handle_repeats) : m_stop_on_continue(stop_on_continue), m_stop_on_error(stop_on_error), m_stop_on_crash(stop_on_crash), m_echo_commands(echo_commands), m_echo_comment_commands(echo_comments), m_print_results(print_results), @@ -248,13 +247,13 @@ class CommandInterpreter : public Broadcaster, enum CommandTypes { eCommandTypesBuiltin = 0x0001, //< native commands such as "frame" eCommandTypesUserDef = 0x0002, //< scripted commands -eCommandTypesUserMW = 0x0004, //< multiword commands (command containers) +eCommandTypesUserMW = 0x0004, //< multiword commands (command containers) eCommandTypesAliases = 0x0008, //< aliases such as "po" -eCommandTypesHidden = 0x0010, //< commands prefixed with an underscore +eCommandTypesHidden = 0x0010, //< commands prefixed with an underscore eCommandTypesAllThem = 0x //< all commands }; - // The CommandAlias and CommandInterpreter both have a hand in + // The CommandAlias and CommandInterpreter both have a hand in // substituting for alias commands. They work by writing special tokens // in the template form of the Alias command, and then detecting them when the // command is executed. These are the special tokens: @@ -334,9 +333,8 @@ class CommandInterpreter : public Broadcaster, /// dummy "contains everything MWC, so we return null here, but /// in this case error.Success is true. - CommandObjectMultiword *VerifyUserMultiwordCmdPath(Args &path, - bool leaf_is_command, - Status &result); + CommandObjectMultiword * + VerifyUserMultiwordCmdPath(Args &path, bool leaf_is_command, Status &result); CommandAlias *AddAlias(llvm::StringRef alias_name, lldb::CommandObjectSP &command_obj_sp, @@ -596,7 +594,7 @@ class CommandInterpreter : public Broadcaster, void SetEchoCommentCommands(bool enable); bool GetRepeatPreviousCommand() const; - + bool GetRequireCommandOverwrite() const; const CommandObject::CommandMap &GetUserCommands() const { >From e1e8d1487194c4e21cf9724da99588796a03883d Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Tue, 28 Jan 2025 16:10:33 -0800 Subject: [PATCH 2/3] [lldb] Constify methods in
[Lldb-commits] [lldb] [lldb] Support CommandInterpreter print callbacks (PR #125006)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Jonas Devlieghere (JDevlieghere) Changes Xcode uses a pseudoterminal for the debugger console. - The upside of this apporach is that it means that it can rely on LLDB's IOHandlers for multiline and script input. - The downside of this approach is that the command output is printed to the PTY and you don't get a SBCommandReturnObject. Adrian added support for inline diagnostics (#110901) and we'd like to access those from the IDE. This patch adds support for registering a callback in the command interpreter that gives access to the `(SB)CommandReturnObject` right before it will be printed. The callback implementation can choose whether it likes to handle printing the result or defer to lldb. If the callback indicated it handled the result, the command interpreter will skip printing the result. We considered a few other alternatives to solve this problem: - The most obvious one is using `HandleCommand`, which returns a `SBCommandReturnObject`. The problem with this approach is the multiline input mentioned above. We would need a way to tell the IDE that it should expect multiline input, which isn't known until LLDB starts handling the command. - To address the multiline issue,we considered exposing (some of the) IOHandler machinery through the SB API. To solve this particular issue, that would require reimplementing a ton of logic that already exists today in the CommandInterpeter. Furthermore that seems like overkill compared to the proposed solution. rdar://141254310 --- Patch is 25.66 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/125006.diff 17 Files Affected: - (modified) lldb/bindings/python/python-swigsafecast.swig (+4) - (modified) lldb/bindings/python/python-typemaps.swig (+19) - (modified) lldb/bindings/python/python-wrapper.swig (+22-2) - (modified) lldb/include/lldb/API/SBCommandInterpreter.h (+5-3) - (modified) lldb/include/lldb/API/SBCommandReturnObject.h (+2) - (modified) lldb/include/lldb/API/SBDefines.h (+3) - (modified) lldb/include/lldb/Interpreter/CommandInterpreter.h (+20-9) - (modified) lldb/include/lldb/Interpreter/CommandReturnObject.h (+5-5) - (modified) lldb/include/lldb/Utility/StreamTee.h (+1-1) - (modified) lldb/include/lldb/lldb-enumerations.h (+9) - (modified) lldb/source/API/SBCommandInterpreter.cpp (+39-1) - (modified) lldb/source/Interpreter/CommandInterpreter.cpp (+40-20) - (modified) lldb/source/Interpreter/CommandReturnObject.cpp (+3-2) - (modified) lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h (+7-6) - (added) lldb/test/API/python_api/interpreter_callback/Makefile (+3) - (added) lldb/test/API/python_api/interpreter_callback/TestCommandInterepterPrintCallback.py (+66) - (added) lldb/test/API/python_api/interpreter_callback/main.c (+6) ``diff diff --git a/lldb/bindings/python/python-swigsafecast.swig b/lldb/bindings/python/python-swigsafecast.swig index 429baad158ca5d..4721dfdc17e6a0 100644 --- a/lldb/bindings/python/python-swigsafecast.swig +++ b/lldb/bindings/python/python-swigsafecast.swig @@ -9,6 +9,10 @@ PythonObject SWIGBridge::ToSWIGWrapper(std::unique_ptr value_sb) return ToSWIGHelper(value_sb.release(), SWIGTYPE_p_lldb__SBValue); } +PythonObject SWIGBridge::ToSWIGWrapper(std::unique_ptr result_up) { + return ToSWIGHelper(result_up.release(), SWIGTYPE_p_lldb__SBCommandReturnObject); +} + PythonObject SWIGBridge::ToSWIGWrapper(lldb::ValueObjectSP value_sp) { return ToSWIGWrapper(std::unique_ptr(new lldb::SBValue(value_sp))); } diff --git a/lldb/bindings/python/python-typemaps.swig b/lldb/bindings/python/python-typemaps.swig index f8c33e15c03e66..88b6cd9ef6b6e7 100644 --- a/lldb/bindings/python/python-typemaps.swig +++ b/lldb/bindings/python/python-typemaps.swig @@ -476,6 +476,25 @@ template <> bool SetNumberFromPyObject(double &number, PyObject *obj) { $1 = $1 || PyCallable_Check(reinterpret_cast($input)); } +// For lldb::SBCommandPrintCallback +%typemap(in) (lldb::SBCommandPrintCallback callback, void *baton) { + if (!($input == Py_None || +PyCallable_Check(reinterpret_cast($input { +PyErr_SetString(PyExc_TypeError, "Need a callable object or None!"); +SWIG_fail; + } + + // Don't lose the callback reference. + Py_INCREF($input); + $1 = LLDBSwigPythonCallPythonCommandPrintCallback; + $2 = $input; +} + +%typemap(typecheck) (lldb::SBCommandPrintCallback callback, void *baton) { + $1 = $input == Py_None; + $1 = $1 || PyCallable_Check(reinterpret_cast($input)); +} + %typemap(in) (lldb::CommandOverrideCallback callback, void *baton) { if (!($input == Py_None || PyCallable_Check(reinterpret_cast($input { diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig index b72a462d04643b..fcabf60008b17d 100644 --- a/lldb/bindings/python/python-wrapper.swig +++ b/lldb/bindings/python/python-wr
[Lldb-commits] [lldb] [lldb] Support CommandInterpreter print callbacks (PR #125006)
JDevlieghere wrote: I recommend reviewing the last commit and ignoring the two NFC commits, which I will land separately anyway. https://github.com/llvm/llvm-project/pull/125006 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -5058,72 +5053,148 @@ int main(int argc, char *argv[]) { auto terminate_debugger = llvm::make_scope_exit([] { lldb::SBDebugger::Terminate(); }); - StreamDescriptor input; - StreamDescriptor output; - std::FILE *redirectOut = nullptr; - std::FILE *redirectErr = nullptr; - if (portno != -1) { -printf("Listening on port %i...\n", portno); -SOCKET socket_fd = AcceptConnection(log.get(), portno); -if (socket_fd < 0) - return EXIT_FAILURE; + std::vector pre_init_commands; + for (const std::string &arg : + input_args.getAllArgValues(OPT_pre_init_command)) { +pre_init_commands.push_back(arg); + } -input = StreamDescriptor::from_socket(socket_fd, true); -output = StreamDescriptor::from_socket(socket_fd, false); - } else { -#if defined(_WIN32) -// Windows opens stdout and stdin in text mode which converts \n to 13,10 -// while the value is just 10 on Darwin/Linux. Setting the file mode to -// binary fixes this. -int result = _setmode(fileno(stdout), _O_BINARY); -assert(result); -result = _setmode(fileno(stdin), _O_BINARY); -UNUSED_IF_ASSERT_DISABLED(result); -assert(result); -#endif + auto HandleClient = + [=, log = log.get()](std::string name, StreamDescriptor input, + StreamDescriptor output, std::FILE *redirectOut, + std::FILE *redirectErr) -> bool { +DAP dap = DAP(name, program_path.str(), log, default_repl_mode, + std::move(input), std::move(output)); -int stdout_fd = DuplicateFileDescriptor(fileno(stdout)); -if (stdout_fd == -1) { +// stdout/stderr redirection to the IDE's console +if (auto Err = dap.ConfigureIO(redirectOut, redirectErr)) { llvm::logAllUnhandledErrors( - llvm::errorCodeToError(llvm::errnoAsErrorCode()), llvm::errs(), - "Failed to configure stdout redirect: "); + std::move(Err), llvm::errs(), + "Failed to configure lldb-dap IO operations: "); return EXIT_FAILURE; } -redirectOut = stdout; -redirectErr = stderr; +RegisterRequestCallbacks(dap); -input = StreamDescriptor::from_file(fileno(stdin), false); -output = StreamDescriptor::from_file(stdout_fd, false); - } +dap.pre_init_commands = pre_init_commands; - DAP dap = DAP(program_path.str(), log.get(), default_repl_mode, -std::move(input), std::move(output)); +// used only by TestVSCode_redirection_to_console.py +if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) + redirection_test(); - // stdout/stderr redirection to the IDE's console - if (auto Err = dap.ConfigureIO(redirectOut, redirectErr)) { -llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), -"Failed to configure lldb-dap IO operations: "); -return EXIT_FAILURE; - } +if (auto Err = dap.Loop()) { + if (log) +*log << "Transport Error: " << llvm::toString(std::move(Err)) << "\n"; + return false; +} +return true; + }; - RegisterRequestCallbacks(dap); + if (!connection.empty()) { +auto maybeProtoclAndName = parseConnection(connection); +if (auto Err = maybeProtoclAndName.takeError()) { + llvm::errs() << "Invalid connection specification " << Err << "\n"; + return EXIT_FAILURE; +} - for (const std::string &arg : - input_args.getAllArgValues(OPT_pre_init_command)) { -dap.pre_init_commands.push_back(arg); - } +Socket::SocketProtocol protocol; +std::string name; +std::tie(protocol, name) = *maybeProtoclAndName; - // used only by TestVSCode_redirection_to_console.py - if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) -redirection_test(); +Status error; +std::unique_ptr listener = Socket::Create(protocol, error); +if (error.Fail()) { + llvm::errs() << "Failed to create listener for protocol " + << Socket::FindSchemeByProtocol(protocol) + << ", error: " << error.takeError() << "\n"; + return EXIT_FAILURE; +} - bool CleanExit = true; - if (auto Err = dap.Loop()) { +error = listener->Listen(name, /* backlog */ 5); +if (error.Fail()) { + llvm::errs() << "Failed to listen, error: " << error.takeError() << "\n"; + return EXIT_FAILURE; +} + +std::string address = +llvm::join(listener->GetListeningConnectionURI(), ", "); if (log) - *log << "Transport Error: " << llvm::toString(std::move(Err)) << "\n"; -CleanExit = false; + *log << "started with connection listeners " << address << "\n"; + +llvm::outs() << "Listening for: " << address << "\n"; +// Ensure listening address are flushed for calles to retrieve the resolve +// address. +llvm::outs().flush(); + +MainLoop mainloop; +mainloop.RegisterSignal( +SIGHUP, [](auto &RL) { RL.RequestTermination(); }, error); + +unsigne
[Lldb-commits] [lldb] [lldb] Support CommandInterpreter print callbacks (PR #125006)
https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/125006 >From fdac9c0292cef848b880904cf84b2c0083065005 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Tue, 28 Jan 2025 15:43:31 -0800 Subject: [PATCH 1/4] [lldb] Fix CommandInterpreter formatting (NFC) --- .../lldb/Interpreter/CommandInterpreter.h| 16 +++- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/lldb/include/lldb/Interpreter/CommandInterpreter.h b/lldb/include/lldb/Interpreter/CommandInterpreter.h index 2bafc30cc8e23a..910c1d84303354 100644 --- a/lldb/include/lldb/Interpreter/CommandInterpreter.h +++ b/lldb/include/lldb/Interpreter/CommandInterpreter.h @@ -100,8 +100,7 @@ class CommandInterpreterRunOptions { LazyBool stop_on_error, LazyBool stop_on_crash, LazyBool echo_commands, LazyBool echo_comments, LazyBool print_results, LazyBool print_errors, - LazyBool add_to_history, - LazyBool handle_repeats) + LazyBool add_to_history, LazyBool handle_repeats) : m_stop_on_continue(stop_on_continue), m_stop_on_error(stop_on_error), m_stop_on_crash(stop_on_crash), m_echo_commands(echo_commands), m_echo_comment_commands(echo_comments), m_print_results(print_results), @@ -248,13 +247,13 @@ class CommandInterpreter : public Broadcaster, enum CommandTypes { eCommandTypesBuiltin = 0x0001, //< native commands such as "frame" eCommandTypesUserDef = 0x0002, //< scripted commands -eCommandTypesUserMW = 0x0004, //< multiword commands (command containers) +eCommandTypesUserMW = 0x0004, //< multiword commands (command containers) eCommandTypesAliases = 0x0008, //< aliases such as "po" -eCommandTypesHidden = 0x0010, //< commands prefixed with an underscore +eCommandTypesHidden = 0x0010, //< commands prefixed with an underscore eCommandTypesAllThem = 0x //< all commands }; - // The CommandAlias and CommandInterpreter both have a hand in + // The CommandAlias and CommandInterpreter both have a hand in // substituting for alias commands. They work by writing special tokens // in the template form of the Alias command, and then detecting them when the // command is executed. These are the special tokens: @@ -334,9 +333,8 @@ class CommandInterpreter : public Broadcaster, /// dummy "contains everything MWC, so we return null here, but /// in this case error.Success is true. - CommandObjectMultiword *VerifyUserMultiwordCmdPath(Args &path, - bool leaf_is_command, - Status &result); + CommandObjectMultiword * + VerifyUserMultiwordCmdPath(Args &path, bool leaf_is_command, Status &result); CommandAlias *AddAlias(llvm::StringRef alias_name, lldb::CommandObjectSP &command_obj_sp, @@ -596,7 +594,7 @@ class CommandInterpreter : public Broadcaster, void SetEchoCommentCommands(bool enable); bool GetRepeatPreviousCommand() const; - + bool GetRequireCommandOverwrite() const; const CommandObject::CommandMap &GetUserCommands() const { >From e1e8d1487194c4e21cf9724da99588796a03883d Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Tue, 28 Jan 2025 16:10:33 -0800 Subject: [PATCH 2/4] [lldb] Constify methods in CommandReturnObject (NFC) --- lldb/include/lldb/Interpreter/CommandReturnObject.h | 10 +- lldb/include/lldb/Utility/StreamTee.h | 2 +- lldb/source/Interpreter/CommandReturnObject.cpp | 5 +++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/lldb/include/lldb/Interpreter/CommandReturnObject.h b/lldb/include/lldb/Interpreter/CommandReturnObject.h index 9fef59337016df..f96da34889a324 100644 --- a/lldb/include/lldb/Interpreter/CommandReturnObject.h +++ b/lldb/include/lldb/Interpreter/CommandReturnObject.h @@ -32,9 +32,9 @@ class CommandReturnObject { ~CommandReturnObject() = default; /// Format any inline diagnostics with an indentation of \c indent. - std::string GetInlineDiagnosticString(unsigned indent); + std::string GetInlineDiagnosticString(unsigned indent) const; - llvm::StringRef GetOutputString() { + llvm::StringRef GetOutputString() const { lldb::StreamSP stream_sp(m_out_stream.GetStreamAtIndex(eStreamStringIndex)); if (stream_sp) return std::static_pointer_cast(stream_sp)->GetString(); @@ -46,7 +46,7 @@ class CommandReturnObject { /// If \c with_diagnostics is true, all diagnostics are also /// rendered into the string. Otherwise the expectation is that they /// are fetched with \ref GetInlineDiagnosticString(). - std::string GetErrorString(bool with_diagnostics = true); + std::string GetErrorString(bool with_diagnostics = true) const; StructuredData:
[Lldb-commits] [lldb] [lldb] Support CommandInterpreter print callbacks (PR #125006)
JDevlieghere wrote: > If this result printing callback was also passed the command string (which it > has from just above where the callback is called) then this would also be an > easy way to do logging of command execution. That's not needed for your > current purpose, but would add another strong motivation for this change... Adrian made a similar observation offline. What do you think about putting that in the `CommandReturnObject`? This seems generally useful and that way it's not tied to the callback. https://github.com/llvm/llvm-project/pull/125006 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Only include necessary files in the lldb-dap VSIX (PR #124986)
https://github.com/matthewbastien edited https://github.com/llvm/llvm-project/pull/124986 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Use Function::GetAddress in Module::FindFunctions (PR #124938)
jimingham wrote: This looks fine, but more generally, is there any good reason to ever use Function::GetAddressRange? Shouldn't that just be removed and all the instances replaced with either GetAddress or get the ranges and iterate over them looking for whatever they wanted? https://github.com/llvm/llvm-project/pull/124938 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [lldb][Windows] WoA HW Watchpoint support in LLDB (PR #108072)
@@ -575,6 +575,10 @@ Changes to LLDB 24 int main() { Likely cause: f->b->d accessed 0x4 ``` +* LLDB now supports hardware watchpoints for AArch64 Windows targets. Windows + does not provide API to query the number of supported hardware watchpoints. + Therefore current implementation allows only 1 watchpoint, as tested with + Windows 11 on the Microsoft SQ2 and Snapdragon Elite X platforms. omjavaid wrote: I have run all tests individually and only those test fail now which require more than single hardware watchpoint resources. I am not really sure why ninja check-lldb fails the watchpoint test even when run single threaded but all tests pass when they are run via dotest.py individually. https://github.com/llvm/llvm-project/pull/108072 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [NFC][lldb] Document a few ivars on the value object system. (PR #124971)
@@ -1187,6 +1187,7 @@ class EntityResultVariable : public Materializer::Entity { private: CompilerType m_type; + /// If this result entity can (and should) track the value on inferior memory. jimingham wrote: on -> in? https://github.com/llvm/llvm-project/pull/124971 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [NFC][lldb] Document a few ivars on the value object system. (PR #124971)
jimingham wrote: Other than that tiny quibble, these are accurate and helpful comments. https://github.com/llvm/llvm-project/pull/124971 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [lldb][Windows] WoA HW Watchpoint support in LLDB (PR #108072)
@@ -492,23 +492,40 @@ NativeProcessWindows::OnDebugException(bool first_chance, } case DWORD(STATUS_BREAKPOINT): case STATUS_WX86_BREAKPOINT: omjavaid wrote: yes. Heres the detail from ntstatus.h // // MessageId: STATUS_WX86_BREAKPOINT // // MessageText: // // Exception status code used by Win32 x86 emulation subsystem. // #define STATUS_WX86_BREAKPOINT ((NTSTATUS)0x401FL) https://github.com/llvm/llvm-project/pull/108072 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support CommandInterpreter print callbacks (PR #125006)
@@ -1012,6 +1012,26 @@ static void LLDBSwigPythonCallPythonLogOutputCallback(const char *str, } } +// For DebuggerTerminateCallback functions jimingham wrote: Is this comment right? https://github.com/llvm/llvm-project/pull/125006 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support CommandInterpreter print callbacks (PR #125006)
@@ -0,0 +1,66 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BreakpointAPITestCase(TestBase): +NO_DEBUG_INFO_TESTCASE = True + +def run_command_interpreter_with_output_file(self, out_filename, input_str): +with open(out_filename, "w") as f: +self.dbg.SetOutputFileHandle(f, False) +self.dbg.SetInputString(input_str) +opts = lldb.SBCommandInterpreterRunOptions() +self.dbg.RunCommandInterpreter(True, False, opts, 0, False, False) + +def test_command_interpreter_print_callback(self): +"""Make sure that if an SBBreakpoint gets deleted its IsValid returns false.""" jimingham wrote: That's not what this test does, is it? https://github.com/llvm/llvm-project/pull/125006 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support CommandInterpreter print callbacks (PR #125006)
jimingham wrote: Man there's a lot of boiler plate in hooking up to SWIG... But this all looks right to me. I wondered whether the callback would benefit from knowing whether the result had been dumped immediately or not, but I can't think of a good reason for that. If this result printing callback was also passed the command string (which it has from just above where the callback is called) then this would also be an easy way to do logging of command execution. That's not needed for your current purpose, but would add another strong motivation for this change... https://github.com/llvm/llvm-project/pull/125006 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Extended if conditions to support alias names for registers (PR #124475)
DavidSpickett wrote: > I have created two tests. Which is great, but we need live processes too and I found those, they are in `lldb/test/Shell/Register/` for example `lldb/test/Shell/Register/aarch64-gp-read.test`. For some reason we don't check all registers there just parameter registers, but there's no reason you can't check them all for RISC-V. It's probably simpler to set each register to `1+register_number` so x0 is 1 and x1 is 2 and so on. Instead of loading values from memory as that example does. The logic of that test is set all the registers in inline asm, then manually break before the inline asm block finishes, so that compiler generated code doesn't restore the values. > However, it turned out that register read x8 is not working. I think, there > is some edge case because it has fp and s0. It's very possible that we have never had a register with 3 names before, or we have support for it but the code that checks them doesn't know that. > I am not sure whether to try to fix this in this PR or another one? I would investigate why this error happens and if you can fix it, see what the changes look like. It can probably be a PR after this one, that updates the tests now that they work. But we'll keep this one open while you do that in case it makes more sense to bundle them. If it seems like it's going to be a massive job to fix it, just let us know what you found and I'll take a look too. I don't want to drown you in unexpected work. https://github.com/llvm/llvm-project/pull/124475 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Fix "in function" detection in "thread until" (PR #123622)
labath wrote: ping @jimingham https://github.com/llvm/llvm-project/pull/123622 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Remove some unused code in SymbolFileDWARF::ResolveFunction (PR #123206)
https://github.com/clayborg approved this pull request. Want to add a [NFC] to the title as well? https://github.com/llvm/llvm-project/pull/123206 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Docs] Expand remote testing instructions (PR #122694)
DavidSpickett wrote: ping! https://github.com/llvm/llvm-project/pull/122694 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Add support for gdb-style 'x' packet (PR #124733)
labath wrote: Let's continue the discussion [here](https://discourse.llvm.org/t/rfc-fixing-incompatibilties-of-the-x-packet-w-r-t-gdb/84288/8). (It could work it's just not how gdb implemented it. Sniffing of zero-length reads was considered, but a qSupported feature was deemed more principled. I suppose one advantage of that is that it saves us one round-trip (after we no longer need to support/detect the lldb-x implementation)) https://github.com/llvm/llvm-project/pull/124733 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Use Function::GetAddress in Module::FindFunctions (PR #124938)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Pavel Labath (labath) Changes The original code resulted in a misfire in the symtab vs. debug info deduplication code, which caused us to return the same function twice when searching via a regex (for functions whose entry point is also not the lowest address). --- Full diff: https://github.com/llvm/llvm-project/pull/124938.diff 2 Files Affected: - (modified) lldb/source/Core/Module.cpp (+2-3) - (modified) lldb/test/Shell/SymbolFile/DWARF/x86/discontinuous-function.s (+16-4) ``diff diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index 9601c834d9b8fe..33668c5d20dde4 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -919,9 +919,8 @@ void Module::FindFunctions(const RegularExpression ®ex, const SymbolContext &sc = sc_list[i]; if (sc.block) continue; - file_addr_to_index[sc.function->GetAddressRange() - .GetBaseAddress() - .GetFileAddress()] = i; + file_addr_to_index[sc.function->GetAddress().GetFileAddress()] = + i; } FileAddrToIndexMap::const_iterator end = file_addr_to_index.end(); diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/discontinuous-function.s b/lldb/test/Shell/SymbolFile/DWARF/x86/discontinuous-function.s index 93ea9f33e762df..197ab9aa14910e 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/x86/discontinuous-function.s +++ b/lldb/test/Shell/SymbolFile/DWARF/x86/discontinuous-function.s @@ -6,17 +6,29 @@ # The function bar has been placed "in the middle" of foo, and the function # entry point is deliberately not its lowest address. -# RUN: llvm-mc -triple x86_64-pc-linux -filetype=obj %s -o %t -# RUN: %lldb %t -o "image lookup -v -n foo" -o "expr -- &foo" -o exit | FileCheck %s +# RUN: split-file %s %t +# RUN: llvm-mc -triple x86_64-pc-linux -filetype=obj %t/input.s -o %t/input.o +# RUN: %lldb %t/input.o -s %t/commands -o exit | FileCheck %s -# CHECK-LABEL: image lookup +#--- commands + +image lookup -v -n foo +# CHECK-LABEL: image lookup -v -n foo +# CHECK: 1 match found in {{.*}} +# CHECK: Summary: input.o`foo +# CHECK: Function: id = {{.*}}, name = "foo", ranges = [0x-0x000e)[0x0014-0x001c) + +image lookup -v --regex -n '^foo$' +# CHECK-LABEL: image lookup -v --regex -n '^foo$' # CHECK: 1 match found in {{.*}} -# CHECK: Summary: {{.*}}`foo +# CHECK: Summary: input.o`foo # CHECK: Function: id = {{.*}}, name = "foo", ranges = [0x-0x000e)[0x0014-0x001c) +expr -- &foo # CHECK-LABEL: expr -- &foo # CHECK: (void (*)()) $0 = 0x0007 +#--- input.s .text foo.__part.1: `` https://github.com/llvm/llvm-project/pull/124938 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [LLDB] Add Lexer (with tests) for DIL (Data Inspection Language). (PR #123521)
cmtice wrote: If DIL is not allowed to recognize any operators except period, arrow, and parentheses, it seems to me that it won't be any more powerful than the current 'frame variable' implementation, in which case what is the point of having it at all? (As a matter of fact, it would be less powerful, since 'frame variable' also recognizes square brackets and star as valid operators and treats them accordingly). At the same time, I understand the concern about wanting to be able to parse synthetic variable names, which can contain arbitrary operator-like symbols. So I have a tentative proposal: How about insisting that synthetic variable names need to be surrounded by special delimiters, such as backquote or slash? Or having some other way of marking them as special? https://github.com/llvm/llvm-project/pull/123521 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [LLDB] Add Lexer (with tests) for DIL (Data Inspection Language). (PR #123521)
cmtice wrote: > > If DIL is not allowed to recognize any operators except period, arrow, and > > parentheses, it seems to me that it won't be any more powerful than the > > current 'frame variable' implementation, in which case what is the point of > > having it at all? (As a matter of fact, it would be less powerful, since > > 'frame variable' also recognizes square brackets and star as valid > > operators and treats them accordingly). > > At the same time, I understand the concern about wanting to be able to > > parse synthetic variable names, which can contain arbitrary operator-like > > symbols. So I have a tentative proposal: How about insisting that synthetic > > variable names need to be surrounded by special delimiters, such as > > backquote or slash? Or having some other way of marking them as special? > > These are unfortunately visible to the user, and they will have to type them > in `frame var` to access the child. So we can't make them something ugly. I don't want to make them ugly, but I *do* think we need to ask the user to distinguish them in some way. Otherwise I don't see how we can make DIL any more powerful than the current 'frame variable'. https://github.com/llvm/llvm-project/pull/123521 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [LLDB] Add Lexer (with tests) for DIL (Data Inspection Language). (PR #123521)
jimingham wrote: > I agree with everything except for the last part. The current parser already > threats `[]` [very > specially](https://github.com/llvm/llvm-project/blob/89ca3e72ca03efbbfb5ae9b1c71d81f2d1753521/lldb/source/Target/StackFrame.cpp#L781). > I think it has to do that so it can treat pointers as C arrays (and then it > just special cases synthetic objects). I think that's a (mostly *) reasonable > setup that we could replicate in the new DIL implementation, particularly as > we would need special handling of `[]` to implement things like `[i+1]`. > We would have to change how synthetic children are made currently for array like things for this to work. If I have a std:vector called `foo` and I write: (lldb) v foo[0] and the DIL parses that it will either ask foo for a child named `0`, which doesn't exist, or ask it for the 0th child which currently is not required to be the one called `[0]`. I think I mentioned this back when we were first discussing this, but if we want to make this part work, then we have to add some API on the synthetic child provider like `AddVectorChild(size_t idx, ValueObjectSP child_sp)` and require you use that to make vector like things. Then we could require that the child named `[0]` HAS to be the 0th child, etc. We still have the problem of all the synthetic child providers in the wild that might not do this. > FWIW, I believe that the main source of keywords in Caroline's implementation > is types (for casts). I think they could be handled generically (just ask the > target whether the identifier names a type), were it not for the nasty C(++) > habit of creating multiword types (`unsigned long long long long int`). > Still, it feels there ought to be recognise these without making `unsigned` a > full-fledged keyword. That comes back to how soon we expect to know the language as we are parsing. `unsigned` is a perfectly good variable name in swift, for instance... I don't think we want to limit lldb to only C-family languages. > > (*) I was recently made aware of an unfortunate difference in behavior of > `frame var` and `expr` for map types: > > ``` > (lldb) v m > (std::map) m = size=3 { > [0] = (first = -42, second = -47) > [1] = (first = 0, second = 42) > [2] = (first = 42, second = 47) > } > (lldb) v m[0] > (std::__1::__value_type::value_type) m[0] = (first = -42, second = > -47) > (lldb) expr m[0] > (std::map::mapped_type) $0 = 42 > ``` > > I know that these are different languages, but this still seems like it could > confuse some people. I don't have any specific ideas on how to fix/improve > this though... Yes, collection classes that use arbitrary types for the keys are problematic. How would we show the map if the keys are structures with some non-trivial compare function in a way that wouldn't be awful to use? I don't think we can get around people having to know that `v` path expressions are NOT expressions in the underlying language. https://github.com/llvm/llvm-project/pull/123521 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Reland "[lldb] Implement basic support for reverse-continue" (#123906)" (PR #123945)
https://github.com/labath edited https://github.com/llvm/llvm-project/pull/123945 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Reland "[lldb] Implement basic support for reverse-continue" (#123906)" (PR #123945)
@@ -0,0 +1,537 @@ +import os +import os.path +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.gdbclientutils import * +from lldbsuite.test.lldbgdbproxy import * +import lldbgdbserverutils +import re + + +class ThreadSnapshot: +def __init__(self, thread_id, registers): +self.thread_id = thread_id +self.registers = registers + + +class MemoryBlockSnapshot: +def __init__(self, address, data): +self.address = address +self.data = data + + +class StateSnapshot: +def __init__(self, thread_snapshots, memory): +self.thread_snapshots = thread_snapshots +self.memory = memory +self.thread_id = None + + +class RegisterInfo: +def __init__(self, lldb_index, name, bitsize, little_endian): +self.lldb_index = lldb_index +self.name = name +self.bitsize = bitsize +self.little_endian = little_endian + + +BELOW_STACK_POINTER = 16384 +ABOVE_STACK_POINTER = 4096 + +BLOCK_SIZE = 1024 + +SOFTWARE_BREAKPOINTS = 0 +HARDWARE_BREAKPOINTS = 1 +WRITE_WATCHPOINTS = 2 + + +class ReverseTestBase(GDBProxyTestBase): +""" +Base class for tests that need reverse execution. + +This class uses a gdbserver proxy to add very limited reverse- +execution capability to lldb-server/debugserver for testing +purposes only. + +To use this class, run the inferior forward until some stopping point. +Then call `start_recording()` and execute forward again until reaching +a software breakpoint; this class records the state before each execution executes. +At that point, the server will accept "bc" and "bs" packets to step +backwards through the state. +When executing during recording, we only allow single-step and continue without +delivering a signal, and only software breakpoint stops are allowed. + +We assume that while recording is enabled, the only effects of instructions +are on general-purpose registers (read/written by the 'g' and 'G' packets) +and on memory bytes between [SP - BELOW_STACK_POINTER, SP + ABOVE_STACK_POINTER). +""" + +NO_DEBUG_INFO_TESTCASE = True + +""" +A list of StateSnapshots in time order. + +There is one snapshot per single-stepped instruction, +representing the state before that instruction was +executed. The last snapshot in the list is the +snapshot before the last instruction was executed. +This is an undo log; we snapshot a superset of the state that may have +been changed by the instruction's execution. +""" +snapshots = None +recording_enabled = False + +breakpoints = None + +pc_register_info = None +sp_register_info = None +general_purpose_register_info = None + +def __init__(self, *args, **kwargs): +GDBProxyTestBase.__init__(self, *args, **kwargs) +self.breakpoints = [set(), set(), set(), set(), set()] + +def respond(self, packet): +if not packet: +raise ValueError("Invalid empty packet") +if packet == self.server.PACKET_INTERRUPT: +# Don't send a response. We'll just run to completion. +return [] +if self.is_command(packet, "qSupported", ":"): +# Disable multiprocess support in the server and in LLDB +# since Mac debugserver doesn't support it and we want lldb-server to +# be consistent with that +reply = self.pass_through(packet.replace(";multiprocess", "")) +return reply.replace(";multiprocess", "") + ";ReverseStep+;ReverseContinue+" +if packet == "c" or packet == "s": +packet = "vCont;" + packet +elif ( +packet[0] == "c" or packet[0] == "s" or packet[0] == "C" or packet[0] == "S" +): +raise ValueError( +"Old-style continuation packets with address or signal not supported yet" +) +if self.is_command(packet, "vCont", ";"): +if self.recording_enabled: +return self.continue_with_recording(packet) +snapshots = [] +if packet == "bc": +return self.reverse_continue() +if packet == "bs": +return self.reverse_step() +if packet == "jThreadsInfo": +# Suppress this because it contains thread stop reasons which we might +# need to modify, and we don't want to have to implement that. +return "" +if packet[0] == "z" or packet[0] == "Z": labath wrote: ```suggestion if packet[0] == "x": # Suppress *binary* reads as results starting with "O" can be mistaken for an output packet # by the test server code return "" if packet[0] == "z" or packet[0] == "Z": ``` https://github.com/llvm/llvm-project/pull/123945 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm
[Lldb-commits] [lldb] Reland "[lldb] Implement basic support for reverse-continue" (#123906)" (PR #123945)
https://github.com/labath approved this pull request. After much deliberation, I came to the conclusion that it's best to just work around this problem, given that we're going to be changing how the `x` packet works (and removing the ambiguity) anyway. This usage technically was not ambiguous because the output packet can only be sent when the target is running (so it can't be confused with an `x` response), but the test code was not tracking the run state of the server. I tried teaching it to do that, but wasn't particularly happy with the result, and given the `x` change, the added complication would not be necessary anyway. For a time I also wanted to wait until the servers start sending the new `x` response, but now it looks like that may still take quite some time. TL;DR: LGTM with the inline suggestion applied https://github.com/llvm/llvm-project/pull/123945 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [NFC][lldb] Document a few ivars on the value object system. (PR #124971)
https://github.com/JDevlieghere approved this pull request. LGTM with one solution since you're already improving the comments. https://github.com/llvm/llvm-project/pull/124971 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [NFC][lldb] Document a few ivars on the value object system. (PR #124971)
https://github.com/JDevlieghere edited https://github.com/llvm/llvm-project/pull/124971 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [NFC][lldb] Document a few ivars on the value object system. (PR #124971)
@@ -108,7 +108,14 @@ class ExpressionVariable FlagType m_flags; // takes elements of Flags // these should be private JDevlieghere wrote: ```suggestion /// These members should be private. /// @{ [...] lldb::ValueObjectSP m_live_sp; /// @} ``` https://github.com/llvm/llvm-project/pull/124971 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [DebugInfo] Add explicit visibility macros to CodeView template functions (PR #113102)
https://github.com/fsfod updated https://github.com/llvm/llvm-project/pull/113102 >From 79408f0a5703c1174ef98130a4106c61cd593d76 Mon Sep 17 00:00:00 2001 From: Thomas Fransham Date: Mon, 12 Aug 2024 16:04:12 +0100 Subject: [PATCH 1/2] [DebugInfo] Add explicit visibility macros to CodeView template functions These will be needed for when llvm is built as a shared library on windows with explicit visibility macros enabled. Change UnionRecord to class instead of a struct so we can use X macros from CodeViewTypes.def to forward declare all record classes. This is part of the work to enable LLVM_BUILD_LLVM_DYLIB and LLVM plugins on window. --- .../SymbolFile/NativePDB/SymbolFileNativePDB.h | 2 +- .../DebugInfo/CodeView/ContinuationRecordBuilder.h | 14 ++ .../llvm/DebugInfo/CodeView/SimpleTypeSerializer.h | 13 + llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h | 3 ++- 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index b0e78a243a3c24..479a8724e2adef 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -32,7 +32,7 @@ class ClassRecord; class EnumRecord; class ModifierRecord; class PointerRecord; -struct UnionRecord; +class UnionRecord; } // namespace codeview } // namespace llvm diff --git a/llvm/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h b/llvm/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h index 84cef520a2f460..8347ef870d0676 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h +++ b/llvm/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h @@ -50,6 +50,20 @@ class ContinuationRecordBuilder { std::vector end(TypeIndex Index); }; + +// Needed by RandomAccessVisitorTest.cpp +#define TYPE_RECORD(EnumName, EnumVal, Name) +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + extern template LLVM_TEMPLATE_ABI void ContinuationRecordBuilder::writeMemberType(\ + Name##Record &Record); +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" +#undef TYPE_RECORD +#undef TYPE_RECORD_ALIAS +#undef MEMBER_RECORD +#undef MEMBER_RECORD_ALIAS + } // namespace codeview } // namespace llvm diff --git a/llvm/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h b/llvm/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h index fcc0452a6ae9a7..713798fc38d2d8 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h +++ b/llvm/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h @@ -32,6 +32,19 @@ class SimpleTypeSerializer { ArrayRef serialize(const FieldListRecord &Record) = delete; }; +// Needed by RandomAccessVisitorTest.cpp +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + class Name##Record; \ + extern template LLVM_TEMPLATE_ABI ArrayRef llvm::codeview::SimpleTypeSerializer::serialize( \ + Name##Record &Record); +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD(EnumName, EnumVal, Name) +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" +#undef TYPE_RECORD +#undef TYPE_RECORD_ALIAS +#undef MEMBER_RECORD +#undef MEMBER_RECORD_ALIAS } // end namespace codeview } // end namespace llvm diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h b/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h index 5a84fac5f59034..484e05b5adc672 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -495,7 +495,8 @@ class ClassRecord : public TagRecord { }; // LF_UNION -struct UnionRecord : public TagRecord { +class UnionRecord : public TagRecord { +public: UnionRecord() = default; explicit UnionRecord(TypeRecordKind Kind) : TagRecord(Kind) {} UnionRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList, >From 0d429239bfa598736c0eb7cb99c5726ba7d7ae93 Mon Sep 17 00:00:00 2001 From: Thomas Fransham Date: Sun, 20 Oct 2024 20:35:48 +0100 Subject: [PATCH 2/2] Fix formatting --- .../llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h | 4 ++-- llvm/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h b/llvm/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h index 8347ef870d0676..3de138f37be2d2 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h +++ b/llvm/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h
[Lldb-commits] [lldb] [lldb] Fix "in function" detection in "thread until" (PR #123622)
@@ -970,19 +969,21 @@ class CommandObjectThreadUntil : public CommandObjectParsed { return; } -AddressRange fun_addr_range = sc.function->GetAddressRange(); -Address fun_start_addr = fun_addr_range.GetBaseAddress(); -line_table->FindLineEntryByAddress(fun_start_addr, function_start, - &index_ptr); - -Address fun_end_addr(fun_start_addr.GetSection(), - fun_start_addr.GetOffset() + - fun_addr_range.GetByteSize()); - -bool all_in_function = true; +uint32_t lowest_func_idx = UINT32_MAX; +uint32_t highest_func_idx = 0; +for (AddressRange range : sc.function->GetAddressRanges()) { + uint32_t idx; + LineEntry unused; + Address addr = range.GetBaseAddress(); + if (line_table->FindLineEntryByAddress(addr, unused, &idx)) +lowest_func_idx = std::min(lowest_func_idx, idx); + + addr.Slide(range.GetByteSize() - 1); jimingham wrote: This deserves a comment. https://github.com/llvm/llvm-project/pull/123622 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Fix "in function" detection in "thread until" (PR #123622)
@@ -1007,29 +1009,29 @@ class CommandObjectThreadUntil : public CommandObjectParsed { addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target); if (address != LLDB_INVALID_ADDRESS) { - if (fun_addr_range.ContainsLoadAddress(address, target)) + AddressRange unused; + if (sc.function->GetRangeContainingLoadAddress(address, *target, + unused)) address_list.push_back(address); - else -all_in_function = false; } start_idx_ptr++; } } for (lldb::addr_t address : m_options.m_until_addrs) { - if (fun_addr_range.ContainsLoadAddress(address, target)) + AddressRange unused; + if (sc.function->GetRangeContainingLoadAddress(address, *target, + unused)) address_list.push_back(address); - else -all_in_function = false; } if (address_list.empty()) { jimingham wrote: Since you only care here about `found_something` and `address_list.size > 0` could you short-circuit this search when you find the first address that matches the line? https://github.com/llvm/llvm-project/pull/123622 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Fix "in function" detection in "thread until" (PR #123622)
@@ -970,19 +969,21 @@ class CommandObjectThreadUntil : public CommandObjectParsed { return; } -AddressRange fun_addr_range = sc.function->GetAddressRange(); -Address fun_start_addr = fun_addr_range.GetBaseAddress(); -line_table->FindLineEntryByAddress(fun_start_addr, function_start, - &index_ptr); - -Address fun_end_addr(fun_start_addr.GetSection(), - fun_start_addr.GetOffset() + - fun_addr_range.GetByteSize()); - -bool all_in_function = true; +uint32_t lowest_func_idx = UINT32_MAX; +uint32_t highest_func_idx = 0; +for (AddressRange range : sc.function->GetAddressRanges()) { + uint32_t idx; + LineEntry unused; + Address addr = range.GetBaseAddress(); + if (line_table->FindLineEntryByAddress(addr, unused, &idx)) +lowest_func_idx = std::min(lowest_func_idx, idx); + + addr.Slide(range.GetByteSize() - 1); jimingham wrote: Magical -1's... https://github.com/llvm/llvm-project/pull/123622 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [LLDB] Add Lexer (with tests) for DIL (Data Inspection Language). (PR #123521)
jimingham wrote: > If DIL is not allowed to recognize any operators except period, arrow, and > parentheses, it seems to me that it won't be any more powerful than the > current 'frame variable' implementation, in which case what is the point of > having it at all? (As a matter of fact, it would be less powerful, since > 'frame variable' also recognizes square brackets and star as valid operators > and treats them accordingly). > > At the same time, I understand the concern about wanting to be able to parse > synthetic variable names, which can contain arbitrary operator-like symbols. > So I have a tentative proposal: How about insisting that synthetic variable > names need to be surrounded by special delimiters, such as backquote or > slash? Or having some other way of marking them as special? These are unfortunately visible to the user, and they will have to type them in `frame var` to access the child. So we can't make them something ugly. https://github.com/llvm/llvm-project/pull/123521 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [NFC][lldb] Document a few ivars on the value object system. (PR #124971)
https://github.com/augusto2112 created https://github.com/llvm/llvm-project/pull/124971 None >From cd28fcaf8739a32897a09bd661cb805b3960a7c7 Mon Sep 17 00:00:00 2001 From: Augusto Noronha Date: Wed, 29 Jan 2025 10:53:23 -0800 Subject: [PATCH] [NFC][lldb] Document a few ivars on the value object system. --- lldb/include/lldb/Expression/ExpressionVariable.h | 7 +++ lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h | 4 lldb/source/Expression/Materializer.cpp| 1 + 3 files changed, 12 insertions(+) diff --git a/lldb/include/lldb/Expression/ExpressionVariable.h b/lldb/include/lldb/Expression/ExpressionVariable.h index fc36793b3a475c..a2175dee7dca9e 100644 --- a/lldb/include/lldb/Expression/ExpressionVariable.h +++ b/lldb/include/lldb/Expression/ExpressionVariable.h @@ -108,7 +108,14 @@ class ExpressionVariable FlagType m_flags; // takes elements of Flags // these should be private + /// A value object whose value's data lives in host (lldb's) memory. lldb::ValueObjectSP m_frozen_sp; + /// The ValueObject counterpart to m_frozen_sp that tracks the value in + /// inferior memory. This object may not always exist; its presence depends on + /// whether it is logical for the value to exist in the inferior memory. For + /// example, when evaluating a C++ expression that generates an r-value, such + /// as a single function call, there is no memory address in the inferior to + /// track. lldb::ValueObjectSP m_live_sp; }; diff --git a/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h b/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h index dbd68160acb4dc..5509886a8965da 100644 --- a/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h +++ b/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h @@ -66,6 +66,10 @@ class ValueObjectConstResultImpl { private: ValueObject *m_impl_backend; + /// The memory address in the inferior process that this ValueObject tracks. + /// This address is used to request additional memory when the actual data + /// size exceeds the initial local buffer size, such as when a dynamic type + /// resolution results in a type larger than its statically determined type. lldb::addr_t m_live_address; AddressType m_live_address_type; lldb::ValueObjectSP m_address_of_backend; diff --git a/lldb/source/Expression/Materializer.cpp b/lldb/source/Expression/Materializer.cpp index 8cd050f9fdb7ef..500b8c098f7ca8 100644 --- a/lldb/source/Expression/Materializer.cpp +++ b/lldb/source/Expression/Materializer.cpp @@ -1187,6 +1187,7 @@ class EntityResultVariable : public Materializer::Entity { private: CompilerType m_type; + /// If this result entity can (and should) track the value on inferior memory. bool m_is_program_reference; bool m_keep_in_memory; ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [NFC][lldb] Document a few ivars on the value object system. (PR #124971)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Augusto Noronha (augusto2112) Changes --- Full diff: https://github.com/llvm/llvm-project/pull/124971.diff 3 Files Affected: - (modified) lldb/include/lldb/Expression/ExpressionVariable.h (+7) - (modified) lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h (+4) - (modified) lldb/source/Expression/Materializer.cpp (+1) ``diff diff --git a/lldb/include/lldb/Expression/ExpressionVariable.h b/lldb/include/lldb/Expression/ExpressionVariable.h index fc36793b3a475c..a2175dee7dca9e 100644 --- a/lldb/include/lldb/Expression/ExpressionVariable.h +++ b/lldb/include/lldb/Expression/ExpressionVariable.h @@ -108,7 +108,14 @@ class ExpressionVariable FlagType m_flags; // takes elements of Flags // these should be private + /// A value object whose value's data lives in host (lldb's) memory. lldb::ValueObjectSP m_frozen_sp; + /// The ValueObject counterpart to m_frozen_sp that tracks the value in + /// inferior memory. This object may not always exist; its presence depends on + /// whether it is logical for the value to exist in the inferior memory. For + /// example, when evaluating a C++ expression that generates an r-value, such + /// as a single function call, there is no memory address in the inferior to + /// track. lldb::ValueObjectSP m_live_sp; }; diff --git a/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h b/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h index dbd68160acb4dc..5509886a8965da 100644 --- a/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h +++ b/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h @@ -66,6 +66,10 @@ class ValueObjectConstResultImpl { private: ValueObject *m_impl_backend; + /// The memory address in the inferior process that this ValueObject tracks. + /// This address is used to request additional memory when the actual data + /// size exceeds the initial local buffer size, such as when a dynamic type + /// resolution results in a type larger than its statically determined type. lldb::addr_t m_live_address; AddressType m_live_address_type; lldb::ValueObjectSP m_address_of_backend; diff --git a/lldb/source/Expression/Materializer.cpp b/lldb/source/Expression/Materializer.cpp index 8cd050f9fdb7ef..500b8c098f7ca8 100644 --- a/lldb/source/Expression/Materializer.cpp +++ b/lldb/source/Expression/Materializer.cpp @@ -1187,6 +1187,7 @@ class EntityResultVariable : public Materializer::Entity { private: CompilerType m_type; + /// If this result entity can (and should) track the value on inferior memory. bool m_is_program_reference; bool m_keep_in_memory; `` https://github.com/llvm/llvm-project/pull/124971 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits