anton.kolesov updated this revision to Diff 243828.
anton.kolesov retitled this revision from "[lldb] Set executable module when 
adding modules to the Target" to "[lldb-vscode] Ensure that target matches the 
executable file".
anton.kolesov edited the summary of this revision.
anton.kolesov added a comment.

Reverted to the original idea of modifying lldb-vscode. Unlike first version, 
this commit also modifies request_attach to have the same behaviour. Two new 
properties are added to request arguments: "targetTriple" and "platformName" to 
specify values to respective arguments of SBDebugger::CreateTarget().


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/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
@@ -110,6 +110,16 @@
   return newsockfd;
 }
 
+void AddBreakpointListener(VSCode &vscode) {
+  // Configure breakpoint event listeners for the target.
+  lldb::SBListener listener = vscode.debugger.GetListener();
+  listener.StartListeningForEvents(
+      vscode.target.GetBroadcaster(),
+      lldb::SBTarget::eBroadcastBitBreakpointChanged);
+  listener.StartListeningForEvents(vscode.broadcaster,
+                                   eBroadcastBitStopEventThread);
+}
+
 std::vector<const char *> MakeArgv(const llvm::ArrayRef<std::string> &strs) {
   // Create and return an array of "const char *", one for each C string in
   // "strs" and terminate the list with a NULL. This can be used for argument
@@ -512,27 +522,45 @@
   // 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;
-    }
+  // 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");
+  lldb::SBError status;
+  g_vsc.target = g_vsc.debugger.CreateTarget(
+    program.data(),
+    target_triple.data(),
+    platform_name.data(),
+    true, // Add dependent modules.
+    status
+  );
+
+  if (!g_vsc.target.IsValid()) {
+    response["success"] = llvm::json::Value(false);
+    std::string errmsg;
+    if (status.Fail())
+      errmsg = llvm::formatv(
+          "Could not create a target for a program '{0}': {1}.",
+          program, status.GetCString());
+    else
+      errmsg = llvm::formatv("Could not create a target for a program '{0}'.",
+          program);
+    EmplaceSafeString(response, "message", errmsg);
+    g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+    return;
   }
 
+  AddBreakpointListener(g_vsc);
+
   const bool detatchOnError = GetBoolean(arguments, "detachOnError", false);
   g_vsc.launch_info.SetDetachOnError(detatchOnError);
 
@@ -951,7 +979,7 @@
   for (size_t i = 0; i < count; i++) {
     std::string match = matches.GetStringAtIndex(i);
     std::string description = descriptions.GetStringAtIndex(i);
-    
+
     llvm::json::Object item;
 
     llvm::StringRef match_ref = match;
@@ -1217,13 +1245,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);
@@ -1261,7 +1282,7 @@
   // The debug adapter supports the stepInTargetsRequest.
   body.try_emplace("supportsStepInTargetsRequest", false);
   // We need to improve the current implementation of completions in order to
-  // enable it again. For some context, this is how VSCode works: 
+  // enable it again. For some context, this is how VSCode works:
   // - VSCode sends a completion request whenever chars are added, the user
   //   triggers completion manually via CTRL-space or similar mechanisms, but
   //   not when there's a deletion. Besides, VSCode doesn't let us know which
@@ -1365,39 +1386,59 @@
 
   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();
 
+  // 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");
+  lldb::SBError status;
+  g_vsc.target = g_vsc.debugger.CreateTarget(
+    program.data(),
+    target_triple.data(),
+    platform_name.data(),
+    true, // Add dependent modules.
+    status
+  );
+
+  if (!g_vsc.target.IsValid()) {
+    response["success"] = llvm::json::Value(false);
+    std::string errmsg;
+    if (status.Fail())
+      errmsg = llvm::formatv(
+          "Could not create a target for a program '{0}': {1}.",
+          program, status.GetCString());
+    else
+      errmsg = llvm::formatv("Could not create a target for a program '{0}'.",
+        program);
+    EmplaceSafeString(response, "message", errmsg);
+    g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+    return;
+  }
+
+  AddBreakpointListener(g_vsc);
+
+  // 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");
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to