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 <yerimy...@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 <yerimy...@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 <yerimy...@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 <yerimy...@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); } _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits