anton.kolesov updated this revision to Diff 244160.
anton.kolesov added a comment.

Updated in attempt to reduce amount of code duplication between request_attach 
and request_launch.
Built and tested with testsuite on Linux/x64, also built and manually tested on 
Windows/x64 host with a baremetal ARC cpu target.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70847/new/

https://reviews.llvm.org/D70847

Files:
  lldb/tools/lldb-vscode/VSCode.cpp
  lldb/tools/lldb-vscode/VSCode.h
  lldb/tools/lldb-vscode/lldb-vscode.cpp
  lldb/tools/lldb-vscode/package.json

Index: lldb/tools/lldb-vscode/package.json
===================================================================
--- lldb/tools/lldb-vscode/package.json
+++ lldb/tools/lldb-vscode/package.json
@@ -122,6 +122,14 @@
 								"type": "string",
 								"description": "Specify a working directory to set the debug adaptor to so relative object files can be located."
 							},
+							"targetTriple": {
+								"type": "string",
+								"description": "Triplet of the target architecture to override value derived from the program file."
+							},
+							"platformName": {
+								"type": "string",
+								"description": "Name of the execution platform to override value derived from the program file."
+							},
 							"initCommands": {
 									"type": "array",
 									"description": "Initialization commands executed upon debugger startup.",
@@ -175,6 +183,14 @@
 								"type": "string",
 								"description": "Specify a working directory to set the debug adaptor to so relative object files can be located."
 							},
+							"targetTriple": {
+								"type": "string",
+								"description": "Triplet of the target architecture to override value derived from the program file."
+							},
+							"platformName": {
+								"type": "string",
+								"description": "Name of the execution platform to override value derived from the program file."
+							},
 							"attachCommands": {
 								"type": "array",
 								"description": "Custom commands that are executed instead of attaching to a process ID or to a process by name. These commands may optionally create a new target and must perform an attach. A valid process must exist after these commands complete or the \"attach\" will fail.",
Index: lldb/tools/lldb-vscode/lldb-vscode.cpp
===================================================================
--- lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -69,8 +69,6 @@
 
 enum LaunchMethod { Launch, Attach, AttachForSuspendedLaunch };
 
-enum VSCodeBroadcasterBits { eBroadcastBitStopEventThread = 1u << 0 };
-
 SOCKET AcceptConnection(int portno) {
   // Accept a socket connection from any host on "portno".
   SOCKET newsockfd = -1;
@@ -512,25 +510,13 @@
   // Run any initialize LLDB commands the user specified in the launch.json
   g_vsc.RunInitCommands();
 
-  // Grab the name of the program we need to debug and set it as the first
-  // argument that will be passed to the program we will debug.
-  const auto program = GetString(arguments, "program");
-  if (!program.empty()) {
-    lldb::SBFileSpec program_fspec(program.data(), true /*resolve_path*/);
-
-    g_vsc.launch_info.SetExecutableFile(program_fspec,
-                                        false /*add_as_first_arg*/);
-    const char *target_triple = nullptr;
-    const char *uuid_cstr = nullptr;
-    // Stand alone debug info file if different from executable
-    const char *symfile = nullptr;
-    g_vsc.target.AddModule(program.data(), target_triple, uuid_cstr, symfile);
-    if (error.Fail()) {
-      response["success"] = llvm::json::Value(false);
-      EmplaceSafeString(response, "message", std::string(error.GetCString()));
-      g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-      return;
-    }
+  lldb::SBError status;
+  g_vsc.SetTarget(g_vsc.CreateTargetFromArguments(*arguments, status));
+  if (status.Fail()) {
+    response["success"] = llvm::json::Value(false);
+    EmplaceSafeString(response, "message", status.GetCString());
+    g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+    return;
   }
 
   const bool detatchOnError = GetBoolean(arguments, "detachOnError", false);
@@ -543,7 +529,8 @@
     char attach_info[256];
     auto attach_info_len =
         snprintf(attach_info, sizeof(attach_info),
-                 "Waiting to attach to \"%s\"...", program.data());
+                 "Waiting to attach to \"%s\"...",
+                 g_vsc.target.GetExecutable().GetFilename());
     g_vsc.SendOutput(OutputType::Console, llvm::StringRef(attach_info,
                                                           attach_info_len));
   }
@@ -1217,13 +1204,6 @@
     g_vsc.debugger.SetErrorFileHandle(out, false);
   }
 
-  g_vsc.target = g_vsc.debugger.CreateTarget(nullptr);
-  lldb::SBListener listener = g_vsc.debugger.GetListener();
-  listener.StartListeningForEvents(
-      g_vsc.target.GetBroadcaster(),
-      lldb::SBTarget::eBroadcastBitBreakpointChanged);
-  listener.StartListeningForEvents(g_vsc.broadcaster,
-                                   eBroadcastBitStopEventThread);
   // Start our event thread so we can receive events from the debugger, target,
   // process and more.
   g_vsc.event_thread = std::thread(EventThreadFunction);
@@ -1365,39 +1345,29 @@
 
   SetSourceMapFromArguments(*arguments);
 
-  // Run any initialize LLDB commands the user specified in the launch.json
+  // Run any initialize LLDB commands the user specified in the launch.json.
+  // This is run before target is created, so commands can't do anything with
+  // the targets - preRunCommands are run with the target.
   g_vsc.RunInitCommands();
 
