This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGff15efc1a701: [trace][intelpt] Support system-wide tracing 
[16] - Create threads… (authored by Walter Erquinigo <wall...@fb.com>).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D127001

Files:
  lldb/include/lldb/Target/Trace.h
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h
  lldb/source/Target/Trace.cpp
  lldb/test/API/commands/trace/TestTraceLoad.py
  
lldb/test/API/commands/trace/intelpt-multi-core-trace/trace_missing_threads.json

Index: lldb/test/API/commands/trace/intelpt-multi-core-trace/trace_missing_threads.json
===================================================================
--- /dev/null
+++ lldb/test/API/commands/trace/intelpt-multi-core-trace/trace_missing_threads.json
@@ -0,0 +1,44 @@
+{
+  "cores": [
+    {
+      "contextSwitchTrace": "/tmp/trace8/cores/45.perf_context_switch_trace",
+      "coreId": 45,
+      "traceBuffer": "/tmp/trace8/cores/45.intelpt_trace"
+    },
+    {
+      "contextSwitchTrace": "/tmp/trace8/cores/51.perf_context_switch_trace",
+      "coreId": 51,
+      "traceBuffer": "/tmp/trace8/cores/51.intelpt_trace"
+    }
+  ],
+  "cpuInfo": {
+    "family": 6,
+    "model": 85,
+    "stepping": 4,
+    "vendor": "GenuineIntel"
+  },
+  "processes": [
+    {
+      "modules": [
+        {
+          "file": "modules/m.out",
+          "systemPath": "/tmp/m.out",
+          "loadAddress": 4194304,
+          "uuid": "AEFB0D59-233F-80FF-6D3C-4DED498534CF-11017B3B"
+        }
+      ],
+      "pid": 3497234,
+      "threads": [
+        {
+          "tid": 3497234
+        }
+      ]
+    }
+  ],
+  "tscPerfZeroConversion": {
+    "timeMult": 1076264588,
+    "timeShift": 31,
+    "timeZero": 18433473881008870804
+  },
+  "type": "intel-pt"
+}
Index: lldb/test/API/commands/trace/TestTraceLoad.py
===================================================================
--- lldb/test/API/commands/trace/TestTraceLoad.py
+++ lldb/test/API/commands/trace/TestTraceLoad.py
@@ -21,6 +21,18 @@
           substrs=["67910: [tsc=0x008fb5211bfdf270] 0x0000000000400bd7    addl   $0x1, -0x4(%rbp)",
                    "m.out`bar() + 26 at multi_thread.cpp:20:6"])
 
+    def testLoadMultiCoreTraceWithMissingThreads(self):
+        src_dir = self.getSourceDir()
+        trace_definition_file = os.path.join(src_dir, "intelpt-multi-core-trace", "trace_missing_threads.json")
+        self.expect("trace load -v " + trace_definition_file, substrs=["intel-pt"])
+        self.expect("thread trace dump instructions 3 -t",
+          substrs=["19521: [tsc=0x008fb5211c143fd8] error: expected tracing enabled event",
+                   "m.out`foo() + 65 at multi_thread.cpp:12:21",
+                   "19520: [tsc=0x008fb5211bfbc69e] 0x0000000000400ba7    jg     0x400bb3"])
+        self.expect("thread trace dump instructions 2 -t",
+          substrs=["67910: [tsc=0x008fb5211bfdf270] 0x0000000000400bd7    addl   $0x1, -0x4(%rbp)",
+                   "m.out`bar() + 26 at multi_thread.cpp:20:6"])
+
     def testLoadTrace(self):
         src_dir = self.getSourceDir()
         trace_definition_file = os.path.join(src_dir, "intelpt-trace", "trace.json")
Index: lldb/source/Target/Trace.cpp
===================================================================
--- lldb/source/Target/Trace.cpp
+++ lldb/source/Target/Trace.cpp
@@ -449,3 +449,14 @@
     return *m_cores;
   return {};
 }
+
+std::vector<Process *> Trace::GetTracedProcesses() const {
+  std::vector<Process *> processes;
+
+  for (Process *proc : m_postmortem_processes)
+    processes.push_back(proc);
+
+  if (m_live_process)
+    processes.push_back(m_live_process);
+  return processes;
+}
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h
@@ -52,7 +52,7 @@
   ///   errors, return a null pointer.
   llvm::Expected<lldb::TraceSP> Parse();
 
-  lldb::TraceSP
+  llvm::Expected<lldb::TraceSP>
   CreateTraceIntelPTInstance(JSONTraceSession &session,
                              std::vector<ParsedProcess> &parsed_processes);
 
@@ -64,6 +64,11 @@
   lldb::ThreadPostMortemTraceSP ParseThread(lldb::ProcessSP &process_sp,
                                             const JSONThread &thread);
 
+  /// Create the corresponding Threads and Process objects given the JSON
+  /// process definition.
+  ///
+  /// \param[in] process
+  ///   The JSON process definition
   llvm::Expected<ParsedProcess> ParseProcess(const JSONProcess &process);
 
   llvm::Error ParseModule(lldb::TargetSP &target_sp, const JSONModule &module);
@@ -82,6 +87,8 @@
   llvm::Error CreateJSONError(llvm::json::Path::Root &root,
                               const llvm::json::Value &value);
 
+  /// Create the corresponding Process, Thread and Module objects given this
+  /// session file.
   llvm::Expected<std::vector<ParsedProcess>>
   ParseSessionFile(const JSONTraceSession &session);
 
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
@@ -164,6 +164,10 @@
       "triple"?: string,
           // Optional clang/llvm target triple.
       "threads": [
+          // A list of known threads for the given process. When context switch
+          // data is provided, LLDB will automatically create threads for the
+          // this process whenever it finds new threads when traversing the
+          // context switches.
         {
           "tid": integer,
           "traceBuffer"?: string
@@ -205,6 +209,10 @@
     "timeShift": integer,
     "timeZero": integer,
   }
+  "dontCreateThreadsFromContextSwitches"?: boolean,
+    // If this is true, then the automatic creation of threads from context switch
+    // data is disabled, and thus only the threads provided in the "processes.threads"
+    // section will be created.
 }
 
 Notes:
@@ -217,7 +225,7 @@
   return schema;
 }
 
-TraceSP TraceIntelPTSessionFileParser::CreateTraceIntelPTInstance(
+Expected<TraceSP> TraceIntelPTSessionFileParser::CreateTraceIntelPTInstance(
     JSONTraceSession &session, std::vector<ParsedProcess> &parsed_processes) {
   std::vector<ThreadPostMortemTraceSP> threads;
   std::vector<ProcessSP> processes;
@@ -227,10 +235,16 @@
                    parsed_process.threads.end());
   }
 
-  TraceSP trace_instance(new TraceIntelPT(session, processes, threads));
+  TraceIntelPTSP trace_instance(new TraceIntelPT(
+      session, FileSpec(m_session_file_dir), processes, threads));
   for (const ParsedProcess &parsed_process : parsed_processes)
     parsed_process.target_sp->SetTrace(trace_instance);
 
+  if (session.cores) {
+    if (Error err = trace_instance->CreateThreadsFromContextSwitches())
+      return std::move(err);
+  }
+
   return trace_instance;
 }
 
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
@@ -163,6 +163,15 @@
 private:
   friend class TraceIntelPTSessionFileParser;
 
+  /// Create post-mortem threads associated with the processes traced by this
+  /// instance using the context switch traces.
+  ///
+  /// This does nothing if the threads already exist.
+  ///
+  /// \return
+  ///   An \a llvm::Error in case of failures.
+  llvm::Error CreateThreadsFromContextSwitches();
+
   llvm::Expected<pt_cpu> GetCPUInfoForLiveProcess();
 
   /// Postmortem trace constructor
@@ -176,7 +185,7 @@
   /// \param[in] trace_threads
   ///     The threads traced in the live session. They must belong to the
   ///     processes mentioned above.
-  TraceIntelPT(JSONTraceSession &session,
+  TraceIntelPT(JSONTraceSession &session, const FileSpec &session_file_dir,
                llvm::ArrayRef<lldb::ProcessSP> traced_processes,
                llvm::ArrayRef<lldb::ThreadPostMortemTraceSP> traced_threads);
 
@@ -209,6 +218,8 @@
   llvm::Optional<LinuxPerfZeroTscConversion> m_tsc_conversion;
 };
 
