Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reapply LLDB-Telemetry TargetInfo branch (pr/127834) #132043

Merged
merged 8 commits into from
Mar 20, 2025

Conversation

oontvoo
Copy link
Member

@oontvoo oontvoo commented Mar 19, 2025

New changes: add check to avoid accessing invalid obj

@oontvoo oontvoo requested a review from labath March 19, 2025 14:46
@oontvoo oontvoo requested a review from JDevlieghere as a code owner March 19, 2025 14:46
@llvmbot llvmbot added the lldb label Mar 19, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 19, 2025

@llvm/pr-subscribers-lldb

Author: Vy Nguyen (oontvoo)

Changes

New changes: add check to avoid accessing invalid obj


Full diff: https://github.com/llvm/llvm-project/pull/132043.diff

5 Files Affected:

  • (modified) lldb/include/lldb/Core/Telemetry.h (+68-6)
  • (modified) lldb/source/Core/Telemetry.cpp (+23-2)
  • (modified) lldb/source/Interpreter/CommandInterpreter.cpp (+1-1)
  • (modified) lldb/source/Target/Process.cpp (+23)
  • (modified) lldb/source/Target/Target.cpp (+21)
diff --git a/lldb/include/lldb/Core/Telemetry.h b/lldb/include/lldb/Core/Telemetry.h
index 29ec36b2d64d1..28897f283dc55 100644
--- a/lldb/include/lldb/Core/Telemetry.h
+++ b/lldb/include/lldb/Core/Telemetry.h
@@ -23,9 +23,12 @@
 #include <atomic>
 #include <chrono>
 #include <ctime>
+#include <functional>
 #include <memory>
 #include <optional>
 #include <string>