+  lldb::SBError status;
+  g_vsc.SetTarget(g_vsc.CreateTargetFromArguments(*arguments, status));
+  if (status.Fail()) {
+    response["success"] = llvm::json::Value(false);
+    EmplaceSafeString(response, "message", status.GetCString());
+    g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+    return;
+  }
+
+  // Instantiate a launch info instance for the target.
+  g_vsc.launch_info = g_vsc.target.GetLaunchInfo();
+
   // Grab the current working directory if there is one and set it in the
   // launch info.
   const auto cwd = GetString(arguments, "cwd");
   if (!cwd.empty())
     g_vsc.launch_info.SetWorkingDirectory(cwd.data());
 
-  // Grab the name of the program we need to debug and set it as the first
-  // argument that will be passed to the program we will debug.
-  llvm::StringRef program = GetString(arguments, "program");
-  if (!program.empty()) {
-    lldb::SBFileSpec program_fspec(program.data(), true /*resolve_path*/);
-    g_vsc.launch_info.SetExecutableFile(program_fspec,
-                                        true /*add_as_first_arg*/);
-    const char *target_triple = nullptr;
-    const char *uuid_cstr = nullptr;
-    // Stand alone debug info file if different from executable
-    const char *symfile = nullptr;
-    lldb::SBModule module = g_vsc.target.AddModule(
-        program.data(), target_triple, uuid_cstr, symfile);
-    if (!module.IsValid()) {
-      response["success"] = llvm::json::Value(false);
-
-      EmplaceSafeString(
-          response, "message",
-          llvm::formatv("Could not load program '{0}'.", program).str());
-      g_vsc.SendJSON(llvm::json::Value(std::move(response)));
-      return;
-    }
-  }
-
   // Extract any extra arguments and append them to our program arguments for
   // when we launch
   auto args = GetStrings(arguments, "args");
Index: lldb/tools/lldb-vscode/VSCode.h
===================================================================
--- lldb/tools/lldb-vscode/VSCode.h
+++ lldb/tools/lldb-vscode/VSCode.h
@@ -63,6 +63,8 @@
 typedef llvm::StringMap<FunctionBreakpoint> FunctionBreakpointMap;
 enum class OutputType { Console, Stdout, Stderr, Telemetry };
 
+enum VSCodeBroadcasterBits { eBroadcastBitStopEventThread = 1u << 0 };
+
 struct VSCode {
   InputStream input;
   OutputStream output;
@@ -132,6 +134,24 @@
   void RunPreRunCommands();
   void RunStopCommands();
   void RunExitCommands();
+
+  /// Create a new SBTarget object from the given request arguments.
+  /// \param[in] arguments
+  ///     Launch configuration arguments.
+  ///
+  /// \param[out] error
+  ///     An SBError object that will contain an error description if
+  ///     function failed to create the target.
+  ///
+  /// \return
+  ///     An SBTarget object.
+  lldb::SBTarget CreateTargetFromArguments(
+      const llvm::json::Object &arguments,
+      lldb::SBError &error);
+
+  /// Set given target object as a current target for lldb-vscode and start
+  /// listeing for its breakpoint events.
+  void SetTarget(const lldb::SBTarget target);
 };
 
 extern VSCode g_vsc;
Index: lldb/tools/lldb-vscode/VSCode.cpp
===================================================================
--- lldb/tools/lldb-vscode/VSCode.cpp
+++ lldb/tools/lldb-vscode/VSCode.cpp
@@ -303,4 +303,52 @@
   RunLLDBCommands("Running exitCommands:", exit_commands);
 }
 
+lldb::SBTarget VSCode::CreateTargetFromArguments(
+    const llvm::json::Object &arguments,
+    lldb::SBError &error) {
+  // Grab the name of the program we need to debug and create a target using
+  // the given program as an argument. Executable file can be a source of target
+  // architecture and platform, if they differ from the host. Setting exe path
+  // in launch info is useless because Target.Launch() will not change
+  // architecture and platform, therefore they should be known at the target
+  // creation. We also use target triple and platform from the launch
+  // configuration, if given, since in some cases ELF file doesn't contain
+  // enough information to determine correct arch and platform (or ELF can be
+  // omitted at all), so it is good to leave the user an apportunity to specify
+  // those. Any of those three can be left empty.
+  llvm::StringRef target_triple = GetString(arguments, "targetTriple");
+  llvm::StringRef platform_name = GetString(arguments, "platformName");
+  llvm::StringRef program = GetString(arguments, "program");
+  auto target = this->debugger.CreateTarget(
+    program.data(),
+    target_triple.data(),
+    platform_name.data(),
+    true, // Add dependent modules.
+    error
+  );
+
+  if (error.Fail()) {
+    // Update message if there was an error.
+    error.SetErrorStringWithFormat(
+        "Could not create a target for a program '%s': %s.",
+        program.data(), error.GetCString());
+  }
+
+  return target;
+}
+
+void VSCode::SetTarget(const lldb::SBTarget target) {
+  this->target = target;
+
+  if (target.IsValid()) {
+    // Configure breakpoint event listeners for the target.
+    lldb::SBListener listener = this->debugger.GetListener();
+    listener.StartListeningForEvents(
+        this->target.GetBroadcaster(),
+        lldb::SBTarget::eBroadcastBitBreakpointChanged);
+    listener.StartListeningForEvents(this->broadcaster,
+                                     eBroadcastBitStopEventThread);
+  }
+}
+
 } // namespace lldb_vscode
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to