Index: lldb/include/lldb/Core/Disassembler.h =================================================================== --- lldb/include/lldb/Core/Disassembler.h +++ lldb/include/lldb/Core/Disassembler.h @@ -79,6 +79,12 @@ return m_comment.c_str(); } + lldb::InstructionControlFlowType + instruction_decode(uint8_t opcode, uint8_t modrm, uint8_t map); + + lldb::InstructionControlFlowType + GetControlFlowInstructionKind(const ExecutionContext *exe_ctx); + virtual void CalculateMnemonicOperandsAndComment(const ExecutionContext *exe_ctx) = 0; @@ -105,6 +111,9 @@ /// \param[in] show_bytes /// Whether the bytes of the assembly instruction should be printed. /// + /// \param[in] show_kind + /// Whether the control flow type of the instruction should be printed. + /// /// \param[in] max_opcode_byte_size /// The size (in bytes) of the largest instruction in the list that /// we are printing (for text justification/alignment purposes) @@ -140,7 +149,8 @@ /// so this method can properly align the instruction opcodes. /// May be 0 to indicate no indentation/alignment of the opcodes. virtual void Dump(Stream *s, uint32_t max_opcode_byte_size, bool show_address, - bool show_bytes, const ExecutionContext *exe_ctx, + bool show_bytes, bool show_kind, + const ExecutionContext *exe_ctx, const SymbolContext *sym_ctx, const SymbolContext *prev_sym_ctx, const FormatEntity::Entry *disassembly_addr_format, @@ -213,6 +223,15 @@ virtual bool IsCall() { return false; } + enum { + PTI_MAP_0, + PTI_MAP_1, + PTI_MAP_2, + PTI_MAP_3, + PTI_MAP_AMD3DNOW, + PTI_MAP_INVALID + }; + protected: Address m_address; // The section offset address of this instruction // We include an address class in the Instruction class to @@ -319,7 +338,7 @@ void Append(lldb::InstructionSP &inst_sp); - void Dump(Stream *s, bool show_address, bool show_bytes, + void Dump(Stream *s, bool show_address, bool show_bytes, bool show_kind, const ExecutionContext *exe_ctx); private: @@ -375,7 +394,8 @@ eOptionMarkPCSourceLine = (1u << 2), // Mark the source line that contains // the current PC (mixed mode only) eOptionMarkPCAddress = - (1u << 3) // Mark the disassembly line the contains the PC + (1u << 3), // Mark the disassembly line the contains the PC + eOptionShowKind = (1u << 4), }; enum HexImmediateStyle { Index: lldb/include/lldb/Target/TraceCursor.h =================================================================== --- lldb/include/lldb/Target/TraceCursor.h +++ lldb/include/lldb/Target/TraceCursor.h @@ -40,34 +40,29 @@ /// /// 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; /// else if (cursor->GetInstructionControlFlowType() & -/// eTraceInstructionControlFlowTypeCall) +/// eInstructionControlFlowTypeCall) /// std::cout << "call found at " << cursor->GetLoadAddress() << /// std::endl; /// else if (cursor->GetInstructionControlFlowType() & -/// eTraceInstructionControlFlowTypeReturn) +/// eInstructionControlFlowTypeReturn) /// std::cout << "return found at " << cursor->GetLoadAddress() << /// std::endl; /// } 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; @@ -251,19 +228,15 @@ virtual lldb::TraceEvents GetEvents() = 0; /// \return - /// The \a lldb::TraceInstructionControlFlowType categories the + /// The \a lldb::InstructionControlFlowType categories the /// instruction the cursor is pointing at falls into. If the cursor points /// to an error in the trace, return \b 0. - virtual lldb::TraceInstructionControlFlowType - GetInstructionControlFlowType() = 0; + virtual lldb::InstructionControlFlowType GetInstructionControlFlowType() = 0; /// \} protected: ExecutionContextRef m_exe_ctx_ref; - lldb::TraceInstructionControlFlowType m_granularity = - lldb::eTraceInstructionControlFlowTypeInstruction; - bool m_ignore_errors = false; bool m_forwards = false; }; Index: lldb/include/lldb/Target/TraceInstructionDumper.h =================================================================== --- lldb/include/lldb/Target/TraceInstructionDumper.h +++ lldb/include/lldb/Target/TraceInstructionDumper.h @@ -34,6 +34,8 @@ bool show_tsc = false; /// Dump the events that happened between instructions. bool show_events = false; + /// For each instruction, print the instruction type. + bool show_kind = false; /// Optional custom id to start traversing from. llvm::Optional id = llvm::None; /// Optional number of instructions to skip from the starting position Index: lldb/include/lldb/lldb-enumerations.h =================================================================== --- lldb/include/lldb/lldb-enumerations.h +++ lldb/include/lldb/lldb-enumerations.h @@ -970,20 +970,30 @@ /// control flow of a trace. /// /// A single instruction can match one or more of these categories. -FLAGS_ENUM(TraceInstructionControlFlowType){ - /// Any instruction. - 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)}; - -LLDB_MARK_AS_BITMASK_ENUM(TraceInstructionControlFlowType) +FLAGS_ENUM(InstructionControlFlowType){ + /// The instruction could not be classified. + eInstructionControlFlowTypeUnknown = 0, + /// The instruction is something not listed below. + eInstructionControlFlowTypeOther = (1u << 1), + /// The instruction is a near (function) call. + eInstructionControlFlowTypeCall = (1u << 2), + /// The instruction is a near (function) return. + eInstructionControlFlowTypeReturn = (1u << 3), + /// The instruction is a near unconditional jump. + eInstructionControlFlowTypeJump = (1u << 4), + /// The instruction is a near conditional jump. + eInstructionControlFlowTypeCondJump = (1u << 5), + /// The instruction is a call-like far transfer. + /// E.g. SYSCALL, SYSENTER, or FAR CALL. + eInstructionControlFlowTypeFarCall = (1u << 6), + /// The instruction is a return-like far transfer. + /// E.g. SYSRET, SYSEXIT, IRET, or FAR RET. + eInstructionControlFlowTypeFarReturn = (1u << 7), + /// The instruction is a jump-like far transfer. + /// E.g. FAR JMP. + eInstructionControlFlowTypeFarJump = (1u << 8)}; + +LLDB_MARK_AS_BITMASK_ENUM(InstructionControlFlowType) /// Watchpoint Kind. /// Index: lldb/source/API/SBInstruction.cpp =================================================================== --- lldb/source/API/SBInstruction.cpp +++ lldb/source/API/SBInstruction.cpp @@ -241,7 +241,8 @@ // didn't have a stream already created, one will get created... FormatEntity::Entry format; FormatEntity::Parse("${addr}: ", format); - inst_sp->Dump(&s.ref(), 0, true, false, nullptr, &sc, nullptr, &format, 0); + inst_sp->Dump(&s.ref(), 0, true, false, false, nullptr, &sc, nullptr, + &format, 0); return true; } return false; @@ -275,8 +276,8 @@ StreamFile out_stream(out_sp); FormatEntity::Entry format; FormatEntity::Parse("${addr}: ", format); - inst_sp->Dump(&out_stream, 0, true, false, nullptr, &sc, nullptr, &format, - 0); + inst_sp->Dump(&out_stream, 0, true, false, false, nullptr, &sc, nullptr, + &format, 0); } } Index: lldb/source/API/SBInstructionList.cpp =================================================================== --- lldb/source/API/SBInstructionList.cpp +++ lldb/source/API/SBInstructionList.cpp @@ -165,8 +165,8 @@ addr, eSymbolContextEverything, sc); } - inst->Dump(&sref, max_opcode_byte_size, true, false, nullptr, &sc, - &prev_sc, &format, 0); + inst->Dump(&sref, max_opcode_byte_size, true, false, false, nullptr, + &sc, &prev_sc, &format, 0); sref.EOL(); } return true; Index: lldb/source/Commands/CommandObjectDisassemble.h =================================================================== --- lldb/source/Commands/CommandObjectDisassemble.h +++ lldb/source/Commands/CommandObjectDisassemble.h @@ -46,6 +46,7 @@ bool show_mixed; // Show mixed source/assembly bool show_bytes; + bool show_kind; uint32_t num_lines_context = 0; uint32_t num_instructions = 0; bool raw; Index: lldb/source/Commands/CommandObjectDisassemble.cpp =================================================================== --- lldb/source/Commands/CommandObjectDisassemble.cpp +++ lldb/source/Commands/CommandObjectDisassemble.cpp @@ -65,6 +65,10 @@ show_bytes = true; break; + case 'k': + show_kind = true; + break; + case 's': { start_addr = OptionArgParser::ToAddress(execution_context, option_arg, LLDB_INVALID_ADDRESS, &error); @@ -154,6 +158,7 @@ ExecutionContext *execution_context) { show_mixed = false; show_bytes = false; + show_kind = false; num_lines_context = 0; num_instructions = 0; func_name.clear(); @@ -493,6 +498,9 @@ if (m_options.show_bytes) options |= Disassembler::eOptionShowBytes; + if (m_options.show_kind) + options |= Disassembler::eOptionShowKind; + if (m_options.raw) options |= Disassembler::eOptionRawOuput; Index: lldb/source/Commands/CommandObjectThread.cpp =================================================================== --- lldb/source/Commands/CommandObjectThread.cpp +++ lldb/source/Commands/CommandObjectThread.cpp @@ -2164,6 +2164,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/source/Commands/Options.td =================================================================== --- lldb/source/Commands/Options.td +++ lldb/source/Commands/Options.td @@ -300,6 +300,8 @@ let Command = "disassemble" in { def disassemble_options_bytes : Option<"bytes", "b">, Desc<"Show opcode bytes when disassembling.">; + def disassemble_options_kind : Option<"kind", "k">, + Desc<"Show instruction control flow type.">; def disassemble_options_context : Option<"context", "C">, Arg<"NumLines">, Desc<"Number of context lines of source to show.">; def disassemble_options_mixed : Option<"mixed", "m">, @@ -1150,6 +1152,8 @@ def thread_trace_dump_instructions_pretty_print: Option<"pretty-json", "J">, Group<1>, Desc<"Dump in JSON format but pretty printing the output for easier readability.">; + 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/Core/Disassembler.cpp =================================================================== --- lldb/source/Core/Disassembler.cpp +++ lldb/source/Core/Disassembler.cpp @@ -527,8 +527,9 @@ } const bool show_bytes = (options & eOptionShowBytes) != 0; - inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, - &prev_sc, nullptr, address_text_size); + const bool show_kind = (options & eOptionShowKind) != 0; + inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, show_kind, + &exe_ctx, &sc, &prev_sc, nullptr, address_text_size); strm.EOL(); } else { break; @@ -568,6 +569,234 @@ Instruction::~Instruction() = default; +lldb::InstructionControlFlowType +Instruction::instruction_decode(uint8_t opcode, uint8_t modrm, uint8_t map) { + lldb::InstructionControlFlowType itype; + // Decide iclass based on opcode and modrm, map + if (map > PTI_MAP_1) + return lldb::eInstructionControlFlowTypeUnknown; + + if (opcode >= 0x70 && opcode <= 0x7F) { + if (map == PTI_MAP_0) + return lldb::eInstructionControlFlowTypeCondJump; + } else if (opcode >= 0x80 && opcode <= 0x8F) { + if (map == PTI_MAP_1) + return lldb::eInstructionControlFlowTypeCondJump; + } + + itype = lldb::eInstructionControlFlowTypeOther; + switch (opcode) { + case 0x9A: + if (map == PTI_MAP_0) + itype = lldb::eInstructionControlFlowTypeFarCall; + break; + case 0xFF: + if (map == PTI_MAP_0) { + uint8_t modrm_reg = (modrm >> 3) & 7; + if (modrm_reg == 2) + itype = lldb::eInstructionControlFlowTypeCall; + else if (modrm_reg == 3) + itype = lldb::eInstructionControlFlowTypeFarCall; + else if (modrm_reg == 4) + itype = lldb::eInstructionControlFlowTypeJump; + else if (modrm_reg == 5) + itype = lldb::eInstructionControlFlowTypeFarJump; + } + break; + case 0xE8: + if (map == PTI_MAP_0) + itype = lldb::eInstructionControlFlowTypeCall; + break; + case 0xCD: + case 0xCC: + case 0xCE: + case 0xF1: + if (map == PTI_MAP_0) + itype = lldb::eInstructionControlFlowTypeFarCall; + break; + case 0xCF: + if (map == PTI_MAP_0) + itype = lldb::eInstructionControlFlowTypeFarReturn; + break; + case 0xE9: + case 0xEB: + if (map == PTI_MAP_0) + itype = lldb::eInstructionControlFlowTypeJump; + break; + case 0xEA: + if (map == PTI_MAP_0) + itype = lldb::eInstructionControlFlowTypeFarJump; + break; + case 0xE3: + case 0xE0: + case 0xE1: + case 0xE2: + if (map == PTI_MAP_0) + itype = lldb::eInstructionControlFlowTypeCondJump; + break; + case 0xC3: + case 0xC2: + if (map == PTI_MAP_0) + itype = lldb::eInstructionControlFlowTypeReturn; + break; + case 0xCB: + case 0xCA: + if (map == PTI_MAP_0) + itype = lldb::eInstructionControlFlowTypeFarReturn; + break; + case 0x05: + case 0x34: + if (map == PTI_MAP_1) + itype = lldb::eInstructionControlFlowTypeFarCall; + break; + case 0x35: + case 0x07: + if (map == PTI_MAP_1) + itype = lldb::eInstructionControlFlowTypeFarReturn; + break; + case 0x01: + if (map == PTI_MAP_1) { + switch (modrm) { + case 0xc1: + itype = lldb::eInstructionControlFlowTypeFarCall; + break; + case 0xc2: + case 0xc3: + itype = lldb::eInstructionControlFlowTypeFarReturn; + break; + default: + break; + } + } + break; + default: + break; + } + return itype; +} + +lldb::InstructionControlFlowType +Instruction::GetControlFlowInstructionKind(const ExecutionContext *exe_ctx) { + uint8_t *opcode_bytes = (uint8_t *)m_opcode.GetOpcodeBytes(); + uint8_t opcode, modrm, map; + int op_idx = 0; + bool prefix_done = false; + + if (!opcode_bytes) { + // x86_64 and i386 are the only ones that use bytes right now + // Else, we have ARM or MIPS, not yet implemented + return lldb::eInstructionControlFlowTypeUnknown; + } + + // Get opcode and modrm + map = PTI_MAP_INVALID; + while (!prefix_done) { + opcode = opcode_bytes[op_idx]; + switch (opcode) { + // prefix_ignore + case 0x26: + case 0x2e: + case 0x36: + case 0x3e: + case 0x64: + case 0x65: + // prefix_osz, prefix_asz + case 0x66: + case 0x67: + // prefix_lock, prefix_f2, prefix_f3 + case 0xf0: + case 0xf2: + case 0xf3: + op_idx++; + break; + + // prefix_rex + case 0x40 ... 0x4f: + if (exe_ctx->GetTargetRef().GetArchitecture().GetMachine() == + llvm::Triple::ArchType::x86_64) + op_idx++; + else + prefix_done = true; + break; + + // prefix_vex_c4, c5 + case 0xc5: + if (exe_ctx->GetTargetRef().GetArchitecture().GetMachine() != + llvm::Triple::ArchType::x86_64 && + (opcode_bytes[op_idx + 1] & 0xc0) != 0xc0) { + prefix_done = true; + break; + } + + map = PTI_MAP_1; + opcode = opcode_bytes[op_idx + 2]; + modrm = opcode_bytes[op_idx + 3]; + return instruction_decode(opcode, modrm, map); + break; + + case 0xc4: + if (exe_ctx->GetTargetRef().GetArchitecture().GetMachine() != + llvm::Triple::ArchType::x86_64 && + (opcode_bytes[op_idx + 1] & 0xc0) != 0xc0) { + prefix_done = true; + break; + } + map = opcode_bytes[op_idx + 1] & 0x1f; + opcode = opcode_bytes[op_idx + 3]; + modrm = opcode_bytes[op_idx + 4]; + return instruction_decode(opcode, modrm, map); + break; + + // prefix_evex + case 0x62: + if (exe_ctx->GetTargetRef().GetArchitecture().GetMachine() != + llvm::Triple::ArchType::x86_64 && + (opcode_bytes[op_idx + 1] & 0xc0) != 0xc0) { + prefix_done = true; + break; + } + map = opcode_bytes[op_idx + 1] & 0x03; + opcode = opcode_bytes[op_idx + 4]; + modrm = opcode_bytes[op_idx + 5]; + return instruction_decode(opcode, modrm, map); + break; + default: + prefix_done = true; + break; + } + } // prefix done + + opcode = opcode_bytes[op_idx]; + modrm = opcode_bytes[op_idx + 1]; + map = PTI_MAP_0; + + if (opcode == 0x0F) { + if (opcode_bytes[op_idx + 1] == 0x38) { + map = PTI_MAP_2; + opcode = opcode_bytes[op_idx + 2]; + modrm = opcode_bytes[op_idx + 3]; + } else if (opcode_bytes[op_idx + 1] == 0x3A) { + map = PTI_MAP_3; + opcode = opcode_bytes[op_idx + 2]; + modrm = opcode_bytes[op_idx + 3]; + } else if ((opcode_bytes[op_idx + 1] & 0xf8) == 0x38) { + map = PTI_MAP_INVALID; + opcode = opcode_bytes[op_idx + 2]; + modrm = opcode_bytes[op_idx + 3]; + } else if (opcode_bytes[op_idx + 1] == 0x0F) { + map = PTI_MAP_AMD3DNOW; + opcode = opcode_bytes[op_idx + 1]; + modrm = opcode_bytes[op_idx + 2]; + } else { + map = PTI_MAP_1; + opcode = opcode_bytes[op_idx + 1]; + modrm = opcode_bytes[op_idx + 2]; + } + } + + return instruction_decode(opcode, modrm, map); +} + AddressClass Instruction::GetAddressClass() { if (m_address_class == AddressClass::eInvalid) m_address_class = m_address.GetAddressClass(); @@ -575,7 +804,7 @@ } void Instruction::Dump(lldb_private::Stream *s, uint32_t max_opcode_byte_size, - bool show_address, bool show_bytes, + bool show_address, bool show_bytes, bool show_kind, const ExecutionContext *exe_ctx, const SymbolContext *sym_ctx, const SymbolContext *prev_sym_ctx, @@ -613,6 +842,39 @@ } } + if (show_kind) { + // TODO-SUJIN + switch (GetControlFlowInstructionKind(exe_ctx)) { + case eInstructionControlFlowTypeUnknown: + ss.Printf("%-12s", "unknwon"); + break; + case eInstructionControlFlowTypeOther: + ss.Printf("%-12s", "other"); + break; + case eInstructionControlFlowTypeCall: + ss.Printf("%-12s", "call"); + break; + case eInstructionControlFlowTypeReturn: + ss.Printf("%-12s", "return"); + break; + case eInstructionControlFlowTypeJump: + ss.Printf("%-12s", "jump"); + break; + case eInstructionControlFlowTypeCondJump: + ss.Printf("%-12s", "cond jump"); + break; + case eInstructionControlFlowTypeFarCall: + ss.Printf("%-12s", "far call"); + break; + case eInstructionControlFlowTypeFarReturn: + ss.Printf("%-12s", "far return"); + break; + case eInstructionControlFlowTypeFarJump: + ss.Printf("%-12s", "far jump"); + break; + } + } + const size_t opcode_pos = ss.GetSizeOfLastLine(); // The default opcode size of 7 characters is plenty for most architectures @@ -957,7 +1219,7 @@ } void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes, - const ExecutionContext *exe_ctx) { + bool show_kind, const ExecutionContext *exe_ctx) { const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize(); collection::const_iterator pos, begin, end; @@ -975,8 +1237,8 @@ pos != end; ++pos) { if (pos != begin) s->EOL(); - (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx, - nullptr, nullptr, disassembly_format, 0); + (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, show_kind, + exe_ctx, nullptr, nullptr, disassembly_format, 0); } } @@ -994,7 +1256,7 @@ size_t num_instructions = m_instructions.size(); uint32_t next_branch = UINT32_MAX; - + if (found_calls) *found_calls = false; for (size_t i = start; i < num_instructions; i++) { Index: lldb/source/Core/DumpDataExtractor.cpp =================================================================== --- lldb/source/Core/DumpDataExtractor.cpp +++ lldb/source/Core/DumpDataExtractor.cpp @@ -170,10 +170,11 @@ offset += bytes_consumed; const bool show_address = base_addr != LLDB_INVALID_ADDRESS; const bool show_bytes = true; + const bool show_kind = true; ExecutionContext exe_ctx; exe_scope->CalculateExecutionContext(exe_ctx); disassembler_sp->GetInstructionList().Dump(s, show_address, show_bytes, - &exe_ctx); + show_kind, &exe_ctx); } } } else Index: lldb/source/Expression/IRExecutionUnit.cpp =================================================================== --- lldb/source/Expression/IRExecutionUnit.cpp +++ lldb/source/Expression/IRExecutionUnit.cpp @@ -200,7 +200,7 @@ UINT32_MAX, false, false); InstructionList &instruction_list = disassembler_sp->GetInstructionList(); - instruction_list.Dump(&stream, true, true, &exe_ctx); + instruction_list.Dump(&stream, true, true, true, &exe_ctx); return ret; } 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 @@ -182,7 +182,7 @@ /// /// \return /// The control flow categories, or \b 0 if the instruction is an error. - lldb::TraceInstructionControlFlowType + lldb::InstructionControlFlowType GetInstructionControlFlowType(size_t insn_index) const; /// Construct the TSC range that covers the given instruction index. 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 @@ -59,34 +59,36 @@ return m_instruction_ips[insn_index]; } -TraceInstructionControlFlowType +InstructionControlFlowType DecodedThread::GetInstructionControlFlowType(size_t insn_index) const { if (IsInstructionAnError(insn_index)) - return (TraceInstructionControlFlowType)0; + return eInstructionControlFlowTypeUnknown; - TraceInstructionControlFlowType mask = - eTraceInstructionControlFlowTypeInstruction; + InstructionControlFlowType mask = eInstructionControlFlowTypeOther; - 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 |= eInstructionControlFlowTypeCall; break; case ptic_return: - case ptic_far_return: - mask |= eTraceInstructionControlFlowTypeReturn; + mask |= eInstructionControlFlowTypeReturn; + break; + case ptic_jump: + mask |= eInstructionControlFlowTypeJump; + break; + case ptic_cond_jump: + mask |= eInstructionControlFlowTypeCondJump; break; - case ptic_call: case ptic_far_call: - mask |= eTraceInstructionControlFlowTypeCall; + mask |= eInstructionControlFlowTypeFarCall; + break; + case ptic_far_return: + mask |= eInstructionControlFlowTypeFarReturn; + break; + case ptic_far_jump: + mask |= eInstructionControlFlowTypeFarJump; break; default: break; Index: lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h =================================================================== --- lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h +++ lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h @@ -31,8 +31,7 @@ lldb::TraceEvents GetEvents() override; - lldb::TraceInstructionControlFlowType - GetInstructionControlFlowType() override; + lldb::InstructionControlFlowType GetInstructionControlFlowType() override; bool IsError() override; 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 @@ -112,8 +109,7 @@ return m_decoded_thread_sp->GetEvents(m_pos); } -TraceInstructionControlFlowType -TraceCursorIntelPT::GetInstructionControlFlowType() { +InstructionControlFlowType TraceCursorIntelPT::GetInstructionControlFlowType() { return m_decoded_thread_sp->GetInstructionControlFlowType(m_pos); } Index: lldb/source/Plugins/TraceExporter/common/TraceHTR.cpp =================================================================== --- lldb/source/Plugins/TraceExporter/common/TraceHTR.cpp +++ lldb/source/Plugins/TraceExporter/common/TraceHTR.cpp @@ -157,14 +157,13 @@ more_data_in_trace = cursor.Next(); } else { lldb::addr_t current_instruction_load_address = cursor.GetLoadAddress(); - lldb::TraceInstructionControlFlowType current_instruction_type = + lldb::InstructionControlFlowType current_instruction_type = cursor.GetInstructionControlFlowType(); m_instruction_layer_up->AppendInstruction( current_instruction_load_address); more_data_in_trace = cursor.Next(); - if (current_instruction_type & - lldb::eTraceInstructionControlFlowTypeCall) { + if (current_instruction_type & lldb::eInstructionControlFlowTypeCall) { if (more_data_in_trace && !cursor.IsError()) { m_instruction_layer_up->AddCallInstructionMetadata( current_instruction_load_address, Index: lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp =================================================================== --- lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -83,6 +83,7 @@ const uint32_t addr_byte_size = m_arch.GetAddressByteSize(); const bool show_address = true; const bool show_bytes = true; + const bool show_kind = true; m_inst_emulator_up->GetRegisterInfo(unwind_plan.GetRegisterKind(), unwind_plan.GetInitialCFARegister(), m_cfa_reg_info); @@ -244,7 +245,8 @@ lldb_private::FormatEntity::Entry format; FormatEntity::Parse("${frame.pc}: ", format); inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize(), show_address, - show_bytes, nullptr, nullptr, nullptr, &format, 0); + show_bytes, show_kind, nullptr, nullptr, nullptr, + &format, 0); log->PutString(strm.GetString()); } Index: lldb/source/Symbol/Function.cpp =================================================================== --- lldb/source/Symbol/Function.cpp +++ lldb/source/Symbol/Function.cpp @@ -440,8 +440,9 @@ if (disassembler_sp) { const bool show_address = true; const bool show_bytes = false; + const bool show_kind = false; disassembler_sp->GetInstructionList().Dump(&strm, show_address, show_bytes, - &exe_ctx); + show_kind, &exe_ctx); return true; } return false; Index: lldb/source/Symbol/Symbol.cpp =================================================================== --- lldb/source/Symbol/Symbol.cpp +++ lldb/source/Symbol/Symbol.cpp @@ -558,8 +558,9 @@ if (disassembler_sp) { const bool show_address = true; const bool show_bytes = false; + const bool show_kind = false; disassembler_sp->GetInstructionList().Dump(&strm, show_address, show_bytes, - &exe_ctx); + show_kind, &exe_ctx); return true; } return false; Index: lldb/source/Target/ThreadPlanTracer.cpp =================================================================== --- lldb/source/Target/ThreadPlanTracer.cpp +++ lldb/source/Target/ThreadPlanTracer.cpp @@ -170,12 +170,13 @@ if (instruction_list.GetSize()) { const bool show_bytes = true; const bool show_address = true; + const bool show_kind = true; Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get(); const FormatEntity::Entry *disassemble_format = m_process.GetTarget().GetDebugger().GetDisassemblyFormat(); instruction->Dump(stream, max_opcode_byte_size, show_address, - show_bytes, nullptr, nullptr, nullptr, + show_bytes, show_kind, nullptr, nullptr, nullptr, disassemble_format, 0); } } 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/source/Target/TraceInstructionDumper.cpp =================================================================== --- lldb/source/Target/TraceInstructionDumper.cpp +++ lldb/source/Target/TraceInstructionDumper.cpp @@ -151,6 +151,7 @@ insn.symbol_info->instruction->Dump(&m_s, /*max_opcode_byte_size=*/0, /*show_address=*/false, /*show_bytes=*/false, + /*show_kind=*/m_options.show_kind, &insn.symbol_info->exe_ctx, &insn.symbol_info->sc, /*prev_sym_ctx=*/nullptr,