wallace updated this revision to Diff 350652.
wallace added a comment.
I tried to use a ConstString instead of a const char *, but that's not trivial
because
the compilers wants a safe destructor all the way down, and it seems that this
is non-standard
across compilers, except for C++17 and onwards, which has the std::variant type.
So I'm just adding a comment as suggested.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D103588/new/
https://reviews.llvm.org/D103588
Files:
lldb/include/lldb/Target/Trace.h
lldb/include/lldb/lldb-enumerations.h
lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.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
@@ -52,6 +52,23 @@
} // namespace json
} // namespace llvm
+TraceInstruction::TraceInstruction() : m_is_error(true) {
+ m_data.m_error = "invalid instruction";
+}
+
+TraceInstruction::TraceInstruction(lldb::addr_t load_address, uint8_t byte_size,
+ lldb::TraceInstructionType instruction_type)
+ : m_is_error(false), m_byte_size(byte_size),
+ m_instruction_type(instruction_type) {
+ m_data.m_load_address = load_address;
+}
+
+TraceInstruction::TraceInstruction(Error error) : m_is_error(true) {
+ // We are assuming that errors will be rare, so using the ConstrString pool
+ // helps us make this class smaller.
+ m_data.m_error = ConstString(toString(std::move(error))).GetCString();
+}
+
static Error createInvalidPlugInError(StringRef plugin_name) {
return createStringError(
std::errc::invalid_argument,
@@ -124,9 +141,9 @@
struct InstructionSymbolInfo {
SymbolContext sc;
Address address;
- lldb::addr_t load_address;
+ TraceInstruction instruction;
lldb::DisassemblerSP disassembler;
- lldb::InstructionSP instruction;
+ lldb::InstructionSP instruction_sp;
lldb_private::ExecutionContext exe_ctx;
};
@@ -144,7 +161,7 @@
Trace &trace, Thread &thread, size_t position,
Trace::TraceDirection direction, SymbolContextItem symbol_scope,
bool include_disassembler,
- std::function<bool(size_t index, Expected<InstructionSymbolInfo> insn)>
+ std::function<bool(size_t index, const InstructionSymbolInfo &insn)>
callback) {
InstructionSymbolInfo prev_insn;
@@ -199,18 +216,18 @@
trace.TraverseInstructions(
thread, position, direction,
- [&](size_t index, Expected<lldb::addr_t> load_address) -> bool {
- if (!load_address)
- return callback(index, load_address.takeError());
-
+ [&](size_t index, const TraceInstruction &instruction) -> bool {
InstructionSymbolInfo insn;
- insn.load_address = *load_address;
+ insn.instruction = instruction;
+ if (instruction.IsError())
+ return callback(index, insn);
+
insn.exe_ctx = exe_ctx;
- insn.address.SetLoadAddress(*load_address, &target);
+ insn.address.SetLoadAddress(instruction.GetLoadAddress(), &target);
if (symbol_scope != 0)
insn.sc = calculate_symbol_context(insn.address);
if (include_disassembler)
- std::tie(insn.disassembler, insn.instruction) =
+ std::tie(insn.disassembler, insn.instruction_sp) =
calculate_disass(insn.address, insn.sc);
prev_insn = insn;
return callback(index, insn);
@@ -268,7 +285,7 @@
static void
DumpInstructionSymbolContext(Stream &s,
Optional<InstructionSymbolInfo> prev_insn,
- InstructionSymbolInfo &insn) {
+ const InstructionSymbolInfo &insn) {
if (prev_insn && IsSameInstructionSymbolContext(*prev_insn, insn))
return;
@@ -288,15 +305,16 @@
s.Printf("\n");
}
-static void DumpInstructionDisassembly(Stream &s, InstructionSymbolInfo &insn) {
- if (!insn.instruction)
+static void DumpInstructionDisassembly(Stream &s,
+ const InstructionSymbolInfo &insn) {
+ if (insn.instruction.IsError())
return;
s.Printf(" ");
- 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);
+ insn.instruction_sp->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,
@@ -327,10 +345,10 @@
TraverseInstructionsWithSymbolInfo(
*this, thread, start_position, TraceDirection::Forwards,
eSymbolContextEverything, /*disassembler*/ true,
- [&](size_t index, Expected<InstructionSymbolInfo> insn) -> bool {
- if (!insn) {
+ [&](size_t index, const InstructionSymbolInfo &insn) -> bool {
+ if (insn.instruction.IsError()) {
printInstructionIndex(index);
- s << toString(insn.takeError());
+ s << insn.instruction.GetError();
prev_insn = None;
was_prev_instruction_an_error = true;
@@ -339,15 +357,15 @@
s.Printf(" ...missing instructions\n");
if (!raw)
- DumpInstructionSymbolContext(s, prev_insn, *insn);
+ DumpInstructionSymbolContext(s, prev_insn, insn);
printInstructionIndex(index);
- s.Printf("0x%016" PRIx64, insn->load_address);
+ s.Printf("0x%016" PRIx64, insn.instruction.GetLoadAddress());
if (!raw)
- DumpInstructionDisassembly(s, *insn);
+ DumpInstructionDisassembly(s, insn);
- prev_insn = *insn;
+ prev_insn = insn;
was_prev_instruction_an_error = false;
}
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
@@ -67,7 +67,7 @@
void TraverseInstructions(
Thread &thread, size_t position, TraceDirection direction,
- std::function<bool(size_t index, llvm::Expected<lldb::addr_t> load_addr)>
+ std::function<bool(size_t index, const TraceInstruction &instruction)>
callback) override;
llvm::Optional<size_t> GetInstructionCount(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
@@ -108,18 +108,18 @@
void TraceIntelPT::TraverseInstructions(
Thread &thread, size_t position, TraceDirection direction,
- std::function<bool(size_t index, Expected<lldb::addr_t> load_addr)>
+ std::function<bool(size_t index, const TraceInstruction &load_addr)>
callback) {
const DecodedThread *decoded_thread = Decode(thread);
if (!decoded_thread)
return;
- ArrayRef<IntelPTInstruction> instructions = decoded_thread->GetInstructions();
+ ArrayRef<TraceInstruction> instructions = decoded_thread->GetInstructions();
ssize_t delta = direction == TraceDirection::Forwards ? 1 : -1;
for (ssize_t i = position; i < (ssize_t)instructions.size() && i >= 0;
i += delta)
- if (!callback(i, instructions[i].GetLoadAddress()))
+ if (!callback(i, instructions[i]))
break;
}
Index: lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp
+++ lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp
@@ -8,19 +8,32 @@
#include "IntelPTDecoder.h"
#include "llvm/Support/MemoryBuffer.h"
+#include <intel-pt.h>
#include "TraceIntelPT.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPostMortemTrace.h"
-#include "lldb/Utility/StringExtractor.h"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::trace_intel_pt;
using namespace llvm;
+static llvm::Error
+CreateIntelPTError(int libipt_error_code,
+ lldb::addr_t address = LLDB_INVALID_ADDRESS) {
+ const char *libipt_error_message = pt_errstr(pt_errcode(libipt_error_code));
+ if (address != LLDB_INVALID_ADDRESS && address > 0) {
+ return createStringError(inconvertibleErrorCode(),
+ "0x%16.16" PRIx64 " error: %s", address,
+ libipt_error_message);
+ }
+ return createStringError(inconvertibleErrorCode(), "error: %s",
+ libipt_error_message);
+}
+
/// Move the decoder forward to the next synchronization point (i.e. next PSB
/// packet).
///
@@ -88,6 +101,31 @@
return 0;
}
+TraceInstructionType GetTraceInstructionType(const pt_insn &insn) {
+ switch (insn.iclass) {
+ case ptic_other:
+ return lldb::eTraceInstructionOther;
+ case ptic_call:
+ return lldb::eTraceInstructionCall;
+ case ptic_return:
+ return lldb::eTraceInstructionReturn;
+ case ptic_jump:
+ return lldb::eTraceInstructionJump;
+ case ptic_cond_jump:
+ return lldb::eTraceInstructionCondJump;
+ case ptic_far_call:
+ return lldb::eTraceInstructionFarCall;
+ case ptic_far_return:
+ return lldb::eTraceInstructionFarReturn;
+ case ptic_far_jump:
+ return lldb::eTraceInstructionFarJump;
+ case ptic_ptwrite:
+ return lldb::eTraceInstructionTraceWrite;
+ default:
+ return lldb::eTraceInstructionUnknown;
+ }
+}
+
/// Decode all the instructions from a configured decoder.
/// The decoding flow is based on
/// https://github.com/intel/libipt/blob/master/doc/howto_libipt.md#the-instruction-flow-decode-loop
@@ -103,9 +141,9 @@
///
/// \return
/// The decoded instructions.
-static std::vector<IntelPTInstruction>
+static std::vector<TraceInstruction>
DecodeInstructions(pt_insn_decoder &decoder) {
- std::vector<IntelPTInstruction> instructions;
+ std::vector<TraceInstruction> instructions;
while (true) {
int errcode = FindNextSynchronizationPoint(decoder);
@@ -113,7 +151,7 @@
break;
if (errcode < 0) {
- instructions.emplace_back(make_error<IntelPTError>(errcode));
+ instructions.emplace_back(CreateIntelPTError(errcode));
break;
}
@@ -122,7 +160,7 @@
while (true) {
errcode = ProcessPTEvents(decoder, errcode);
if (errcode < 0) {
- instructions.emplace_back(make_error<IntelPTError>(errcode));
+ instructions.emplace_back(CreateIntelPTError(errcode));
break;
}
pt_insn insn;
@@ -132,11 +170,12 @@
break;
if (errcode < 0) {
- instructions.emplace_back(make_error<IntelPTError>(errcode, insn.ip));
+ instructions.emplace_back(CreateIntelPTError(errcode, insn.ip));
break;
}
- instructions.emplace_back(insn);
+ instructions.emplace_back(insn.ip, insn.size,
+ GetTraceInstructionType(insn));
}
}
@@ -159,7 +198,7 @@
return bytes_read;
}
-static Expected<std::vector<IntelPTInstruction>>
+static Expected<std::vector<TraceInstruction>>
DecodeInMemoryTrace(Process &process, TraceIntelPT &trace_intel_pt,
MutableArrayRef<uint8_t> buffer) {
Expected<pt_cpu> cpu_info = trace_intel_pt.GetCPUInfo();
@@ -171,14 +210,14 @@
config.cpu = *cpu_info;
if (int errcode = pt_cpu_errata(&config.errata, &config.cpu))
- return make_error<IntelPTError>(errcode);
+ return CreateIntelPTError(errcode);
config.begin = buffer.data();
config.end = buffer.data() + buffer.size();
pt_insn_decoder *decoder = pt_insn_alloc_decoder(&config);
if (!decoder)
- return make_error<IntelPTError>(-pte_nomem);
+ return CreateIntelPTError(-pte_nomem);
pt_image *image = pt_insn_get_image(decoder);
@@ -186,13 +225,13 @@
assert(errcode == 0);
(void)errcode;
- std::vector<IntelPTInstruction> instructions = DecodeInstructions(*decoder);
+ std::vector<TraceInstruction> instructions = DecodeInstructions(*decoder);
pt_insn_free_decoder(decoder);
return instructions;
}
-static Expected<std::vector<IntelPTInstruction>>
+static Expected<std::vector<TraceInstruction>>
DecodeTraceFile(Process &process, TraceIntelPT &trace_intel_pt,
const FileSpec &trace_file) {
ErrorOr<std::unique_ptr<MemoryBuffer>> trace_or_error =
@@ -209,7 +248,7 @@
return DecodeInMemoryTrace(process, trace_intel_pt, trace_data);
}
-static Expected<std::vector<IntelPTInstruction>>
+static Expected<std::vector<TraceInstruction>>
DecodeLiveThread(Thread &thread, TraceIntelPT &trace) {
Expected<std::vector<uint8_t>> buffer =
trace.GetLiveThreadBuffer(thread.GetID());
@@ -233,7 +272,7 @@
: m_trace_thread(trace_thread), m_trace(trace) {}
DecodedThread PostMortemThreadDecoder::DoDecode() {
- if (Expected<std::vector<IntelPTInstruction>> instructions =
+ if (Expected<std::vector<TraceInstruction>> instructions =
DecodeTraceFile(*m_trace_thread->GetProcess(), m_trace,
m_trace_thread->GetTraceFile()))
return DecodedThread(std::move(*instructions));
@@ -245,7 +284,7 @@
: m_thread_sp(thread.shared_from_this()), m_trace(trace) {}
DecodedThread LiveThreadDecoder::DoDecode() {
- if (Expected<std::vector<IntelPTInstruction>> instructions =
+ if (Expected<std::vector<TraceInstruction>> instructions =
DecodeLiveThread(*m_thread_sp, m_trace))
return DecodedThread(std::move(*instructions));
else
Index: lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
+++ lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
@@ -11,7 +11,6 @@
#include <vector>
-#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "lldb/Target/Trace.h"
@@ -22,83 +21,6 @@
namespace lldb_private {
namespace trace_intel_pt {
-/// Class for representing a libipt decoding error.
-class IntelPTError : public llvm::ErrorInfo<IntelPTError> {
-public:
- static char ID;
-
- /// \param[in] libipt_error_code
- /// Negative number returned by libipt when decoding the trace and
- /// signaling errors.
- ///
- /// \param[in] address
- /// Optional instruction address. When decoding an individual instruction,
- /// its address might be available in the \a pt_insn object, and should be
- /// passed to this constructor. Other errors don't have an associated
- /// address.
- IntelPTError(int libipt_error_code,
- lldb::addr_t address = LLDB_INVALID_ADDRESS);
-
- std::error_code convertToErrorCode() const override {
- return llvm::errc::not_supported;
- }
-
- void log(llvm::raw_ostream &OS) const override;
-
-private:
- int m_libipt_error_code;
- lldb::addr_t m_address;
-};
-
-/// \class IntelPTInstruction
-/// An instruction obtained from decoding a trace. It is either an actual
-/// instruction or an error indicating a gap in the trace.
-///
-/// Gaps in the trace can come in a few flavors:
-/// - tracing gaps (e.g. tracing was paused and then resumed)
-/// - tracing errors (e.g. buffer overflow)
-/// - decoding errors (e.g. some memory region couldn't be decoded)
-/// As mentioned, any gap is represented as an error in this class.
-class IntelPTInstruction {
-public:
- IntelPTInstruction(const pt_insn &pt_insn) : m_pt_insn(pt_insn) {}
-
- /// Error constructor
- ///
- /// libipt errors should use the underlying \a IntelPTError class.
- IntelPTInstruction(llvm::Error err) {
- llvm::handleAllErrors(std::move(err),
- [&](std::unique_ptr<llvm::ErrorInfoBase> info) {
- m_error = std::move(info);
- });
- }
-
- /// Check if this object represents an error (i.e. a gap).
- ///
- /// \return
- /// Whether this object represents an error.
- bool IsError() const;
-
- /// \return
- /// The instruction pointer address, or an \a llvm::Error if it is an
- /// error.
- llvm::Expected<lldb::addr_t> GetLoadAddress() const;
-
- /// \return
- /// An \a llvm::Error object if this class corresponds to an Error, or an
- /// \a llvm::Error::success otherwise.
- llvm::Error ToError() const;
-
- IntelPTInstruction(IntelPTInstruction &&other) = default;
-
-private:
- IntelPTInstruction(const IntelPTInstruction &other) = delete;
- const IntelPTInstruction &operator=(const IntelPTInstruction &other) = delete;
-
- pt_insn m_pt_insn;
- std::unique_ptr<llvm::ErrorInfoBase> m_error;
-};
-
/// \class DecodedThread
/// Class holding the instructions and function call hierarchy obtained from
/// decoding a trace, as well as a position cursor used when reverse debugging
@@ -108,7 +30,7 @@
/// stopped at. See \a Trace::GetCursorPosition for more information.
class DecodedThread {
public:
- DecodedThread(std::vector<IntelPTInstruction> &&instructions)
+ DecodedThread(std::vector<TraceInstruction> &&instructions)
: m_instructions(std::move(instructions)), m_position(GetLastPosition()) {
}
@@ -121,7 +43,7 @@
///
/// \return
/// The instructions of the trace.
- llvm::ArrayRef<IntelPTInstruction> GetInstructions() const;
+ llvm::ArrayRef<TraceInstruction> GetInstructions() const;
/// \return
/// The current position of the cursor of this trace, or 0 if there are no
@@ -141,7 +63,7 @@
/// The index of the last element of the trace, or 0 if empty.
size_t GetLastPosition() const;
- std::vector<IntelPTInstruction> m_instructions;
+ std::vector<TraceInstruction> m_instructions;
size_t m_position;
};
Index: lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
+++ lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
@@ -14,45 +14,11 @@
using namespace lldb_private::trace_intel_pt;
using namespace llvm;
-char IntelPTError::ID;
-
-IntelPTError::IntelPTError(int libipt_error_code, lldb::addr_t address)
- : m_libipt_error_code(libipt_error_code), m_address(address) {
- assert(libipt_error_code < 0);
-}
-
-void IntelPTError::log(llvm::raw_ostream &OS) const {
- const char *libipt_error_message = pt_errstr(pt_errcode(m_libipt_error_code));
- if (m_address != LLDB_INVALID_ADDRESS && m_address > 0) {
- write_hex(OS, m_address, HexPrintStyle::PrefixLower, 18);
- OS << " ";
- }
- OS << "error: " << libipt_error_message;
-}
-
-bool IntelPTInstruction::IsError() const { return (bool)m_error; }
-
-Expected<lldb::addr_t> IntelPTInstruction::GetLoadAddress() const {
- if (IsError())
- return ToError();
- return m_pt_insn.ip;
-}
-
-Error IntelPTInstruction::ToError() const {
- if (!IsError())
- return Error::success();
-
- if (m_error->isA<IntelPTError>())
- return make_error<IntelPTError>(static_cast<IntelPTError &>(*m_error));
- return make_error<StringError>(m_error->message(),
- m_error->convertToErrorCode());
-}
-
size_t DecodedThread::GetLastPosition() const {
return m_instructions.empty() ? 0 : m_instructions.size() - 1;
}
-ArrayRef<IntelPTInstruction> DecodedThread::GetInstructions() const {
+ArrayRef<TraceInstruction> DecodedThread::GetInstructions() const {
return makeArrayRef(m_instructions);
}
Index: lldb/include/lldb/lldb-enumerations.h
===================================================================
--- lldb/include/lldb/lldb-enumerations.h
+++ lldb/include/lldb/lldb-enumerations.h
@@ -9,6 +9,7 @@
#ifndef LLDB_LLDB_ENUMERATIONS_H
#define LLDB_LLDB_ENUMERATIONS_H
+#include <cstdint>
#include <type_traits>
#ifndef SWIG
@@ -781,6 +782,34 @@
eTraceTypeProcessorTrace
};
+/// Architecture-agnostic categorization of instructions. Useful for doing
+/// analysis on traces.
+enum TraceInstructionType : uint8_t {
+ /// The instruction is not recognized by LLDB
+ eTraceInstructionUnknown = 0,
+ /// The instruction is something not listed below
+ eTraceInstructionOther,
+ /// The instruction is a near (function) call
+ eTraceInstructionCall,
+ /// The instruction is a near (function) return
+ eTraceInstructionReturn,
+ /// The instruction is a near unconditional jump
+ eTraceInstructionJump,
+ /// The instruction is a near conditional jump
+ eTraceInstructionCondJump,
+ /// The instruction is a call-like far transfer
+ /// e.g. SYSCALL, SYSENTER, or FAR CALL
+ eTraceInstructionFarCall,
+ /// The instruction is a return-like far transfer
+ /// e.g. SYSRET, SYSEXIT, IRET, or FAR RET
+ eTraceInstructionFarReturn,
+ /// The instruction is a jump-like far transfer
+ /// e.g. FAR JMP
+ eTraceInstructionFarJump,
+ /// The instruction is a PTWRITE or similar
+ eTraceInstructionTraceWrite,
+};
+
enum StructuredDataType {
eStructuredDataTypeInvalid = -1,
eStructuredDataTypeNull = 0,
Index: lldb/include/lldb/Target/Trace.h
===================================================================
--- lldb/include/lldb/Target/Trace.h
+++ lldb/include/lldb/Target/Trace.h
@@ -22,6 +22,62 @@
namespace lldb_private {
+/// Class that represents a decoded instruction from a trace. It's supposed to
+/// have a minimal memory footprint as the number of instructions can be in the
+/// order of millions.
+///
+/// For complex operations, \a lldb_private::Instruction can be used sparingly.
+///
+/// This class assumes that errors will be extremely rare compared to the number
+/// of correct instructions and storing them as \a ConstString should be fine.
+class TraceInstruction {
+public:
+ TraceInstruction(lldb::addr_t load_address, uint8_t byte_size,
+ lldb::TraceInstructionType instruction_type);
+
+ /// Constructor for an instruction that couldn't be decoded
+ TraceInstruction(llvm::Error error);
+
+ /// This constructs a failed instruction, i.e. \a GetError() returns \b true.
+ TraceInstruction();
+
+ /// \return
+ /// The architecture-agnostic instruction type
+ lldb::TraceInstructionType GetInstructionType() const {
+ return m_instruction_type;
+ }
+
+ /// \return
+ /// The load adress (aka instruction pointer)
+ lldb::addr_t GetLoadAddress() const { return m_data.m_load_address; }
+
+ /// \return
+ /// The error message or \b nullptr if not an error.
+ const char *GetError() const {
+ if (m_is_error)
+ return m_data.m_error;
+ return nullptr;
+ }
+
+ /// \return
+ /// The size in bytes of the instruction.
+ uint8_t GetByteSize() const { return m_byte_size; }
+
+ bool IsError() const { return m_is_error; }
+
+private:
+ uint8_t m_is_error;
+ uint8_t m_byte_size;
+ lldb::TraceInstructionType m_instruction_type;
+
+ union {
+ lldb::addr_t m_load_address;
+ /// This const char * comes from a \a ConstString, and thus doesn't need to
+ /// be freed.
+ const char *m_error;
+ } m_data;
+};
+
/// \class Trace Trace.h "lldb/Target/Trace.h"
/// A plug-in interface definition class for trace information.
///
@@ -201,7 +257,7 @@
/// the iteration stops.
virtual void TraverseInstructions(
Thread &thread, size_t position, TraceDirection direction,
- std::function<bool(size_t index, llvm::Expected<lldb::addr_t> load_addr)>
+ std::function<bool(size_t index, const TraceInstruction &instruction)>
callback) = 0;
/// Get the number of available instructions in the trace of the given thread.
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits