persona0220 created this revision. persona0220 added reviewers: wallace, jj10306. Herald added a project: All. persona0220 requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits.
To build complex binding upon instruction trace, additional metadata 'instruction type' is needed. This diff has followings: - Add a flag -k / --kind for instruction dump - Remove SetGranularity and SetIgnoreErros from Trace cursor Sample output: (lldb) thread trace dump instruction -k thread #1: tid = 3198805 libc.so.6`_IO_puts + 356 2107: 0x00007ffff7163594 ( return) retq 2106: 0x00007ffff7163592 ( other) popq %r13 2105: 0x00007ffff7163590 ( other) popq %r12 2104: 0x00007ffff716358f ( other) popq %rbp 2103: 0x00007ffff716358e ( other) popq %rbx 2102: 0x00007ffff716358c ( other) movl %ebx, %eax 2101: 0x00007ffff7163588 ( other) addq $0x8, %rsp 2100: 0x00007ffff7163570 ( cond jump) je 0x89588 ; <+344> 2099: 0x00007ffff716356e ( other) decl (%rdx) 2098: 0x00007ffff7163565 ( cond jump) je 0x8956e ; <+318> 2097: 0x00007ffff716355e ( other) cmpl $0x0, 0x33c02b(%rip) ; __libc_multiple_threads 2096: 0x00007ffff7163556 ( other) movq $0x0, 0x8(%rdx) 2095: 0x00007ffff7163554 ( cond jump) jne 0x89588 ; <+344> 2094: 0x00007ffff7163550 ( other) subl $0x1, 0x4(%rdx) 2093: 0x00007ffff7163549 ( other) movq 0x88(%rbp), %rdx 2092: 0x00007ffff7163547 ( cond jump) jne 0x89588 ; <+344> 2091: 0x00007ffff7163540 ( other) testl $0x8000, (%rbp) ; imm = 0x8000 2090: 0x00007ffff716353c ( other) cmovaq %rax, %rbx 2089: 0x00007ffff7163535 ( other) cmpq $0x7fffffff, %rbx ; imm = 0x7FFFFFFF 2088: 0x00007ffff7163530 ( other) movl $0x7fffffff, %eax ; imm = 0x7FFFFFFF Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D128477 Files: lldb/include/lldb/Target/TraceCursor.h lldb/include/lldb/Target/TraceInstructionDumper.h lldb/include/lldb/lldb-enumerations.h lldb/source/Commands/CommandObjectThread.cpp lldb/source/Commands/Options.td lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp lldb/source/Target/TraceCursor.cpp lldb/source/Target/TraceInstructionDumper.cpp
Index: lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp =================================================================== --- lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp +++ lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp @@ -46,10 +46,7 @@ if (m_tsc_range && !m_tsc_range->InRange(m_pos)) m_tsc_range = IsForwards() ? m_tsc_range->Next() : m_tsc_range->Prev(); - if (!m_ignore_errors && IsError()) - return true; - if (GetInstructionControlFlowType() & m_granularity) - return true; + return true; } // Didn't find any matching instructions 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 @@ -62,31 +62,34 @@ TraceInstructionControlFlowType DecodedThread::GetInstructionControlFlowType(size_t insn_index) const { if (IsInstructionAnError(insn_index)) - return (TraceInstructionControlFlowType)0; + return eTraceInstructionControlFlowTypeError; TraceInstructionControlFlowType mask = eTraceInstructionControlFlowTypeInstruction; - lldb::addr_t load_address = m_instruction_ips[insn_index]; - uint8_t insn_byte_size = m_instruction_sizes[insn_index]; pt_insn_class iclass = m_instruction_classes[insn_index]; switch (iclass) { - case ptic_cond_jump: - case ptic_jump: - case ptic_far_jump: - mask |= eTraceInstructionControlFlowTypeBranch; - if (insn_index + 1 < m_instruction_ips.size() && - load_address + insn_byte_size != m_instruction_ips[insn_index + 1]) - mask |= eTraceInstructionControlFlowTypeTakenBranch; + case ptic_call: + mask |= eTraceInstructionControlFlowTypeCall; break; case ptic_return: - case ptic_far_return: mask |= eTraceInstructionControlFlowTypeReturn; break; - case ptic_call: + case ptic_jump: + mask |= eTraceInstructionControlFlowTypeJump; + break; + case ptic_cond_jump: + mask |= eTraceInstructionControlFlowTypeCondJump; + break; case ptic_far_call: - mask |= eTraceInstructionControlFlowTypeCall; + mask |= eTraceInstructionControlFlowTypeFarCall; + break; + case ptic_far_return: + mask |= eTraceInstructionControlFlowTypeFarReturn; + break; + case ptic_far_jump: + mask |= eTraceInstructionControlFlowTypeFarJump; break; default: break; Index: lldb/source/Target/TraceCursor.cpp =================================================================== --- lldb/source/Target/TraceCursor.cpp +++ lldb/source/Target/TraceCursor.cpp @@ -21,15 +21,6 @@ return m_exe_ctx_ref; } -void TraceCursor::SetGranularity( - lldb::TraceInstructionControlFlowType granularity) { - m_granularity = granularity; -} - -void TraceCursor::SetIgnoreErrors(bool ignore_errors) { - m_ignore_errors = ignore_errors; -} - void TraceCursor::SetForwards(bool forwards) { m_forwards = forwards; } bool TraceCursor::IsForwards() const { return m_forwards; } Index: lldb/include/lldb/lldb-enumerations.h =================================================================== --- lldb/include/lldb/lldb-enumerations.h +++ lldb/include/lldb/lldb-enumerations.h @@ -965,17 +965,27 @@ /// /// A single instruction can match one or more of these categories. FLAGS_ENUM(TraceInstructionControlFlowType){ - /// Any instruction. + /// The instruction could not be classified. + eTraceInstructionControlFlowTypeError = 0, + /// The instruction is something not listed below. eTraceInstructionControlFlowTypeInstruction = (1u << 1), - /// A conditional or unconditional branch/jump. - eTraceInstructionControlFlowTypeBranch = (1u << 2), - /// A conditional or unconditional branch/jump that changed - /// the control flow of the program. - eTraceInstructionControlFlowTypeTakenBranch = (1u << 3), - /// A call to a function. - eTraceInstructionControlFlowTypeCall = (1u << 4), - /// A return from a function. - eTraceInstructionControlFlowTypeReturn = (1u << 5)}; + /// The instruction is a near (function) call. + eTraceInstructionControlFlowTypeCall = (1u << 2), + /// The instruction is a near (function) return. + eTraceInstructionControlFlowTypeReturn = (1u << 3), + /// The instruction is a near unconditional jump. + eTraceInstructionControlFlowTypeJump = (1u << 4), + /// The instruction is a near conditional jump. + eTraceInstructionControlFlowTypeCondJump = (1u << 5), + /// The instruction is a call-like far transfer. + /// E.g. SYSCALL, SYSENTER, or FAR CALL. + eTraceInstructionControlFlowTypeFarCall = (1u << 6), + /// The instruction is a return-like far transfer. + /// E.g. SYSRET, SYSEXIT, IRET, or FAR RET. + eTraceInstructionControlFlowTypeFarReturn = (1u << 7), + /// The instruction is a jump-like far transfer. + /// E.g. FAR JMP. + eTraceInstructionControlFlowTypeFarJump = (1u << 8)}; LLDB_MARK_AS_BITMASK_ENUM(TraceInstructionControlFlowType) Index: lldb/source/Commands/Options.td =================================================================== --- lldb/source/Commands/Options.td +++ lldb/source/Commands/Options.td @@ -1128,6 +1128,8 @@ Group<1>, Desc<"Dump only instruction address without disassembly nor symbol " "information.">; + def thread_trace_dump_instructions_show_kind : Option<"kind", "k">, Group<1>, + Desc<"For each instruction, print the instruction type">; def thread_trace_dump_instructions_show_tsc : Option<"tsc", "t">, Group<1>, Desc<"For each instruction, print the corresponding timestamp counter if " "available.">; Index: lldb/source/Commands/CommandObjectThread.cpp =================================================================== --- lldb/source/Commands/CommandObjectThread.cpp +++ lldb/source/Commands/CommandObjectThread.cpp @@ -2156,6 +2156,10 @@ m_dumper_options.forwards = true; break; } + case 'k': { + m_dumper_options.show_kind = true; + break; + } case 't': { m_dumper_options.show_tsc = true; break; Index: lldb/include/lldb/Target/TraceInstructionDumper.h =================================================================== --- lldb/include/lldb/Target/TraceInstructionDumper.h +++ lldb/include/lldb/Target/TraceInstructionDumper.h @@ -36,6 +36,8 @@ /// Dump only instruction addresses without disassembly nor symbol /// information. bool raw = false; + /// For each instruction, print the instruction type. + bool show_kind = false; /// For each instruction, print the corresponding timestamp counter if /// available. bool show_tsc = false; @@ -100,6 +102,8 @@ void PrintInstructionHeader(); + void PrintInstructionType(); + void DumpInstructionDisassembly(const InstructionSymbolInfo &insn); /// Dump the symbol context of the given instruction address if it's different Index: lldb/include/lldb/Target/TraceCursor.h =================================================================== --- lldb/include/lldb/Target/TraceCursor.h +++ lldb/include/lldb/Target/TraceCursor.h @@ -40,18 +40,13 @@ /// /// Defaults: /// By default, the cursor points at the end item of the trace, moves -/// backwards, has a move granularity of \a -/// eTraceInstructionControlFlowTypeInstruction (i.e. visit every instruction) -/// and stops at every error (the "ignore errors" flag is \b false). See the -/// \a TraceCursor::Next() method for more documentation. +/// backwards, and stops at every error. +// See the \a TraceCursor::Next() method for more documentation. /// /// Sample usage: /// /// TraceCursorUP cursor = trace.GetTrace(thread); /// -/// cursor->SetGranularity(eTraceInstructionControlFlowTypeCall | -/// eTraceInstructionControlFlowTypeReturn); -/// /// do { /// if (llvm::Error error = cursor->GetError()) /// cout << "error found at: " << llvm::toString(error) << endl; @@ -66,8 +61,8 @@ /// } while(cursor->Next()); /// /// Low level traversal: -/// Unlike the \a TraceCursor::Next() API, which uses a given granularity and -/// direction to advance the cursor, the \a TraceCursor::Seek() method can be +/// Unlike the \a TraceCursor::Next() API, which direction to advance +// the cursor, the \a TraceCursor::Seek() method can be /// used to reposition the cursor to an offset of the end, beginning, or /// current position of the trace. class TraceCursor { @@ -90,12 +85,6 @@ virtual ~TraceCursor() = default; - /// Set the granularity to use in the \a TraceCursor::Next() method. - void SetGranularity(lldb::TraceInstructionControlFlowType granularity); - - /// Set the "ignore errors" flag to use in the \a TraceCursor::Next() method. - void SetIgnoreErrors(bool ignore_errors); - /// Set the direction to use in the \a TraceCursor::Next() method. /// /// \param[in] forwards @@ -109,8 +98,7 @@ /// \b true if the current direction is forwards, \b false if backwards. bool IsForwards() const; - /// Move the cursor to the next instruction that matches the current - /// granularity. + /// Move the cursor to the next instruction /// /// Direction: /// The traversal is done following the current direction of the trace. If @@ -119,17 +107,6 @@ /// the opposite direction. By default, a cursor moves backwards unless /// changed with \a TraceCursor::SetForwards(). /// - /// Granularity: - /// The cursor will traverse the trace looking for the first instruction - /// that matches the current granularity. If there aren't any matching - /// instructions, the cursor won't move, to give the opportunity of - /// changing granularities. - /// - /// Ignore errors: - /// If the "ignore errors" flags is \b false, the traversal will stop as - /// soon as it finds an error in the trace and the cursor will point at - /// it. - /// /// \return /// \b true if the cursor effectively moved, \b false otherwise. virtual bool Next() = 0; @@ -256,9 +233,6 @@ protected: ExecutionContextRef m_exe_ctx_ref; - lldb::TraceInstructionControlFlowType m_granularity = - lldb::eTraceInstructionControlFlowTypeInstruction; - bool m_ignore_errors = false; bool m_forwards = false; }; Index: lldb/source/Target/TraceInstructionDumper.cpp =================================================================== --- lldb/source/Target/TraceInstructionDumper.cpp +++ lldb/source/Target/TraceInstructionDumper.cpp @@ -168,6 +168,47 @@ } } +void TraceInstructionDumper::PrintInstructionType() { + if (m_options.show_kind) { + m_s << " ("; + + if (m_cursor_up->GetInstructionControlFlowType() == + eTraceInstructionControlFlowTypeError) { + m_s.Format("{0,10}", "error) "); + return; + } + + switch (m_cursor_up->GetInstructionControlFlowType() ^ + eTraceInstructionControlFlowTypeInstruction) { + case eTraceInstructionControlFlowTypeCall: + m_s.Format("{0,10}", "call"); + break; + case eTraceInstructionControlFlowTypeReturn: + m_s.Format("{0,10}", "return"); + break; + case eTraceInstructionControlFlowTypeJump: + m_s.Format("{0,10}", "jump"); + break; + case eTraceInstructionControlFlowTypeCondJump: + m_s.Format("{0,10}", "cond jump"); + break; + case eTraceInstructionControlFlowTypeFarCall: + m_s.Format("{0,10}", "far call"); + break; + case eTraceInstructionControlFlowTypeFarReturn: + m_s.Format("{0,10}", "far return"); + break; + case eTraceInstructionControlFlowTypeFarJump: + m_s.Format("{0,10}", "far jump"); + break; + default: + m_s.Format("{0,10}", "other"); + break; + } + m_s << ") "; + } +} + void TraceInstructionDumper::PrintEvents() { if (!m_options.show_events) return; @@ -288,6 +329,7 @@ PrintInstructionHeader(); m_s.Format("{0:x+16}", m_cursor_up->GetLoadAddress()); + PrintInstructionType(); if (!m_options.raw) DumpInstructionDisassembly(insn_info);
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits