wallace updated this revision to Diff 338435.
wallace added a comment.

only json is left


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D100740

Files:
  lldb/include/lldb/Target/Trace.h
  lldb/source/Commands/CommandObjectThread.cpp
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
  lldb/source/Target/Trace.cpp

Index: lldb/source/Target/Trace.cpp
===================================================================
--- lldb/source/Target/Trace.cpp
+++ lldb/source/Target/Trace.cpp
@@ -101,6 +101,35 @@
   return num == 0 ? 1 : static_cast<int>(log10(num)) + 1;
 }
 
+static bool
+IsSameInstructionSymbolContext(Optional<Trace::InstructionSymbolInfo> prev_insn,
+                               Trace::InstructionSymbolInfo &insn) {
+  if (!prev_insn)
+    return false;
+
+  // line entry checks
+  if (insn.sc.line_entry.IsValid() ^ prev_insn->sc.line_entry.IsValid())
+    return false;
+  if (insn.sc.line_entry.IsValid() && prev_insn->sc.line_entry.IsValid())
+    return LineEntry::Compare(insn.sc.line_entry, prev_insn->sc.line_entry) ==
+           0;
+
+  // function checks
+  if ((insn.sc.function != nullptr) ^ (prev_insn->sc.function != nullptr))
+    return false;
+  if (insn.sc.function != nullptr && prev_insn->sc.function != nullptr)
+    return insn.sc.function == prev_insn->sc.function;
+
+  // symbol checks
+  if ((insn.sc.symbol != nullptr) ^ (prev_insn->sc.symbol != nullptr))
+    return false;
+  if (insn.sc.symbol != nullptr && prev_insn->sc.symbol != nullptr)
+    return insn.sc.symbol == prev_insn->sc.symbol;
+
+  // module checks
+  return insn.sc.module_sp == prev_insn->sc.module_sp;
+}
+
 /// Dump the symbol context of the given instruction address if it's different
 /// from the symbol context of the previous instruction in the trace.
 ///
@@ -113,181 +142,164 @@
 /// \return
 ///     The symbol context of the current address, which might differ from the
 ///     previous one.
-static SymbolContext DumpSymbolContext(Stream &s, const SymbolContext &prev_sc,
-                                       Target &target, const Address &address) {
-  AddressRange range;
-  if (prev_sc.GetAddressRange(eSymbolContextEverything, 0,
-                              /*inline_block_range*/ false, range) &&
-      range.ContainsFileAddress(address))
-    return prev_sc;
-
-  SymbolContext sc;
-  address.CalculateSymbolContext(&sc, eSymbolContextEverything);
-
-  if (!prev_sc.module_sp && !sc.module_sp)
-    return sc;
-  if (prev_sc.module_sp == sc.module_sp && !sc.function && !sc.symbol &&
-      !prev_sc.function && !prev_sc.symbol)
-    return sc;
+static void
+DumpInstructionSymbolContext(Stream &s,
+                             Optional<Trace::InstructionSymbolInfo> prev_insn,
+                             Trace::InstructionSymbolInfo &insn) {
+  if (IsSameInstructionSymbolContext(prev_insn, insn))
+    return;
 
   s.Printf("  ");
 
-  if (!sc.module_sp)
+  if (!insn.sc.module_sp)
     s.Printf("(none)");
-  else if (!sc.function && !sc.symbol)
+  else if (!insn.sc.function && !insn.sc.symbol)
     s.Printf("%s`(none)",
-             sc.module_sp->GetFileSpec().GetFilename().AsCString());
+             insn.sc.module_sp->GetFileSpec().GetFilename().AsCString());
   else
-    sc.DumpStopContext(&s, &target, address, /*show_fullpath*/ false,
-                       /*show_module*/ true, /*show_inlined_frames*/ false,
+    insn.sc.DumpStopContext(&s, insn.exe_ctx.GetTargetPtr(), insn.address,
+                            /*show_fullpath*/ false,
+                            /*show_module*/ true, /*show_inlined_frames*/ false,
                        /*show_function_arguments*/ true,
                        /*show_function_name*/ true);
   s.Printf("\n");
-  return sc;
-}
-
-/// Dump an instruction given by its address using a given disassembler, unless
-/// the instruction is not present in the disassembler.
-///
-/// \param[in] disassembler
-///     A disassembler containing a certain instruction list.
-///
-/// \param[in] address
-///     The address of the instruction to dump.
-///
-/// \return
-///     \b true if the information could be dumped, \b false otherwise.
-static bool TryDumpInstructionInfo(Stream &s,
-                                   const DisassemblerSP &disassembler,
-                                   const ExecutionContext &exe_ctx,
-                                   const Address &address) {
-  if (!disassembler)
-    return false;
-
-  if (InstructionSP instruction =
-          disassembler->GetInstructionList().GetInstructionAtAddress(address)) {
-    instruction->Dump(&s, /*show_address*/ false, /*show_bytes*/ false,
-                      /*max_opcode_byte_size*/ 0, &exe_ctx,
-                      /*sym_ctx*/ nullptr, /*prev_sym_ctx*/ nullptr,
-                      /*disassembly_addr_format*/ nullptr,
-                      /*max_address_text_size*/ 0);
-    return true;
-  }
-
-  return false;
 }
 
-/// Dump an instruction instruction given by its address.
-///
-/// \param[in] prev_disassembler
-///     The disassembler that was used to dump the previous instruction in the
-///     trace. It is useful to avoid recomputations.
-///
-/// \param[in] address
-///     The address of the instruction to dump.
-///
-/// \return
-///     A disassembler that contains the given instruction, which might differ
-///     from the previous disassembler.
-static DisassemblerSP
-DumpInstructionInfo(Stream &s, const SymbolContext &sc,
-                    const DisassemblerSP &prev_disassembler,
-                    ExecutionContext &exe_ctx, const Address &address) {
-  // We first try to use the previous disassembler
-  if (TryDumpInstructionInfo(s, prev_disassembler, exe_ctx, address))
-    return prev_disassembler;
-
-  // Now we try using the current function's disassembler
-  if (sc.function) {
-    DisassemblerSP disassembler =
-        sc.function->GetInstructions(exe_ctx, nullptr, true);
-    if (TryDumpInstructionInfo(s, disassembler, exe_ctx, address))
-      return disassembler;
-  }
-
-  // We fallback to disassembly one instruction
-  Target &target = exe_ctx.GetTargetRef();
-  const ArchSpec &arch = target.GetArchitecture();
-  AddressRange range(address, arch.GetMaximumOpcodeByteSize() * 1);
-  DisassemblerSP disassembler = Disassembler::DisassembleRange(
-      arch, /*plugin_name*/ nullptr,
-      /*flavor*/ nullptr, target, range, /*prefer_file_cache*/ true);
-  if (TryDumpInstructionInfo(s, disassembler, exe_ctx, address))
-    return disassembler;
-  return nullptr;
+static void DumpInstructionDisassembly(Stream &s,
+                                       Trace::InstructionSymbolInfo &insn) {
+  if (!insn.instruction)
+    return;
+  insn.instruction->Dump(&s, /*show_address*/ false, /*show_bytes*/ false,
+                         /*max_opcode_byte_size*/ 0, &insn.exe_ctx, &insn.sc,
+                         /*prev_sym_ctx*/ nullptr,
+                         /*disassembly_addr_format*/ nullptr,
+                         /*max_address_text_size*/ 0);
 }
 
 void Trace::DumpTraceInstructions(Thread &thread, Stream &s, size_t count,
-                                  size_t end_position, bool raw) {
-  if (!IsTraced(thread)) {
+                                  size_t end_position, TraceDumpFormat format) {
+  Optional<size_t> instructions_count = GetInstructionCount(thread);
+  if (!instructions_count) {
     s.Printf("thread #%u: tid = %" PRIu64 ", not traced\n", thread.GetIndexID(),
              thread.GetID());
     return;
   }
 
-  size_t instructions_count = GetInstructionCount(thread);
   s.Printf("thread #%u: tid = %" PRIu64 ", total instructions = %zu\n",
-           thread.GetIndexID(), thread.GetID(), instructions_count);
+           thread.GetIndexID(), thread.GetID(), *instructions_count);
 
-  if (count == 0 || end_position >= instructions_count)
+  if (count == 0 || end_position >= *instructions_count)
     return;
 
+  int digits_count = GetNumberOfDigits(end_position);
   size_t start_position =
       end_position + 1 < count ? 0 : end_position + 1 - count;
-
-  int digits_count = GetNumberOfDigits(end_position);
   auto printInstructionIndex = [&](size_t index) {
     s.Printf("    [%*zu] ", digits_count, index);
   };
 
   bool was_prev_instruction_an_error = false;
-  Target &target = thread.GetProcess()->GetTarget();
+  Optional<InstructionSymbolInfo> prev_insn;
 
-  SymbolContext sc;
-  DisassemblerSP disassembler;
-  ExecutionContext exe_ctx;
-  target.CalculateExecutionContext(exe_ctx);
-
-  TraverseInstructions(
+  TraverseInstructionsWithSymbolInfo(
       thread, start_position, TraceDirection::Forwards,
-      [&](size_t index, Expected<lldb::addr_t> load_address) -> bool {
-        if (load_address) {
-          // We print an empty line after a sequence of errors to show more
-          // clearly that there's a gap in the trace
+      [&](size_t index, Expected<InstructionSymbolInfo> insn) -> bool {
+        if (!insn) {
+          printInstructionIndex(index);
+          s << toString(insn.takeError());
+
+          prev_insn = None;
+          was_prev_instruction_an_error = true;
+        } else {
           if (was_prev_instruction_an_error)
             s.Printf("    ...missing instructions\n");
 
-          Address address;
-          if (!raw) {
-            target.GetSectionLoadList().ResolveLoadAddress(*load_address,
-                                                           address);
-
-            sc = DumpSymbolContext(s, sc, target, address);
-          }
+          if (format != TraceDumpFormat::Raw)
+            DumpInstructionSymbolContext(s, prev_insn, *insn);
 
           printInstructionIndex(index);
-          s.Printf("0x%016" PRIx64 "    ", *load_address);
+          s.Printf("0x%016" PRIx64 "    ", insn->load_address);
 
-          if (!raw) {
-            disassembler =
-                DumpInstructionInfo(s, sc, disassembler, exe_ctx, address);
-          }
+          if (format != TraceDumpFormat::Raw)
+            DumpInstructionDisassembly(s, *insn);
 
+          prev_insn = *insn;
           was_prev_instruction_an_error = false;
-        } else {
-          printInstructionIndex(index);
-          s << toString(load_address.takeError());
-          was_prev_instruction_an_error = true;
-          if (!raw)
-            sc = SymbolContext();
         }
 
         s.Printf("\n");
-
         return index < end_position;
       });
 }
 
+void Trace::TraverseInstructionsWithSymbolInfo(
+    Thread &thread, size_t position, TraceDirection direction,
+    std::function<bool(size_t index, Expected<InstructionSymbolInfo> insn)>
+        callback) {
+  InstructionSymbolInfo prev_insn;
+
+  Target &target = thread.GetProcess()->GetTarget();
+  ExecutionContext exe_ctx;
+  target.CalculateExecutionContext(exe_ctx);
+  const ArchSpec &arch = target.GetArchitecture();
+
+  auto calculate_symbol_context = [&](const Address &address) {
+    AddressRange range;
+    if (prev_insn.sc.GetAddressRange(eSymbolContextEverything, 0,
+                                     /*inline_block_range*/ false, range) &&
+        range.ContainsFileAddress(address))
+      return prev_insn.sc;
+
+    SymbolContext sc;
+    address.CalculateSymbolContext(&sc, eSymbolContextEverything);
+    return sc;
+  };
+
+  auto calculate_disass = [&](const Address &address, const SymbolContext &sc) {
+    if (prev_insn.disassembler)
+      if (InstructionSP instruction =
+              prev_insn.disassembler->GetInstructionList()
+                  .GetInstructionAtAddress(address))
+        return std::make_tuple(prev_insn.disassembler, instruction);
+
+    if (sc.function) {
+      DisassemblerSP disassembler =
+          sc.function->GetInstructions(exe_ctx, nullptr, true);
+      if (disassembler)
+        if (InstructionSP instruction =
+                disassembler->GetInstructionList().GetInstructionAtAddress(
+                    address))
+          return std::make_tuple(disassembler, instruction);
+    }
+    AddressRange range(address, arch.GetMaximumOpcodeByteSize() * 1);
+    DisassemblerSP disassembler = Disassembler::DisassembleRange(
+        arch, /*plugin_name*/ nullptr,
+        /*flavor*/ nullptr, target, range, /*prefer_file_cache*/ true);
+    return std::make_tuple(disassembler,
+                           disassembler ? disassembler->GetInstructionList()
+                                              .GetInstructionAtAddress(address)
+                                        : InstructionSP());
+  };
+
+  TraverseInstructions(
+      thread, position, direction,
+      [&](size_t index, Expected<lldb::addr_t> load_address) -> bool {
+        if (!load_address)
+          return callback(index, load_address.takeError());
+
+        InstructionSymbolInfo insn;
+        insn.load_address = *load_address;
+        insn.exe_ctx = exe_ctx;
+        target.GetSectionLoadList().ResolveLoadAddress(*load_address,
+                                                       insn.address);
+        insn.sc = calculate_symbol_context(insn.address);
+        std::tie(insn.disassembler, insn.instruction) =
+            calculate_disass(insn.address, insn.sc);
+        prev_insn = insn;
+        return callback(index, insn);
+      });
+}
+
 Error Trace::Start(const llvm::json::Value &request) {
   if (!m_live_process)
     return createStringError(inconvertibleErrorCode(),
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
@@ -70,7 +70,7 @@
       std::function<bool(size_t index, llvm::Expected<lldb::addr_t> load_addr)>
           callback) override;
 
-  size_t GetInstructionCount(Thread &thread) override;
+  llvm::Optional<size_t> GetInstructionCount(Thread &thread) override;
 
   size_t GetCursorPosition(Thread &thread) override;
 
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
@@ -122,11 +122,11 @@
       break;
 }
 
-size_t TraceIntelPT::GetInstructionCount(Thread &thread) {
+Optional<size_t> TraceIntelPT::GetInstructionCount(Thread &thread) {
   if (const DecodedThread *decoded_thread = Decode(thread))
     return decoded_thread->GetInstructions().size();
   else
-    return 0;
+    return None;
 }
 
 Expected<pt_cpu> TraceIntelPT::GetCPUInfoForLiveProcess() {
Index: lldb/source/Commands/CommandObjectThread.cpp
===================================================================
--- lldb/source/Commands/CommandObjectThread.cpp
+++ lldb/source/Commands/CommandObjectThread.cpp
@@ -2148,8 +2148,10 @@
     if (position < 0)
       result.SetError("error: no more data");
     else
-      trace_sp->DumpTraceInstructions(*thread_sp, result.GetOutputStream(),
-                                      count, position, m_options.m_raw);
+      trace_sp->DumpTraceInstructions(
+          *thread_sp, result.GetOutputStream(), count, position,
+          m_options.m_raw ? Trace::TraceDumpFormat::Raw
+                          : Trace::TraceDumpFormat::Default);
     return true;
   }
 
Index: lldb/include/lldb/Target/Trace.h
===================================================================
--- lldb/include/lldb/Target/Trace.h
+++ lldb/include/lldb/Target/Trace.h
@@ -14,6 +14,7 @@
 #include "llvm/Support/JSON.h"
 
 #include "lldb/Core/PluginInterface.h"
+#include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Thread.h"
 #include "lldb/Utility/ArchSpec.h"
 #include "lldb/Utility/TraceGDBRemotePackets.h"
@@ -49,6 +50,12 @@
     Backwards,
   };
 
+  enum class TraceDumpFormat {
+    Default = 0,
+    Raw = 1,
+    JSON = 2,
+  };
+
   /// Dump the trace data that this plug-in has access to.
   ///
   /// This function will dump all of the trace data for all threads in a user
@@ -167,11 +174,12 @@
   /// \param[in] end_position
   ///     The position of the last instruction to print.
   ///
-  /// \param[in] raw
-  ///     Dump only instruction addresses without disassembly nor symbol
-  ///     information.
+  /// \param[in] format
+  ///     If \b Default, then dump instruction addresses with disassembly and
+  ///     symbol information. If \b Raw, then only dump instruction addresses.
+  ///     If \b JSON, then print addresses and disassembly in JSON format.
   void DumpTraceInstructions(Thread &thread, Stream &s, size_t count,
-                             size_t end_position, bool raw);
+                             size_t end_position, TraceDumpFormat format);
 
   /// Run the provided callback on the instructions of the trace of the given
   /// thread.
@@ -204,14 +212,33 @@
       std::function<bool(size_t index, llvm::Expected<lldb::addr_t> load_addr)>
           callback) = 0;
 
+  struct InstructionSymbolInfo {
+    SymbolContext sc;
+    Address address;
+    lldb::addr_t load_address;
+    lldb::DisassemblerSP disassembler;
+    lldb::InstructionSP instruction;
+    lldb_private::ExecutionContext exe_ctx;
+  };
+
+  /// Similar to \a TraverseInstructions byt the callback receives a \a
+  /// InstructionSymbolInfo object with symbol information for the given
+  /// instruction, calculated efficiently.
+  void TraverseInstructionsWithSymbolInfo(
+      Thread &thread, size_t position, TraceDirection direction,
+      std::function<bool(size_t index,
+                         llvm::Expected<InstructionSymbolInfo> insn)>
+          callback);
+
   /// Get the number of available instructions in the trace of the given thread.
   ///
   /// \param[in] thread
   ///     The thread whose trace will be inspected.
   ///
   /// \return
-  ///     The total number of instructions in the trace.
-  virtual size_t GetInstructionCount(Thread &thread) = 0;
+  ///     The total number of instructions in the trace, or \a llvm::None if the
+  ///     thread is not being traced.
+  virtual llvm::Optional<size_t> GetInstructionCount(Thread &thread) = 0;
 
   /// Check if a thread is currently traced by this object.
   ///
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to