[Lldb-commits] [lldb] [LLDB] Add Lexer (with tests) for DIL (Data Inspection Language). (PR #123521)
labath wrote: > There's one small area that our desire to parse the widest range of > identifiers comes into conflict with, namely the "persistent variable" > namespace. For the C family of languages, we reserve the initial `$` for this > purpose, for swift (where `$1` etc. were already taken) we use `$R` as the > namespace identifier. This doesn't matter for the DIL at present, because > `frame var` and the like don't have access to the persistent variables, but I > don't think in the long run that's desirable. But it looks like to get that > right generally we would have to figure out the language of the identifier > which we don't want to do. I'm not sure how to finesse this (other than to > keep not allowing access to persistent variables in the DIL...) Yeah, access to persistent variables is one of the first things that I'd add to the "frame var" language. It's true that this can create some conflicts and, but I think it we don't need to handle those at the lexer level. And variables with dollars in their names are currently accepted in frame var: ``` 2 int a$b = 47; -> 3 return a$b; 4} (lldb) v a$b (int) a$b = 47 ``` One way to handle this ambiguity would be to use the (imaginary) identifier disambiguation/scoping mechanism I alluded to in one of my previous comments. We could e.g. say that identifiers that start with a dollar are reserved by lldb, and if you want to access a variable with that name, you do something like `$locals.$47`. The fact that swift uses identifiers like `$1` does complicate things, and I guess it means we may have to have some context-sensitive rules about when does that refer to a program variable and when an lldb internal concept. 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)
labath wrote: > > * The expression `foo["bar"]` tries: > > > > * `foo.GetChildWithName("bar")` > > * `foo.GetChildWithName("[bar]")` > > * The expression `foo[]` -- `expr` is evaluated and treated as > > cases above. If the result of `expr` is not a number or a string -- produce > > an error > > > I think this is an interesting idea whose usefulness mainly depends on what > kind of string operations we have in the language. If there's no way to > construct strings, then I don't think it's very useful. You could write > things like `some_variable[another_variable]`, but I don't think that's going > to be useful because for static types (e.g. C structs) you're unlikely to > have a variable with a value that contains the name of a field, and for types > with synthetic children the names of the children are not going to have any > relation to the way it's seen by the code (map is still going > to have a child called `[0]`). > > Overall I'd leave this out for the time being because it doesn't impact > parsing or lexing, just how some (currently invalid) syntax trees can be > interpreted. Thinking about this further, I can think of one reason to allow this even without sophisticated string operations -- because this allows you to access identifiers with weird child names. This way we could have users write `obj["a+b"]` for accessing the child `a+b` of object `obj` -- and we wouldn't "use up" a quote character in the process. This is sort of like how you can access global variables (even those with weird names) with `globals()["my_var"]` in python. I'd still try to avoid things like guessing whether the user forgot to add `[]` to the name or not.. 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-dap] Implement `runInTerminal` for Windows (PR #121269)
https://github.com/SuibianP updated https://github.com/llvm/llvm-project/pull/121269 >From 41650cf89122dbc35285488ae4d7bd03034a751e Mon Sep 17 00:00:00 2001 From: Hu Jialun Date: Sat, 28 Dec 2024 22:39:33 +0800 Subject: [PATCH] [lldb-dap] Implement runInTerminal for Windows Currently, the named pipe is passed by name and a transient ofstream is constructed at each I/O request. This assumes, - Blocking semantics: FIFO I/O waits for the other side to connect. - Buffered semantics: Closing one side does not discard existing data. The former can be replaced by WaitNamedPipe/ConnectNamedPipe on Win32, but the second cannot be easily worked around. It is also impossible to have another "keep-alive" pipe server instance, as server-client pairs are fixed on connection on Win32 and the client may get connected to it instead of the real one. Refactor FifoFile[IO] to use an open file handles rather than file name. --- Win32 provides no way to replace the process image. Under the hood exec* actually creates a new process with a new PID. DebugActiveProcess also cannot get notified of process creations. Create the new process in a suspended state and resume it after attach. --- lldb/packages/Python/lldbsuite/test/dotest.py | 2 +- .../runInTerminal/TestDAP_runInTerminal.py| 3 - .../API/tools/lldb-dap/runInTerminal/main.c | 6 +- lldb/tools/lldb-dap/FifoFiles.cpp | 120 +++--- lldb/tools/lldb-dap/FifoFiles.h | 27 ++-- lldb/tools/lldb-dap/RunInTerminal.cpp | 40 +++--- lldb/tools/lldb-dap/RunInTerminal.h | 9 +- lldb/tools/lldb-dap/lldb-dap.cpp | 52 ++-- 8 files changed, 196 insertions(+), 63 deletions(-) diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py index 681ea1638f2d6f..538cece8b4913d 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest.py +++ b/lldb/packages/Python/lldbsuite/test/dotest.py @@ -545,7 +545,7 @@ def setupSysPath(): lldbDir = os.path.dirname(lldbtest_config.lldbExec) -lldbDAPExec = os.path.join(lldbDir, "lldb-dap") +lldbDAPExec = os.path.join(lldbDir, "lldb-dap.exe" if os.name == "nt" else "lldb-dap") if is_exe(lldbDAPExec): os.environ["LLDBDAP_EXEC"] = lldbDAPExec diff --git a/lldb/test/API/tools/lldb-dap/runInTerminal/TestDAP_runInTerminal.py b/lldb/test/API/tools/lldb-dap/runInTerminal/TestDAP_runInTerminal.py index ac96bcc1364a27..18a92dd3fa3359 100644 --- a/lldb/test/API/tools/lldb-dap/runInTerminal/TestDAP_runInTerminal.py +++ b/lldb/test/API/tools/lldb-dap/runInTerminal/TestDAP_runInTerminal.py @@ -43,7 +43,6 @@ def isTestSupported(self): except: return False -@skipIfWindows @skipIf(archs=no_match(["x86_64"])) def test_runInTerminal(self): if not self.isTestSupported(): @@ -113,7 +112,6 @@ def test_runInTerminalWithObjectEnv(self): self.assertIn("FOO", request_envs) self.assertEqual("BAR", request_envs["FOO"]) -@skipIfWindows @skipIf(archs=no_match(["x86_64"])) def test_runInTerminalInvalidTarget(self): if not self.isTestSupported(): @@ -132,7 +130,6 @@ def test_runInTerminalInvalidTarget(self): response["message"], ) -@skipIfWindows @skipIf(archs=no_match(["x86_64"])) def test_missingArgInRunInTerminalLauncher(self): if not self.isTestSupported(): diff --git a/lldb/test/API/tools/lldb-dap/runInTerminal/main.c b/lldb/test/API/tools/lldb-dap/runInTerminal/main.c index 676bd830e657b4..9cc25b2e45a494 100644 --- a/lldb/test/API/tools/lldb-dap/runInTerminal/main.c +++ b/lldb/test/API/tools/lldb-dap/runInTerminal/main.c @@ -1,11 +1,13 @@ #include #include -#include + +#include +#include int main(int argc, char *argv[]) { const char *foo = getenv("FOO"); for (int counter = 1;; counter++) { -sleep(1); // breakpoint +thrd_sleep(&(struct timespec){.tv_sec = 1}, NULL); // breakpoint } return 0; } diff --git a/lldb/tools/lldb-dap/FifoFiles.cpp b/lldb/tools/lldb-dap/FifoFiles.cpp index 1f1bba80bd3b11..e3ed7c5d064135 100644 --- a/lldb/tools/lldb-dap/FifoFiles.cpp +++ b/lldb/tools/lldb-dap/FifoFiles.cpp @@ -9,7 +9,13 @@ #include "FifoFiles.h" #include "JSONUtils.h" -#if !defined(_WIN32) +#include "llvm/Support/FileSystem.h" + +#if defined(_WIN32) +#include +#include +#include +#else #include #include #include @@ -24,27 +30,74 @@ using namespace llvm; namespace lldb_dap { -FifoFile::FifoFile(StringRef path) : m_path(path) {} +std::error_code EC; +FifoFile::FifoFile(StringRef path) +: m_path(path), m_file(fopen(path.data(), "r+")) { + if (m_file == nullptr) { +EC = std::error_code(errno, std::generic_category()); +llvm::errs() << "Failed to open fifo file " << path << ": " << EC.message() + << "\n"; +std::terminate(); + } + if (setvbuf(m_file, NULL, _IONBF, 0)) +llvm::errs() << "Error
[Lldb-commits] [lldb] [llvm] [NFC][DebugInfo] Make some block-start-position methods return iterators (PR #124287)
jmorse wrote: Indeed, that's a pattern we've seen elsewhere in the instruction APIs -- you can select whether you want an instruction inserted into a block or not by whether you pass an instruction pointer or nullptr in. However, without a common "no-such-location" instruction iterator (or by making the argument std::optional) we can't replicate that with the new APIs. For things like the instruction constructor APIs we've used overloads, and forced users who don't want instruction insertion to call a function without an insertion location argument. Here, we'd have a `insertDbgValueIntrinsic` function without the InsertBefore argument for users to call -- that would preserve the generality, however it wouldn't solve your backwards-compatibility objectives. If that's the case, there might be nothing we can do about that here. https://github.com/llvm/llvm-project/pull/124287 ___ 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)
@@ -0,0 +1,132 @@ +//===-- DILLexer.h --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLDB_VALUEOBJECT_DILLEXER_H_ +#define LLDB_VALUEOBJECT_DILLEXER_H_ + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Error.h" +#include +#include +#include +#include +#include + +namespace lldb_private::dil { + +/// Class defining the tokens generated by the DIL lexer and used by the +/// DIL parser. +class Token { +public: + enum Kind { +coloncolon, +eof, +identifier, +l_paren, +r_paren, +unknown, + }; + + Token(Kind kind, std::string spelling, uint32_t start) + : m_kind(kind), m_spelling(std::move(spelling)), m_start_pos(start) {} + + Kind GetKind() const { return m_kind; } + + std::string GetSpelling() const { return m_spelling; } + + bool Is(Kind kind) const { return m_kind == kind; } + + bool IsNot(Kind kind) const { return m_kind != kind; } + + bool IsOneOf(Kind kind1, Kind kind2) const { return Is(kind1) || Is(kind2); } + + template bool IsOneOf(Kind kind, Ts... Ks) const { +return Is(kind) || IsOneOf(Ks...); + } + + uint32_t GetLocation() const { return m_start_pos; } + + static llvm::StringRef GetTokenName(Kind kind); + +private: + Kind m_kind; + std::string m_spelling; + uint32_t m_start_pos; // within entire expression string +}; + +/// Class for doing the simple lexing required by DIL. +class DILLexer { +public: + /// Lexes all the tokens in expr and calls the private constructor + /// with the lexed tokens. + static llvm::Expected Create(llvm::StringRef expr); + + /// Return the current token to be handled by the DIL parser. + const Token &GetCurrentToken() { return m_lexed_tokens[m_tokens_idx]; } + + /// Advance the current token position by N. + void Advance(uint32_t N = 1) { +// UINT_MAX means uninitialized, no "current" position, so move to start. +if (m_tokens_idx == UINT_MAX) + m_tokens_idx = 0; +else if (m_tokens_idx + N >= m_lexed_tokens.size()) + // N is too large; advance to the end of the lexed tokens. + m_tokens_idx = m_lexed_tokens.size() - 1; +else + m_tokens_idx += N; + } + + /// Return the lexed token N positions ahead of the 'current' token + /// being handled by the DIL parser. + const Token &LookAhead(uint32_t N) { +if (m_tokens_idx + N < m_lexed_tokens.size()) + return m_lexed_tokens[m_tokens_idx + N]; + +// Last token should be an 'eof' token. +return m_lexed_tokens.back(); + } + + /// Return the index for the 'current' token being handled by the DIL parser. + uint32_t GetCurrentTokenIdx() { return m_tokens_idx; } + + /// Set the index for the 'current' token (to be handled by the parser) + /// to a particular position. Used for either committing 'look ahead' parsing + /// or rolling back tentative parsing. + void ResetTokenIdx(uint32_t new_value) { +assert(new_value == UINT_MAX || new_value < m_lexed_tokens.size()); +m_tokens_idx = new_value; + } + + uint32_t NumLexedTokens() { return m_lexed_tokens.size(); } + +private: + DILLexer(llvm::StringRef dil_expr, std::vector lexed_tokens) + : m_expr(dil_expr), m_lexed_tokens(std::move(lexed_tokens)), +m_tokens_idx(UINT_MAX), m_eof_token(Token(Token::eof, "", 0)) {} + + static llvm::Expected Lex(llvm::StringRef expr, + llvm::StringRef &remainder); + + // The input string we are lexing & parsing. + llvm::StringRef m_expr; + + // Holds all of the tokens lexed so far. + std::vector m_lexed_tokens; + + // Index into m_lexed_tokens; indicates which token the DIL parser is + // currently trying to parse/handle. + uint32_t m_tokens_idx; + + // "eof" token; to be returned by lexer when 'look ahead' fails. + Token m_eof_token; +}; labath wrote: ```suggestion }; ``` 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)
@@ -0,0 +1,132 @@ +//===-- DILLexer.h --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLDB_VALUEOBJECT_DILLEXER_H_ +#define LLDB_VALUEOBJECT_DILLEXER_H_ + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Error.h" +#include +#include labath wrote: It fits in nicer with the other headers (though maybe you don't need it if you remove the UINT_MAX thing below) ```suggestion #include ``` 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)
@@ -0,0 +1,132 @@ +//===-- DILLexer.h --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLDB_VALUEOBJECT_DILLEXER_H_ +#define LLDB_VALUEOBJECT_DILLEXER_H_ labath wrote: I believe our headers don't have the ending underscore. ```suggestion #ifndef LLDB_VALUEOBJECT_DILLEXER_H #define LLDB_VALUEOBJECT_DILLEXER_H ``` 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)
@@ -0,0 +1,131 @@ +//===-- DILLexer.h --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLDB_VALUEOBJECT_DILLEXER_H_ +#define LLDB_VALUEOBJECT_DILLEXER_H_ + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Error.h" +#include +#include +#include +#include +#include + +namespace lldb_private::dil { + +/// Class defining the tokens generated by the DIL lexer and used by the +/// DIL parser. +class Token { +public: + enum Kind { +coloncolon, +eof, +identifier, +l_paren, +r_paren, +unknown, labath wrote: The unknown token is still here. Are you sure you uploaded the right version of the patch? 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)
@@ -0,0 +1,131 @@ +//===-- DILLexer.h --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLDB_VALUEOBJECT_DILLEXER_H_ +#define LLDB_VALUEOBJECT_DILLEXER_H_ + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Error.h" +#include +#include +#include +#include +#include + +namespace lldb_private::dil { + +/// Class defining the tokens generated by the DIL lexer and used by the +/// DIL parser. +class Token { +public: + enum Kind { +coloncolon, +eof, +identifier, +l_paren, +r_paren, +unknown, + }; + + Token(Kind kind, std::string spelling, uint32_t start) + : m_kind(kind), m_spelling(spelling), m_start_pos(start) {} + + Kind GetKind() const { return m_kind; } + + std::string GetSpelling() const { return m_spelling; } + + bool Is(Kind kind) const { return m_kind == kind; } + + bool IsNot(Kind kind) const { return m_kind != kind; } + + bool IsOneOf(Kind kind1, Kind kind2) const { return Is(kind1) || Is(kind2); } + + template bool IsOneOf(Kind kind, Ts... Ks) const { +return Is(kind) || IsOneOf(Ks...); + } + + uint32_t GetLocation() const { return m_start_pos; } + + static llvm::StringRef GetTokenName(Kind kind); + +private: + Kind m_kind; + std::string m_spelling; + uint32_t m_start_pos; // within entire expression string +}; + +/// Class for doing the simple lexing required by DIL. +class DILLexer { +public: + /// Lexes all the tokens in expr and calls the private constructor + /// with the lexed tokens. + static llvm::Expected Create(llvm::StringRef expr); + + /// Return the current token to be handled by the DIL parser. + const Token &GetCurrentToken() { return m_lexed_tokens[m_tokens_idx]; } + + /// Advance the current token position by N. + void Advance(uint32_t N = 1) { +// UINT_MAX means uninitialized, no "current" position, so move to start. +if (m_tokens_idx == UINT_MAX) labath wrote: And I'd hope that all of the UINT_MAX business can go away if we really start at token zero. 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] Store the command in the CommandReturnObject (PR #125132)
labath wrote: I think this is better. As much as I like initializing things in the constructor, I don't think it makes sense when the whole CommandReturnObject is built around using it as a by-ref return value. https://github.com/llvm/llvm-project/pull/125132 ___ 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: /cherry-pick 13d0318a9848ec322ceea4f37fb6b421d70407b0 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] Add support for gdb-style 'x' packet (PR #124733)
https://github.com/labath milestoned 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][telemetry] Implement LLDB Telemetry (part 1) (PR #119716)
https://github.com/oontvoo updated https://github.com/llvm/llvm-project/pull/119716 >From b7216d7c3edd5974d84612586fbabdef19037387 Mon Sep 17 00:00:00 2001 From: Vy Nguyen Date: Thu, 26 Dec 2024 20:50:40 -0500 Subject: [PATCH 1/2] Implement LLDB Telemetry (Part 1) This contains only the concrete implementation of the framework to be used but no usages yet. This is a subset of PR/98528. I plan to send a few follow-up patches: part2 : includes changes in the plugin-manager to set up the plugin stuff (ie., how to create a default vs vendor impl) part3 (all of the following can be done in parallel): * part 3_a: define DebuggerTelemetryInfo and related methods to collect data about debugger startup/exit * part 3_b: define TargetTelemetryInfo and related methods to collect data about debug target(s) * part 3_c: define CommandTelemetryInfo and related methods to collect data about debug-commands * part 3_d: define ClientTelemtryInfo and related methods to collect data about lldb-dap/any other client --- lldb/include/lldb/Core/Telemetry.h| 101 ++ lldb/include/lldb/lldb-enumerations.h | 4 +- lldb/source/Core/CMakeLists.txt | 2 + lldb/source/Core/Telemetry.cpp| 92 +++ lldb/test/CMakeLists.txt | 3 + 5 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 lldb/include/lldb/Core/Telemetry.h create mode 100644 lldb/source/Core/Telemetry.cpp diff --git a/lldb/include/lldb/Core/Telemetry.h b/lldb/include/lldb/Core/Telemetry.h new file mode 100644 index 00..882511efd804d2 --- /dev/null +++ b/lldb/include/lldb/Core/Telemetry.h @@ -0,0 +1,101 @@ +//===-- Telemetry.h --*- C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLDB_CORE_TELEMETRY_H +#define LLDB_CORE_TELEMETRY_H + +#include +#include +#include +#include +#include +#include + +#include "lldb/Core/StructuredDataImpl.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Utility/StructuredData.h" +#include "lldb/lldb-forward.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/JSON.h" +#include "llvm/Telemetry/Telemetry.h" + +namespace lldb_private { + +using llvm::telemetry::Destination; +using llvm::telemetry::KindType; +using llvm::telemetry::Serializer; +using llvm::telemetry::TelemetryInfo; + +struct LldbEntryKind : public ::llvm::telemetry::EntryKind { + static const KindType BaseInfo = 0b11000; +}; + +/// Defines a convenient type for timestamp of various events. +/// This is used by the EventStats below. +using SteadyTimePoint = std::chrono::time_point; + +/// Various time (and possibly memory) statistics of an event. +struct EventStats { + // REQUIRED: Start time of an event + SteadyTimePoint start; + // OPTIONAL: End time of an event - may be empty if not meaningful. + std::optional end; + // TBD: could add some memory stats here too? + + EventStats() = default; + EventStats(SteadyTimePoint start) : start(start) {} + EventStats(SteadyTimePoint start, SteadyTimePoint end) + : start(start), end(end) {} +}; + +/// Describes the exit signal of an event. +struct ExitDescription { + int exit_code; + std::string description; +}; + +struct LldbBaseTelemetryInfo : public TelemetryInfo { + EventStats stats; + + std::optional exit_desc; + + Debugger *debugger; + + // For dyn_cast, isa, etc operations. + KindType getKind() const override { return LldbEntryKind::BaseInfo; } + + static bool classof(const TelemetryInfo *t) { +// Subclasses of this is also acceptable. +return (t->getKind() & LldbEntryKind::BaseInfo) == LldbEntryKind::BaseInfo; + } + + void serialize(Serializer &serializer) const override; +}; + +/// The base Telemetry manager instance in LLDB +/// This class declares additional instrumentation points +/// applicable to LLDB. +class TelemetryManager : public llvm::telemetry::Manager { +public: + TelemetryManager(std::unique_ptr config); + + llvm::Error dispatch(TelemetryInfo *entry) override; + + void addDestination(std::unique_ptr destination) override; + +private: + std::unique_ptr m_config; + const std::string m_session_uuid; + std::vector> m_destinations; +}; + +} // namespace lldb_private +#endif // LLDB_CORE_TELEMETRY_H diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index 0094fcd596fdf7..f63e446b6042f6 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -257,8 +257,8 @@ enum StopReason { }; /// Command Return Status Types. -enum ReturnStatus { - eReturnStatusInvalid, +enum ReturnStatus : int { + eReturnStatusInvalid =
[Lldb-commits] [lldb] [lldb] Implement a statusline in LLDB (PR #121860)
@@ -0,0 +1,163 @@ +//===-- Statusline.cpp ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "lldb/Core/Statusline.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/FormatEntity.h" +#include "lldb/Host/ThreadLauncher.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Utility/AnsiTerminal.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" +#include "llvm/Support/Locale.h" + +#define ESCAPE "\x1b" +#define ANSI_SAVE_CURSOR ESCAPE "7" +#define ANSI_RESTORE_CURSOR ESCAPE "8" +#define ANSI_CLEAR_BELOW ESCAPE "[J" +#define ANSI_CLEAR_LINE "\r\x1B[2K" +#define ANSI_SET_SCROLL_ROWS ESCAPE "[0;%ur" +#define ANSI_TO_START_OF_ROW ESCAPE "[%u;0f" +#define ANSI_UP_ROWS ESCAPE "[%dA" +#define ANSI_DOWN_ROWS ESCAPE "[%dB" +#define ANSI_FORWARD_COLS ESCAPE "\033[%dC" +#define ANSI_BACKWARD_COLS ESCAPE "\033[%dD" + +using namespace lldb; +using namespace lldb_private; + +static size_t ColumnWidth(llvm::StringRef str) { + std::string stripped = ansi::StripAnsiTerminalCodes(str); + return llvm::sys::locale::columnWidth(stripped); +} + +Statusline::Statusline(Debugger &debugger) : m_debugger(debugger) { Enable(); } + +Statusline::~Statusline() { Disable(); } + +void Statusline::TerminalSizeChanged() { + m_terminal_size_has_changed = 1; + + // FIXME: This code gets called from a signal handler. It's probably not safe + // to redraw the statusline, even without recomputing it? labath wrote: It definitely isn't. And the Enable/Disable functions are called from a signal handler as well. https://github.com/llvm/llvm-project/pull/121860 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement a statusline in LLDB (PR #121860)
https://github.com/labath commented: I think this looks pretty good. The signal-safety of the code is very dubious (it was dubious even before that, but now it's even more), but I don't think that there's anything we can do about it from here. I think the only way we can have a real signal-safety guarantee is if we have a signal-catcher thread in the lldb driver, which catches the signals very safely (for example, using our MainLoop class) and then notifies lldb outside of the signal context. Definitely needs some tests though (I thought you had some -- what happened to those?) https://github.com/llvm/llvm-project/pull/121860 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement a statusline in LLDB (PR #121860)
https://github.com/labath edited https://github.com/llvm/llvm-project/pull/121860 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement a statusline in LLDB (PR #121860)
@@ -73,6 +73,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Regex.h" labath wrote: ? https://github.com/llvm/llvm-project/pull/121860 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Implement `runInTerminal` for Windows (PR #121269)
@@ -24,41 +30,95 @@ using namespace llvm; namespace lldb_dap { -FifoFile::FifoFile(StringRef path) : m_path(path) {} +std::error_code EC; +FifoFile::FifoFile(StringRef path) +: m_path(path), m_file(fopen(path.data(), "r+")) { + if (m_file == nullptr) { +EC = std::error_code(errno, std::generic_category()); +llvm::errs() << "Failed to open fifo file " << path << ": " << EC.message() + << "\n"; +std::terminate(); + } + if (setvbuf(m_file, NULL, _IONBF, 0)) +llvm::errs() << "Error setting unbuffered mode on C FILE\n"; +} +FifoFile::FifoFile(StringRef path, FILE *f) : m_path(path), m_file(f) {} +FifoFile::FifoFile(FifoFile &&other) +: m_path(other.m_path), m_file(other.m_file) { + other.m_file = nullptr; +} FifoFile::~FifoFile() { + if (m_file) +fclose(m_file); #if !defined(_WIN32) + // Unreferenced named pipes are deleted automatically on Win32 unlink(m_path.c_str()); #endif } -Expected> CreateFifoFile(StringRef path) { -#if defined(_WIN32) - return createStringError(inconvertibleErrorCode(), "Unimplemented"); +// This probably belongs to llvm::sys::fs as another FSEntity type +std::error_code createNamedPipe(const Twine &Prefix, StringRef Suffix, +int &ResultFd, +SmallVectorImpl &ResultPath) { + const char *Middle = Suffix.empty() ? "-%%" : "-%%."; + auto EC = sys::fs::getPotentiallyUniqueFileName( +#ifdef _WIN32 + ".\\pipe\\LOCAL\\" +#else + "/tmp/" +#endif + + Prefix + Middle + Suffix, + ResultPath); + if (EC) +return EC; + ResultPath.push_back(0); + const char *path = ResultPath.data(); +#ifdef _WIN32 + HANDLE h = ::CreateNamedPipeA( + path, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 1024, 1024, 0, NULL); + if (h == INVALID_HANDLE_VALUE) +return std::error_code(::GetLastError(), std::system_category()); + ResultFd = _open_osfhandle((intptr_t)h, _O_TEXT | _O_RDWR); + if (ResultFd == -1) +return std::error_code(::GetLastError(), std::system_category()); #else - if (int err = mkfifo(path.data(), 0600)) -return createStringError(std::error_code(err, std::generic_category()), - "Couldn't create fifo file: %s", path.data()); - return std::make_shared(path); + if (mkfifo(path, 0600) == -1) +return std::error_code(errno, std::generic_category()); + EC = openFileForWrite(ResultPath, ResultFd, sys::fs::CD_OpenExisting, +sys::fs::OF_None, 0600); + if (EC) +return EC; #endif + ResultPath.pop_back(); + return std::error_code(); } -FifoFileIO::FifoFileIO(StringRef fifo_file, StringRef other_endpoint_name) -: m_fifo_file(fifo_file), m_other_endpoint_name(other_endpoint_name) {} +FifoFileIO::FifoFileIO(FifoFile &&fifo_file, StringRef other_endpoint_name) +: m_fifo_file(std::move(fifo_file)), + m_other_endpoint_name(other_endpoint_name) {} Expected FifoFileIO::ReadJSON(std::chrono::milliseconds timeout) { // We use a pointer for this future, because otherwise its normal destructor // would wait for the getline to end, rendering the timeout useless. std::optional line; std::future *future = new std::future(std::async(std::launch::async, [&]() { -std::ifstream reader(m_fifo_file, std::ifstream::in); -std::string buffer; -std::getline(reader, buffer); -if (!buffer.empty()) - line = buffer; +rewind(m_fifo_file.m_file); SuibianP wrote: It seemed to help on Windows, but I did not investigate further, as it is technically also required by ISO C standard (C23 draft N3220 §7.23.5.3.7) > When a file is opened with update mode (’+’ as the second or third character > in the previously described list of mode argument values), both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the `fflush` function or to a file positioning function (`fseek`, `fsetpos`, or `rewind`), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file. Opening (or creating) a text file with update mode may instead open (or create) a binary stream in some implementations. https://github.com/llvm/llvm-project/pull/121269 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Implement `runInTerminal` for Windows (PR #121269)
@@ -24,41 +30,95 @@ using namespace llvm; namespace lldb_dap { -FifoFile::FifoFile(StringRef path) : m_path(path) {} +std::error_code EC; +FifoFile::FifoFile(StringRef path) +: m_path(path), m_file(fopen(path.data(), "r+")) { + if (m_file == nullptr) { +EC = std::error_code(errno, std::generic_category()); +llvm::errs() << "Failed to open fifo file " << path << ": " << EC.message() + << "\n"; +std::terminate(); + } + if (setvbuf(m_file, NULL, _IONBF, 0)) +llvm::errs() << "Error setting unbuffered mode on C FILE\n"; +} +FifoFile::FifoFile(StringRef path, FILE *f) : m_path(path), m_file(f) {} +FifoFile::FifoFile(FifoFile &&other) +: m_path(other.m_path), m_file(other.m_file) { + other.m_file = nullptr; +} FifoFile::~FifoFile() { + if (m_file) +fclose(m_file); #if !defined(_WIN32) + // Unreferenced named pipes are deleted automatically on Win32 unlink(m_path.c_str()); #endif } -Expected> CreateFifoFile(StringRef path) { -#if defined(_WIN32) - return createStringError(inconvertibleErrorCode(), "Unimplemented"); +// This probably belongs to llvm::sys::fs as another FSEntity type +std::error_code createNamedPipe(const Twine &Prefix, StringRef Suffix, +int &ResultFd, +SmallVectorImpl &ResultPath) { + const char *Middle = Suffix.empty() ? "-%%" : "-%%."; + auto EC = sys::fs::getPotentiallyUniqueFileName( +#ifdef _WIN32 + ".\\pipe\\LOCAL\\" +#else + "/tmp/" SuibianP wrote: On Windows FIFOs live on a virtual hierarchy `\\.\pipe\` not backed a real filesystem. I don't think it is possible to `mkdir` on them, although it is possible to specify something like `\\.\pipe\tmp\dir\myfifo` to `CreateNamedPipe`. https://github.com/llvm/llvm-project/pull/121269 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [clang] [lldb] Reland: [clang] fix P3310 overload resolution flag propagation (PR #125791)
@@ -280,7 +280,8 @@ std::optional CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { new_class_template->getDeclContext(), new_class_template->getTemplatedDecl()->getLocation(), new_class_template->getLocation(), new_class_template, imported_args, - nullptr); + td->hasMatchedPackOnParmToNonPackOnArg(), + /*PrevDecl=*/nullptr); mizvekov wrote: @DavidSpickett @Michael137 this is the only change for this relanding of the patch. As far as I understood reading this code, this is basically importing a template instantiation into a different context, so this is much like what we would do at the AST Importer, ie just forward the new bool from the original specialization into this new one. Also as I understand, this implementation whitelists only a few template names from the STL, none of which have template template parameter to begin with, so this new flag will always be false here and this is pretty much untestable. https://github.com/llvm/llvm-project/pull/125791 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [clang] [lldb] Reland: [clang] fix P3310 overload resolution flag propagation (PR #125791)
llvmbot wrote: @llvm/pr-subscribers-clang-modules Author: Matheus Izvekov (mizvekov) Changes Class templates might be only instantiated when they are required to be complete, but checking the template args against the primary template is immediate. This result is cached so that later when the class is instantiated, checking against the primary template is not repeated. The 'MatchedPackOnParmToNonPackOnArg' flag is also produced upon checking against the primary template, so it needs to be cached in the specialziation as well. This fixes a bug which has not been in any release, so there are no release notes. Fixes #125290 --- Patch is 232.54 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/125791.diff 16 Files Affected: - (modified) clang/include/clang/AST/DeclTemplate.h (+14-2) - (modified) clang/include/clang/Sema/Sema.h (+2-2) - (modified) clang/lib/AST/ASTImporter.cpp (+3-3) - (modified) clang/lib/AST/DeclTemplate.cpp (+24-23) - (modified) clang/lib/AST/JSONNodeDumper.cpp (+5) - (modified) clang/lib/AST/TextNodeDumper.cpp (+4-1) - (modified) clang/lib/Sema/SemaTemplate.cpp (+5-3) - (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (-2) - (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+1-1) - (modified) clang/lib/Sema/SemaType.cpp (+2-1) - (modified) clang/lib/Serialization/ASTReaderDecl.cpp (+1) - (modified) clang/lib/Serialization/ASTWriterDecl.cpp (+1) - (modified) clang/test/AST/ast-dump-templates.cpp (+6045-2) - (modified) clang/test/AST/gen_ast_dump_json_test.py (+17-4) - (modified) clang/test/SemaTemplate/cwg2398.cpp (+17) - (modified) lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp (+2-1) ``diff diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 9ecff2c898acd5..03c43765206b18 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -1841,15 +1841,23 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl, LLVM_PREFERRED_TYPE(TemplateSpecializationKind) unsigned SpecializationKind : 3; + /// Indicate that we have matched a parameter pack with a non pack + /// argument, when the opposite match is also allowed (strict pack match). + /// This needs to be cached as deduction is performed during declaration, + /// and we need the information to be preserved so that it is consistent + /// during instantiation. + bool MatchedPackOnParmToNonPackOnArg : 1; + protected: ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate, ArrayRef Args, + bool MatchedPackOnParmToNonPackOnArg, ClassTemplateSpecializationDecl *PrevDecl); - explicit ClassTemplateSpecializationDecl(ASTContext &C, Kind DK); + ClassTemplateSpecializationDecl(ASTContext &C, Kind DK); public: friend class ASTDeclReader; @@ -1859,7 +1867,7 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl, Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate, - ArrayRef Args, + ArrayRef Args, bool MatchedPackOnParmToNonPackOnArg, ClassTemplateSpecializationDecl *PrevDecl); static ClassTemplateSpecializationDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID); @@ -1930,6 +1938,10 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl, SpecializationKind = TSK; } + bool hasMatchedPackOnParmToNonPackOnArg() const { +return MatchedPackOnParmToNonPackOnArg; + } + /// Get the point of instantiation (if any), or null if none. SourceLocation getPointOfInstantiation() const { return PointOfInstantiation; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 472a0e25adc975..79bf6c04ee4969 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -13493,8 +13493,8 @@ class Sema final : public SemaBase { bool InstantiateClassTemplateSpecialization( SourceLocation PointOfInstantiation, ClassTemplateSpecializationDecl *ClassTemplateSpec, - TemplateSpecializationKind TSK, bool Complain = true, - bool PrimaryHasMatchedPackOnParmToNonPackOnArg = false); + TemplateSpecializationKind TSK, bool Complain, + bool PrimaryHasMatchedPackOnParmToNonPackOnArg); /// Instantiates the definitions of all of the member /// of the given class, which is an instantiation of a class template diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp inde
[Lldb-commits] [lldb] [lldb][telemetry] Implement LLDB Telemetry (part 1) (PR #119716)
oontvoo wrote: @labath Hi, I've updated the patch to sync up with the changes from llvm::Telemetry. (Aslo addressed all the open-questions.) Please have another look when you can. Thanks! https://github.com/llvm/llvm-project/pull/119716 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [clang] [lldb] Reland: [clang] fix P3310 overload resolution flag propagation (PR #125791)
cor3ntin wrote: Initially reverted by https://github.com/llvm/llvm-project/pull/125710 @mizvekov did you do a stage2 build of lldb? https://github.com/llvm/llvm-project/pull/125791 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Implement `runInTerminal` for Windows (PR #121269)
@@ -111,8 +111,10 @@ Error RunInTerminalLauncherCommChannel::WaitUntilDebugAdaptorAttaches( return message.takeError(); } -Error RunInTerminalLauncherCommChannel::NotifyPid() { - return m_io.SendJSON(RunInTerminalMessagePid(getpid()).ToJSON()); +Error RunInTerminalLauncherCommChannel::NotifyPid(lldb::pid_t pid) { + if (pid == 0) +pid = getpid(); SuibianP wrote: Refactored with explicitly specified arguments. https://github.com/llvm/llvm-project/pull/121269 ___ 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)
@@ -58,12 +57,13 @@ const char DEV_NULL[] = "/dev/null"; namespace lldb_dap { -DAP::DAP(llvm::StringRef path, std::ofstream *log, ReplMode repl_mode, - StreamDescriptor input, StreamDescriptor output) -: debug_adaptor_path(path), log(log), input(std::move(input)), +DAP::DAP(std::string name, llvm::StringRef path, std::ofstream *log, + StreamDescriptor input, StreamDescriptor output, ReplMode repl_mode, + std::vector pre_init_commands) +: name(name), debug_adaptor_path(path), log(log), input(std::move(input)), output(std::move(output)), broadcaster("lldb-dap"), - exception_breakpoints(), focus_tid(LLDB_INVALID_THREAD_ID), - stop_at_entry(false), is_attach(false), + exception_breakpoints(), pre_init_commands(pre_init_commands), labath wrote: ```suggestion exception_breakpoints(), pre_init_commands(std::move(pre_init_commands)), ``` 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 good, modulo the question about (detached) threads. I'd be nice to have an lldb-dap expert take a look as well. 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)
@@ -5058,72 +5053,144 @@ 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 RunDAP = [](llvm::StringRef program_path, ReplMode repl_mode, + std::vector pre_init_commands, + std::ofstream *log, std::string name, StreamDescriptor input, + StreamDescriptor output, std::FILE *redirectOut = nullptr, + std::FILE *redirectErr = nullptr) -> bool { +DAP dap = DAP(name, program_path, log, std::move(input), std::move(output), + repl_mode, pre_init_commands); -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 false; +} + +RegisterRequestCallbacks(dap); + +// used only by TestVSCode_redirection_to_console.py +if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) + redirection_test(); + +if (auto Err = dap.Loop()) { + std::string errorMessage = llvm::toString(std::move(Err)); + if (log) +*log << "Transport Error: " << errorMessage << "\n"; + return false; +} +return true; + }; + + if (!connection.empty()) { +auto maybeProtoclAndName = validateConnection(connection); +if (auto Err = maybeProtoclAndName.takeError()) { + llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), + "Invalid connection: "); return EXIT_FAILURE; } -redirectOut = stdout; -redirectErr = stderr; +Socket::SocketProtocol protocol; +std::string name; +std::tie(protocol, name) = *maybeProtoclAndName; -input = StreamDescriptor::from_file(fileno(stdin), false); -output = StreamDescriptor::from_file(stdout_fd, false); - } +Status error; +std::unique_ptr listener = Socket::Create(protocol, error); +if (error.Fail()) { + llvm::logAllUnhandledErrors(error.takeError(), llvm::errs(), + "Failed to create socket listener: "); + return EXIT_FAILURE; +} - DAP dap = DAP(program_path.str(), log.get(), default_repl_mode, -std::move(input), std::move(output)); +error = listener->Listen(name, /* backlog */ 5); +if (error.Fail()) { + llvm::logAllUnhandledErrors(error.takeError(), llvm::errs(), + "Failed to listen for connections: "); + return EXIT_FAILURE; +} - // 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; - } +std::string address = +llvm::join(listener->GetListeningConnectionURI(), ", "); +if (log) + *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(); + +llvm::DefaultThreadPool pool(llvm::optimal_concurrency()); labath wrote: Isn't this (not picking up new connections if the pool is full) going to be a problem? I mean some sort of rate limiting might be reasonable, but I'm not sure if that was the intention behind this (last thing we were talking about here were detached threads). FWIW, even though you didn't say so explicitly, I get the impression that the only w
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -5058,72 +5053,144 @@ 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 RunDAP = [](llvm::StringRef program_path, ReplMode repl_mode, + std::vector pre_init_commands, + std::ofstream *log, std::string name, StreamDescriptor input, + StreamDescriptor output, std::FILE *redirectOut = nullptr, + std::FILE *redirectErr = nullptr) -> bool { +DAP dap = DAP(name, program_path, log, std::move(input), std::move(output), + repl_mode, pre_init_commands); -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 false; +} + +RegisterRequestCallbacks(dap); + +// used only by TestVSCode_redirection_to_console.py +if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) + redirection_test(); + +if (auto Err = dap.Loop()) { + std::string errorMessage = llvm::toString(std::move(Err)); + if (log) +*log << "Transport Error: " << errorMessage << "\n"; + return false; +} +return true; + }; + + if (!connection.empty()) { +auto maybeProtoclAndName = validateConnection(connection); +if (auto Err = maybeProtoclAndName.takeError()) { + llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), + "Invalid connection: "); return EXIT_FAILURE; } -redirectOut = stdout; -redirectErr = stderr; +Socket::SocketProtocol protocol; +std::string name; +std::tie(protocol, name) = *maybeProtoclAndName; -input = StreamDescriptor::from_file(fileno(stdin), false); -output = StreamDescriptor::from_file(stdout_fd, false); - } +Status error; +std::unique_ptr listener = Socket::Create(protocol, error); +if (error.Fail()) { + llvm::logAllUnhandledErrors(error.takeError(), llvm::errs(), + "Failed to create socket listener: "); + return EXIT_FAILURE; +} - DAP dap = DAP(program_path.str(), log.get(), default_repl_mode, -std::move(input), std::move(output)); +error = listener->Listen(name, /* backlog */ 5); labath wrote: ```suggestion error = listener->Listen(name, /*backlog=*/5); ``` 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)
@@ -11,6 +11,8 @@ // IWYU pragma: begin_exports +#include "lldb/lldb-forward.h" labath wrote: Probably revert this too? 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)
@@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules labath wrote: I think this stop sign indicates a missing newline. 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] Fix Block::GetRangeIndexContainingAddress for discontinuous functions (PR #124931)
@@ -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()); labath wrote: `function->GetAddress()` returns the address of the start of the function. The address is internally stored as a section+offset pair, but for the most part, you can think of it as an absolute address of the function. Block ranges are internally stored as pairs of integers (offset+size), where the offset is relative to the start of the function. This converts the internal (implicitly relative to section start) representation of the range to the external, absolute (well, section-relative) representation. It basically does that by adjusting the section offset, but it actually does that incorrectly since different parts of the function may be in different sections. So, the correct thing to do is to convert the address into a file address (which is relative to the "base address" of the file -- what ELF would call "virtual address"), do the subtraction there, and then re-resolve the result into a section-relative address. My updated version will do that. https://github.com/llvm/llvm-project/pull/124931 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] 906eeed - [lldb] Store the command in the CommandReturnObject (#125132)
Author: Jonas Devlieghere Date: 2025-02-04T08:55:30-08:00 New Revision: 906eeeda833b30fb7fdc3b7586de34b65d575b45 URL: https://github.com/llvm/llvm-project/commit/906eeeda833b30fb7fdc3b7586de34b65d575b45 DIFF: https://github.com/llvm/llvm-project/commit/906eeeda833b30fb7fdc3b7586de34b65d575b45.diff LOG: [lldb] Store the command in the CommandReturnObject (#125132) As suggested in #125006. Depending on which PR lands first, I'll update `TestCommandInterepterPrintCallback.py` to check that the `CommandReturnObject` passed to the callback has the correct command. Added: lldb/test/API/python_api/commandreturnobject/TestSBCommandReturnObject.py Modified: lldb/include/lldb/API/SBCommandReturnObject.h lldb/include/lldb/Interpreter/CommandReturnObject.h lldb/source/API/SBCommandReturnObject.cpp lldb/source/Interpreter/CommandInterpreter.cpp Removed: diff --git a/lldb/include/lldb/API/SBCommandReturnObject.h b/lldb/include/lldb/API/SBCommandReturnObject.h index e8e20a3f3016b8..9a63c1f96aa707 100644 --- a/lldb/include/lldb/API/SBCommandReturnObject.h +++ b/lldb/include/lldb/API/SBCommandReturnObject.h @@ -42,6 +42,10 @@ class LLDB_API SBCommandReturnObject { bool IsValid() const; + /// Get the command as the user typed it. Empty string if commands were run on + /// behalf of lldb. + const char *GetCommand(); + const char *GetOutput(); const char *GetError(); diff --git a/lldb/include/lldb/Interpreter/CommandReturnObject.h b/lldb/include/lldb/Interpreter/CommandReturnObject.h index f96da34889a324..803bcd76995ede 100644 --- a/lldb/include/lldb/Interpreter/CommandReturnObject.h +++ b/lldb/include/lldb/Interpreter/CommandReturnObject.h @@ -31,6 +31,12 @@ class CommandReturnObject { ~CommandReturnObject() = default; + /// Get the command as the user typed it. Empty string if commands were run on + /// behalf of lldb. + const std::string &GetCommand() const { return m_command; } + + void SetCommand(std::string command) { m_command = std::move(command); } + /// Format any inline diagnostics with an indentation of \c indent. std::string GetInlineDiagnosticString(unsigned indent) const; @@ -182,6 +188,8 @@ class CommandReturnObject { private: enum { eStreamStringIndex = 0, eImmediateStreamIndex = 1 }; + std::string m_command; + StreamTee m_out_stream; StreamTee m_err_stream; std::vector m_diagnostics; diff --git a/lldb/source/API/SBCommandReturnObject.cpp b/lldb/source/API/SBCommandReturnObject.cpp index 9df8aa48b99366..6f54581e64ef41 100644 --- a/lldb/source/API/SBCommandReturnObject.cpp +++ b/lldb/source/API/SBCommandReturnObject.cpp @@ -84,6 +84,13 @@ SBCommandReturnObject::operator bool() const { return true; } +const char *SBCommandReturnObject::GetCommand() { + LLDB_INSTRUMENT_VA(this); + + ConstString output(ref().GetCommand()); + return output.AsCString(/*value_if_empty*/ ""); +} + const char *SBCommandReturnObject::GetOutput() { LLDB_INSTRUMENT_VA(this); diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index 4869b811f99e71..8398226da10961 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -1887,12 +1887,13 @@ bool CommandInterpreter::HandleCommand(const char *command_line, std::string real_original_command_string(command_string); Log *log = GetLog(LLDBLog::Commands); - llvm::PrettyStackTraceFormat stack_trace("HandleCommand(command = \"%s\")", - command_line); - LLDB_LOGF(log, "Processing command: %s", command_line); LLDB_SCOPED_TIMERF("Processing command: %s.", command_line); + // Set the command in the CommandReturnObject here so that it's there even if + // the command is interrupted. + result.SetCommand(command_line); + if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted initiating command")) { result.AppendError("... Interrupted"); return false; @@ -2644,7 +2645,8 @@ void CommandInterpreter::HandleCommands( (uint64_t)idx, cmd, error_msg); m_debugger.SetAsyncExecution(old_async_execution); return; - } else if (options.GetPrintResults()) { + } + if (options.GetPrintResults()) { result.AppendMessageWithFormatv("Command #{0} '{1}' failed with {2}", (uint64_t)idx + 1, cmd, error_msg); } diff --git a/lldb/test/API/python_api/commandreturnobject/TestSBCommandReturnObject.py b/lldb/test/API/python_api/commandreturnobject/TestSBCommandReturnObject.py new file mode 100644 index 00..b0d0b7a8dfe4e7 --- /dev/null +++ b/lldb/test/API/python_api/commandreturnobject/TestSBCommandReturnObject.py @@ -0,0 +1,17 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbte
[Lldb-commits] [lldb] [lldb] Store the command in the CommandReturnObject (PR #125132)
https://github.com/JDevlieghere closed https://github.com/llvm/llvm-project/pull/125132 ___ 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)
llvmbot wrote: /pull-request llvm/llvm-project#125653 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] Document lldb `x` packet deprecation. (PR #125682)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Pavel Labath (labath) Changes --- Full diff: https://github.com/llvm/llvm-project/pull/125682.diff 1 Files Affected: - (modified) lldb/docs/resources/lldbgdbremote.md (+5) ``diff diff --git a/lldb/docs/resources/lldbgdbremote.md b/lldb/docs/resources/lldbgdbremote.md index 5cac3736337a8f..162815148a18bf 100644 --- a/lldb/docs/resources/lldbgdbremote.md +++ b/lldb/docs/resources/lldbgdbremote.md @@ -2412,6 +2412,11 @@ value of errno if unlink failed. ## "x" - Binary memory read +> **Warning:** The format of this packet was decided before GDB 16 +> introduced its own format for `x`. Future versions of LLDB may not +> support the format described here, and new code should produce and +> expect the format used by GDB. + Like the `m` (read) and `M` (write) packets, this is a partner to the `X` (write binary data) packet, `x`. `` https://github.com/llvm/llvm-project/pull/125682 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Document lldb `x` packet deprecation. (PR #125682)
https://github.com/labath created https://github.com/llvm/llvm-project/pull/125682 None >From cfe826019bb54bdb62cccbd8e8d3eba8f4d6f312 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Tue, 4 Feb 2025 14:11:03 +0100 Subject: [PATCH] Document lldb `x` packet deprecation. --- lldb/docs/resources/lldbgdbremote.md | 5 + 1 file changed, 5 insertions(+) diff --git a/lldb/docs/resources/lldbgdbremote.md b/lldb/docs/resources/lldbgdbremote.md index 5cac3736337a8f..162815148a18bf 100644 --- a/lldb/docs/resources/lldbgdbremote.md +++ b/lldb/docs/resources/lldbgdbremote.md @@ -2412,6 +2412,11 @@ value of errno if unlink failed. ## "x" - Binary memory read +> **Warning:** The format of this packet was decided before GDB 16 +> introduced its own format for `x`. Future versions of LLDB may not +> support the format described here, and new code should produce and +> expect the format used by GDB. + Like the `m` (read) and `M` (write) packets, this is a partner to the `X` (write binary data) packet, `x`. ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [NFC][DebugInfo] Make some block-start-position methods return iterators (PR #124287)
hvdijk wrote: I'm taking a look, but I'm having some doubts about the change itself, `DIBuilder::insertDbgValueIntrinsic`'s `BasicBlock *BB = InsertBefore->getParent();` (where `InsertBefore` is an iterator) doesn't seem safe, it seems like it should be valid to pass an at-the-end iterator there that cannot be dereferenced. I'll take a more in-depth look at the change and see whether I'm able to add any testing. https://github.com/llvm/llvm-project/pull/124287 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] 97f6e53 - [lldb] Support CommandInterpreter print callbacks (#125006)
Author: Jonas Devlieghere Date: 2025-02-04T09:01:08-08:00 New Revision: 97f6e533865c66ea08840be78154099180293094 URL: https://github.com/llvm/llvm-project/commit/97f6e533865c66ea08840be78154099180293094 DIFF: https://github.com/llvm/llvm-project/commit/97f6e533865c66ea08840be78154099180293094.diff LOG: [lldb] Support CommandInterpreter print callbacks (#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 Added: lldb/test/API/python_api/interpreter_callback/Makefile lldb/test/API/python_api/interpreter_callback/TestCommandInterepterPrintCallback.py lldb/test/API/python_api/interpreter_callback/main.c Modified: lldb/bindings/python/python-swigsafecast.swig lldb/bindings/python/python-typemaps.swig lldb/bindings/python/python-wrapper.swig lldb/include/lldb/API/SBCommandInterpreter.h lldb/include/lldb/API/SBDefines.h lldb/include/lldb/Interpreter/CommandInterpreter.h lldb/include/lldb/lldb-enumerations.h lldb/source/API/SBCommandInterpreter.cpp lldb/source/Interpreter/CommandInterpreter.cpp lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h Removed: diff --git a/lldb/bindings/python/python-swigsafecast.swig b/lldb/bindings/python/python-swigsafecast.swig index 429baad158ca5da..4721dfdc17e6a0f 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 f8c33e15c03e666..88b6cd9ef6b6e79 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 b72a462d04643bf..57c7ac387145eff 100644 --- a/lldb/bindings/python/python-wrapper.swig +++ b/lldb/bindings/python/python-wrapper.swig @@ -727,7 +727,7 @@ lldb_private::python::SWIGBridge::LLDBSwigPythonHandleOptionArgumentCompletionFo dict_sp->AddBooleanItem("no-completion", true); return dict_sp; } - + // Convert the return dictionary to a DictionaryS
[Lldb-commits] [lldb] [lldb] Support CommandInterpreter print callbacks (PR #125006)
https://github.com/JDevlieghere closed 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] Implement a statusline in LLDB (PR #121860)
@@ -0,0 +1,163 @@ +//===-- Statusline.cpp ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "lldb/Core/Statusline.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/FormatEntity.h" +#include "lldb/Host/ThreadLauncher.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Utility/AnsiTerminal.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" +#include "llvm/Support/Locale.h" + +#define ESCAPE "\x1b" +#define ANSI_SAVE_CURSOR ESCAPE "7" +#define ANSI_RESTORE_CURSOR ESCAPE "8" +#define ANSI_CLEAR_BELOW ESCAPE "[J" +#define ANSI_CLEAR_LINE "\r\x1B[2K" +#define ANSI_SET_SCROLL_ROWS ESCAPE "[0;%ur" +#define ANSI_TO_START_OF_ROW ESCAPE "[%u;0f" +#define ANSI_UP_ROWS ESCAPE "[%dA" +#define ANSI_DOWN_ROWS ESCAPE "[%dB" +#define ANSI_FORWARD_COLS ESCAPE "\033[%dC" +#define ANSI_BACKWARD_COLS ESCAPE "\033[%dD" + +using namespace lldb; +using namespace lldb_private; + +static size_t ColumnWidth(llvm::StringRef str) { + std::string stripped = ansi::StripAnsiTerminalCodes(str); + return llvm::sys::locale::columnWidth(stripped); +} + +Statusline::Statusline(Debugger &debugger) : m_debugger(debugger) { Enable(); } + +Statusline::~Statusline() { Disable(); } + +void Statusline::TerminalSizeChanged() { + m_terminal_size_has_changed = 1; + + // FIXME: This code gets called from a signal handler. It's probably not safe + // to redraw the statusline, even without recomputing it? JDevlieghere wrote: Yeah I knew the answer :-) https://github.com/llvm/llvm-project/pull/121860 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement a statusline in LLDB (PR #121860)
@@ -73,6 +73,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Regex.h" JDevlieghere wrote: Remnant of trying to regex-away ANSI escape characters before I did #123430. https://github.com/llvm/llvm-project/pull/121860 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Implement a statusline in LLDB (PR #121860)
JDevlieghere wrote: > Definitely needs some tests though (I thought you had some -- what happened > to those?) Yup, I'm planning on adding dedicated PExpect tests. The ones you remember are probably the ones from dependencies that have landed in separate PRs. https://github.com/llvm/llvm-project/pull/121860 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Make ValueObjectDynamicValue::UpdateValue() point to a host b… (PR #125143)
jimingham wrote: This is a little weird - why would the value of a ValueObject when interpreted as its Dynamic Value ever be in host memory? That seems odd, made doubly so because it's unused in the current sources. So I really worry about this getting broken. Would it be possible to cons up a unittest that makes this artificially? https://github.com/llvm/llvm-project/pull/125143 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] WatchAddress ignores modify option (PR #124847)
JDevlieghere wrote: @puremourning Please confirm whether this is ready to be merged and I can press the ✅ button. https://github.com/llvm/llvm-project/pull/124847 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] WatchAddress ignores modify option (PR #124847)
https://github.com/JDevlieghere approved this pull request. https://github.com/llvm/llvm-project/pull/124847 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Make ValueObjectDynamicValue::UpdateValue() point to a host b… (PR #125143)
augusto2112 wrote: To make sure I understand, you want me to write a unittest where I have a value object, and make sure it's dynamic value object child uses the local buffer to store the contents? What should I test? That it prints correctly? https://github.com/llvm/llvm-project/pull/125143 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Document lldb `x` packet deprecation. (PR #125682)
https://github.com/jasonmolenda approved this pull request. https://github.com/llvm/llvm-project/pull/125682 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][telemetry] Implement LLDB Telemetry (part 1) (PR #119716)
https://github.com/oontvoo updated https://github.com/llvm/llvm-project/pull/119716 >From b7216d7c3edd5974d84612586fbabdef19037387 Mon Sep 17 00:00:00 2001 From: Vy Nguyen Date: Thu, 26 Dec 2024 20:50:40 -0500 Subject: [PATCH 1/2] Implement LLDB Telemetry (Part 1) This contains only the concrete implementation of the framework to be used but no usages yet. This is a subset of PR/98528. I plan to send a few follow-up patches: part2 : includes changes in the plugin-manager to set up the plugin stuff (ie., how to create a default vs vendor impl) part3 (all of the following can be done in parallel): * part 3_a: define DebuggerTelemetryInfo and related methods to collect data about debugger startup/exit * part 3_b: define TargetTelemetryInfo and related methods to collect data about debug target(s) * part 3_c: define CommandTelemetryInfo and related methods to collect data about debug-commands * part 3_d: define ClientTelemtryInfo and related methods to collect data about lldb-dap/any other client --- lldb/include/lldb/Core/Telemetry.h| 101 ++ lldb/include/lldb/lldb-enumerations.h | 4 +- lldb/source/Core/CMakeLists.txt | 2 + lldb/source/Core/Telemetry.cpp| 92 +++ lldb/test/CMakeLists.txt | 3 + 5 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 lldb/include/lldb/Core/Telemetry.h create mode 100644 lldb/source/Core/Telemetry.cpp diff --git a/lldb/include/lldb/Core/Telemetry.h b/lldb/include/lldb/Core/Telemetry.h new file mode 100644 index 000..882511efd804d23 --- /dev/null +++ b/lldb/include/lldb/Core/Telemetry.h @@ -0,0 +1,101 @@ +//===-- Telemetry.h --*- C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLDB_CORE_TELEMETRY_H +#define LLDB_CORE_TELEMETRY_H + +#include +#include +#include +#include +#include +#include + +#include "lldb/Core/StructuredDataImpl.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Utility/StructuredData.h" +#include "lldb/lldb-forward.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/JSON.h" +#include "llvm/Telemetry/Telemetry.h" + +namespace lldb_private { + +using llvm::telemetry::Destination; +using llvm::telemetry::KindType; +using llvm::telemetry::Serializer; +using llvm::telemetry::TelemetryInfo; + +struct LldbEntryKind : public ::llvm::telemetry::EntryKind { + static const KindType BaseInfo = 0b11000; +}; + +/// Defines a convenient type for timestamp of various events. +/// This is used by the EventStats below. +using SteadyTimePoint = std::chrono::time_point; + +/// Various time (and possibly memory) statistics of an event. +struct EventStats { + // REQUIRED: Start time of an event + SteadyTimePoint start; + // OPTIONAL: End time of an event - may be empty if not meaningful. + std::optional end; + // TBD: could add some memory stats here too? + + EventStats() = default; + EventStats(SteadyTimePoint start) : start(start) {} + EventStats(SteadyTimePoint start, SteadyTimePoint end) + : start(start), end(end) {} +}; + +/// Describes the exit signal of an event. +struct ExitDescription { + int exit_code; + std::string description; +}; + +struct LldbBaseTelemetryInfo : public TelemetryInfo { + EventStats stats; + + std::optional exit_desc; + + Debugger *debugger; + + // For dyn_cast, isa, etc operations. + KindType getKind() const override { return LldbEntryKind::BaseInfo; } + + static bool classof(const TelemetryInfo *t) { +// Subclasses of this is also acceptable. +return (t->getKind() & LldbEntryKind::BaseInfo) == LldbEntryKind::BaseInfo; + } + + void serialize(Serializer &serializer) const override; +}; + +/// The base Telemetry manager instance in LLDB +/// This class declares additional instrumentation points +/// applicable to LLDB. +class TelemetryManager : public llvm::telemetry::Manager { +public: + TelemetryManager(std::unique_ptr config); + + llvm::Error dispatch(TelemetryInfo *entry) override; + + void addDestination(std::unique_ptr destination) override; + +private: + std::unique_ptr m_config; + const std::string m_session_uuid; + std::vector> m_destinations; +}; + +} // namespace lldb_private +#endif // LLDB_CORE_TELEMETRY_H diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index 0094fcd596fdf70..f63e446b6042f62 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -257,8 +257,8 @@ enum StopReason { }; /// Command Return Status Types. -enum ReturnStatus { - eReturnStatusInvalid, +enum ReturnStatus : int { + eReturnStatusInvali
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/116392 >From 88a8522f1b29b2ff392974322acdb722b7e00b70 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 28 Jan 2025 12:39:38 -0800 Subject: [PATCH 1/2] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. This adjusts the lldb-dap listening mode to accept multiple clients. Each client initializes a new instance of DAP and an associated `lldb::SBDebugger` instance. The listening mode is configured with the `--connection` option and supports listening on a port or a unix socket on supported platforms. --- .../test/tools/lldb-dap/dap_server.py | 74 - .../test/tools/lldb-dap/lldbdap_testcase.py | 6 +- lldb/test/API/tools/lldb-dap/server/Makefile | 3 + .../tools/lldb-dap/server/TestDAP_server.py | 77 + lldb/test/API/tools/lldb-dap/server/main.c| 10 + lldb/test/Shell/DAP/TestOptions.test | 4 +- lldb/tools/lldb-dap/DAP.cpp | 18 +- lldb/tools/lldb-dap/DAP.h | 6 +- lldb/tools/lldb-dap/DAPForward.h | 2 + lldb/tools/lldb-dap/Options.td| 22 +- lldb/tools/lldb-dap/lldb-dap.cpp | 283 +++--- 11 files changed, 358 insertions(+), 147 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/server/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/server/TestDAP_server.py create mode 100644 lldb/test/API/tools/lldb-dap/server/main.c diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index c29992ce9c7848..6d765e10236733 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -903,7 +903,7 @@ def request_setBreakpoints(self, file_path, line_array, data=None): "sourceModified": False, } if line_array is not None: -args_dict["lines"] = "%s" % line_array +args_dict["lines"] = line_array breakpoints = [] for i, line in enumerate(line_array): breakpoint_data = None @@ -1150,11 +1150,12 @@ def request_setInstructionBreakpoints(self, memory_reference=[]): } return self.send_recv(command_dict) + class DebugAdaptorServer(DebugCommunication): def __init__( self, executable=None, -port=None, +connection=None, init_commands=[], log_file=None, env=None, @@ -1167,21 +1168,62 @@ 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] +) + +scheme, address = connection.split("://") +if scheme == "unix-connect": # unix-connect:///path +s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +s.connect(address) +elif scheme == "connection": # connection://[host]:port +host, port = address.rsplit(":", 1) +# create_connection with try both ipv4 and ipv6. +s = socket.create_connection((host.strip("[]"), int(port))) +
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -58,12 +57,13 @@ const char DEV_NULL[] = "/dev/null"; namespace lldb_dap { -DAP::DAP(llvm::StringRef path, std::ofstream *log, ReplMode repl_mode, - StreamDescriptor input, StreamDescriptor output) -: debug_adaptor_path(path), log(log), input(std::move(input)), +DAP::DAP(std::string name, llvm::StringRef path, std::ofstream *log, + StreamDescriptor input, StreamDescriptor output, ReplMode repl_mode, + std::vector pre_init_commands) +: name(name), debug_adaptor_path(path), log(log), input(std::move(input)), output(std::move(output)), broadcaster("lldb-dap"), - exception_breakpoints(), focus_tid(LLDB_INVALID_THREAD_ID), - stop_at_entry(false), is_attach(false), + exception_breakpoints(), pre_init_commands(pre_init_commands), ashgti wrote: Applied 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)
@@ -11,6 +11,8 @@ // IWYU pragma: begin_exports +#include "lldb/lldb-forward.h" ashgti wrote: Reverted 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)
@@ -5058,72 +5053,144 @@ 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 RunDAP = [](llvm::StringRef program_path, ReplMode repl_mode, + std::vector pre_init_commands, + std::ofstream *log, std::string name, StreamDescriptor input, + StreamDescriptor output, std::FILE *redirectOut = nullptr, + std::FILE *redirectErr = nullptr) -> bool { +DAP dap = DAP(name, program_path, log, std::move(input), std::move(output), + repl_mode, pre_init_commands); -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 false; +} + +RegisterRequestCallbacks(dap); + +// used only by TestVSCode_redirection_to_console.py +if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) + redirection_test(); + +if (auto Err = dap.Loop()) { + std::string errorMessage = llvm::toString(std::move(Err)); + if (log) +*log << "Transport Error: " << errorMessage << "\n"; + return false; +} +return true; + }; + + if (!connection.empty()) { +auto maybeProtoclAndName = validateConnection(connection); +if (auto Err = maybeProtoclAndName.takeError()) { + llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), + "Invalid connection: "); return EXIT_FAILURE; } -redirectOut = stdout; -redirectErr = stderr; +Socket::SocketProtocol protocol; +std::string name; +std::tie(protocol, name) = *maybeProtoclAndName; -input = StreamDescriptor::from_file(fileno(stdin), false); -output = StreamDescriptor::from_file(stdout_fd, false); - } +Status error; +std::unique_ptr listener = Socket::Create(protocol, error); +if (error.Fail()) { + llvm::logAllUnhandledErrors(error.takeError(), llvm::errs(), + "Failed to create socket listener: "); + return EXIT_FAILURE; +} - DAP dap = DAP(program_path.str(), log.get(), default_repl_mode, -std::move(input), std::move(output)); +error = listener->Listen(name, /* backlog */ 5); ashgti wrote: Applied 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] [NFC][DebugInfo] Make some block-start-position methods return iterators (PR #124287)
hvdijk wrote: Thanks, I knew it was possible (it had to be: it would be possible to create a dummy instruction, insert it at the specified point, and inspect its parent) but had not yet found the best way of doing it, I was trying to get it working with `IP.getNodePtr()->getParent()`. I'll update it to use that instead before I post anything for review. https://github.com/llvm/llvm-project/pull/124287 ___ 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,144 @@ 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 RunDAP = [](llvm::StringRef program_path, ReplMode repl_mode, + std::vector pre_init_commands, + std::ofstream *log, std::string name, StreamDescriptor input, + StreamDescriptor output, std::FILE *redirectOut = nullptr, + std::FILE *redirectErr = nullptr) -> bool { +DAP dap = DAP(name, program_path, log, std::move(input), std::move(output), + repl_mode, pre_init_commands); -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 false; +} + +RegisterRequestCallbacks(dap); + +// used only by TestVSCode_redirection_to_console.py +if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) + redirection_test(); + +if (auto Err = dap.Loop()) { + std::string errorMessage = llvm::toString(std::move(Err)); + if (log) +*log << "Transport Error: " << errorMessage << "\n"; + return false; +} +return true; + }; + + if (!connection.empty()) { +auto maybeProtoclAndName = validateConnection(connection); +if (auto Err = maybeProtoclAndName.takeError()) { + llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), + "Invalid connection: "); return EXIT_FAILURE; } -redirectOut = stdout; -redirectErr = stderr; +Socket::SocketProtocol protocol; +std::string name; +std::tie(protocol, name) = *maybeProtoclAndName; -input = StreamDescriptor::from_file(fileno(stdin), false); -output = StreamDescriptor::from_file(stdout_fd, false); - } +Status error; +std::unique_ptr listener = Socket::Create(protocol, error); +if (error.Fail()) { + llvm::logAllUnhandledErrors(error.takeError(), llvm::errs(), + "Failed to create socket listener: "); + return EXIT_FAILURE; +} - DAP dap = DAP(program_path.str(), log.get(), default_repl_mode, -std::move(input), std::move(output)); +error = listener->Listen(name, /* backlog */ 5); +if (error.Fail()) { + llvm::logAllUnhandledErrors(error.takeError(), llvm::errs(), + "Failed to listen for connections: "); + return EXIT_FAILURE; +} - // 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; - } +std::string address = +llvm::join(listener->GetListeningConnectionURI(), ", "); +if (log) + *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(); + +llvm::DefaultThreadPool pool(llvm::optimal_concurrency()); ashgti wrote: I misread the `optimal_concurrency` and thought it didn't limit the number of threads created. Switched this to the default `hardware_concurrency` which doesn't limit the number of threads. I had previously tried using `SIGHUP` to try to have the server shutdown all the active sessions but I ran into some issues with the current DAP terminate
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules ashgti wrote: Done. 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][telemetry] Implement LLDB Telemetry (part 1) (PR #119716)
@@ -0,0 +1,101 @@ +//===-- Telemetry.h --*- C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLDB_CORE_TELEMETRY_H +#define LLDB_CORE_TELEMETRY_H + +#include +#include +#include +#include +#include +#include + +#include "lldb/Core/StructuredDataImpl.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Utility/StructuredData.h" +#include "lldb/lldb-forward.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/JSON.h" +#include "llvm/Telemetry/Telemetry.h" + +namespace lldb_private { + +using llvm::telemetry::Destination; +using llvm::telemetry::KindType; +using llvm::telemetry::Serializer; +using llvm::telemetry::TelemetryInfo; + +struct LldbEntryKind : public ::llvm::telemetry::EntryKind { + static const KindType BaseInfo = 0b11000; +}; + +/// Defines a convenient type for timestamp of various events. +/// This is used by the EventStats below. +using SteadyTimePoint = std::chrono::time_point; + +/// Various time (and possibly memory) statistics of an event. +struct EventStats { + // REQUIRED: Start time of an event + SteadyTimePoint start; + // OPTIONAL: End time of an event - may be empty if not meaningful. + std::optional end; + // TBD: could add some memory stats here too? + + EventStats() = default; + EventStats(SteadyTimePoint start) : start(start) {} + EventStats(SteadyTimePoint start, SteadyTimePoint end) + : start(start), end(end) {} +}; + +/// Describes the exit signal of an event. +struct ExitDescription { + int exit_code; + std::string description; +}; + +struct LldbBaseTelemetryInfo : public TelemetryInfo { + EventStats stats; + + std::optional exit_desc; + + // For dyn_cast, isa, etc operations. + KindType getKind() const override { return LldbEntryKind::BaseInfo; } + + static bool classof(const TelemetryInfo *t) { +// Subclasses of this is also acceptable. +return (t->getKind() & LldbEntryKind::BaseInfo) == LldbEntryKind::BaseInfo; + } + + void serialize(Serializer &serializer) const override; +}; + +/// The base Telemetry manager instance in LLDB +/// This class declares additional instrumentation points +/// applicable to LLDB. +class TelemetryManager : public llvm::telemetry::Manager { +public: + TelemetryManager(std::unique_ptr config, + Debugger *debugger); + + llvm::Error dispatch(TelemetryInfo *entry) override; + + void addDestination(std::unique_ptr destination) override; + +private: + std::unique_ptr m_config; + Debugger *m_debugger; oontvoo wrote: (done) https://github.com/llvm/llvm-project/pull/119716 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][telemetry] Implement LLDB Telemetry (part 1) (PR #119716)
@@ -108,6 +108,9 @@ endfunction(add_lldb_test_dependency) add_lldb_test_dependency(lldb) add_lldb_test_dependency(lldb-test) +# Enable Telemetry for testing. +target_compile_definitions(lldb PRIVATE -DTEST_TELEMETRY) + oontvoo wrote: done (removed the macro) https://github.com/llvm/llvm-project/pull/119716 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] WatchAddress ignores modify option (PR #124847)
puremourning wrote: Yep. Good to go. https://github.com/llvm/llvm-project/pull/124847 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] e8d437f - [lldb] WatchAddress ignores modify option (#124847)
Author: Ben Jackson Date: 2025-02-04T16:03:13-08:00 New Revision: e8d437f827144061d051ecf199d4075bef317285 URL: https://github.com/llvm/llvm-project/commit/e8d437f827144061d051ecf199d4075bef317285 DIFF: https://github.com/llvm/llvm-project/commit/e8d437f827144061d051ecf199d4075bef317285.diff LOG: [lldb] WatchAddress ignores modify option (#124847) The WatchAddress API includes a flag to indicate if watchpoint should be for read, modify or both. This API uses 2 booleans, but the 'modify' flag was ignored and WatchAddress unconditionally watched write (actually modify). We now only watch for modify when the modify flag is true. --- The included test fails prior to this patch and succeeds after. That is previously specifying `False` for `modify` would still stop on _write_, but after the patch correctly only stops on _read_ Added: lldb/test/API/python_api/watchpoint/TestWatchpointRead.py Modified: lldb/source/API/SBTarget.cpp lldb/test/API/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py Removed: diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index 2a33161bc21edc7..dd9caa724ea3628 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -1342,7 +1342,8 @@ lldb::SBWatchpoint SBTarget::WatchAddress(lldb::addr_t addr, size_t size, SBWatchpointOptions options; options.SetWatchpointTypeRead(read); - options.SetWatchpointTypeWrite(eWatchpointWriteTypeOnModify); + if (modify) +options.SetWatchpointTypeWrite(eWatchpointWriteTypeOnModify); return WatchpointCreateByAddress(addr, size, options, error); } diff --git a/lldb/test/API/python_api/watchpoint/TestWatchpointRead.py b/lldb/test/API/python_api/watchpoint/TestWatchpointRead.py new file mode 100644 index 000..f482ebe5b1ecee6 --- /dev/null +++ b/lldb/test/API/python_api/watchpoint/TestWatchpointRead.py @@ -0,0 +1,129 @@ +""" +Use lldb Python SBTarget API to set read watchpoints +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class SetReadOnlyWatchpointTestCase(TestBase): +NO_DEBUG_INFO_TESTCASE = True + +def setUp(self): +# Call super's setUp(). +TestBase.setUp(self) +# Our simple source filename. +self.source = "main.c" +# Find the line number to break inside main(). +self.line = line_number(self.source, "// Set break point at this line.") +self.build() + +# Intel hardware does not support read-only watchpoints +@expectedFailureAll(archs=["i386", "x86_64"]) +def test_read_watchpoint_watch_address(self): +exe = self.getBuildArtifact("a.out") + +target = self.dbg.CreateTarget(exe) +self.assertTrue(target, VALID_TARGET) + +# Now create a breakpoint on main.c. +breakpoint = target.BreakpointCreateByLocation(self.source, self.line) +self.assertTrue( +breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT +) + +# Now launch the process, and do not stop at the entry point. +process = target.LaunchSimple(None, None, self.get_process_working_directory()) + +# We should be stopped due to the breakpoint. Get frame #0. +process = target.GetProcess() +self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) +thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) +frame0 = thread.GetFrameAtIndex(0) + +value = frame0.FindValue("global", lldb.eValueTypeVariableGlobal) +local = frame0.FindValue("local", lldb.eValueTypeVariableLocal) +error = lldb.SBError() + +watchpoint = target.WatchAddress(value.GetLoadAddress(), 1, True, False, error) +self.assertTrue( +value and local and watchpoint, +"Successfully found the values and set a watchpoint", +) +self.DebugSBValue(value) +self.DebugSBValue(local) + +# Hide stdout if not running with '-t' option. +if not self.TraceOn(): +self.HideStdout() + +print(watchpoint) + +# Continue. Expect the program to stop due to the variable being +# read, but *not* written to. +process.Continue() + +if self.TraceOn(): +lldbutil.print_stacktraces(process) + +self.assertTrue( +local.GetValueAsSigned() > 0, "The local variable has been incremented" +) + +# Intel hardware does not support read-only watchpoints +@expectedFailureAll(archs=["i386", "x86_64"]) +def test_read_watchpoint_watch_create_by_address(self): +exe = self.getBuildArtifact("a.out") + +target = self.dbg.CreateTarget(exe) +self.assertTrue(target, VALID_TARGET) + +# Now create a breakpoint on main.c. +
[Lldb-commits] [lldb] [lldb] WatchAddress ignores modify option (PR #124847)
https://github.com/JDevlieghere closed https://github.com/llvm/llvm-project/pull/124847 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [lldb-dap] Support column breakpoints (PR #125347)
vogelsgesang wrote: On `clang-aarch64-quick` the test `CompletionTest.ObjectiveCProtocolFromIndexSpeculation` from the `clangd` test suite failed - unrelated to this commit https://github.com/llvm/llvm-project/pull/125347 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits