[Lldb-commits] [lldb] 1e82b20 - [lldb/Target] Add ability to set a label to targets

Med Ismail Bennani via lldb-commits lldb-commits at lists.llvm.org
Tue Jun 6 10:58:50 PDT 2023


Author: Med Ismail Bennani
Date: 2023-06-06T10:58:34-07:00
New Revision: 1e82b20118e31bd6c3844a84e03f701997a9b7ed

URL: https://github.com/llvm/llvm-project/commit/1e82b20118e31bd6c3844a84e03f701997a9b7ed
DIFF: https://github.com/llvm/llvm-project/commit/1e82b20118e31bd6c3844a84e03f701997a9b7ed.diff

LOG: [lldb/Target] Add ability to set a label to targets

This patch add the ability for the user to set a label for a target.

This can be very useful when debugging targets with the same executables
in the same session.

Labels can be set either at the target creation in the command
interpreter or at any time using the SBAPI.

Target labels show up in the `target list` output, following the target
index, and they also allow the user to switch targets using them.

rdar://105016191

Differential Revision: https://reviews.llvm.org/D151859

Signed-off-by: Med Ismail Bennani <ismail at bennani.ma>

Added: 
    lldb/test/Shell/Target/target-label.test

Modified: 
    lldb/include/lldb/API/SBTarget.h
    lldb/include/lldb/Target/Target.h
    lldb/include/lldb/Target/TargetList.h
    lldb/source/API/SBTarget.cpp
    lldb/source/Commands/CommandObjectTarget.cpp
    lldb/source/Target/Target.cpp
    lldb/source/Target/TargetList.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h
index e7dc76396fb68..ea5212ea56d93 100644
--- a/lldb/include/lldb/API/SBTarget.h
+++ b/lldb/include/lldb/API/SBTarget.h
@@ -328,6 +328,10 @@ class LLDB_API SBTarget {
   
   const char *GetABIName();
 
+  const char *GetLabel() const;
+
+  SBError SetLabel(const char *label);
+
   /// Architecture data byte width accessor
   ///
   /// \return

diff  --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index d15f0705630ce..eb5e87dcacb39 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -554,6 +554,17 @@ class Target : public std::enable_shared_from_this<Target>,
 
   bool IsDummyTarget() const { return m_is_dummy_target; }
 
+  const std::string &GetLabel() const { return m_label; }
+
+  /// Set a label for a target.
+  ///
+  /// The label cannot be used by another target or be only integral.
+  ///
+  /// \return
+  ///     The label for this target or an error if the label didn't match the
+  ///     requirements.
+  llvm::Error SetLabel(llvm::StringRef label);
+
   /// Find a binary on the system and return its Module,
   /// or return an existing Module that is already in the Target.
   ///
@@ -1520,6 +1531,7 @@ class Target : public std::enable_shared_from_this<Target>,
   /// detect that code is running on the private state thread.
   std::recursive_mutex m_private_mutex;
   Arch m_arch;
+  std::string m_label;
   ModuleList m_images; ///< The list of images for this process (shared
                        /// libraries and anything dynamically loaded).
   SectionLoadHistory m_section_load_history;

diff  --git a/lldb/include/lldb/Target/TargetList.h b/lldb/include/lldb/Target/TargetList.h
index 65781a4811fd8..a1d5a84511e02 100644
--- a/lldb/include/lldb/Target/TargetList.h
+++ b/lldb/include/lldb/Target/TargetList.h
@@ -115,7 +115,7 @@ class TargetList : public Broadcaster {
   ///     in \a target_sp which can then be properly released.
   bool DeleteTarget(lldb::TargetSP &target_sp);
 
-  int GetNumTargets() const;
+  size_t GetNumTargets() const;
 
   lldb::TargetSP GetTargetAtIndex(uint32_t index) const;
 

diff  --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index 53af5b1d7a477..53b1bd6a535d6 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -1601,6 +1601,26 @@ const char *SBTarget::GetABIName() {
   return const_name.GetCString();
 }
 
+const char *SBTarget::GetLabel() const {
+  LLDB_INSTRUMENT_VA(this);
+
+  TargetSP target_sp(GetSP());
+  if (!target_sp)
+    return nullptr;
+
+  return ConstString(target_sp->GetLabel().data()).AsCString();
+}
+
+SBError SBTarget::SetLabel(const char *label) {
+  LLDB_INSTRUMENT_VA(this, label);
+
+  TargetSP target_sp(GetSP());
+  if (!target_sp)
+    return Status("Couldn't get internal target object.");
+
+  return Status(target_sp->SetLabel(label));
+}
+
 uint32_t SBTarget::GetDataByteSize() {
   LLDB_INSTRUMENT_VA(this);
 

diff  --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index e3bb7fc06ed1a..0088211c49e37 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -82,8 +82,14 @@ static void DumpTargetInfo(uint32_t target_idx, Target *target,
   if (!exe_valid)
     ::strcpy(exe_path, "<none>");
 
-  strm.Printf("%starget #%u: %s", prefix_cstr ? prefix_cstr : "", target_idx,
-              exe_path);
+  std::string formatted_label = "";
+  const std::string &label = target->GetLabel();
+  if (!label.empty()) {
+    formatted_label = " (" + label + ")";
+  }
+
+  strm.Printf("%starget #%u%s: %s", prefix_cstr ? prefix_cstr : "", target_idx,
+              formatted_label.data(), exe_path);
 
   uint32_t properties = 0;
   if (target_arch.IsValid()) {
@@ -209,6 +215,8 @@ class CommandObjectTargetCreate : public CommandObjectParsed {
         m_platform_options(true), // Include the --platform option.
         m_core_file(LLDB_OPT_SET_1, false, "core", 'c', 0, eArgTypeFilename,
                     "Fullpath to a core file to use for this target."),
+        m_label(LLDB_OPT_SET_1, false, "label", 'l', 0, eArgTypeName,
+                "Optional name for this target.", nullptr),
         m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
                       eArgTypeFilename,
                       "Fullpath to a stand alone debug "
@@ -234,6 +242,7 @@ class CommandObjectTargetCreate : public CommandObjectParsed {
     m_option_group.Append(&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
     m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1);
     m_option_group.Append(&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+    m_option_group.Append(&m_label, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
     m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
     m_option_group.Append(&m_remote_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
     m_option_group.Append(&m_add_dependents, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
@@ -303,6 +312,14 @@ class CommandObjectTargetCreate : public CommandObjectParsed {
         return false;
       }
 
+      const llvm::StringRef label =
+          m_label.GetOptionValue().GetCurrentValueAsRef();
+      if (!label.empty()) {
+        if (auto E = target_sp->SetLabel(label))
+          result.SetError(std::move(E));
+        return false;
+      }
+
       auto on_error = llvm::make_scope_exit(
           [&target_list = debugger.GetTargetList(), &target_sp]() {
             target_list.DeleteTarget(target_sp);
@@ -455,6 +472,7 @@ class CommandObjectTargetCreate : public CommandObjectParsed {
   OptionGroupArchitecture m_arch_option;
   OptionGroupPlatform m_platform_options;
   OptionGroupFile m_core_file;
+  OptionGroupString m_label;
   OptionGroupFile m_symbol_file;
   OptionGroupFile m_remote_file;
   OptionGroupDependents m_add_dependents;
@@ -503,11 +521,11 @@ class CommandObjectTargetSelect : public CommandObjectParsed {
 protected:
   bool DoExecute(Args &args, CommandReturnObject &result) override {
     if (args.GetArgumentCount() == 1) {
-      const char *target_idx_arg = args.GetArgumentAtIndex(0);
-      uint32_t target_idx;
-      if (llvm::to_integer(target_idx_arg, target_idx)) {
-        TargetList &target_list = GetDebugger().GetTargetList();
-        const uint32_t num_targets = target_list.GetNumTargets();
+      const char *target_identifier = args.GetArgumentAtIndex(0);
+      uint32_t target_idx = LLDB_INVALID_INDEX32;
+      TargetList &target_list = GetDebugger().GetTargetList();
+      const uint32_t num_targets = target_list.GetNumTargets();
+      if (llvm::to_integer(target_identifier, target_idx)) {
         if (target_idx < num_targets) {
           target_list.SetSelectedTarget(target_idx);
           Stream &strm = result.GetOutputStream();
@@ -526,8 +544,26 @@ class CommandObjectTargetSelect : public CommandObjectParsed {
           }
         }
       } else {
-        result.AppendErrorWithFormat("invalid index string value '%s'\n",
-                                     target_idx_arg);
+        for (size_t i = 0; i < num_targets; i++) {
+          if (TargetSP target_sp = target_list.GetTargetAtIndex(i)) {
+            const std::string &label = target_sp->GetLabel();
+            if (!label.empty() && label == target_identifier) {
+              target_idx = i;
+              break;
+            }
+          }
+        }
+
+        if (target_idx != LLDB_INVALID_INDEX32) {
+          target_list.SetSelectedTarget(target_idx);
+          Stream &strm = result.GetOutputStream();
+          bool show_stopped_process_status = false;
+          DumpTargetList(target_list, show_stopped_process_status, strm);
+          result.SetStatus(eReturnStatusSuccessFinishResult);
+        } else {
+          result.AppendErrorWithFormat("invalid index string value '%s'\n",
+                                       target_identifier);
+        }
       }
     } else {
       result.AppendError(
@@ -576,7 +612,7 @@ class CommandObjectTargetDelete : public CommandObjectParsed {
     TargetSP target_sp;
 
     if (m_all_option.GetOptionValue()) {
-      for (int i = 0; i < target_list.GetNumTargets(); ++i)
+      for (size_t i = 0; i < target_list.GetNumTargets(); ++i)
         delete_target_list.push_back(target_list.GetTargetAtIndex(i));
     } else if (argc > 0) {
       const uint32_t num_targets = target_list.GetNumTargets();

diff  --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 0cc66ee0dc4c1..9f4a18eb68aa2 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -69,6 +69,7 @@
 #include <memory>
 #include <mutex>
 #include <optional>
+#include <sstream>
 
 using namespace lldb;
 using namespace lldb_private;
@@ -2536,6 +2537,27 @@ void Target::SetDefaultArchitecture(const ArchSpec &arch) {
   Target::GetGlobalProperties().SetDefaultArchitecture(arch);
 }
 
+llvm::Error Target::SetLabel(llvm::StringRef label) {
+  size_t n = LLDB_INVALID_INDEX32;
+  if (llvm::to_integer(label, n))
+    return llvm::make_error<llvm::StringError>(
+        "Cannot use integer as target label.", llvm::inconvertibleErrorCode());
+  TargetList &targets = GetDebugger().GetTargetList();
+  for (size_t i = 0; i < targets.GetNumTargets(); i++) {
+    TargetSP target_sp = targets.GetTargetAtIndex(i);
+    if (target_sp && target_sp->GetLabel() == label) {
+        return llvm::make_error<llvm::StringError>(
+            llvm::formatv(
+                "Cannot use label '{0}' since it's set in target #{1}.", label,
+                i),
+            llvm::inconvertibleErrorCode());
+    }
+  }
+
+  m_label = label.str();
+  return llvm::Error::success();
+}
+
 Target *Target::GetTargetFromContexts(const ExecutionContext *exe_ctx_ptr,
                                       const SymbolContext *sc_ptr) {
   // The target can either exist in the "process" of ExecutionContext, or in

diff  --git a/lldb/source/Target/TargetList.cpp b/lldb/source/Target/TargetList.cpp
index 8ce2ae8c2898e..1424fd05f2157 100644
--- a/lldb/source/Target/TargetList.cpp
+++ b/lldb/source/Target/TargetList.cpp
@@ -489,7 +489,7 @@ uint32_t TargetList::SignalIfRunning(lldb::pid_t pid, int signo) {
   return num_signals_sent;
 }
 
-int TargetList::GetNumTargets() const {
+size_t TargetList::GetNumTargets() const {
   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
   return m_target_list.size();
 }

diff  --git a/lldb/test/Shell/Target/target-label.test b/lldb/test/Shell/Target/target-label.test
new file mode 100644
index 0000000000000..7194f4b558f34
--- /dev/null
+++ b/lldb/test/Shell/Target/target-label.test
@@ -0,0 +1,38 @@
+# RUN: %lldb -b -o 'settings set interpreter.stop-command-source-on-error false' -s %s 2>&1 | FileCheck %s
+
+target create -l "ls" /bin/ls
+target list
+# CHECK: * target #0 (ls): /bin/ls
+
+script lldb.target.SetLabel("")
+target list
+# CHECK: * target #0: /bin/ls
+
+target create -l "cat" /bin/cat
+target list
+# CHECK: target #0: /bin/ls
+# CHECK-NEXT: * target #1 (cat): /bin/cat
+
+target create -l "cat" /bin/cat
+# CHECK: Cannot use label 'cat' since it's set in target #1.
+
+target create -l 42 /bin/cat
+# CHECK: error: Cannot use integer as target label.
+
+target select 0
+# CHECK: * target #0: /bin/ls
+# CHECK-NEXT: target #1 (cat): /bin/cat
+
+target select cat
+# CHECK: target #0: /bin/ls
+# CHECK-NEXT: * target #1 (cat): /bin/cat
+
+script lldb.target.GetLabel()
+# CHECK: 'cat'
+
+script lldb.debugger.GetTargetAtIndex(0).SetLabel('Not cat')
+# CHECK: success
+
+target list
+# CHECK: target #0 (Not cat): /bin/ls
+# CHECK-NEXT: * target #1 (cat): /bin/cat


        


More information about the lldb-commits mailing list