+using TraceIntelPTSP = std::shared_ptr<TraceIntelPT>;
+
 } // namespace trace_intel_pt
 } // namespace lldb_private
 
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
@@ -75,6 +75,7 @@
 }
 
 TraceIntelPT::TraceIntelPT(JSONTraceSession &session,
+                           const FileSpec &session_file_dir,
                            ArrayRef<ProcessSP> traced_processes,
                            ArrayRef<ThreadPostMortemTraceSP> traced_threads)
     : Trace(traced_processes, session.GetCoreIds()),
@@ -92,11 +93,19 @@
     std::vector<core_id_t> cores;
 
     for (const JSONCore &core : *session.cores) {
+      FileSpec trace_buffer(core.trace_buffer);
+      if (trace_buffer.IsRelative())
+        trace_buffer.PrependPathComponent(session_file_dir);
+
       SetPostMortemCoreDataFile(core.core_id, IntelPTDataKinds::kTraceBuffer,
-                                FileSpec(core.trace_buffer));
+                                trace_buffer);
+
+      FileSpec context_switch(core.context_switch_trace);
+      if (context_switch.IsRelative())
+        context_switch.PrependPathComponent(session_file_dir);
       SetPostMortemCoreDataFile(core.core_id,
                                 IntelPTDataKinds::kPerfContextSwitchTrace,
-                                FileSpec(core.context_switch_trace));
+                                context_switch);
       cores.push_back(core.core_id);
     }
 
@@ -473,3 +482,45 @@
 }
 
 TaskTimer &TraceIntelPT::GetTimer() { return m_task_timer; }
+
+Error TraceIntelPT::CreateThreadsFromContextSwitches() {
+  DenseMap<lldb::pid_t, DenseSet<lldb::tid_t>> pids_to_tids;
+
+  for (core_id_t core_id : GetTracedCores()) {
+    Error err = OnCoreBinaryDataRead(
+        core_id, IntelPTDataKinds::kPerfContextSwitchTrace,
+        [&](ArrayRef<uint8_t> data) -> Error {
+          Expected<std::vector<ThreadContinuousExecution>> executions =
+              DecodePerfContextSwitchTrace(data, core_id, *m_tsc_conversion);
+          if (!executions)
+            return executions.takeError();
+          for (const ThreadContinuousExecution &execution : *executions)
+            pids_to_tids[execution.pid].insert(execution.tid);
+          return Error::success();
+        });
+    if (err)
+      return err;
+  }
+
+  DenseMap<lldb::pid_t, Process *> processes;
+  for (Process *proc : GetTracedProcesses())
+    processes.try_emplace(proc->GetID(), proc);
+
+  for (const auto &pid_to_tids : pids_to_tids) {
+    lldb::pid_t pid = pid_to_tids.first;
+    auto it = processes.find(pid);
+    if (it == processes.end())
+      continue;
+
+    Process &process = *it->second;
+    ThreadList &thread_list = process.GetThreadList();
+
+    for (lldb::tid_t tid : pid_to_tids.second) {
+      if (!thread_list.FindThreadByID(tid)) {
+        thread_list.AddThread(std::make_shared<ThreadPostMortemTrace>(
+            process, tid, /*trace_file*/ None));
+      }
+    }
+  }
+  return Error::success();
+}
Index: lldb/include/lldb/Target/Trace.h
===================================================================
--- lldb/include/lldb/Target/Trace.h
+++ lldb/include/lldb/Target/Trace.h
@@ -496,6 +496,10 @@
   DoRefreshLiveProcessState(TraceGetStateResponse state,
                             llvm::StringRef json_response) = 0;
 
+  /// Return the list of processes traced by this instance. None of the returned
+  /// pointers are invalid.
+  std::vector<Process *> GetTracedProcesses() const;
+
   /// Method to be invoked by the plug-in to refresh the live process state. It
   /// will invoked DoRefreshLiveProcessState at some point, which should be
   /// implemented by the plug-in for custom state handling.
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to