[Lldb-commits] [lldb] [lldb][windows] add support for out of PATH python.dll resolution (PR #162509)
https://github.com/charles-zablit updated
https://github.com/llvm/llvm-project/pull/162509
>From 37cf46ea187afd50ce8b1eae58239aafe9b115db Mon Sep 17 00:00:00 2001
From: Charles Zablit
Date: Wed, 8 Oct 2025 17:18:51 +0100
Subject: [PATCH 1/4] [lldb][windows] add support for out of PATH python.dll
resolution
---
lldb/cmake/modules/AddLLDB.cmake | 6
lldb/tools/driver/CMakeLists.txt | 4 +++
lldb/tools/driver/Driver.cpp | 49
3 files changed, 59 insertions(+)
diff --git a/lldb/cmake/modules/AddLLDB.cmake b/lldb/cmake/modules/AddLLDB.cmake
index 28bf8d816d89a..4d2036e68704f 100644
--- a/lldb/cmake/modules/AddLLDB.cmake
+++ b/lldb/cmake/modules/AddLLDB.cmake
@@ -167,6 +167,12 @@ function(add_lldb_executable name)
)
target_link_libraries(${name} PRIVATE ${ARG_LINK_LIBS})
+ if(WIN32)
+list(FIND ARG_LINK_LIBS liblldb LIBLLD_INDEX)
+if(NOT LIBLLD_INDEX EQUAL -1)
+ target_link_options(${name} PRIVATE
"/DELAYLOAD:$.dll")
+endif()
+ endif()
if(CLANG_LINK_CLANG_DYLIB)
target_link_libraries(${name} PRIVATE clang-cpp)
else()
diff --git a/lldb/tools/driver/CMakeLists.txt b/lldb/tools/driver/CMakeLists.txt
index 5c0cac484cc94..941ef0d83385b 100644
--- a/lldb/tools/driver/CMakeLists.txt
+++ b/lldb/tools/driver/CMakeLists.txt
@@ -34,6 +34,10 @@ add_dependencies(lldb
${tablegen_deps}
)
+if(DEFINED LLDB_PYTHON_DLL_RELATIVE_PATH)
+ target_compile_definitions(lldb PRIVATE
LLDB_PYTHON_DLL_RELATIVE_PATH="${LLDB_PYTHON_DLL_RELATIVE_PATH}")
+endif()
+
if(LLDB_BUILD_FRAMEWORK)
# In the build-tree, we know the exact path to the framework directory.
# The installed framework can be in different locations.
diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp
index 16cc736441b59..df31d649ada48 100644
--- a/lldb/tools/driver/Driver.cpp
+++ b/lldb/tools/driver/Driver.cpp
@@ -22,11 +22,15 @@
#include "lldb/Host/MainLoop.h"
#include "lldb/Host/MainLoopBase.h"
#include "lldb/Utility/Status.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Signals.h"
+#include "llvm/Support/Windows/WindowsSupport.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
@@ -426,6 +430,47 @@ SBError Driver::ProcessArgs(const opt::InputArgList &args,
bool &exiting) {
return error;
}
+#ifdef _WIN32
+// Returns the full path to the lldb.exe executable
+inline std::wstring GetPathToExecutableW() {
+ // Iterate until we reach the Windows max path length (32,767).
+ std::vector buffer;
+ buffer.resize(MAX_PATH);
+ while (buffer.size() < 32767) {
+if (GetModuleFileNameW(NULL, buffer.data(), buffer.size()) < buffer.size())
+ return std::wstring(buffer.begin(), buffer.end());
+buffer.resize(buffer.size() * 2);
+ }
+ return L"";
+}
+
+// Resolve the full path of the directory defined by
+// LLDB_PYTHON_DLL_RELATIVE_PATH. If it exists, add it to the list of DLL
search
+// directories.
+void AddPythonDLLToSearchPath() {
+ std::wstring modulePath = GetPathToExecutableW();
+ if (modulePath.empty()) {
+WithColor::error() << "Unable to find python: " << GetLastError() << '\n';
+return;
+ }
+
+ SmallVector utf8Path;
+ if (sys::windows::UTF16ToUTF8(modulePath.c_str(), modulePath.length(),
+utf8Path))
+return;
+ sys::path::remove_filename(utf8Path);
+ sys::path::append(utf8Path, LLDB_PYTHON_DLL_RELATIVE_PATH);
+ sys::fs::make_absolute(utf8Path);
+
+ SmallVector widePath;
+ if (sys::windows::widenPath(utf8Path.data(), widePath))
+return;
+
+ if (sys::fs::exists(utf8Path))
+SetDllDirectoryW(widePath.data());
+}
+#endif
+
std::string EscapeString(std::string arg) {
std::string::size_type pos = 0;
while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) {
@@ -728,6 +773,10 @@ int main(int argc, char const *argv[]) {
"~/Library/Logs/DiagnosticReports/.\n");
#endif
+#ifdef _WIN32
+ AddPythonDLLToSearchPath();
+#endif
+
// Parse arguments.
LLDBOptTable T;
unsigned MissingArgIndex;
>From 2f7a6f1bc40143dbfcef85cc903167fc0ac6e5e0 Mon Sep 17 00:00:00 2001
From: Charles Zablit
Date: Wed, 8 Oct 2025 17:35:32 +0100
Subject: [PATCH 2/4] fixup! [lldb][windows] add support for out of PATH
python.dll resolution
---
lldb/tools/driver/Driver.cpp | 7 +--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp
index df31d649ada48..d35c30d2c6aea 100644
--- a/lldb/tools/driver/Driver.cpp
+++ b/lldb/tools/driver/Driver.cpp
@@ -30,10 +30,13 @@
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Signals.h"
-#include "llvm/Support/Windows/WindowsSupport.h"
#include "llvm/Support/Wi
[Lldb-commits] [lldb] [lldb-dap] expand tilde in dap executable path (PR #162635)
https://github.com/da-viper created
https://github.com/llvm/llvm-project/pull/162635
Users may have multiple devices and would like to resolve the homepath based on
the machine they are on.
>From c62a3532785cc0b5a72475a965ba4a99404432ba Mon Sep 17 00:00:00 2001
From: Ebuka Ezike
Date: Thu, 9 Oct 2025 12:04:09 +0100
Subject: [PATCH] [lldb-dap] expand tilde in dap executable path
Users may have multiple devices and would like to resolve the homepath based on
the machine they are on.
---
.../lldb-dap/src-ts/debug-adapter-factory.ts | 16 ++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/lldb/tools/lldb-dap/src-ts/debug-adapter-factory.ts
b/lldb/tools/lldb-dap/src-ts/debug-adapter-factory.ts
index 7060638a94864..c34f8866fb2e3 100644
--- a/lldb/tools/lldb-dap/src-ts/debug-adapter-factory.ts
+++ b/lldb/tools/lldb-dap/src-ts/debug-adapter-factory.ts
@@ -1,3 +1,4 @@
+import * as os from "os";
import * as path from "path";
import * as util from "util";
import * as vscode from "vscode";
@@ -9,6 +10,16 @@ import { LogFilePathProvider, LogType } from "./logging";
const exec = util.promisify(child_process.execFile);
+/**
+ * Expands the character `~` to the user's home directory
+ */
+function expandUser(file_path: string): string {
+ if (file_path.startsWith("~")) {
+return os.homedir() + file_path.slice(1);
+ }
+ return file_path;
+}
+
async function isExecutable(path: string): Promise {
try {
await fs.access(path, fs.constants.X_OK);
@@ -116,8 +127,9 @@ async function getDAPExecutable(
configuration: vscode.DebugConfiguration,
): Promise {
// Check if the executable was provided in the launch configuration.
- const launchConfigPath = configuration["debugAdapterExecutable"];
+ let launchConfigPath = configuration["debugAdapterExecutable"];
if (typeof launchConfigPath === "string" && launchConfigPath.length !== 0) {
+launchConfigPath = expandUser(launchConfigPath);
if (!(await isExecutable(launchConfigPath))) {
throw new ErrorWithNotification(
`Debug adapter path "${launchConfigPath}" is not a valid file. The
path comes from your launch configuration.`,
@@ -129,7 +141,7 @@ async function getDAPExecutable(
// Check if the executable was provided in the extension's configuration.
const config = vscode.workspace.getConfiguration("lldb-dap",
workspaceFolder);
- const configPath = config.get("executable-path");
+ const configPath = expandUser(config.get("executable-path") ?? "");
if (configPath && configPath.length !== 0) {
if (!(await isExecutable(configPath))) {
throw new ErrorWithNotification(
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [debugserver][NFC] Add helper function for escaping special characters (PR #162297)
felipepiovezan wrote: > Assuming this is part of `lldbDebugserverCommon`, can we add a unit test for > this? I don't believe that exists today, but it shouldn't be hard to add. We > have some prior art with the unit tests that I added for the library code of > lldb-dap. it's not, these are internal linkage functions! https://github.com/llvm/llvm-project/pull/162297 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] 36bce68 - Add a scripted way to re-present a stop location (#158128)
Author: jimingham
Date: 2025-10-09T08:37:21-07:00
New Revision: 36bce68b97316363085ae3681e8dde33a62fc9b1
URL:
https://github.com/llvm/llvm-project/commit/36bce68b97316363085ae3681e8dde33a62fc9b1
DIFF:
https://github.com/llvm/llvm-project/commit/36bce68b97316363085ae3681e8dde33a62fc9b1.diff
LOG: Add a scripted way to re-present a stop location (#158128)
This patch adds the notion of "Facade" locations which can be reported
from a ScriptedResolver instead of the actual underlying breakpoint
location for the breakpoint. Also add a "was_hit" method to the scripted
resolver that allows the breakpoint to say which of these "Facade"
locations was hit, and "get_location_description" to provide a
description for the facade locations.
I apologize in advance for the size of the patch. Almost all of what's
here was necessary to (a) make the feature testable and (b) not break
any of the current behavior.
The motivation for this feature is given in the "Providing Facade
Locations" section that I added to the python-reference.rst so I won't
repeat it here.
rdar://152112327
Added:
lldb/test/API/functionalities/breakpoint/scripted_bkpt/was_hit/Makefile
lldb/test/API/functionalities/breakpoint/scripted_bkpt/was_hit/TestWasHit.py
lldb/test/API/functionalities/breakpoint/scripted_bkpt/was_hit/bkpt_resolver.py
lldb/test/API/functionalities/breakpoint/scripted_bkpt/was_hit/main.c
Modified:
lldb/bindings/python/python-swigsafecast.swig
lldb/bindings/python/python-wrapper.swig
lldb/docs/use/python-reference.rst
lldb/docs/use/tutorials/creating-custom-breakpoints.md
lldb/include/lldb/API/SBBreakpoint.h
lldb/include/lldb/API/SBBreakpointLocation.h
lldb/include/lldb/API/SBFrame.h
lldb/include/lldb/Breakpoint/Breakpoint.h
lldb/include/lldb/Breakpoint/BreakpointLocation.h
lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h
lldb/include/lldb/Breakpoint/BreakpointLocationList.h
lldb/include/lldb/Breakpoint/BreakpointResolverScripted.h
lldb/include/lldb/Breakpoint/BreakpointSite.h
lldb/include/lldb/Breakpoint/StopPointSiteList.h
lldb/include/lldb/Breakpoint/StoppointSite.h
lldb/include/lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h
lldb/include/lldb/Interpreter/ScriptInterpreter.h
lldb/source/API/SBBreakpoint.cpp
lldb/source/Breakpoint/Breakpoint.cpp
lldb/source/Breakpoint/BreakpointLocation.cpp
lldb/source/Breakpoint/BreakpointLocationCollection.cpp
lldb/source/Breakpoint/BreakpointLocationList.cpp
lldb/source/Breakpoint/BreakpointResolverScripted.cpp
lldb/source/Breakpoint/BreakpointSite.cpp
lldb/source/Interpreter/ScriptInterpreter.cpp
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.cpp
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.h
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
lldb/source/Target/StopInfo.cpp
lldb/test/API/functionalities/breakpoint/scripted_bkpt/resolver.py
lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
Removed:
diff --git a/lldb/bindings/python/python-swigsafecast.swig
b/lldb/bindings/python/python-swigsafecast.swig
index 4721dfdc17e6a..3ea24f1a31414 100644
--- a/lldb/bindings/python/python-swigsafecast.swig
+++ b/lldb/bindings/python/python-swigsafecast.swig
@@ -142,5 +142,9 @@ PythonObject SWIGBridge::ToSWIGWrapper(
return ToSWIGHelper(module_spec_sb.release(), SWIGTYPE_p_lldb__SBModuleSpec);
}
+PythonObject SWIGBridge::ToSWIGWrapper(lldb::DescriptionLevel level) {
+ return PythonInteger((int64_t) level);
+}
+
} // namespace python
} // namespace lldb_private
diff --git a/lldb/bindings/python/python-wrapper.swig
b/lldb/bindings/python/python-wrapper.swig
index 2c30d536a753d..64b7dc8381073 100644
--- a/lldb/bindings/python/python-wrapper.swig
+++ b/lldb/bindings/python/python-wrapper.swig
@@ -422,6 +422,30 @@ void
*lldb_private::python::LLDBSWIGPython_CastPyObjectToSBBreakpoint(PyObject *
return sb_ptr;
}
+void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBFrame(PyObject *
data) {
+ lldb::SBFrame *sb_ptr = nullptr;
+
+ int valid_cast =
+ SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBFrame, 0);
+
+ if (valid_cast == -1)
+return NULL;
+
+ return sb_ptr;
+}
+
+void
*lldb_private::python::LLDBSWIGPython_CastPyObjectToSBBreakpointLocation(PyObject
* data) {
+ lldb::SBBreakpointLocation *sb_ptr = nullptr;
+
+ int valid_cast =
+ SWIG_ConvertPtr(data, (void **)&sb_ptr,
SWIGTYPE_p_lldb__SBBreakpointLocation, 0);
+
+ if (valid_cast == -1)
+return NULL;
+
+ return sb_ptr;
+}
+
void *lldb_private::python::L
[Lldb-commits] [lldb] [lldb][test] Don't run libc++ API tests without a locally built libc++ (PR #162657)
https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/162657 >From 0b23bd05541354a493acea8fbb2c89b771a3e774 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Thu, 9 Oct 2025 13:06:40 +0100 Subject: [PATCH 1/2] [lldb][test] Don't run libc++ API tests without a locally built libc++ API tests in the `libc++` category will try their best to build against a locally built libc++. If none exists, the `Makefile.rules` currently fall back to using the system libc++. The issue with falling back to the system libc++ is that we are now potentially not testing what we intended to. But we also can't rely on certain libc++ features being available that the tests are trying to use. On Apple platforms this is a configuration error (because libc++ is the only stdlib supported), but we can't make it an error on Linux because a user might want to run the API tests with libstdc++. The Ubunutu 22.04 bots on the Apple fork are failing to run following tests are failing: * `TestLibcxxInternalsRecognizer.py` * `TestDataFormatterStdRangesRefView.py` because the system stdlib doesn't have `std::ranges` support yet. And the tests just fail to build. Building libc++ on those bots is also not possible because the system compiler is too old (and the Apple fork builds all the subprojects standalone, so it requires the system compiler). This patch marks tests in the `libc++` category as `UNSUPPORTED` if no local libc++ is available. The downside is that we will inevitably lose coverage on bots that were running these tests without a local libc++. Arguably those weren't really testing the right thing. But for vendors with LLDB forks it might have been useful to at least know that the tests on the fork don't fail against the system libc++. --- lldb/packages/Python/lldbsuite/test/dotest.py | 4 1 file changed, 4 insertions(+) diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py index 2966ac04227cb..0c854c23e31a4 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest.py +++ b/lldb/packages/Python/lldbsuite/test/dotest.py @@ -788,7 +788,11 @@ def canRunLibcxxTests(): if lldbplatformutil.target_is_android() or lldbplatformutil.platformIsDarwin(): return True, "libc++ always present" +# Make sure -stdlib=libc++ works since that's how the tests will be built. if platform == "linux": +if not configuration.libcxx_include_dir or not configuration.libcxx_library_dir: +return False, "API tests require a locally built libc++." + with temp_file.OnDiskTempFile() as f: cmd = [configuration.compiler, "-xc++", "-stdlib=libc++", "-o", f.path, "-"] p = subprocess.Popen( >From cc9b3e83f4e23723ea94314c18432c244e298e31 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Thu, 9 Oct 2025 15:08:21 +0100 Subject: [PATCH 2/2] fixup! move comment --- lldb/packages/Python/lldbsuite/test/dotest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py index 0c854c23e31a4..1d474a2180d22 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest.py +++ b/lldb/packages/Python/lldbsuite/test/dotest.py @@ -788,11 +788,11 @@ def canRunLibcxxTests(): if lldbplatformutil.target_is_android() or lldbplatformutil.platformIsDarwin(): return True, "libc++ always present" -# Make sure -stdlib=libc++ works since that's how the tests will be built. if platform == "linux": if not configuration.libcxx_include_dir or not configuration.libcxx_library_dir: return False, "API tests require a locally built libc++." +# Make sure -stdlib=libc++ works since that's how the tests will be built. with temp_file.OnDiskTempFile() as f: cmd = [configuration.compiler, "-xc++", "-stdlib=libc++", "-o", f.path, "-"] p = subprocess.Popen( ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Adding A new Binding helper for JSONTransport. (PR #159160)
ashgti wrote: I can update the test names to not match the using definition. https://github.com/llvm/llvm-project/pull/159160 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][test] Don't run libc++ API tests without a locally built libc++ (PR #162657)
https://github.com/Michael137 ready_for_review https://github.com/llvm/llvm-project/pull/162657 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] expand tilde in dap executable path (PR #162635)
llvmbot wrote:
@llvm/pr-subscribers-lldb
Author: Ebuka Ezike (da-viper)
Changes
Users may have multiple devices and would like to resolve the homepath based on
the machine they are on.
---
Full diff: https://github.com/llvm/llvm-project/pull/162635.diff
1 Files Affected:
- (modified) lldb/tools/lldb-dap/src-ts/debug-adapter-factory.ts (+14-2)
``diff
diff --git a/lldb/tools/lldb-dap/src-ts/debug-adapter-factory.ts
b/lldb/tools/lldb-dap/src-ts/debug-adapter-factory.ts
index 7060638a94864..c34f8866fb2e3 100644
--- a/lldb/tools/lldb-dap/src-ts/debug-adapter-factory.ts
+++ b/lldb/tools/lldb-dap/src-ts/debug-adapter-factory.ts
@@ -1,3 +1,4 @@
+import * as os from "os";
import * as path from "path";
import * as util from "util";
import * as vscode from "vscode";
@@ -9,6 +10,16 @@ import { LogFilePathProvider, LogType } from "./logging";
const exec = util.promisify(child_process.execFile);
+/**
+ * Expands the character `~` to the user's home directory
+ */
+function expandUser(file_path: string): string {
+ if (file_path.startsWith("~")) {
+return os.homedir() + file_path.slice(1);
+ }
+ return file_path;
+}
+
async function isExecutable(path: string): Promise {
try {
await fs.access(path, fs.constants.X_OK);
@@ -116,8 +127,9 @@ async function getDAPExecutable(
configuration: vscode.DebugConfiguration,
): Promise {
// Check if the executable was provided in the launch configuration.
- const launchConfigPath = configuration["debugAdapterExecutable"];
+ let launchConfigPath = configuration["debugAdapterExecutable"];
if (typeof launchConfigPath === "string" && launchConfigPath.length !== 0) {
+launchConfigPath = expandUser(launchConfigPath);
if (!(await isExecutable(launchConfigPath))) {
throw new ErrorWithNotification(
`Debug adapter path "${launchConfigPath}" is not a valid file. The
path comes from your launch configuration.`,
@@ -129,7 +141,7 @@ async function getDAPExecutable(
// Check if the executable was provided in the extension's configuration.
const config = vscode.workspace.getConfiguration("lldb-dap",
workspaceFolder);
- const configPath = config.get("executable-path");
+ const configPath = expandUser(config.get("executable-path") ?? "");
if (configPath && configPath.length !== 0) {
if (!(await isExecutable(configPath))) {
throw new ErrorWithNotification(
``
https://github.com/llvm/llvm-project/pull/162635
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Fix comment typo in `StructuredDataPlugin.cpp` (PR #162637)
https://github.com/MaxDesiatov created
https://github.com/llvm/llvm-project/pull/162637
`structured-data ommand` -> `structured-data command`
>From 6eb937909ca641e949d4ea05b9dfb1f9be7121cd Mon Sep 17 00:00:00 2001
From: Max Desiatov
Date: Thu, 9 Oct 2025 12:42:42 +0100
Subject: [PATCH] Fix comment typo in `StructuredDataPlugin.cpp`
`structured-data ommand` -> `structured-data command`
---
lldb/source/Target/StructuredDataPlugin.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/source/Target/StructuredDataPlugin.cpp
b/lldb/source/Target/StructuredDataPlugin.cpp
index 8e3ceb094b361..8ce7f9f391d7b 100644
--- a/lldb/source/Target/StructuredDataPlugin.cpp
+++ b/lldb/source/Target/StructuredDataPlugin.cpp
@@ -52,7 +52,7 @@ void
StructuredDataPlugin::InitializeBasePluginForDebugger(Debugger &debugger) {
if (!parent_command)
return;
-// Create the structured-data ommand object.
+// Create the structured-data command object.
auto command_name = "structured-data";
auto command_sp = CommandObjectSP(new CommandStructuredData(interpreter));
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Fix comment typo in `StructuredDataPlugin.cpp` (PR #162637)
github-actions[bot] wrote: Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using `@` followed by their GitHub username. If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the [LLVM GitHub User Guide](https://llvm.org/docs/GitHub.html). You can also ask questions in a comment on this PR, on the [LLVM Discord](https://discord.com/invite/xS7Z362) or on the [forums](https://discourse.llvm.org/). https://github.com/llvm/llvm-project/pull/162637 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Fix assertion caused by invalid SupportFileSP (PR #162710)
llvmbot wrote:
@llvm/pr-subscribers-lldb
Author: Jonas Devlieghere (JDevlieghere)
Changes
SupportFileSP should never be null, and instead should use a default
constructed SupportFile to represent an invalid instance. This is because the
class used to be a value type before it became polymorphic.
We have various places in LLDB where we check this precondition, including in
DisplaySourceLinesWithLineNumbers. The assertion was tripped when calling
GetStartLineSourceInfo which starts by resetting the SupportFileSP and has a
series of early returns which leave the shared pointer in that state.
rdar://161607247
---
Full diff: https://github.com/llvm/llvm-project/pull/162710.diff
1 Files Affected:
- (modified) lldb/source/Symbol/Function.cpp (+1-1)
``diff
diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp
index 6114eccd935ee..2be1e389aa1d0 100644
--- a/lldb/source/Symbol/Function.cpp
+++ b/lldb/source/Symbol/Function.cpp
@@ -275,7 +275,7 @@ Function::~Function() = default;
void Function::GetStartLineSourceInfo(SupportFileSP &source_file_sp,
uint32_t &line_no) {
line_no = 0;
- source_file_sp.reset();
+ source_file_sp = std::make_shared();
if (m_comp_unit == nullptr)
return;
``
https://github.com/llvm/llvm-project/pull/162710
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] 8523c6a - [lldb] Actually use new SharedModuleList class (#162574)
Author: Augusto Noronha
Date: 2025-10-09T10:39:45-07:00
New Revision: 8523c6a448c3f01396b805aca30376072c469845
URL:
https://github.com/llvm/llvm-project/commit/8523c6a448c3f01396b805aca30376072c469845
DIFF:
https://github.com/llvm/llvm-project/commit/8523c6a448c3f01396b805aca30376072c469845.diff
LOG: [lldb] Actually use new SharedModuleList class (#162574)
Now that the use after free bug has been fixed (397181d5c), actually use
the new SharedModuleList class.
Added:
Modified:
lldb/source/Core/ModuleList.cpp
Removed:
diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp
index 2ccebf3fabfc5..c40612c1ced5e 100644
--- a/lldb/source/Core/ModuleList.cpp
+++ b/lldb/source/Core/ModuleList.cpp
@@ -989,7 +989,7 @@ class SharedModuleList {
};
struct SharedModuleListInfo {
- ModuleList module_list;
+ SharedModuleList module_list;
ModuleListProperties module_list_properties;
};
}
@@ -1007,7 +1007,7 @@ static SharedModuleListInfo &GetSharedModuleListInfo()
return *g_shared_module_list_info;
}
-static ModuleList &GetSharedModuleList() {
+static SharedModuleList &GetSharedModuleList() {
return GetSharedModuleListInfo().module_list;
}
@@ -1017,8 +1017,8 @@ ModuleListProperties
&ModuleList::GetGlobalModuleListProperties() {
bool ModuleList::ModuleIsInCache(const Module *module_ptr) {
if (module_ptr) {
-ModuleList &shared_module_list = GetSharedModuleList();
-return shared_module_list.FindModule(module_ptr).get() != nullptr;
+SharedModuleList &shared_module_list = GetSharedModuleList();
+return shared_module_list.FindModule(*module_ptr).get() != nullptr;
}
return false;
}
@@ -1041,9 +1041,8 @@ ModuleList::GetSharedModule(const ModuleSpec
&module_spec, ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr,
llvm::SmallVectorImpl *old_modules,
bool *did_create_ptr, bool always_create) {
- ModuleList &shared_module_list = GetSharedModuleList();
- std::lock_guard guard(
- shared_module_list.m_modules_mutex);
+ SharedModuleList &shared_module_list = GetSharedModuleList();
+ std::lock_guard guard(shared_module_list.GetMutex());
char path[PATH_MAX];
Status error;
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [gdbremote] Document MultiMemRead packet in protocol extensions (PR #162675)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Felipe de Azevedo Piovezan (felipepiovezan) Changes This adds a specification for the new packet discussed in the RFC [1]. [1]: https://discourse.llvm.org/t/rfc-a-new-vectorized-memory-read-packet/88441/12 --- Full diff: https://github.com/llvm/llvm-project/pull/162675.diff 1 Files Affected: - (modified) lldb/docs/resources/lldbgdbremote.md (+38) ``diff diff --git a/lldb/docs/resources/lldbgdbremote.md b/lldb/docs/resources/lldbgdbremote.md index 36b95f1073ebc..d5e42890e14b1 100644 --- a/lldb/docs/resources/lldbgdbremote.md +++ b/lldb/docs/resources/lldbgdbremote.md @@ -2530,3 +2530,41 @@ read packet: $e0030100#b9 **Priority to Implement:** Only required for Wasm support. Necessary to show variables. + +### MultiMemRead + +Read memory from multiple memory addresses. + +There are two arguments to the request: + +* `ranges`: a list of base-16 pairs of numbers. Each pair is separated by a +`,`, as is each number in the pair. The first number of the pair denotes the +base address of the memory read, the second denotes the number of bytes to be +read. +* `options`: an optional string of options. If present, it may be empty. If +present, it is the last argument of the request. + +Both arguments must end with a `;`. + +The reply packet starts with a comma-separated list of base-16 numbers, +denoting how many bytes were read from each address, followed by a `;`, +followed by a sequence of bytes containing the memory data. The length of this +sequence must be equal to the sum of the numbers provided at the start of the +reply. + +If the stub is unable to read from any individual address, it should return a +length of "zero" for that address in the reply packet. + +A stub that supports this packet should return `MultiMemRead+` in the reply to +`qSupported`. + +``` +send packet: $MultiMemRead:ranges:100a00,4,200200,a0,40,4; +read packet: $4,0,2; +``` + +In the example above, the first read produced `abcd1000`, the read of `a0` +bytes from address `200200` failed, and the third read produced two bytes – +`eeff` – out of the four requested. + +**Priority to Implement:** Only required for performance. `` https://github.com/llvm/llvm-project/pull/162675 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [debugserver] Implement MultiMemRead packet (PR #162670)
https://github.com/felipepiovezan ready_for_review https://github.com/llvm/llvm-project/pull/162670 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][windows] fix undeclared identifier error (PR #162705)
https://github.com/charles-zablit closed https://github.com/llvm/llvm-project/pull/162705 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [debugserver] Implement MultiMemRead packet (PR #162670)
@@ -3160,6 +3165,140 @@ rnb_err_t RNBRemote::HandlePacket_m(const char *p) {
return SendPacket(ostrm.str());
}
+/// Returns true if `str` starts with `prefix`.
+static bool starts_with(std::string_view str, std::string_view prefix) {
+ return str.size() >= prefix.size() &&
+ str.compare(0, prefix.size(), prefix) == 0;
+}
+
+/// Attempts to parse a prefix of `number_str` as a number of type `T`. If
+/// successful, the number is returned and the prefix is dropped from
+/// `number_str`.
+template
+static std::optional extract_number(std::string_view &number_str) {
+ static_assert(std::is_integral());
+ char *str_end = nullptr;
+ errno = 0;
+ nub_addr_t number = strtoull(number_str.data(), &str_end, 16);
kastiglione wrote:
```suggestion
T number = strtoull(number_str.data(), &str_end, 16);
```
https://github.com/llvm/llvm-project/pull/162670
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [debugserver] Implement MultiMemRead packet (PR #162670)
@@ -3160,6 +3165,140 @@ rnb_err_t RNBRemote::HandlePacket_m(const char *p) {
return SendPacket(ostrm.str());
}
+/// Returns true if `str` starts with `prefix`.
+static bool starts_with(std::string_view str, std::string_view prefix) {
+ return str.size() >= prefix.size() &&
+ str.compare(0, prefix.size(), prefix) == 0;
+}
+
+/// Attempts to parse a prefix of `number_str` as a number of type `T`. If
+/// successful, the number is returned and the prefix is dropped from
+/// `number_str`.
+template
+static std::optional extract_number(std::string_view &number_str) {
+ static_assert(std::is_integral());
+ char *str_end = nullptr;
+ errno = 0;
+ nub_addr_t number = strtoull(number_str.data(), &str_end, 16);
felipepiovezan wrote:
I am tempted to get rid of the template and make this a uint64_t function only,
as this is using that `strtoull` function.
https://github.com/llvm/llvm-project/pull/162670
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Adding A new Binding helper for JSONTransport. (PR #159160)
CarlosAlbertoEnciso wrote:
> I'm seeing compilation errors with gcc 11:
>
> ```
> /work/kparzysz/git/llvm.org/lldb/unittests/Host/JSONTransportTest.cpp:190:9:
> error: declaration of ‘using Req = struct {anonymous}::test_protocol::Req’
> changes meaning of ‘Req’ [-fpermissive]
> 190 | using Req = Req;
> | ^~~
> /work/kparzysz/git/llvm.org/lldb/unittests/Host/JSONTransportTest.cpp:52:8:
> note: ‘Req’ declared here as ‘struct {anonymous}::test_protocol::Req’
>52 | struct Req {
> |^~~
> ```
I am seeing the same compilation errors.
https://github.com/llvm/llvm-project/pull/159160
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [gdbremote] Document MultiMemRead packet in protocol extensions (PR #162675)
@@ -2530,3 +2530,41 @@ read packet: $e0030100#b9 **Priority to Implement:** Only required for Wasm support. Necessary to show variables. + +### MultiMemRead + +Read memory from multiple memory addresses. + +There are two arguments to the request: + +* `ranges`: a list of base-16 pairs of numbers. Each pair is separated by a +`,`, as is each number in the pair. The first number of the pair denotes the +base address of the memory read, the second denotes the number of bytes to be +read. +* `options`: an optional string of options. If present, it may be empty. If +present, it is the last argument of the request. + +Both arguments must end with a `;`. + +The reply packet starts with a comma-separated list of base-16 numbers, +denoting how many bytes were read from each address, followed by a `;`, +followed by a sequence of bytes containing the memory data. The length of this +sequence must be equal to the sum of the numbers provided at the start of the +reply. + +If the stub is unable to read from any individual address, it should return a +length of "zero" for that address in the reply packet. + +A stub that supports this packet should return `MultiMemRead+` in the reply to +`qSupported`. bulbazord wrote: Suggestion: `should return` -> `should include` https://github.com/llvm/llvm-project/pull/162675 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [gdbremote] Document MultiMemRead packet in protocol extensions (PR #162675)
@@ -2530,3 +2530,41 @@ read packet: $e0030100#b9 **Priority to Implement:** Only required for Wasm support. Necessary to show variables. + +### MultiMemRead + +Read memory from multiple memory addresses. + +There are two arguments to the request: + +* `ranges`: a list of base-16 pairs of numbers. Each pair is separated by a +`,`, as is each number in the pair. The first number of the pair denotes the +base address of the memory read, the second denotes the number of bytes to be +read. +* `options`: an optional string of options. If present, it may be empty. If +present, it is the last argument of the request. bulbazord wrote: Suggestion: ``` If present, it may be empty. If present, it is the last argument of the request. ``` into ``` If present, it must be the last argument of the request and may be empty. ``` https://github.com/llvm/llvm-project/pull/162675 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] support attaching by name for platform android (PR #160931)
https://github.com/JDevlieghere closed https://github.com/llvm/llvm-project/pull/160931 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [debugserver] Implement MultiMemRead packet (PR #162670)
@@ -3160,6 +3165,140 @@ rnb_err_t RNBRemote::HandlePacket_m(const char *p) {
return SendPacket(ostrm.str());
}
+/// Returns true if `str` starts with `prefix`.
+static bool starts_with(std::string_view str, std::string_view prefix) {
+ return str.size() >= prefix.size() &&
+ str.compare(0, prefix.size(), prefix) == 0;
felipepiovezan wrote:
Oh you're totally right. My bad!
https://github.com/llvm/llvm-project/pull/162670
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Fix TypeSystemClang::GetBasicTypeEnumeration for 128-bit int types (PR #162278)
@@ -849,8 +849,8 @@ lldb::BasicType
TypeSystemClang::GetBasicTypeEnumeration(llvm::StringRef name) {
{"unsigned long long int", eBasicTypeUnsignedLongLong},
// "int128"
- {"__int128_t", eBasicTypeInt128},
- {"__uint128_t", eBasicTypeUnsignedInt128},
+ {"__int128", eBasicTypeInt128},
+ {"unsigned __int128", eBasicTypeUnsignedInt128},
clayborg wrote:
Do we want to leave in the old defines in to make sure it doesn't break anyone?
So just add the new entries and leave the old ones?
https://github.com/llvm/llvm-project/pull/162278
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Fix TypeSystemClang::GetBasicTypeEnumeration for 128-bit int types (PR #162278)
https://github.com/clayborg commented: This looks ok, but I think we should leave the old typename mappings in to make sure we don't break anyone's scripts that might be using the `__int128_t` or `__uint128_t` https://github.com/llvm/llvm-project/pull/162278 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] eb06c7e - [lldb] Fix assertion caused by invalid SupportFileSP (#162710)
Author: Jonas Devlieghere
Date: 2025-10-09T12:05:00-07:00
New Revision: eb06c7e7d25da30dd611812a9bec56bf5c3f5ac3
URL:
https://github.com/llvm/llvm-project/commit/eb06c7e7d25da30dd611812a9bec56bf5c3f5ac3
DIFF:
https://github.com/llvm/llvm-project/commit/eb06c7e7d25da30dd611812a9bec56bf5c3f5ac3.diff
LOG: [lldb] Fix assertion caused by invalid SupportFileSP (#162710)
SupportFileSP should never be null, and instead should use a default
constructed SupportFile to represent an invalid instance. This is
because the class used to be a value type before it became polymorphic.
We have various places in LLDB where we check this precondition,
including in DisplaySourceLinesWithLineNumbers. The assertion was
tripped when calling GetStartLineSourceInfo which starts by resetting
the SupportFileSP and has a series of early returns which leave the
shared pointer in that state.
rdar://161607247
Added:
Modified:
lldb/source/Symbol/Function.cpp
Removed:
diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp
index 6114eccd935ee..2be1e389aa1d0 100644
--- a/lldb/source/Symbol/Function.cpp
+++ b/lldb/source/Symbol/Function.cpp
@@ -275,7 +275,7 @@ Function::~Function() = default;
void Function::GetStartLineSourceInfo(SupportFileSP &source_file_sp,
uint32_t &line_no) {
line_no = 0;
- source_file_sp.reset();
+ source_file_sp = std::make_shared();
if (m_comp_unit == nullptr)
return;
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [lldb] Add type hints to gdbclientutils.py and use abstract base class (PR #162172)
@@ -242,7 +245,7 @@ def qProcessInfo(self): def qHostInfo(self): return "ptrsize:8;endian:little;" -def qEcho(self): +def qEcho(self, _: int): dsandersllvm wrote: Ok, I've added the name. This does cause tools like pyright to report it as an unused parameter as a 'hint' diagnostic but there's lots of those and I can easily filter them out https://github.com/llvm/llvm-project/pull/162172 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] update lldb-server platform help text (PR #162730)
cs01 wrote: Added a few tests, one for help text, one for error messages, and one for successful startups. ``` llvm-lit -v lldb-server/TestPlatformHelp.test lldb-server/TestPlatformErrorMessages.test lldb-server/TestPlatformSuccessfulStartup.test ... -- Testing: 3 tests, 3 workers -- PASS: lldb-shell :: lldb-server/TestPlatformHelp.test (1 of 3) PASS: lldb-shell :: lldb-server/TestPlatformErrorMessages.test (2 of 3) PASS: lldb-shell :: lldb-server/TestPlatformSuccessfulStartup.test (3 of 3) Testing Time: 1.08s Total Discovered Tests: 3 Passed: 3 (100.00%) 1 warning(s) in tests ``` https://github.com/llvm/llvm-project/pull/162730 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [lldb] Add type hints to gdbclientutils.py and use abstract base class (PR #162172)
dsandersllvm wrote: > And yes we should have something somewhere enforcing our minimums but let me > put it this way: we claim minimum compiler versions and those aren't tested > by anyone either. So I'm sorry you had to encounter this confusion but it is > what it is for the time being. No worries. FWIW I've tried running `vermin` on the other files with `uvx vermin -t 3.8 $(find lldb/packages/Python -name '*.py')`. It doesn't like something about one file: ``` File with incompatible versions: llvm-project/lldb/packages/Python/lldbsuite/test/tools/lldb-server/lldbgdbserverutils.py Versions could not be combined: !2, 3.5 and 2.2, !3 Note: Some files had incompatible versions so the results might not be correct! ``` and I've never tried this tool before so I'm not sure how much to trust it but if it's accurate then the code that runs is all 3.8 compatible with a few files that need 3.9 for the type hints (add `--eval-annotations` to the command). https://github.com/llvm/llvm-project/pull/162172 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] update lldb-server platform help parsing (PR #162730)
@@ -371,107 +424,107 @@ int main_platform(int argc, char *argv[]) {
signal(SIGPIPE, SIG_IGN);
signal(SIGHUP, signal_handler);
#endif
- int long_option_index = 0;
+
+ // Special handling for 'help' as first argument
+ if (argc > 0 && strcmp(argv[0], "help") == 0) {
+LLPlatformOptTable Opts;
+display_usage(Opts, progname, subcommand);
+return 0;
+ }
+
Status error;
std::string listen_host_port;
- int ch;
-
std::string log_file;
- StringRef
- log_channels; // e.g. "lldb process threads:gdb-remote default:linux all"
-
+ StringRef log_channels;
shared_fd_t fd = SharedSocket::kInvalidFD;
-
uint16_t gdbserver_port = 0;
-
FileSpec socket_file;
- bool show_usage = false;
- int option_error = 0;
-
- std::string
short_options(OptionParser::GetShortOptionString(g_long_options));
-
-#if __GLIBC__
- optind = 0;
-#else
- optreset = 1;
- optind = 1;
-#endif
-
- while ((ch = getopt_long_only(argc, argv, short_options.c_str(),
-g_long_options, &long_option_index)) != -1) {
-switch (ch) {
-case 0: // Any optional that auto set themselves will return 0
- break;
-
-case 'L':
- listen_host_port.append(optarg);
- break;
+ bool multi_client = false;
+ [[maybe_unused]] bool debug = false;
+ [[maybe_unused]] bool verbose = false;
+
+ LLPlatformOptTable Opts;
+ llvm::BumpPtrAllocator Alloc;
+ llvm::StringSaver Saver(Alloc);
+ bool HasError = false;
+
+ opt::InputArgList Args =
+ Opts.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](llvm::StringRef Msg) {
+WithColor::error() << Msg << "\n";
+HasError = true;
+ });
+
+ std::string Name =
+ (llvm::sys::path::filename(progname) + " " + subcommand).str();
+ std::string HelpText =
+ "Use '" + Name + " --help' for a complete list of options.\n";
+
+ if (HasError) {
+llvm::errs() << HelpText;
+return 1;
+ }
-case 'l': // Set Log File
- if (optarg && optarg[0])
-log_file.assign(optarg);
- break;
+ if (Args.hasArg(OPT_help)) {
+display_usage(Opts, progname, subcommand);
+return 0;
+ }
-case 'c': // Log Channels
- if (optarg && optarg[0])
-log_channels = StringRef(optarg);
- break;
+ // Parse arguments
+ listen_host_port = Args.getLastArgValue(OPT_listen).str();
+ log_file = Args.getLastArgValue(OPT_log_file).str();
+ log_channels = Args.getLastArgValue(OPT_log_channels);
+ multi_client = Args.hasArg(OPT_server);
+ debug = Args.hasArg(OPT_debug);
+ verbose = Args.hasArg(OPT_verbose);
+
+ if (Args.hasArg(OPT_socket_file)) {
+socket_file.SetFile(Args.getLastArgValue(OPT_socket_file),
+FileSpec::Style::native);
+ }
-case 'f': // Socket file
- if (optarg && optarg[0])
-socket_file.SetFile(optarg, FileSpec::Style::native);
- break;
+ if (Args.hasArg(OPT_gdbserver_port)) {
+if (!llvm::to_integer(Args.getLastArgValue(OPT_gdbserver_port),
+ gdbserver_port)) {
+ WithColor::error() << "invalid --gdbserver-port value\n";
+ return 1;
+}
+ }
-case 'P':
-case 'm':
-case 'M': {
- uint16_t portnum;
- if (!llvm::to_integer(optarg, portnum)) {
-WithColor::error() << "invalid port number string " << optarg << "\n";
-option_error = 2;
-break;
- }
- // Note the condition gdbserver_port > HIGH_PORT is valid in case of
using
- // --child-platform-fd. Check gdbserver_port later.
- if (ch == 'P')
-gdbserver_port = portnum;
- else if (gdbserver_port == 0)
-gdbserver_port = portnum;
-} break;
-
-case 2: {
- uint64_t _fd;
- if (!llvm::to_integer(optarg, _fd)) {
-WithColor::error() << "invalid fd " << optarg << "\n";
-option_error = 6;
- } else
-fd = (shared_fd_t)_fd;
-} break;
-
-case 'h': /* fall-through is intentional */
-case '?':
- show_usage = true;
- break;
+ if (Args.hasArg(OPT_child_platform_fd)) {
+uint64_t _fd;
+if (!llvm::to_integer(Args.getLastArgValue(OPT_child_platform_fd), _fd)) {
+ WithColor::error() << "invalid --child-platform-fd value\n";
+ return 1;
}
+fd = (shared_fd_t)_fd;
}
if (!LLDBServerUtilities::SetupLogging(log_file, log_channels, 0))
return -1;
// Print usage and exit if no listening port is specified.
- if (listen_host_port.empty() && fd == SharedSocket::kInvalidFD)
-show_usage = true;
+ if (listen_host_port.empty() && fd == SharedSocket::kInvalidFD) {
+WithColor::error() << "either --listen or --child-platform-fd is
required\n"
+ << HelpText;
+return 1;
+ }
- if (show_usage || option_error) {
-display_usage(progname, subcommand);
-exit(option_error);
+ // Get remaining arguments for inferior
JDevlieghere wrote:
```suggestion
// Get remaining arguments for inferior.
```
https:
[Lldb-commits] [lldb] [lldb][Expression] Emit a 'Note' diagnostic that indicates the language used for expression evaluation (PR #161688)
https://github.com/Michael137 updated
https://github.com/llvm/llvm-project/pull/161688
>From 7300143d42a2a496d5ce522c7f862cb458fa6d9d Mon Sep 17 00:00:00 2001
From: Michael Buch
Date: Thu, 2 Oct 2025 16:24:12 +0100
Subject: [PATCH 1/7] [lldb][Expression] Emit a 'Note' diagnistc that indicates
the language used for expression evaluation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Since it's a 'Note' diagnostic it would only show up when expression
evaluation actually failed. This helps with expression evaluation
failure reports in mixed language environments where it's not quite clear
what language the expression ran as. It may also reduce confusion around
why the expression evaluator ran an expression in a language it wasn't
asked to run (a softer alternative to what I attempted in
https://github.com/llvm/llvm-project/pull/156648).
Here are some example outputs:
```
(lldb) expr -l c -- blah
˄
╰─ error: use of undeclared identifier 'blah'
note: Requested expression evaluation as 'c' but fell back to 'c++'.
(lldb) expr -l c++ -- blah
˄
╰─ error: use of undeclared identifier 'blah'
note: Requested expression evaluation as c++
(lldb) expr -l objc -- blah
˄
╰─ error: use of undeclared identifier 'blah'
note: Requested expression evaluation as 'objective-c' but fell back to
'objective-c++'.
(lldb) expr -l rust -- blah
˄
╰─ error: use of undeclared identifier 'blah'
note: Requested expression evaluation as rust
```
I didn't put the diagnostic on the same line as the inline diagnostic
for now because of implementation convenience, but if reviewers deem
that a blocker I can take a stab at that again.
Also, other language plugins (namely Swift), won't immediately benefit
from this and will have to emit their own diagnistc. I played around
with having a virtual API on `UserExpression` or `ExpressionParser` that
will be called consistently, but by the time we're about to parse the
expression we are already several frames deep into the plugin. Before
(and at the beginning of) the generic `UserExpression::Parse` call we
don't have enough information to notify which language we're going to
parse in (at least for the C++ plugin).
rdar://160297649
---
.../Clang/ClangExpressionParser.cpp | 29 ---
.../Clang/ClangExpressionParser.h | 1 +
.../Clang/ClangFunctionCaller.cpp | 4 +--
.../Clang/ClangUserExpression.cpp | 4 +--
.../Clang/ClangUtilityFunction.cpp| 2 +-
5 files changed, 31 insertions(+), 9 deletions(-)
diff --git
a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index 3c49c911108a3..b3aebfcc77039 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -74,6 +74,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Module.h"
+#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Expression/IRInterpreter.h"
#include "lldb/Host/File.h"
@@ -527,7 +528,8 @@ static void SetupTargetOpts(CompilerInstance &compiler,
static void SetupLangOpts(CompilerInstance &compiler,
ExecutionContextScope &exe_scope,
- const Expression &expr) {
+ const Expression &expr,
+ DiagnosticManager &diagnostic_manager) {
Log *log = GetLog(LLDBLog::Expressions);
// If the expression is being evaluated in the context of an existing stack
@@ -547,6 +549,8 @@ static void SetupLangOpts(CompilerInstance &compiler,
: lldb::eLanguageTypeUnknown),
lldb_private::Language::GetNameForLanguageType(language));
+ lldb::LanguageType language_for_note = language;
+
LangOptions &lang_opts = compiler.getLangOpts();
switch (language) {
@@ -560,12 +564,14 @@ static void SetupLangOpts(CompilerInstance &compiler,
// family language, because the expression parser uses features of C++ to
// capture values.
lang_opts.CPlusPlus = true;
+language_for_note = lldb::eLanguageTypeC_plus_plus;
break;
case lldb::eLanguageTypeObjC:
lang_opts.ObjC = true;
// FIXME: the following language option is a temporary workaround,
// to "ask for ObjC, get ObjC++" (see comment above).
lang_opts.CPlusPlus = true;
+language_for_note = lldb::eLanguageTypeObjC_plus_plus;
// Clang now sets as default C++14 as the default standard (with
// GNU extensions), so we do the same here to avoid mismatches that
@@ -610,6 +616,21 @@ static void SetupLangOpts(CompilerInstance &compiler,
brea
[Lldb-commits] [lldb] [lldb][test] Don't run libc++ API tests without a locally built libc++ (PR #162657)
https://github.com/Michael137 created https://github.com/llvm/llvm-project/pull/162657 API tests in the `libc++` category will try their best to build against a locally built libc++. If none exists, the `Makefile.rules` currently fall back to using the system libc++. The issue with falling back to the system libc++ is that we are now potentially not testing what we intended to. But we also can't rely on certain libc++ features being available that the tests are trying to use. On Apple platforms this is a configuration error (because libc++ is the only stdlib supported), but we can't make it an error on Linux because a user might want to run the API tests with libstdc++. The Ubunutu 22.04 bots on the Apple fork are failing to run following tests are failing: * `TestLibcxxInternalsRecognizer.py` * `TestDataFormatterStdRangesRefView.py` because the system stdlib doesn't have `std::ranges` support yet. And the tests just fail to build. Building libc++ on those bots is also not possible because the system compiler is too old (and the Apple fork builds all the subprojects standalone, so it requires the system compiler). This patch marks tests in the `libc++` category as `UNSUPPORTED` if no local libc++ is available. The downside is that we will inevitably lose coverage on bots that were running these tests without a local libc++. Arguably those weren't really testing the right thing. But for vendors with LLDB forks it might have been useful to at least know that the tests on the fork don't fail against the system libc++. >From 0b23bd05541354a493acea8fbb2c89b771a3e774 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Thu, 9 Oct 2025 13:06:40 +0100 Subject: [PATCH] [lldb][test] Don't run libc++ API tests without a locally built libc++ API tests in the `libc++` category will try their best to build against a locally built libc++. If none exists, the `Makefile.rules` currently fall back to using the system libc++. The issue with falling back to the system libc++ is that we are now potentially not testing what we intended to. But we also can't rely on certain libc++ features being available that the tests are trying to use. On Apple platforms this is a configuration error (because libc++ is the only stdlib supported), but we can't make it an error on Linux because a user might want to run the API tests with libstdc++. The Ubunutu 22.04 bots on the Apple fork are failing to run following tests are failing: * `TestLibcxxInternalsRecognizer.py` * `TestDataFormatterStdRangesRefView.py` because the system stdlib doesn't have `std::ranges` support yet. And the tests just fail to build. Building libc++ on those bots is also not possible because the system compiler is too old (and the Apple fork builds all the subprojects standalone, so it requires the system compiler). This patch marks tests in the `libc++` category as `UNSUPPORTED` if no local libc++ is available. The downside is that we will inevitably lose coverage on bots that were running these tests without a local libc++. Arguably those weren't really testing the right thing. But for vendors with LLDB forks it might have been useful to at least know that the tests on the fork don't fail against the system libc++. --- lldb/packages/Python/lldbsuite/test/dotest.py | 4 1 file changed, 4 insertions(+) diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py index 2966ac04227cb..0c854c23e31a4 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest.py +++ b/lldb/packages/Python/lldbsuite/test/dotest.py @@ -788,7 +788,11 @@ def canRunLibcxxTests(): if lldbplatformutil.target_is_android() or lldbplatformutil.platformIsDarwin(): return True, "libc++ always present" +# Make sure -stdlib=libc++ works since that's how the tests will be built. if platform == "linux": +if not configuration.libcxx_include_dir or not configuration.libcxx_library_dir: +return False, "API tests require a locally built libc++." + with temp_file.OnDiskTempFile() as f: cmd = [configuration.compiler, "-xc++", "-stdlib=libc++", "-o", f.path, "-"] p = subprocess.Popen( ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][test] Don't run libc++ API tests without a locally built libc++ (PR #162657)
https://github.com/Michael137 edited https://github.com/llvm/llvm-project/pull/162657 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] support attaching by name for platform android (PR #160931)
https://github.com/walter-erquinigo approved this pull request. fancy https://github.com/llvm/llvm-project/pull/160931 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] support attaching by name for platform android (PR #160931)
@@ -477,6 +477,248 @@ std::string PlatformAndroid::GetRunAs() {
}
return run_as.str();
}
+
+// Helper function to populate process status information from
+// /proc/[pid]/status
+void PlatformAndroid::PopulateProcessStatusInfo(
+lldb::pid_t pid, ProcessInstanceInfo &process_info) {
+ // Read /proc/[pid]/status to get parent PID, UIDs, and GIDs
+ Status error;
+ auto status_adb = GetAdbClient(error);
+ if (error.Fail())
+return;
+
+ std::string status_output;
+ StreamString status_cmd;
+ status_cmd.Printf(
+ "cat /proc/%llu/status 2>/dev/null | grep -E '^(PPid|Uid|Gid):'",
+ (unsigned long long)pid);
+ Status status_error =
+ status_adb->Shell(status_cmd.GetData(), seconds(5), &status_output);
+
+ if (status_error.Fail() || status_output.empty())
+return;
+
+ llvm::SmallVector lines;
+ llvm::StringRef(status_output).split(lines, '\n');
+
+ for (llvm::StringRef line : lines) {
+line = line.trim();
+if (line.starts_with("PPid:")) {
+ llvm::StringRef ppid_str = line.substr(5).trim();
+ lldb::pid_t ppid;
+ if (llvm::to_integer(ppid_str, ppid))
+process_info.SetParentProcessID(ppid);
+} else if (line.starts_with("Uid:")) {
+ llvm::SmallVector uid_parts;
+ line.substr(4).trim().split(uid_parts, '\t', -1, false);
+ if (uid_parts.size() >= 2) {
+uint32_t uid, euid;
+if (llvm::to_integer(uid_parts[0].trim(), uid))
+ process_info.SetUserID(uid);
+if (llvm::to_integer(uid_parts[1].trim(), euid))
+ process_info.SetEffectiveUserID(euid);
+ }
+} else if (line.starts_with("Gid:")) {
+ llvm::SmallVector gid_parts;
+ line.substr(4).trim().split(gid_parts, '\t', -1, false);
+ if (gid_parts.size() >= 2) {
+uint32_t gid, egid;
+if (llvm::to_integer(gid_parts[0].trim(), gid))
+ process_info.SetGroupID(gid);
+if (llvm::to_integer(gid_parts[1].trim(), egid))
+ process_info.SetEffectiveGroupID(egid);
+ }
+}
+ }
+}
+
+// Helper function to populate command line arguments from /proc/[pid]/cmdline
+void PlatformAndroid::PopulateProcessCommandLine(
+lldb::pid_t pid, ProcessInstanceInfo &process_info) {
+ // Read /proc/[pid]/cmdline to get command line arguments
+ Status error;
+ auto cmdline_adb = GetAdbClient(error);
walter-erquinigo wrote:
ditto
https://github.com/llvm/llvm-project/pull/160931
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Allow empty memory reference in disassemble arguments (PR #162517)
https://github.com/walter-erquinigo edited https://github.com/llvm/llvm-project/pull/162517 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] update lldb-server platform help text (PR #162730)
https://github.com/cs01 updated https://github.com/llvm/llvm-project/pull/162730
>From 6d6cabbca4280bed1041423096bb071487e19248 Mon Sep 17 00:00:00 2001
From: Chad Smith
Date: Thu, 9 Oct 2025 11:52:01 -0700
Subject: [PATCH] update lldb-server platform help text
---
lldb/tools/lldb-server/CMakeLists.txt | 5 +
lldb/tools/lldb-server/LLPlatformOptions.td | 75 ++
lldb/tools/lldb-server/lldb-platform.cpp| 269
3 files changed, 241 insertions(+), 108 deletions(-)
create mode 100644 lldb/tools/lldb-server/LLPlatformOptions.td
diff --git a/lldb/tools/lldb-server/CMakeLists.txt
b/lldb/tools/lldb-server/CMakeLists.txt
index 1d8dc72a3f872..50f294f1b5712 100644
--- a/lldb/tools/lldb-server/CMakeLists.txt
+++ b/lldb/tools/lldb-server/CMakeLists.txt
@@ -2,6 +2,10 @@ set(LLVM_TARGET_DEFINITIONS LLGSOptions.td)
tablegen(LLVM LLGSOptions.inc -gen-opt-parser-defs)
add_public_tablegen_target(LLGSOptionsTableGen)
+set(LLVM_TARGET_DEFINITIONS LLPlatformOptions.td)
+tablegen(LLVM LLPlatformOptions.inc -gen-opt-parser-defs)
+add_public_tablegen_target(LLPlatformOptionsTableGen)
+
set(LLDB_PLUGINS)
if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android")
@@ -67,6 +71,7 @@ add_lldb_tool(lldb-server
add_dependencies(lldb-server
LLGSOptionsTableGen
+ LLPlatformOptionsTableGen
${tablegen_deps}
)
target_include_directories(lldb-server PRIVATE "${LLDB_SOURCE_DIR}/source")
diff --git a/lldb/tools/lldb-server/LLPlatformOptions.td
b/lldb/tools/lldb-server/LLPlatformOptions.td
new file mode 100644
index 0..eedd1d8c35343
--- /dev/null
+++ b/lldb/tools/lldb-server/LLPlatformOptions.td
@@ -0,0 +1,75 @@
+include "llvm/Option/OptParser.td"
+
+class F: Flag<["--", "-"], name>;
+class R prefixes, string name>
+ : Option;
+
+multiclass SJ {
+ def NAME: Separate<["--", "-"], name>,
+HelpText;
+ def NAME # _eq: Joined<["--", "-"], name # "=">,
+Alias(NAME)>;
+}
+
+def grp_connect : OptionGroup<"connection">, HelpText<"CONNECTION OPTIONS">;
+
+defm listen: SJ<"listen", "Host and port to listen on. Format: [host]:port or
protocol://[host]:port (e.g., tcp://localhost:1234, unix:///path/to/socket).
Short form: -L">,
+ MetaVarName<"<[host]:port>">,
+ Group;
+def: Separate<["-"], "L">, Alias,
+ Group;
+
+defm socket_file: SJ<"socket-file", "Write listening socket information (port
number for TCP or path for Unix domain sockets) to the specified file. Short
form: -f">,
+ MetaVarName<"">,
+ Group;
+def: Separate<["-"], "f">, Alias,
+ Group;
+
+defm gdbserver_port: SJ<"gdbserver-port", "Port to use for spawned gdbserver
instances. If 0 or unspecified, a port will be chosen automatically. Short
form: -P">,
+ MetaVarName<"">,
+ Group;
+def: Separate<["-"], "P">, Alias,
+ Group;
+
+defm child_platform_fd: SJ<"child-platform-fd", "File descriptor for
communication with parent platform process (internal use only).">,
+ MetaVarName<"">,
+ Group,
+ Flags<[HelpHidden]>;
+
+def grp_general : OptionGroup<"general options">, HelpText<"GENERAL OPTIONS">;
+
+def server: F<"server">,
+ HelpText<"Run in server mode, accepting multiple client connections
sequentially. Without this flag, the server exits after handling the first
connection.">,
+ Group;
+
+defm log_channels: SJ<"log-channels", "Channels to log. A colon-separated list
of entries. Each entry starts with a channel followed by a space-separated list
of categories. Common channels: lldb, gdb-remote, platform, process. Short
form: -c">,
+ MetaVarName<"">,
+ Group;
+def: Separate<["-"], "c">, Alias,
+ Group;
+
+defm log_file: SJ<"log-file", "Destination file to log to. If empty, log to
stderr. Short form: -l">,
+ MetaVarName<"">,
+ Group;
+def: Separate<["-"], "l">, Alias,
+ Group;
+
+def debug: F<"debug">,
+ HelpText<"(Unused, kept for backward compatibility)">,
+ Group,
+ Flags<[HelpHidden]>;
+
+def verbose: F<"verbose">,
+ HelpText<"(Unused, kept for backward compatibility)">,
+ Group,
+ Flags<[HelpHidden]>;
+
+def help: F<"help">,
+ HelpText<"Display this help message and exit.">,
+ Group;
+def: Flag<["-"], "h">, Alias,
+ Group;
+
+def REM : R<["--"], "">,
+ HelpText<"Arguments to pass to launched gdbserver instances.">,
+ MetaVarName<"program args">;
diff --git a/lldb/tools/lldb-server/lldb-platform.cpp
b/lldb/tools/lldb-server/lldb-platform.cpp
index 0bd928507ba89..37f0e1b95570c 100644
--- a/lldb/tools/lldb-server/lldb-platform.cpp
+++ b/lldb/tools/lldb-server/lldb-platform.cpp
@@ -21,6 +21,9 @@
#include
#include
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/WithColor.h"
@@ -56,22 +59,69 @@ using namespace llvm;
// of target CPUs. For now, let's just use 100.
static const int backlog = 100;
static const int socket_error = -1;
-static int g_debug = 0;
-static int g_verbose = 0;
-static int g_server = 0;
-
-// option desc
[Lldb-commits] [lldb] [debugserver] Implement MultiMemRead packet (PR #162670)
@@ -3160,6 +3165,140 @@ rnb_err_t RNBRemote::HandlePacket_m(const char *p) {
return SendPacket(ostrm.str());
}
+/// Returns true if `str` starts with `prefix`.
+static bool starts_with(std::string_view str, std::string_view prefix) {
+ return str.size() >= prefix.size() &&
+ str.compare(0, prefix.size(), prefix) == 0;
+}
+
+/// Attempts to parse a prefix of `number_str` as a number of type `T`. If
+/// successful, the number is returned and the prefix is dropped from
+/// `number_str`.
+template
+static std::optional extract_number(std::string_view &number_str) {
+ static_assert(std::is_integral());
+ char *str_end = nullptr;
+ errno = 0;
+ nub_addr_t number = strtoull(number_str.data(), &str_end, 16);
+ if (errno != 0)
+return std::nullopt;
+ assert(str_end);
+ number_str.remove_prefix(str_end - number_str.data());
+ return number;
+}
+
+/// Splits `list_str` into multiple string_views separated by `,`.
+static std::vector
+parse_comma_separated_list(std::string_view list_str) {
+ std::vector list;
+ while (!list_str.empty()) {
+auto pos = list_str.find(',');
+list.push_back(list_str.substr(0, pos));
+if (pos == list_str.npos)
+ break;
+list_str.remove_prefix(pos + 1);
+ }
+ return list;
+}
+
+rnb_err_t RNBRemote::HandlePacket_MultiMemRead(const char *p) {
+ const std::string_view packet_name("MultiMemRead:");
+ std::string_view packet(p);
+
+ if (!starts_with(packet, packet_name))
+return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Invalid MultiMemRead packet prefix");
+
+ packet.remove_prefix(packet_name.size());
+
+ const std::string_view ranges_prefix("ranges:");
+ if (!starts_with(packet, ranges_prefix))
+return HandlePacket_ILLFORMED(__FILE__, __LINE__, packet.data(),
+ "Missing 'ranges' in MultiMemRead packet");
+ packet.remove_prefix(ranges_prefix.size());
+
+ std::vector> ranges;
+ std::size_t total_length = 0;
+
+ // Ranges should have the form: ,[,,]*;
+ auto end_of_ranges_pos = packet.find(';');
+ if (end_of_ranges_pos == packet.npos)
+return HandlePacket_ILLFORMED(__FILE__, __LINE__, packet.data(),
+ "MultiMemRead missing end of ranges marker");
+
+ std::vector numbers_list =
+ parse_comma_separated_list(packet.substr(0, end_of_ranges_pos));
+ packet.remove_prefix(end_of_ranges_pos + 1);
+
+ // Ranges are pairs, so the number of elements must be even.
+ if (numbers_list.size() % 2 == 1)
+return HandlePacket_ILLFORMED(
+__FILE__, __LINE__, p,
+"MultiMemRead has an odd number of numbers for the ranges");
+
+ for (unsigned idx = 0; idx < numbers_list.size(); idx += 2) {
+std::optional maybe_addr =
+extract_number(numbers_list[idx]);
+std::optional maybe_length =
+extract_number(numbers_list[idx + 1]);
+if (!maybe_addr || !maybe_length)
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, packet.data(),
+"Invalid MultiMemRead range");
+// A sanity check that the packet requested is not too large or a negative
+// number.
+if (*maybe_length > 4 * 1024 * 1024)
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, packet.data(),
+"MultiMemRead length is too large");
+
+ranges.emplace_back(*maybe_addr, *maybe_length);
+total_length += *maybe_length;
+ }
+
+ if (ranges.empty())
+return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "MultiMemRead has an empty range list");
+
+ // If 'options:' is present, ensure it's empty.
+ const std::string_view options_prefix("options:");
+ if (starts_with(packet, options_prefix)) {
+packet.remove_prefix(options_prefix.size());
+if (packet.empty())
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, packet.data(),
+ "Too short 'options' in MultiMemRead packet");
+if (packet[0] != ';')
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, packet.data(),
+"Unimplemented 'options' in MultiMemRead");
+packet.remove_prefix(1);
+ }
+
+ if (!packet.empty())
+return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Invalid MultiMemRead address_range");
+
+ std::vector> buffers;
+ buffers.reserve(ranges.size());
+ for (auto [base_addr, length] : ranges) {
+buffers.emplace_back(length, '\0');
jasonmolenda wrote:
it's such a minor style nit I hesitate to say it, but '\0' is the NUL character
and is the marker of the end of a c-string. This is a vector and I'd
use a 0 here; there's no string stuff involved.
https://github.com/llvm/llvm-project/pull/162670
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] 7a391e3 - [lldb] Adjusting the naming for gcc11. (#162693)
Author: John Harrison
Date: 2025-10-09T17:15:19-07:00
New Revision: 7a391e32eaf2f2232bd7c81e651dd949f39cc9e1
URL:
https://github.com/llvm/llvm-project/commit/7a391e32eaf2f2232bd7c81e651dd949f39cc9e1
DIFF:
https://github.com/llvm/llvm-project/commit/7a391e32eaf2f2232bd7c81e651dd949f39cc9e1.diff
LOG: [lldb] Adjusting the naming for gcc11. (#162693)
In gcc11 we're getting an error with a `using Req = Req` statement. This
changes the name of the types in JSONTransportTest from `Req` >
`Request`, `Evt` > `Event`, `Resp` > `Response`.
Added:
Modified:
lldb/unittests/Host/JSONTransportTest.cpp
Removed:
diff --git a/lldb/unittests/Host/JSONTransportTest.cpp
b/lldb/unittests/Host/JSONTransportTest.cpp
index 7db6508aa4a3c..54f1372ca0fff 100644
--- a/lldb/unittests/Host/JSONTransportTest.cpp
+++ b/lldb/unittests/Host/JSONTransportTest.cpp
@@ -49,85 +49,85 @@ namespace {
namespace test_protocol {
-struct Req {
+struct Request {
int id = 0;
std::string name;
std::optional params;
};
-json::Value toJSON(const Req &T) {
+json::Value toJSON(const Request &T) {
return json::Object{{"name", T.name}, {"id", T.id}, {"params", T.params}};
}
-bool fromJSON(const json::Value &V, Req &T, json::Path P) {
+bool fromJSON(const json::Value &V, Request &T, json::Path P) {
json::ObjectMapper O(V, P);
return O && O.map("name", T.name) && O.map("id", T.id) &&
O.map("params", T.params);
}
-bool operator==(const Req &a, const Req &b) {
+bool operator==(const Request &a, const Request &b) {
return a.name == b.name && a.id == b.id && a.params == b.params;
}
-inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Req &V) {
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Request &V) {
OS << toJSON(V);
return OS;
}
-void PrintTo(const Req &message, std::ostream *os) {
+void PrintTo(const Request &message, std::ostream *os) {
std::string O;
llvm::raw_string_ostream OS(O);
OS << message;
*os << O;
}
-struct Resp {
+struct Response {
int id = 0;
int errorCode = 0;
std::optional result;
};
-json::Value toJSON(const Resp &T) {
+json::Value toJSON(const Response &T) {
return json::Object{
{"id", T.id}, {"errorCode", T.errorCode}, {"result", T.result}};
}
-bool fromJSON(const json::Value &V, Resp &T, json::Path P) {
+bool fromJSON(const json::Value &V, Response &T, json::Path P) {
json::ObjectMapper O(V, P);
return O && O.map("id", T.id) && O.mapOptional("errorCode", T.errorCode) &&
O.map("result", T.result);
}
-bool operator==(const Resp &a, const Resp &b) {
+bool operator==(const Response &a, const Response &b) {
return a.id == b.id && a.errorCode == b.errorCode && a.result == b.result;
}
-inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Resp &V) {
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Response &V)
{
OS << toJSON(V);
return OS;
}
-void PrintTo(const Resp &message, std::ostream *os) {
+void PrintTo(const Response &message, std::ostream *os) {
std::string O;
llvm::raw_string_ostream OS(O);
OS << message;
*os << O;
}
-struct Evt {
+struct Event {
std::string name;
std::optional params;
};
-json::Value toJSON(const Evt &T) {
+json::Value toJSON(const Event &T) {
return json::Object{{"name", T.name}, {"params", T.params}};
}
-bool fromJSON(const json::Value &V, Evt &T, json::Path P) {
+bool fromJSON(const json::Value &V, Event &T, json::Path P) {
json::ObjectMapper O(V, P);
return O && O.map("name", T.name) && O.map("params", T.params);
}
-bool operator==(const Evt &a, const Evt &b) { return a.name == b.name; }
-inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Evt &V) {
+bool operator==(const Event &a, const Event &b) { return a.name == b.name; }
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Event &V) {
OS << toJSON(V);
return OS;
}
-void PrintTo(const Evt &message, std::ostream *os) {
+void PrintTo(const Event &message, std::ostream *os) {
std::string O;
llvm::raw_string_ostream OS(O);
OS << message;
*os << O;
}
-using Message = std::variant;
+using Message = std::variant;
json::Value toJSON(const Message &msg) {
return std::visit([](const auto &msg) { return toJSON(msg); }, msg);
}
@@ -139,7 +139,7 @@ bool fromJSON(const json::Value &V, Message &msg,
json::Path P) {
}
if (O->find("id") == O->end()) {
-Evt E;
+Event E;
if (!fromJSON(V, E, P))
return false;
@@ -148,7 +148,7 @@ bool fromJSON(const json::Value &V, Message &msg,
json::Path P) {
}
if (O->get("name")) {
-Req R;
+Request R;
if (!fromJSON(V, R, P))
return false;
@@ -156,7 +156,7 @@ bool fromJSON(const json::Value &V, Message &msg,
json::Path P) {
return true;
}
- Resp R;
+ Response R;
if (!fromJSON(V, R, P))
return false;
[Lldb-commits] [lldb] 47d3c5f - [lldb] Cortex-M exception unwind API test cleanup
Author: Jason Molenda Date: 2025-10-09T19:10:42-07:00 New Revision: 47d3c5f3cb159fd261ab5c3efa55afae246c5e0d URL: https://github.com/llvm/llvm-project/commit/47d3c5f3cb159fd261ab5c3efa55afae246c5e0d DIFF: https://github.com/llvm/llvm-project/commit/47d3c5f3cb159fd261ab5c3efa55afae246c5e0d.diff LOG: [lldb] Cortex-M exception unwind API test cleanup This test, with a corefile created via yaml2macho-core plus an ObjectFileJSON binary with symbol addresses and ranges, was failing on some machines/CI because the wrong ABI was being picked. The bytes of the functions were not included in the yaml or .json binary. The unwind falls back to using the ABI plugin default unwind plans. We have two armv7 ABIs - the Darwin ABI that always uses r7 as the frame pointer, and the AAPCS ABI which uses r11 code. In reality, armv7 code uses r11 in arm mode, r7 in thumb code. But the ABI ArchDefaultUnwindPlan doesn't have any access to the Target's ArchSpec or Process register state, to determine the correct processor state (arm or thumb). And in fact, on Cortex-M targets, the instructions are always thumb, so the arch default unwind plan (hardcoded r11) is always wrong. The corefile doesn't specify a vendor/os, only a cpu. The object file json specifies the armv7m-apple-* triple, which will select the correct ABI plugin, and the test runs. In some cases, it looks like the Process ABI was fetched after opening the corefile, but before the binary.json was loaded and corrected the Target's ArchSpec. And we never re-evaluate the ABI once it is set, in a Process. When we picked the AAPCS armv7 ABI, we would try to use r11 as frame pointer, and the unwind would stop after one stack frame. I'm stepping around this problem by (1) adding the register bytes of the prologues of every test function in the backtrace, and (2) shortening the function ranges (in binary.json) to specify that the functions are all just long enough for the prologue where execution is stopped. The instruction emulation plugin will fail if it can't get all of the bytes from the function instructions, so I hacked the function sizes in the .json to cover the prologue plus one and changed the addresses in the backtrace to fit within those ranges. [ updated this commit to keep the @skipIfRemote on the API test because two remote CI bots are failing for reasons I don't quite see. ] Added: Modified: lldb/test/API/functionalities/unwind/cortex-m-exception/TestCortexMExceptionUnwind.py lldb/test/API/functionalities/unwind/cortex-m-exception/armv7m-nofpu-exception.yaml lldb/test/API/functionalities/unwind/cortex-m-exception/binary.json Removed: diff --git a/lldb/test/API/functionalities/unwind/cortex-m-exception/TestCortexMExceptionUnwind.py b/lldb/test/API/functionalities/unwind/cortex-m-exception/TestCortexMExceptionUnwind.py index 768dd6fe6867c..ebba4d1fbcb05 100644 --- a/lldb/test/API/functionalities/unwind/cortex-m-exception/TestCortexMExceptionUnwind.py +++ b/lldb/test/API/functionalities/unwind/cortex-m-exception/TestCortexMExceptionUnwind.py @@ -12,20 +12,6 @@ class TestCortexMExceptionUnwind(TestBase): NO_DEBUG_INFO_TESTCASE = True -# on the lldb-remote-linux-ubuntu CI, the binary.json's triple of -# armv7m-apple is not being set in the Target triple, and we're -# picking the wrong ABI plugin, ABISysV_arm. -# ABISysV_arm::CreateDefaultUnwindPlan() doesn't have a way to detect -# arm/thumb for a stack frame, or even the Target's triple for a -# Cortex-M part that is always thumb. It hardcodes r11 as the frame -# pointer register, which is correct for arm code but not thumb. -# It is never correct # on a Cortex-M target. -# The Darwin ABIMacOSX_arm diverges from AAPCS and always uses r7 for -# the frame pointer -- the thumb convention -- whether executing arm or -# thumb. So its CreateDefaultUnwindPlan picks the correct register for -# the frame pointer, and we can walk the stack. -# ABISysV_arm::CreateDefaultUnwindPlan will only get one frame and -# not be able to continue. @skipIfRemote def test_no_fpu(self): """Test that we can backtrace correctly through an ARM Cortex-M Exception return stack""" @@ -59,9 +45,8 @@ def test_no_fpu(self): # frames above that. The topmost two stack frames # were not interesting for this test, so I didn't # create symbols for them. -self.assertEqual(thread.GetNumFrames(), 6) +self.assertEqual(thread.GetNumFrames(), 3) stackframe_names = [ -"exception_catcher", "exception_catcher", "exception_thrower", "main", diff --git a/lldb/test/API/functionalities/unwind/cortex-m-exception/armv7m-nofpu-exception.yaml b/lldb/test/API/functionalities/unwind/cortex-m-exception/armv7m-nofpu-exception.yaml index 9ce5ff49d9b6e
[Lldb-commits] [lldb] [lldb][mcp] Get the running MCP server connection information (PR #162752)
https://github.com/aperez updated
https://github.com/llvm/llvm-project/pull/162752
>From cf719895cfd59ce55d349d8f27ae60ad13a3f96d Mon Sep 17 00:00:00 2001
From: Alexandre Perez
Date: Thu, 9 Oct 2025 16:23:46 -0700
Subject: [PATCH 1/2] [lldb][mcp] Add protocol-server subcommand to get the
running MCP server connection information
---
.../Commands/CommandObjectProtocolServer.cpp | 45 ++-
.../Protocol/MCP/ProtocolServerMCP.cpp| 1 +
.../commands/protocol/TestMCPUnixSocket.py| 13 ++
3 files changed, 58 insertions(+), 1 deletion(-)
diff --git a/lldb/source/Commands/CommandObjectProtocolServer.cpp
b/lldb/source/Commands/CommandObjectProtocolServer.cpp
index c5ab9e9f05bec..ff9d38c84ed2d 100644
--- a/lldb/source/Commands/CommandObjectProtocolServer.cpp
+++ b/lldb/source/Commands/CommandObjectProtocolServer.cpp
@@ -131,15 +131,58 @@ class CommandObjectProtocolServerStop : public
CommandObjectParsed {
}
};
+class CommandObjectProtocolServerGet : public CommandObjectParsed {
+public:
+ CommandObjectProtocolServerGet(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "protocol-server get",
+"get protocol server connection information",
+"protocol-server get ") {
+AddSimpleArgumentList(lldb::eArgTypeProtocol, eArgRepeatPlain);
+ }
+
+ ~CommandObjectProtocolServerGet() override = default;
+
+protected:
+ void DoExecute(Args &args, CommandReturnObject &result) override {
+if (args.GetArgumentCount() < 1) {
+ result.AppendError("no protocol specified");
+ return;
+}
+
+llvm::StringRef protocol = args.GetArgumentAtIndex(0);
+ProtocolServer *server = ProtocolServer::GetOrCreate(protocol);
+if (!server) {
+ result.AppendErrorWithFormatv(
+ "unsupported protocol: {0}. Supported protocols are: {1}", protocol,
+ llvm::join(ProtocolServer::GetSupportedProtocols(), ", "));
+ return;
+}
+
+Socket *socket = server->GetSocket();
+if (!socket) {
+ result.AppendErrorWithFormatv("{0} server is not running", protocol);
+ return;
+}
+
+std::string address =
+llvm::join(socket->GetListeningConnectionURI(), ", ");
+result.AppendMessageWithFormatv(
+"{0} server connection listeners: {1}", protocol, address);
+result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ }
+};
+
CommandObjectProtocolServer::CommandObjectProtocolServer(
CommandInterpreter &interpreter)
: CommandObjectMultiword(interpreter, "protocol-server",
- "Start and stop a protocol server.",
+ "Start, stop, and query protocol servers.",
"protocol-server") {
LoadSubCommand("start", CommandObjectSP(new CommandObjectProtocolServerStart(
interpreter)));
LoadSubCommand("stop", CommandObjectSP(
new
CommandObjectProtocolServerStop(interpreter)));
+ LoadSubCommand("get", CommandObjectSP(
+new CommandObjectProtocolServerGet(interpreter)));
}
CommandObjectProtocolServer::~CommandObjectProtocolServer() = default;
diff --git a/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp
b/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp
index 33bdd5eec3644..390cf3eeb16a5 100644
--- a/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp
+++ b/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp
@@ -144,6 +144,7 @@ llvm::Error ProtocolServerMCP::Stop() {
m_server.reset(nullptr);
m_server_info_handle.Remove();
+ m_listener.reset();
return llvm::Error::success();
}
diff --git a/lldb/test/API/commands/protocol/TestMCPUnixSocket.py
b/lldb/test/API/commands/protocol/TestMCPUnixSocket.py
index ea9255cc60ef5..9edb97eb791b9 100644
--- a/lldb/test/API/commands/protocol/TestMCPUnixSocket.py
+++ b/lldb/test/API/commands/protocol/TestMCPUnixSocket.py
@@ -32,3 +32,16 @@ def test_unix_socket(self):
startstr="MCP server started with connection listeners:",
substrs=[f"unix-connect://{socket_file}"],
)
+
+self.expect(
+"protocol-server get MCP",
+startstr="MCP server connection listeners:",
+substrs=[f"unix-connect://{socket_file}"],
+)
+
+self.runCmd("protocol-server stop MCP", check=False)
+self.expect(
+"protocol-server get MCP",
+error=True,
+substrs=["MCP server is not running"],
+)
>From da1c9154eef40ab8cf8b7ddfc20318036ba783d8 Mon Sep 17 00:00:00 2001
From: Alexandre Perez
Date: Thu, 9 Oct 2025 16:37:33 -0700
Subject: [PATCH 2/2] Fix formatting
---
lldb/source/Commands/CommandObjectProtocolServer.cpp | 11 +--
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/lldb/source/Commands/CommandObjectProtocolServer.cpp
b/lldb/source/Commands/CommandObjectProtocolServer.cpp
ind
[Lldb-commits] [lldb] update lldb-server platform help parsing (PR #162730)
JDevlieghere wrote: > The one question I had was regarding > > ``` > if (!LLDBServerUtilities::SetupLogging(log_file, log_channels, 0)) > return -1; > ``` > > and whether I should replace the -1 with `EXIT_FAILURE` Personally I would keep the current value, as it seems to have been done on purpose, and the risk of breaking someone's workflow outweighs the benefit of slightly improving consistency. https://github.com/llvm/llvm-project/pull/162730 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [debugserver] Implement MultiMemRead packet (PR #162670)
@@ -3160,6 +3165,140 @@ rnb_err_t RNBRemote::HandlePacket_m(const char *p) {
return SendPacket(ostrm.str());
}
+/// Returns true if `str` starts with `prefix`.
+static bool starts_with(std::string_view str, std::string_view prefix) {
+ return str.size() >= prefix.size() &&
+ str.compare(0, prefix.size(), prefix) == 0;
+}
+
+/// Attempts to parse a prefix of `number_str` as a number of type `T`. If
+/// successful, the number is returned and the prefix is dropped from
+/// `number_str`.
+template
+static std::optional extract_number(std::string_view &number_str) {
jasonmolenda wrote:
do you want to put this next to `decode_uint64()` in the source file, in case
some future person is inspired to update the caller to that old function to use
this one. The other ~37 strtoull's in this file parsing base16 strings do them
all separately.
https://github.com/llvm/llvm-project/pull/162670
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [gdbremote] Document MultiMemRead packet in protocol extensions (PR #162675)
@@ -2530,3 +2530,41 @@ read packet: $e0030100#b9 **Priority to Implement:** Only required for Wasm support. Necessary to show variables. + +### MultiMemRead + +Read memory from multiple memory addresses. + +There are two arguments to the request: + +* `ranges`: a list of base-16 pairs of numbers. Each pair is separated by a +`,`, as is each number in the pair. The first number of the pair denotes the +base address of the memory read, the second denotes the number of bytes to be +read. +* `options`: an optional string of options. If present, it may be empty. If +present, it is the last argument of the request. + +Both arguments must end with a `;`. + +The reply packet starts with a comma-separated list of base-16 numbers, +denoting how many bytes were read from each address, followed by a `;`, +followed by a sequence of bytes containing the memory data. The length of this +sequence must be equal to the sum of the numbers provided at the start of the +reply. + +If the stub is unable to read from any individual address, it should return a +length of "zero" for that address in the reply packet. jasonmolenda wrote: The entire requested memory range may not be readable; a partial memory read may be returned for a range. https://github.com/llvm/llvm-project/pull/162675 ___ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] 446d950 - [libc++] Use std::__{scope, exception}_guard throughout the code base (#161322)
Author: Nikolas Klauser
Date: 2025-10-09T09:32:40+02:00
New Revision: 446d9505246227b514aa6359f17106e1a9c65897
URL:
https://github.com/llvm/llvm-project/commit/446d9505246227b514aa6359f17106e1a9c65897
DIFF:
https://github.com/llvm/llvm-project/commit/446d9505246227b514aa6359f17106e1a9c65897.diff
LOG: [libc++] Use std::__{scope,exception}_guard throughout the code base
(#161322)
This simplifies the code quite a bit and seems to improve code size
slightly in some cases.
Added:
Modified:
libcxx/include/__hash_table
libcxx/include/__memory/shared_ptr.h
libcxx/include/__memory/uninitialized_algorithms.h
libcxx/include/__utility/scope_guard.h
libcxx/include/__vector/vector_bool.h
libcxx/include/deque
libcxx/include/forward_list
libcxx/include/future
libcxx/include/list
libcxx/include/string
libcxx/include/valarray
libcxx/src/filesystem/error.h
libcxx/src/filesystem/format_string.h
libcxx/src/locale.cpp
lldb/test/API/commands/expression/import-std-module/deque-basic/TestDequeFromStdModule.py
lldb/test/API/commands/expression/import-std-module/deque-dbg-info-content/TestDbgInfoContentDequeFromStdModule.py
lldb/test/API/commands/expression/import-std-module/forward_list/TestForwardListFromStdModule.py
lldb/test/API/commands/expression/import-std-module/list-dbg-info-content/TestDbgInfoContentListFromStdModule.py
lldb/test/API/commands/expression/import-std-module/list/TestListFromStdModule.py
Removed:
diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index 2b246f82ce36d..74923ddb74e9c 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -44,6 +44,7 @@
#include <__utility/forward.h>
#include <__utility/move.h>
#include <__utility/pair.h>
+#include <__utility/scope_guard.h>
#include <__utility/swap.h>
#include <__utility/try_key_extraction.h>
#include
@@ -1317,23 +1318,14 @@ void __hash_table<_Tp, _Hash, _Equal,
_Alloc>::__move_assign(__hash_table& __u,
max_load_factor() = __u.max_load_factor();
if (bucket_count() != 0) {
__next_pointer __cache = __detach();
-#if _LIBCPP_HAS_EXCEPTIONS
- try {
-#endif // _LIBCPP_HAS_EXCEPTIONS
-const_iterator __i = __u.begin();
-while (__cache != nullptr && __u.size() != 0) {
- __assign_value(__cache->__upcast()->__get_value(),
std::move(__u.remove(__i++)->__get_value()));
- __next_pointer __next = __cache->__next_;
- __node_insert_multi(__cache->__upcast());
- __cache = __next;
-}
-#if _LIBCPP_HAS_EXCEPTIONS
- } catch (...) {
-__deallocate_node(__cache);
-throw;
+ auto __guard = std::__make_scope_guard([&] {
__deallocate_node(__cache); });
+ const_iterator __i = __u.begin();
+ while (__cache != nullptr && __u.size() != 0) {
+__assign_value(__cache->__upcast()->__get_value(),
std::move(__u.remove(__i++)->__get_value()));
+__next_pointer __next = __cache->__next_;
+__node_insert_multi(__cache->__upcast());
+__cache = __next;
}
-#endif // _LIBCPP_HAS_EXCEPTIONS
- __deallocate_node(__cache);
}
const_iterator __i = __u.begin();
while (__u.size() != 0)
@@ -1361,22 +1353,13 @@ void __hash_table<_Tp, _Hash, _Equal,
_Alloc>::__assign_unique(_InputIterator __
if (bucket_count() != 0) {
__next_pointer __cache = __detach();
-#if _LIBCPP_HAS_EXCEPTIONS
-try {
-#endif // _LIBCPP_HAS_EXCEPTIONS
- for (; __cache != nullptr && __first != __last; ++__first) {
-__assign_value(__cache->__upcast()->__get_value(), *__first);
-__next_pointer __next = __cache->__next_;
-__node_insert_unique(__cache->__upcast());
-__cache = __next;
- }
-#if _LIBCPP_HAS_EXCEPTIONS
-} catch (...) {
- __deallocate_node(__cache);
- throw;
+auto __guard = std::__make_scope_guard([&] {
__deallocate_node(__cache); });
+for (; __cache != nullptr && __first != __last; ++__first) {
+ __assign_value(__cache->__upcast()->__get_value(), *__first);
+ __next_pointer __next = __cache->__next_;
+ __node_insert_unique(__cache->__upcast());
+ __cache = __next;
}
-#endif // _LIBCPP_HAS_EXCEPTIONS
-__deallocate_node(__cache);
}
for (; __first != __last; ++__first)
__emplace_unique(*__first);
@@ -1391,22 +1374,13 @@ void __hash_table<_Tp, _Hash, _Equal,
_Alloc>::__assign_multi(_InputIterator __f
"__assign_multi may only be called with the containers value
type or the nodes value type");
if (bucket_count() != 0) {
__next_pointer __cache = __detach();
-#if _LIBCPP_HAS_EXCEPTIONS
-try {
-#endif // _LIBCPP_HAS_EXCEPTIONS
- for (; __cache != nullptr && __first != __last; ++__first) {
-__assign_value(__cache->__upcast()->__get_value(), *__first);
-