+#include <type_traits>
+#include <utility>
 
 namespace lldb_private {
 namespace telemetry {
@@ -46,12 +49,18 @@ struct LLDBConfig : public ::llvm::telemetry::Config {
 // Specifically:
 //  - Length: 8 bits
 //  - First two bits (MSB) must be 11 - the common prefix
+//  - Last two bits (LSB) are reserved for grand-children of LLDBTelemetryInfo
 // If any of the subclass has descendents, those descendents
-// must have their LLDBEntryKind in the similar form (ie., share common prefix)
+// must have their LLDBEntryKind in the similar form (ie., share common prefix
+// and differ by the last two bits)
 struct LLDBEntryKind : public ::llvm::telemetry::EntryKind {
-  static const llvm::telemetry::KindType BaseInfo = 0b11000000;
-  static const llvm::telemetry::KindType CommandInfo = 0b11010000;
-  static const llvm::telemetry::KindType DebuggerInfo = 0b11000100;
+  // clang-format off
+  static const llvm::telemetry::KindType BaseInfo        = 0b11000000;
+  static const llvm::telemetry::KindType CommandInfo     = 0b11010000;
+  static const llvm::telemetry::KindType DebuggerInfo    = 0b11001000;
+  static const llvm::telemetry::KindType ExecModuleInfo  = 0b11000100;
+  static const llvm::telemetry::KindType ProcessExitInfo = 0b11001100;
+  // clang-format on
 };
 
 /// Defines a convenient type for timestamp of various events.
@@ -89,7 +98,7 @@ struct CommandInfo : public LLDBBaseTelemetryInfo {
   /// session. Necessary because we'd send off an entry right before a command's
   /// execution and another right after. This is to avoid losing telemetry if
   /// the command does not execute successfully.
-  uint64_t command_id;
+  uint64_t command_id = 0;
   /// The command name(eg., "breakpoint set")
   std::string command_name;
   /// These two fields are not collected by default due to PII risks.
@@ -116,7 +125,7 @@ struct CommandInfo : public LLDBBaseTelemetryInfo {
 
   void serialize(llvm::telemetry::Serializer &serializer) const override;
 
-  static uint64_t GetNextId();
+  static uint64_t GetNextID();
 
 private:
   // We assign each command (in the same session) a unique id so that their
@@ -146,6 +155,59 @@ struct DebuggerInfo : public LLDBBaseTelemetryInfo {
   void serialize(llvm::telemetry::Serializer &serializer) const override;
 };
 
+struct ExecutableModuleInfo : public LLDBBaseTelemetryInfo {
+  lldb::ModuleSP exec_mod;
+  /// The same as the executable-module's UUID.
+  UUID uuid;
+  /// PID of the process owned by this target.
+  lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+  /// The triple of this executable module.
+  std::string triple;
+
+  /// If true, this entry was emitted at the beginning of an event (eg., before
+  /// the executable is set). Otherwise, it was emitted at the end of an
+  /// event (eg., after the module and any dependency were loaded.)
+  bool is_start_entry = false;
+
+  ExecutableModuleInfo() = default;
+
+  llvm::telemetry::KindType getKind() const override {
+    return LLDBEntryKind::ExecModuleInfo;
+  }
+
+  static bool classof(const TelemetryInfo *T) {
+    // Subclasses of this is also acceptable
+    return (T->getKind() & LLDBEntryKind::ExecModuleInfo) ==
+           LLDBEntryKind::ExecModuleInfo;
+  }
+  void serialize(llvm::telemetry::Serializer &serializer) const override;
+};
+
+/// Describes an exit status.
+struct ExitDescription {
+  int exit_code;
+  std::string description;
+};
+
+struct ProcessExitInfo : public LLDBBaseTelemetryInfo {
+  // The executable-module's UUID.
+  UUID module_uuid;
+  lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+  bool is_start_entry = false;
+  std::optional<ExitDescription> exit_desc;
+
+  llvm::telemetry::KindType getKind() const override {
+    return LLDBEntryKind::ProcessExitInfo;
+  }
+
+  static bool classof(const TelemetryInfo *T) {
+    // Subclasses of this is also acceptable
+    return (T->getKind() & LLDBEntryKind::ProcessExitInfo) ==
+           LLDBEntryKind::ProcessExitInfo;
+  }
+  void serialize(llvm::telemetry::Serializer &serializer) const override;
+};
+
 /// The base Telemetry manager instance in LLDB.
 /// This class declares additional instrumentation points
 /// applicable to LLDB.
diff --git a/lldb/source/Core/Telemetry.cpp b/lldb/source/Core/Telemetry.cpp
index be929a644706e..62ebdfc027d81 100644
--- a/lldb/source/Core/Telemetry.cpp
+++ b/lldb/source/Core/Telemetry.cpp
@@ -76,6 +76,9 @@ void CommandInfo::serialize(Serializer &serializer) const {
     serializer.write("error_data", error_data.value());
 }
 
+std::atomic<uint64_t> CommandInfo::g_command_id_seed = 1;
+uint64_t CommandInfo::GetNextID() { return g_command_id_seed.fetch_add(1); }
+
 void DebuggerInfo::serialize(Serializer &serializer) const {
   LLDBBaseTelemetryInfo::serialize(serializer);
 
@@ -83,8 +86,26 @@ void DebuggerInfo::serialize(Serializer &serializer) const {
   serializer.write("is_exit_entry", is_exit_entry);
 }
 
-std::atomic<uint64_t> CommandInfo::g_command_id_seed = 0;
-uint64_t CommandInfo::GetNextId() { return g_command_id_seed.fetch_add(1); }
+void ExecutableModuleInfo::serialize(Serializer &serializer) const {
+  LLDBBaseTelemetryInfo::serialize(serializer);
+
+  serializer.write("uuid", uuid.GetAsString());
+  serializer.write("pid", pid);
+  serializer.write("triple", triple);
+  serializer.write("is_start_entry", is_start_entry);
+}
+
+void ProcessExitInfo::serialize(Serializer &serializer) const {
+  LLDBBaseTelemetryInfo::serialize(serializer);
+
+  serializer.write("module_uuid", module_uuid.GetAsString());
+  serializer.write("pid", pid);
+  serializer.write("is_start_entry", is_start_entry);
+  if (exit_desc.has_value()) {
+    serializer.write("exit_code", exit_desc->exit_code);
+    serializer.write("exit_desc", exit_desc->description);
+  }
+}
 
 TelemetryManager::TelemetryManager(std::unique_ptr<LLDBConfig> config)
     : m_config(std::move(config)), m_id(MakeUUID()) {}
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index 8e70922b9bb8d..e0bf5520e16ef 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -1891,7 +1891,7 @@ bool CommandInterpreter::HandleCommand(const char *command_line,
       telemetry::TelemetryManager::GetInstance()
           ->GetConfig()
           ->detailed_command_telemetry;
-  const int command_id = telemetry::CommandInfo::GetNextId();
+  const int command_id = telemetry::CommandInfo::GetNextID();
 
   std::string command_string(command_line);
   std::string original_command_string(command_string);
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 335991018070c..43d7b4625310b 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -22,6 +22,7 @@
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/Progress.h"
+#include "lldb/Core/Telemetry.h"
 #include "lldb/Expression/DiagnosticManager.h"
 #include "lldb/Expression/DynamicCheckerFunctions.h"
 #include "lldb/Expression/UserExpression.h"
@@ -1066,6 +1067,28 @@ const char *Process::GetExitDescription() {
 bool Process::SetExitStatus(int status, llvm::StringRef exit_string) {
   // Use a mutex to protect setting the exit status.
   std::lock_guard<std::mutex> guard(m_exit_status_mutex);
+  telemetry::ScopedDispatcher<telemetry::ProcessExitInfo> helper;
+
+  // Find the executable-module's UUID, if available.
+  UUID module_uuid;
+  TargetSP target_sp(Debugger::FindTargetWithProcessID(m_pid));
+   if (target_sp) {
+    helper.SetDebugger(&target_sp->GetDebugger());
+    if (ModuleSP mod = target_sp->GetExecutableModule())
+      module_uuid = mod->GetUUID();
+   }
+
+  helper.DispatchNow([&](telemetry::ProcessExitInfo *info) {
+    info->module_uuid = module_uuid;
+    info->pid = m_pid;
+    info->is_start_entry = true;
+    info->exit_desc = {status, exit_string.str()};
+  });
+
+  helper.DispatchOnExit([&](telemetry::ProcessExitInfo *info) {
+    info->module_uuid = module_uuid;
+    info->pid = m_pid;
+  });
 
   Log *log(GetLog(LLDBLog::State | LLDBLog::Process));
   LLDB_LOG(log, "(plugin = {0} status = {1} ({1:x8}), description=\"{2}\")",
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index bbc2110dada5b..c26bca546891e 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -24,6 +24,7 @@
 #include "lldb/Core/Section.h"
 #include "lldb/Core/SourceManager.h"
 #include "lldb/Core/StructuredDataImpl.h"
+#include "lldb/Core/Telemetry.h"
 #include "lldb/DataFormatters/FormatterSection.h"
 #include "lldb/Expression/DiagnosticManager.h"
 #include "lldb/Expression/ExpressionVariable.h"
@@ -1559,10 +1560,30 @@ void Target::DidExec() {
 
 void Target::SetExecutableModule(ModuleSP &executable_sp,
                                  LoadDependentFiles load_dependent_files) {
+  telemetry::ScopedDispatcher<telemetry::ExecutableModuleInfo> helper(
+      &m_debugger);
   Log *log = GetLog(LLDBLog::Target);
   ClearModules(false);
 
   if (executable_sp) {
+    lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+    if (ProcessSP proc = GetProcessSP())
+      pid = proc->GetID();
+
+    helper.DispatchNow([&](telemetry::ExecutableModuleInfo *info) {
+      info->exec_mod = executable_sp;
+      info->uuid = executable_sp->GetUUID();
+      info->pid = pid;
+      info->triple = executable_sp->GetArchitecture().GetTriple().getTriple();
+      info->is_start_entry = true;
+    });
+
+    helper.DispatchOnExit([&](telemetry::ExecutableModuleInfo *info) {
+      info->exec_mod = executable_sp;
+      info->uuid = executable_sp->GetUUID();
+      info->pid = pid;
+    });
+
     ElapsedTime elapsed(m_stats.GetCreateTime());
     LLDB_SCOPED_TIMERF("Target::SetExecutableModule (executable = '%s')",
                        executable_sp->GetFileSpec().GetPath().c_str());

Copy link

github-actions bot commented Mar 19, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@oontvoo
Copy link
Member Author

oontvoo commented Mar 19, 2025

@labath Hi, friendly ping? thanks

@oontvoo
Copy link
Member Author

oontvoo commented Mar 20, 2025

@labath Hi, friendly ping? thanks

Sorry - ignore this ping, i put the comment on the wrong patch. meant to ping on #129728

@oontvoo
Copy link
Member Author

oontvoo commented Mar 20, 2025

All checks ✅ passed so I'm going to merge this

@oontvoo oontvoo merged commit ff21b50 into llvm:main Mar 20, 2025
7 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants