[Lldb-commits] [PATCH] D50365: Add a new tool named "lldb-vscode" that implements the Visual Studio Code Debug Adaptor Protocol

Zachary Turner via Phabricator via lldb-commits lldb-commits at lists.llvm.org
Wed Aug 15 09:34:41 PDT 2018


zturner added inline comments.


================
Comment at: tools/lldb-vscode/BreakpointBase.cpp:13-21
+uint64_t string_to_unsigned(const char *s, int base, uint64_t fail_value) {
+  if (s && s[0]) {
+    char *end = nullptr;
+    uint64_t uval = strtoull(s, &end, base);
+    if (*end == '\0')
+      return uval;
+  }
----------------
Can we delete this function and use `StringRef::getAsInteger()` instead?


================
Comment at: tools/lldb-vscode/BreakpointBase.h:18
+
+struct BreakpointBase {
+
----------------
This should have a virtual destructor.


================
Comment at: tools/lldb-vscode/BreakpointBase.h:24
+  // ignored. The backend is expected to interpret the expression as needed
+  std::string hitCondition;
+  // If this attribute exists and is non-empty, the backend must not 'break'
----------------
Shouldn't this be an integer?


================
Comment at: tools/lldb-vscode/ExceptionBreakpoint.cpp:14
+void ExceptionBreakpoint::SetBreakpoint() {
+  if (!bp.IsValid()) {
+    bool catch_value = filter.find("_catch") != std::string::npos;
----------------
Early return.


================
Comment at: tools/lldb-vscode/ExceptionBreakpoint.cpp:22
+
+void ExceptionBreakpoint::ClearBreakpoint() {
+  if (bp.IsValid()) {
----------------
Is it useful to have a notion of a breakpoint object that isn't actually set?  Why not just `delete` this class instance entirely and let the caller allocate a new one when they're ready.  If we want to keep this, then I think an `llvm::Optional<SBBreakpoint>` would be a better approach, because it makes explicit for someone reading the code that not existing is a valid state.


================
Comment at: tools/lldb-vscode/ExceptionBreakpoint.cpp:23
+void ExceptionBreakpoint::ClearBreakpoint() {
+  if (bp.IsValid()) {
+    g_vsc.target.BreakpointDelete(bp.GetID());
----------------
Early return.


================
Comment at: tools/lldb-vscode/ExceptionBreakpoint.h:17
+
+struct ExceptionBreakpoint {
+  std::string filter;
----------------
Should this inherit from `BreakpointBase`?


================
Comment at: tools/lldb-vscode/ExceptionBreakpoint.h:23-24
+  lldb::SBBreakpoint bp;
+  ExceptionBreakpoint(const char *f, const char *l, lldb::LanguageType lang)
+      : filter(f), label(l), language(lang), value(false), bp() {}
+
----------------
Can you make this constructor take the first two arguments as `std::string`, then initialize them with `filter(std::move(f))`, and `label(std::move(l))`?  The current code is guaranteed to make a copy, the suggested approach might not.


================
Comment at: tools/lldb-vscode/FunctionBreakpoint.h:17
+  // The name of the function
+  std::string name;
+
----------------
Can we call this variable `functionName` and delete the comment?


================
Comment at: tools/lldb-vscode/JSONUtils.h:27
+//------------------------------------------------------------------
+std::string GetAsString(const llvm::json::Value &value);
+
----------------
I think this could return `StringRef`


================
Comment at: tools/lldb-vscode/JSONUtils.h:44-45
+//------------------------------------------------------------------
+std::string GetString(const llvm::json::Object &obj, llvm::StringRef key);
+std::string GetString(const llvm::json::Object *obj, llvm::StringRef key);
+
----------------
I think this could return a `StringRef`.  Also, it seems weird to have an overload which takes a pointer.  Can we delete that overload?  I don't think it would make sense for anyone to call this function with a null `obj`.


================
Comment at: tools/lldb-vscode/JSONUtils.h:141-142
+//------------------------------------------------------------------
+std::vector<std::string> GetStrings(const llvm::json::Object *obj,
+                                    llvm::StringRef key);
+
----------------
This could return a `vector<StringRef>`


================
Comment at: tools/lldb-vscode/JSONUtils.h:225
+//----------------------------------------------------------------------
+llvm::json::Object CreateEvent(const char *event_name);
+
----------------
`StringRef event_name`


================
Comment at: tools/lldb-vscode/JSONUtils.h:261-262
+//----------------------------------------------------------------------
+llvm::json::Value CreateScope(const char *name, int64_t variablesReference,
+                              int64_t namedVariables, bool expensive);
+
----------------
`StringRef name`


================
Comment at: tools/lldb-vscode/SourceBreakpoint.h:24
+  // Set this breakpoint in LLDB as a new breakpoint
+  void SetBreakpoint(const char *source_path);
+};
----------------
`StringRef source_path`


================
Comment at: tools/lldb-vscode/SourceReference.h:19
+  std::string content;
+  std::map<lldb::addr_t, int64_t> addr_to_line;
+
----------------
`llvm::DenseMap`


================
Comment at: tools/lldb-vscode/VSCode.cpp:22-24
+  while (*l == '\r' || *l == '\n')
+    ++l;
+  return l[0] == '\0';
----------------
I'd write this as:

```
inline bool is_empty_line(StringRef S) {
  return S.ltrim().empty();
}
```


================
Comment at: tools/lldb-vscode/VSCode.cpp:129
+
+  while (fgets(line, sizeof(line), in)) {
+    if (strncmp(line, header.data(), header.size()) == 0) {
----------------
You should check out `llvm/Support/LineIterator.h`


================
Comment at: tools/lldb-vscode/VSCode.h:45
+
+typedef std::map<uint32_t, SourceBreakpoint> SourceBreakpointMap;
+typedef std::map<std::string, FunctionBreakpoint> FunctionBreakpointMap;
----------------
`llvm::DenseMap`


================
Comment at: tools/lldb-vscode/VSCode.h:46
+typedef std::map<uint32_t, SourceBreakpoint> SourceBreakpointMap;
+typedef std::map<std::string, FunctionBreakpoint> FunctionBreakpointMap;
+
----------------
`llvm::StringMap`


================
Comment at: tools/lldb-vscode/VSCode.h:60-61
+struct VSCode {
+  FILE *in;
+  FILE *out;
+  lldb::SBDebugger debugger;
----------------
Any reason why we have to use `FILE*` instead of fds?


================
Comment at: tools/lldb-vscode/VSCode.h:72-73
+  std::thread event_thread;
+  //  std::thread forward_input_thread;
+  //  std::thread forward_output_thread;
+  std::unique_ptr<std::ofstream> log;
----------------
Delete commented out code


================
Comment at: tools/lldb-vscode/VSCode.h:74
+  //  std::thread forward_output_thread;
+  std::unique_ptr<std::ofstream> log;
+  std::map<lldb::addr_t, int64_t> addr_to_source_ref;
----------------
`llvm::Optional<llvm::raw_fd_ostream>`?


================
Comment at: tools/lldb-vscode/VSCode.h:75-76
+  std::unique_ptr<std::ofstream> log;
+  std::map<lldb::addr_t, int64_t> addr_to_source_ref;
+  std::map<int64_t, SourceReference> source_map;
+  std::map<std::string, SourceBreakpointMap> source_breakpoints;
----------------
`llvm::DenseMap<>`


================
Comment at: tools/lldb-vscode/VSCode.h:77
+  std::map<int64_t, SourceReference> source_map;
+  std::map<std::string, SourceBreakpointMap> source_breakpoints;
+  FunctionBreakpointMap function_breakpoints;
----------------
`llvm::StringMap`


================
Comment at: tools/lldb-vscode/VSCode.h:79-83
+  std::vector<ExceptionBreakpoint> exception_breakpoints;
+  std::vector<std::string> init_commands;
+  std::vector<std::string> pre_run_commands;
+  std::vector<std::string> exit_commands;
+  std::vector<std::string> stop_commands;
----------------
`llvm::SmallVector`


================
Comment at: tools/lldb-vscode/VSCode.h:89
+  // unless we send a "thread" event to indicate the thread exited.
+  std::set<lldb::tid_t> thread_ids;
+  VSCode();
----------------
`llvm::DenseSet<>`


================
Comment at: tools/lldb-vscode/VSCode.h:97
+  int64_t GetLineForPC(int64_t sourceReference, lldb::addr_t pc) const;
+  ExceptionBreakpoint *GetExceptionBreakpoint(const std::string &filter);
+  ExceptionBreakpoint *GetExceptionBreakpoint(const lldb::break_id_t bp_id);
----------------
`StringRef filter`


================
Comment at: tools/lldb-vscode/VSCode.h:104
+  //----------------------------------------------------------------------
+  void SendJSON(const std::string &json_str);
+
----------------
`StringRef json_str`


================
Comment at: tools/lldb-vscode/VSCode.h:114-115
+
+  void SendOutput(OutputType o, const char *output,
+                  size_t output_len = SIZE_MAX);
+
----------------
`StringRef output`


================
Comment at: tools/lldb-vscode/VSCode.h:130-131
+
+  void RunLLDBCommands(const char *prefix,
+                       const std::vector<std::string> &commands);
+
----------------
`StringRef prefix, ArrayRef<std::string> commands`


================
Comment at: tools/lldb-vscode/lldb-vscode.cpp:47-58
+#if defined(_WIN32)
+#define PATH_MAX MAX_PATH
+typedef int socklen_t;
+constexpr const char *dev_null_path = "nul";
+
+static bool ChangeDir(const char *path) { return SetCurrentDirectoryA(path); }
+#else
----------------
This block of code can be deleted.  We have similar abstractions in either lldb or llvm.


================
Comment at: tools/lldb-vscode/lldb-vscode.cpp:61
+typedef void (*RequestCallback)(const llvm::json::Object &command);
+typedef std::map<const char *, bool> ProgressMap;
+
----------------
`llvm::StringMap`


================
Comment at: tools/lldb-vscode/lldb-vscode.cpp:69
+
+#pragma mark-- other utilities
+
----------------
I don't believe these `pragma` statements will work on all compilers


================
Comment at: tools/lldb-vscode/lldb-vscode.cpp:71
+
+int AcceptConnection(int portno) {
+  // Accept a socket connection from any host on "portno".
----------------
Can you make all global functions `static`?


================
Comment at: tools/lldb-vscode/lldb-vscode.cpp:108
+
+std::vector<const char *> MakeArgv(const std::vector<std::string> &strs) {
+  // Create and return an array of "const char *", one for each C string in
----------------
Can this take an `ArrayRef<std::string>` instead?


================
Comment at: tools/lldb-vscode/lldb-vscode.cpp:432
+
+  std::string sourceMapCommand("settings set target.source-map");
+  auto sourcePath = GetString(arguments, "sourcePath");
----------------
This should be an `llvm::raw_string_ostream` which builds up the command, then at the end call `stream.str()` to render the final string.


https://reviews.llvm.org/D50365





More information about the lldb-commits mailing list