[Lldb-commits] [lldb] Make env and source map dictionaries #95137 (PR #106919)
via lldb-commits
lldb-commits at lists.llvm.org
Sun Sep 1 13:02:46 PDT 2024
https://github.com/Da-Viper updated https://github.com/llvm/llvm-project/pull/106919
>From 539d44a522e9e0563079ddbefb59e1b4b4caaca6 Mon Sep 17 00:00:00 2001
From: Ezike Ebuka <yerimyah1 at gmail.com>
Date: Sun, 1 Sep 2024 17:26:11 +0100
Subject: [PATCH 1/4] [lldb-dap] Make environment option an object
---
lldb/tools/lldb-dap/JSONUtils.cpp | 35 +++++++++++++++++++++++++------
lldb/tools/lldb-dap/JSONUtils.h | 21 +++++++++++++++++++
lldb/tools/lldb-dap/README.md | 5 ++++-
lldb/tools/lldb-dap/lldb-dap.cpp | 8 ++++++-
lldb/tools/lldb-dap/package.json | 11 +++++++---
5 files changed, 69 insertions(+), 11 deletions(-)
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp
index 7338e7cf41eb03..fc2ef80c79cfad 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -136,6 +136,31 @@ std::vector<std::string> GetStrings(const llvm::json::Object *obj,
return strs;
}
+std::unordered_map<std::string, std::string>
+GetStringObject(const llvm::json::Object &obj, llvm::StringRef key) {
+ std::unordered_map<std::string, std::string> strs;
+ const auto *const json_object = obj.getObject(key);
+ if (!json_object)
+ return strs;
+
+ for (const auto &[key, value] : *json_object) {
+ switch (value.kind()) {
+ case llvm::json::Value::String:
+ strs.emplace(key.str(), value.getAsString()->str());
+ break;
+ case llvm::json::Value::Number:
+ case llvm::json::Value::Boolean:
+ strs.emplace(key.str(), llvm::to_string(value));
+ break;
+ case llvm::json::Value::Null:
+ case llvm::json::Value::Object:
+ case llvm::json::Value::Array:
+ break;
+ }
+ }
+ return strs;
+}
+
static bool IsClassStructOrUnionType(lldb::SBType t) {
return (t.GetTypeClass() & (lldb::eTypeClassUnion | lldb::eTypeClassStruct |
lldb::eTypeClassArray)) != 0;
@@ -1370,13 +1395,11 @@ CreateRunInTerminalReverseRequest(const llvm::json::Object &launch_request,
if (!cwd.empty())
run_in_terminal_args.try_emplace("cwd", cwd);
- // We need to convert the input list of environments variables into a
- // dictionary
- std::vector<std::string> envs = GetStrings(launch_request_arguments, "env");
+ std::unordered_map<std::string, std::string> envMap =
+ GetStringObject(*launch_request_arguments, "env");
llvm::json::Object environment;
- for (const std::string &env : envs) {
- size_t index = env.find('=');
- environment.try_emplace(env.substr(0, index), env.substr(index + 1));
+ for (const auto &[key, value] : envMap) {
+ environment.try_emplace(key, value);
}
run_in_terminal_args.try_emplace("env",
llvm::json::Value(std::move(environment)));
diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h
index b6356630b72682..de6228a0429944 100644
--- a/lldb/tools/lldb-dap/JSONUtils.h
+++ b/lldb/tools/lldb-dap/JSONUtils.h
@@ -16,6 +16,7 @@
#include "llvm/Support/JSON.h"
#include <cstdint>
#include <optional>
+#include <unordered_map>
namespace lldb_dap {
@@ -151,6 +152,26 @@ bool ObjectContainsKey(const llvm::json::Object &obj, llvm::StringRef key);
/// strings, numbers or booleans.
std::vector<std::string> GetStrings(const llvm::json::Object *obj,
llvm::StringRef key);
+/// Extract an object of key value strings for the specified key from an object.
+///
+/// String values in the array will be extracted without any quotes
+/// around them. Numbers and Booleans will be converted into
+/// strings. Any NULL, array or objects values in the array will be
+/// ignored.
+///
+/// \param[in] obj
+/// A JSON object that we will attempt to extract the array from
+///
+/// \param[in] key
+/// The key to use when extracting the value
+///
+/// \return
+/// An object of key value strings for the specified \a key, or
+/// \a fail_value if there is no key that matches or if the
+/// value is not an object or key and values in the object are not
+/// strings, numbers or booleans.
+std::unordered_map<std::string, std::string>
+GetStringObject(const llvm::json::Object &obj, llvm::StringRef key);
/// Fill a response object given the request object.
///
diff --git a/lldb/tools/lldb-dap/README.md b/lldb/tools/lldb-dap/README.md
index 11a14d29ab51e2..5b6fc5ef990e60 100644
--- a/lldb/tools/lldb-dap/README.md
+++ b/lldb/tools/lldb-dap/README.md
@@ -77,7 +77,10 @@ adds `FOO=1` and `bar` to the environment:
"name": "Debug",
"program": "/tmp/a.out",
"args": [ "one", "two", "three" ],
- "env": [ "FOO=1", "BAR" ],
+ "env": {
+ "FOO": "1"
+ "BAR": ""
+ }
}
```
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index c5c4b09f15622b..804f467c7a4e20 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -1831,7 +1831,13 @@ lldb::SBError LaunchProcess(const llvm::json::Object &request) {
launch_info.SetArguments(MakeArgv(args).data(), true);
// Pass any environment variables along that the user specified.
- auto envs = GetStrings(arguments, "env");
+ auto envMap = GetStringObject(*arguments, "env");
+ std::vector<std::string> envs;
+ envs.reserve(envMap.size());
+ for (const auto &[key, value] : envMap) {
+ envs.emplace_back(key + '=' + value);
+ }
+
if (!envs.empty())
launch_info.SetEnvironmentEntries(MakeArgv(envs).data(), true);
diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json
index 4f4261d1718c01..e5dc707bee11e9 100644
--- a/lldb/tools/lldb-dap/package.json
+++ b/lldb/tools/lldb-dap/package.json
@@ -160,9 +160,14 @@
"default": "${workspaceRoot}"
},
"env": {
- "type": "array",
- "description": "Additional environment variables to set when launching the program. This is an array of strings that contains the variable name followed by an optional '=' character and the environment variable's value.",
- "default": []
+ "type": "object",
+ "description": "Additional environment variables to set when launching the program. eg { \"FOO\": \"1\" }",
+ "patternProperties": {
+ ".*": {
+ "type": "string"
+ }
+ },
+ "default": {}
},
"stopOnEntry": {
"type": "boolean",
>From ff350393ebd2a3c6145ae72fa99ffb55b97087dc Mon Sep 17 00:00:00 2001
From: Ezike Ebuka <yerimyah1 at gmail.com>
Date: Sun, 1 Sep 2024 19:17:14 +0100
Subject: [PATCH 2/4] [lldb-dap] Make sourceMap debug option a dictionary
---
lldb/tools/lldb-dap/README.md | 2 +-
lldb/tools/lldb-dap/lldb-dap.cpp | 23 ++++++++++++-----------
lldb/tools/lldb-dap/package.json | 22 ++++++++++++++++------
3 files changed, 29 insertions(+), 18 deletions(-)
diff --git a/lldb/tools/lldb-dap/README.md b/lldb/tools/lldb-dap/README.md
index 5b6fc5ef990e60..c4f48001dad19a 100644
--- a/lldb/tools/lldb-dap/README.md
+++ b/lldb/tools/lldb-dap/README.md
@@ -34,7 +34,7 @@ file that defines how your program will be run. The JSON configuration file can
|**launchCommands** |[string]| | LLDB commands executed to launch the program. Commands and command output will be sent to the debugger console when they are executed.
|**exitCommands** |[string]| | LLDB commands executed when the program exits. Commands and command output will be sent to the debugger console when they are executed.
|**terminateCommands** |[string]| | LLDB commands executed when the debugging session ends. Commands and command output will be sent to the debugger console when they are executed.
-|**sourceMap** |[string[2]]| | Specify an array of path re-mappings. Each element in the array must be a two element array containing a source and destination pathname.
+|**sourceMap** |dictionary| | Specify an array of path re-mappings. Each element in the array must be a two element array containing a source and destination pathname.
|**debuggerRoot** | string| |Specify a working directory to use when launching lldb-dap. If the debug information in your executable contains relative paths, this option can be used so that `lldb-dap` can find source files and object files that have relative paths.
### Attaching Settings
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index 804f467c7a4e20..ba77ca145051a0 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -599,27 +599,28 @@ lldb::SBValue FindVariable(uint64_t variablesReference, llvm::StringRef name) {
// argument (or neither), from which we need to set the target.source-map.
void SetSourceMapFromArguments(const llvm::json::Object &arguments) {
const char *sourceMapHelp =
- "source must be be an array of two-element arrays, "
- "each containing a source and replacement path string.\n";
+ "source must be be an object of key-value strings "
+ "key as the source and replacement path as the value.\n";
std::string sourceMapCommand;
llvm::raw_string_ostream strm(sourceMapCommand);
strm << "settings set target.source-map ";
- auto sourcePath = GetString(arguments, "sourcePath");
+ const auto sourcePath = GetString(arguments, "sourcePath");
// sourceMap is the new, more general form of sourcePath and overrides it.
- auto sourceMap = arguments.getArray("sourceMap");
+ const auto *sourceMap = arguments.getObject("sourceMap");
if (sourceMap) {
- for (const auto &value : *sourceMap) {
- auto mapping = value.getAsArray();
- if (mapping == nullptr || mapping->size() != 2 ||
- (*mapping)[0].kind() != llvm::json::Value::String ||
- (*mapping)[1].kind() != llvm::json::Value::String) {
+ for (const auto &[key, value] : *sourceMap) {
+ const auto mapFrom = llvm::StringRef(key);
+ if (mapFrom.empty()) {
+ return;
+ }
+ if (value.kind() != llvm::json::Value::String) {
g_dap.SendOutput(OutputType::Console, llvm::StringRef(sourceMapHelp));
return;
}
- auto mapFrom = GetAsString((*mapping)[0]);
- auto mapTo = GetAsString((*mapping)[1]);
+
+ const llvm::StringRef mapTo = GetAsString(value);
strm << "\"" << mapFrom << "\" \"" << mapTo << "\" ";
}
} else {
diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json
index e5dc707bee11e9..1404a1f29c6bb0 100644
--- a/lldb/tools/lldb-dap/package.json
+++ b/lldb/tools/lldb-dap/package.json
@@ -199,9 +199,14 @@
"description": "Specify a source path to remap \"./\" to allow full paths to be used when setting breakpoints in binaries that have relative source paths."
},
"sourceMap": {
- "type": "array",
- "description": "Specify an array of path remappings; each element must itself be a two element array containing a source and destination path name. Overrides sourcePath.",
- "default": []
+ "type": "object",
+ "description": "Specify an object of path remappings; each entry has a key containing the source path and a value containing the destination path. E.g { \"/the/source/path\": \"/the/destination/path\" } Overrides sourcePath.",
+ "patternProperties": {
+ ".*": {
+ "type": "string"
+ }
+ },
+ "default": {}
},
"debuggerRoot": {
"type": "string",
@@ -304,9 +309,14 @@
"description": "Specify a source path to remap \"./\" to allow full paths to be used when setting breakpoints in binaries that have relative source paths."
},
"sourceMap": {
- "type": "array",
- "description": "Specify an array of path remappings; each element must itself be a two element array containing a source and destination path name. Overrides sourcePath.",
- "default": []
+ "type": "object",
+ "description": "Specify an object of path remappings; each entry has a key containing the source path and a value containing the destination path. E.g { \"/the/source/path\": \"/the/destination/path\" } Overrides sourcePath.",
+ "patternProperties": {
+ ".*": {
+ "type": "string"
+ }
+ },
+ "default": {}
},
"debuggerRoot": {
"type": "string",
>From 864225ea1180f7e1098b6c64d1d29a617961583c Mon Sep 17 00:00:00 2001
From: Ezike Ebuka <yerimyah1 at gmail.com>
Date: Sun, 1 Sep 2024 20:01:29 +0100
Subject: [PATCH 3/4] [lldb-dap] handle empty cases for env and sourceMap
option
---
lldb/tools/lldb-dap/JSONUtils.cpp | 6 +++++-
lldb/tools/lldb-dap/lldb-dap.cpp | 9 +++++----
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp
index fc2ef80c79cfad..333c0b21e57d01 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -1399,7 +1399,11 @@ CreateRunInTerminalReverseRequest(const llvm::json::Object &launch_request,
GetStringObject(*launch_request_arguments, "env");
llvm::json::Object environment;
for (const auto &[key, value] : envMap) {
- environment.try_emplace(key, value);
+ if (key.empty())
+ g_dap.SendOutput(OutputType::Stderr,
+ "empty environment variable for value: \"" + value + '\"');
+ else
+ environment.try_emplace(key, value);
}
run_in_terminal_args.try_emplace("env",
llvm::json::Value(std::move(environment)));
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index ba77ca145051a0..59957344ff7f50 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -599,8 +599,8 @@ lldb::SBValue FindVariable(uint64_t variablesReference, llvm::StringRef name) {
// argument (or neither), from which we need to set the target.source-map.
void SetSourceMapFromArguments(const llvm::json::Object &arguments) {
const char *sourceMapHelp =
- "source must be be an object of key-value strings "
- "key as the source and replacement path as the value.\n";
+ "source must be be an object of key-value strings. "
+ "e.g sourceMap: { \"/path/to/source\": \"/path/to/destination\" }.\n";
std::string sourceMapCommand;
llvm::raw_string_ostream strm(sourceMapCommand);
@@ -609,7 +609,7 @@ void SetSourceMapFromArguments(const llvm::json::Object &arguments) {
// sourceMap is the new, more general form of sourcePath and overrides it.
const auto *sourceMap = arguments.getObject("sourceMap");
- if (sourceMap) {
+ if (sourceMap && !sourceMap->empty()) {
for (const auto &[key, value] : *sourceMap) {
const auto mapFrom = llvm::StringRef(key);
if (mapFrom.empty()) {
@@ -1836,7 +1836,8 @@ lldb::SBError LaunchProcess(const llvm::json::Object &request) {
std::vector<std::string> envs;
envs.reserve(envMap.size());
for (const auto &[key, value] : envMap) {
- envs.emplace_back(key + '=' + value);
+ if (!key.empty())
+ envs.emplace_back(key + '=' + value);
}
if (!envs.empty())
>From 58e5c8e2c083fb50f41de95b4e7f4cf17469f688 Mon Sep 17 00:00:00 2001
From: Ezike Ebuka <yerimyah1 at gmail.com>
Date: Sun, 1 Sep 2024 21:02:28 +0100
Subject: [PATCH 4/4] [lldb-dap] fix code format
---
lldb/tools/lldb-dap/JSONUtils.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp
index 333c0b21e57d01..ce1845525c965b 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -1401,7 +1401,8 @@ CreateRunInTerminalReverseRequest(const llvm::json::Object &launch_request,
for (const auto &[key, value] : envMap) {
if (key.empty())
g_dap.SendOutput(OutputType::Stderr,
- "empty environment variable for value: \"" + value + '\"');
+ "empty environment variable for value: \"" + value +
+ '\"');
else
environment.try_emplace(key, value);
}
More information about the lldb-commits
mailing list