[Lldb-commits] [lldb] [lldb] add stop-at-user-entry option to process launch (PR #67019)

José Lira Junior via lldb-commits lldb-commits at lists.llvm.org
Wed Oct 4 14:17:16 PDT 2023


https://github.com/junior-jl updated https://github.com/llvm/llvm-project/pull/67019

>From 6de148adcdd1eedea7e23b4e267c6f42bb68bc45 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20L=2E=20Junior?= <jljuniorpb at gmail.com>
Date: Tue, 3 Oct 2023 15:28:45 -0300
Subject: [PATCH 1/3] [lldb] add stop-at-user-entry option to process launch

---
 lldb/include/lldb/Target/Language.h           |  4 ++
 lldb/include/lldb/Target/Target.h             |  2 +
 .../Commands/CommandOptionsProcessLaunch.cpp  | 13 +++++-
 lldb/source/Commands/Options.td               |  4 ++
 .../Language/CPlusPlus/CPlusPlusLanguage.h    |  2 +
 .../Plugins/Language/ObjC/ObjCLanguage.h      |  2 +
 .../ObjCPlusPlus/ObjCPlusPlusLanguage.h       |  2 +
 lldb/source/Target/Target.cpp                 | 42 +++++++++++++++++++
 .../command-process-launch-user-entry.test    |  8 ++++
 9 files changed, 77 insertions(+), 2 deletions(-)
 create mode 100644 lldb/test/Shell/Commands/command-process-launch-user-entry.test

diff --git a/lldb/include/lldb/Target/Language.h b/lldb/include/lldb/Target/Language.h
index a6b9ccaf31b3c42..d53089ba4a59974 100644
--- a/lldb/include/lldb/Target/Language.h
+++ b/lldb/include/lldb/Target/Language.h
@@ -160,6 +160,10 @@ class Language : public PluginInterface {
 
   virtual lldb::LanguageType GetLanguageType() const = 0;
 
+  // Implement this function to return the user-defined entry point name
+  // for the language
+  virtual llvm::StringRef GetUserEntryPointName() const { return {}; }
+
   virtual bool IsTopLevelFunction(Function &function);
 
   virtual bool IsSourceFile(llvm::StringRef file_path) const = 0;
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index e9e531d0e12640a..82a343ee03fb516 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -654,6 +654,8 @@ class Target : public std::enable_shared_from_this<Target>,
 
   lldb::BreakpointSP GetBreakpointByID(lldb::break_id_t break_id);
 
+  lldb::BreakpointSP CreateBreakpointAtUserEntry();
+
   // Use this to create a file and line breakpoint to a given module or all
   // module it is nullptr
   lldb::BreakpointSP CreateBreakpoint(const FileSpecList *containingModules,
diff --git a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
index 85ad8ff5e07132c..3055e4ca45bd230 100644
--- a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
+++ b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
@@ -8,6 +8,7 @@
 
 #include "CommandOptionsProcessLaunch.h"
 
+#include "lldb/Core/Module.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Host/OptionParser.h"
@@ -15,11 +16,13 @@
 #include "lldb/Interpreter/CommandObject.h"
 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
 #include "lldb/Interpreter/OptionArgParser.h"
+#include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Language.h"
 #include "lldb/Target/Platform.h"
 #include "lldb/Target/Target.h"
-
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SetVector.h"
 
 using namespace llvm;
 using namespace lldb;
@@ -38,7 +41,13 @@ Status CommandOptionsProcessLaunch::SetOptionValue(
   case 's': // Stop at program entry point
     launch_info.GetFlags().Set(eLaunchFlagStopAtEntry);
     break;
-
+  case 'm': // Stop at user entry point
+  {
+    TargetSP target_sp =
+        execution_context ? execution_context->GetTargetSP() : TargetSP();
+    target_sp->CreateBreakpointAtUserEntry();
+    break;
+  }
   case 'i': // STDIN for read only
   {
     FileAction action;
diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td
index 04830b8b990efae..dd4cf5c4dc043e7 100644
--- a/lldb/source/Commands/Options.td
+++ b/lldb/source/Commands/Options.td
@@ -675,6 +675,10 @@ let Command = "platform shell" in {
 let Command = "process launch" in {
   def process_launch_stop_at_entry : Option<"stop-at-entry", "s">,
     Desc<"Stop at the entry point of the program when launching a process.">;
+  def process_launch_stop_at_user_entry : Option<"stop-at-user-entry", "m">,
+    Desc<"Stop at the user entry point when launching a process. For C based "
+    "languages this will be the 'main' function, but this might differ for "
+    "other languages.">;
   def process_launch_disable_aslr : Option<"disable-aslr", "A">, Arg<"Boolean">,
     Desc<"Set whether to disable address space layout randomization when launching a process.">;
   def process_launch_plugin : Option<"plugin", "P">, Arg<"Plugin">,
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
index 7712a60b7795951..623d481bf117f48 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
@@ -103,6 +103,8 @@ class CPlusPlusLanguage : public Language {
     return lldb::eLanguageTypeC_plus_plus;
   }
 
+  llvm::StringRef GetUserEntryPointName() const override { return "main"; }
+
   std::unique_ptr<TypeScavenger> GetTypeScavenger() override;
   lldb::TypeCategoryImplSP GetFormatters() override;
 
diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
index bb8057846bb7c30..a50f4b036108d7a 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
@@ -127,6 +127,8 @@ class ObjCLanguage : public Language {
     return lldb::eLanguageTypeObjC;
   }
 
+  llvm::StringRef GetUserEntryPointName() const override { return "main"; }
+
   // Get all possible names for a method. Examples:
   // If method_name is "+[NSString(my_additions) myStringWithCString:]"
   //   variant_names[0] => "+[NSString myStringWithCString:]"
diff --git a/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h b/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
index b7c71b5dbb1c991..1beab9348eb72e8 100644
--- a/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
+++ b/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
@@ -27,6 +27,8 @@ class ObjCPlusPlusLanguage : public Language {
     return lldb::eLanguageTypeObjC_plus_plus;
   }
 
+  llvm::StringRef GetUserEntryPointName() const override { return "main"; }
+
   llvm::StringRef GetNilReferenceSummaryString() override { return "nil"; }
 
   bool IsSourceFile(llvm::StringRef file_path) const override;
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index f197b1b1aa097c3..013d72bda6308be 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -335,6 +335,48 @@ BreakpointSP Target::GetBreakpointByID(break_id_t break_id) {
   return bp_sp;
 }
 
+lldb::BreakpointSP lldb_private::Target::CreateBreakpointAtUserEntry() {
+  TargetSP target_sp = shared_from_this();
+  Status error;
+  ModuleSP main_module_sp = target_sp->GetExecutableModule();
+  FileSpecList shared_lib_filter;
+  shared_lib_filter.Append(main_module_sp->GetFileSpec());
+  llvm::SetVector<std::string, std::vector<std::string>,
+                  std::unordered_set<std::string>>
+      entryPointNamesSet;
+  for (LanguageType lang_type : Language::GetSupportedLanguages()) {
+    Language *lang = Language::FindPlugin(lang_type);
+    if (!lang) {
+      error.SetErrorString("Language not found\n");
+      return lldb::BreakpointSP();
+    }
+    std::string entryPointName = lang->GetUserEntryPointName().str();
+    if (!entryPointName.empty())
+      entryPointNamesSet.insert(entryPointName);
+  }
+  if (entryPointNamesSet.empty()) {
+    error.SetErrorString("No entry point name found\n");
+    return lldb::BreakpointSP();
+  }
+  BreakpointSP bp_sp =
+      target_sp->CreateBreakpoint(&shared_lib_filter,
+                                  nullptr, // containingSourceFiles
+                                  entryPointNamesSet.takeVector(),
+                                  eFunctionNameTypeFull, // func_name_type_mask
+                                  eLanguageTypeUnknown,  // language
+                                  0,                     // offset
+                                  eLazyBoolNo,           // skip_prologue
+                                  false,                 // internal
+                                  false                  // hardware
+      );
+  if (!bp_sp) {
+    error.SetErrorString("Breakpoint creation failed.\n");
+    return lldb::BreakpointSP();
+  }
+  bp_sp->SetOneShot(true);
+  return bp_sp;
+}
+
 BreakpointSP Target::CreateSourceRegexBreakpoint(
     const FileSpecList *containingModules,
     const FileSpecList *source_file_spec_list,
diff --git a/lldb/test/Shell/Commands/command-process-launch-user-entry.test b/lldb/test/Shell/Commands/command-process-launch-user-entry.test
new file mode 100644
index 000000000000000..32ef710fe567439
--- /dev/null
+++ b/lldb/test/Shell/Commands/command-process-launch-user-entry.test
@@ -0,0 +1,8 @@
+# RUN: %clang_host -g %S/Inputs/main.c -o %t
+# RUN: %lldb %t -s %s -o exit | FileCheck %s
+
+process launch -m
+# CHECK-LABEL: process launch -m
+# CHECK: Process {{.*}} stopped
+# CHECK: stop reason = one-shot breakpoint 1
+# CHECK:   frame #0: {{.*}}`main at main.c
\ No newline at end of file

>From 8e0151842db6d261535f26e48a9194e9d90830fc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20L=2E=20Junior?= <jljuniorpb at gmail.com>
Date: Tue, 3 Oct 2023 18:08:39 -0300
Subject: [PATCH 2/3] refactor CreateBreakpointAtUserEntry method

---
 lldb/include/lldb/Target/Target.h             |  2 +-
 .../Commands/CommandOptionsProcessLaunch.cpp  | 10 +++-----
 lldb/source/Target/Target.cpp                 | 25 +++++++++----------
 3 files changed, 16 insertions(+), 21 deletions(-)

diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 82a343ee03fb516..8752b42a9518983 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -654,7 +654,7 @@ class Target : public std::enable_shared_from_this<Target>,
 
   lldb::BreakpointSP GetBreakpointByID(lldb::break_id_t break_id);
 
-  lldb::BreakpointSP CreateBreakpointAtUserEntry();
+  lldb::BreakpointSP CreateBreakpointAtUserEntry(Status &error);
 
   // Use this to create a file and line breakpoint to a given module or all
   // module it is nullptr
diff --git a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
index 3055e4ca45bd230..e3a9cc8aca2356e 100644
--- a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
+++ b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
@@ -37,17 +37,15 @@ Status CommandOptionsProcessLaunch::SetOptionValue(
   Status error;
   const int short_option = g_process_launch_options[option_idx].short_option;
 
+  TargetSP target_sp =
+      execution_context ? execution_context->GetTargetSP() : TargetSP();
   switch (short_option) {
   case 's': // Stop at program entry point
     launch_info.GetFlags().Set(eLaunchFlagStopAtEntry);
     break;
   case 'm': // Stop at user entry point
-  {
-    TargetSP target_sp =
-        execution_context ? execution_context->GetTargetSP() : TargetSP();
-    target_sp->CreateBreakpointAtUserEntry();
+    target_sp->CreateBreakpointAtUserEntry(error);
     break;
-  }
   case 'i': // STDIN for read only
   {
     FileAction action;
@@ -98,8 +96,6 @@ Status CommandOptionsProcessLaunch::SetOptionValue(
     break;
 
   case 'a': {
-    TargetSP target_sp =
-        execution_context ? execution_context->GetTargetSP() : TargetSP();
     PlatformSP platform_sp =
         target_sp ? target_sp->GetPlatform() : PlatformSP();
     launch_info.GetArchitecture() =
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 013d72bda6308be..eaf9e51a7e56a90 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -335,10 +335,9 @@ BreakpointSP Target::GetBreakpointByID(break_id_t break_id) {
   return bp_sp;
 }
 
-lldb::BreakpointSP lldb_private::Target::CreateBreakpointAtUserEntry() {
-  TargetSP target_sp = shared_from_this();
-  Status error;
-  ModuleSP main_module_sp = target_sp->GetExecutableModule();
+lldb::BreakpointSP
+lldb_private::Target::CreateBreakpointAtUserEntry(Status &error) {
+  ModuleSP main_module_sp = GetExecutableModule();
   FileSpecList shared_lib_filter;
   shared_lib_filter.Append(main_module_sp->GetFileSpec());
   llvm::SetVector<std::string, std::vector<std::string>,
@@ -359,15 +358,15 @@ lldb::BreakpointSP lldb_private::Target::CreateBreakpointAtUserEntry() {
     return lldb::BreakpointSP();
   }
   BreakpointSP bp_sp =
-      target_sp->CreateBreakpoint(&shared_lib_filter,
-                                  nullptr, // containingSourceFiles
-                                  entryPointNamesSet.takeVector(),
-                                  eFunctionNameTypeFull, // func_name_type_mask
-                                  eLanguageTypeUnknown,  // language
-                                  0,                     // offset
-                                  eLazyBoolNo,           // skip_prologue
-                                  false,                 // internal
-                                  false                  // hardware
+      CreateBreakpoint(&shared_lib_filter,
+                       nullptr, // containingSourceFiles
+                       entryPointNamesSet.takeVector(),
+                       eFunctionNameTypeFull, // func_name_type_mask
+                       eLanguageTypeUnknown,  // language
+                       0,                     // offset
+                       eLazyBoolNo,           // skip_prologue
+                       false,                 // internal
+                       false                  // hardware
       );
   if (!bp_sp) {
     error.SetErrorString("Breakpoint creation failed.\n");

>From 62edff5495e5a3e7e399a93f47ab4bc3d07ecdf6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20L=2E=20Junior?= <jljuniorpb at gmail.com>
Date: Wed, 4 Oct 2023 18:16:59 -0300
Subject: [PATCH 3/3] remove unecessary includes

---
 lldb/source/Commands/CommandOptionsProcessLaunch.cpp | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
index e3a9cc8aca2356e..b1c13d4df79e0ee 100644
--- a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
+++ b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp
@@ -8,7 +8,6 @@
 
 #include "CommandOptionsProcessLaunch.h"
 
-#include "lldb/Core/Module.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Host/OptionParser.h"
@@ -16,13 +15,11 @@
 #include "lldb/Interpreter/CommandObject.h"
 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
 #include "lldb/Interpreter/OptionArgParser.h"
-#include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Language.h"
 #include "lldb/Target/Platform.h"
 #include "lldb/Target/Target.h"
+
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SetVector.h"
 
 using namespace llvm;
 using namespace lldb;



More information about the lldb-commits mailing list