Skip to content

Commit ad7bcda

Browse files
author
Walter Erquinigo
committed
[trace] Add a flag to the decoder to output the instruction type
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 ``` Reviewed By: wallace Differential Revision: https://reviews.llvm.org/D128477
1 parent 5f8cefe commit ad7bcda

24 files changed

+643
-60
lines changed

lldb/include/lldb/Core/Disassembler.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ class Instruction {
7979
return m_comment.c_str();
8080
}
8181

82+
/// \return
83+
/// The control flow kind of this instruction, or
84+
/// eInstructionControlFlowKindUnknown if the instruction
85+
/// can't be classified.
86+
lldb::InstructionControlFlowKind GetControlFlowKind(const ArchSpec &arch);
87+
8288
virtual void
8389
CalculateMnemonicOperandsAndComment(const ExecutionContext *exe_ctx) = 0;
8490

@@ -105,6 +111,9 @@ class Instruction {
105111
/// \param[in] show_bytes
106112
/// Whether the bytes of the assembly instruction should be printed.
107113
///
114+
/// \param[in] show_control_flow_kind
115+
/// Whether the control flow kind of the instruction should be printed.
116+
///
108117
/// \param[in] max_opcode_byte_size
109118
/// The size (in bytes) of the largest instruction in the list that
110119
/// we are printing (for text justification/alignment purposes)
@@ -140,7 +149,8 @@ class Instruction {
140149
/// so this method can properly align the instruction opcodes.
141150
/// May be 0 to indicate no indentation/alignment of the opcodes.
142151
virtual void Dump(Stream *s, uint32_t max_opcode_byte_size, bool show_address,
143-
bool show_bytes, const ExecutionContext *exe_ctx,
152+
bool show_bytes, bool show_control_flow_kind,
153+
const ExecutionContext *exe_ctx,
144154
const SymbolContext *sym_ctx,
145155
const SymbolContext *prev_sym_ctx,
146156
const FormatEntity::Entry *disassembly_addr_format,
@@ -320,7 +330,7 @@ class InstructionList {
320330
void Append(lldb::InstructionSP &inst_sp);
321331

322332
void Dump(Stream *s, bool show_address, bool show_bytes,
323-
const ExecutionContext *exe_ctx);
333+
bool show_control_flow_kind, const ExecutionContext *exe_ctx);
324334

325335
private:
326336
typedef std::vector<lldb::InstructionSP> collection;
@@ -375,7 +385,8 @@ class Disassembler : public std::enable_shared_from_this<Disassembler>,
375385
eOptionMarkPCSourceLine = (1u << 2), // Mark the source line that contains
376386
// the current PC (mixed mode only)
377387
eOptionMarkPCAddress =
378-
(1u << 3) // Mark the disassembly line the contains the PC
388+
(1u << 3), // Mark the disassembly line the contains the PC
389+
eOptionShowControlFlowKind = (1u << 4),
379390
};
380391

381392
enum HexImmediateStyle {

lldb/include/lldb/Target/TraceDumper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ struct TraceDumperOptions {
3434
bool show_tsc = false;
3535
/// Dump the events that happened between instructions.
3636
bool show_events = false;
37+
/// For each instruction, print the instruction kind.
38+
bool show_control_flow_kind = false;
3739
/// Optional custom id to start traversing from.
3840
llvm::Optional<uint64_t> id = llvm::None;
3941
/// Optional number of instructions to skip from the starting position

lldb/include/lldb/lldb-enumerations.h

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -970,20 +970,30 @@ enum ExpressionEvaluationPhase {
970970
/// control flow of a trace.
971971
///
972972
/// A single instruction can match one or more of these categories.
973-
FLAGS_ENUM(TraceInstructionControlFlowType){
974-
/// Any instruction.
975-
eTraceInstructionControlFlowTypeInstruction = (1u << 1),
976-
/// A conditional or unconditional branch/jump.
977-
eTraceInstructionControlFlowTypeBranch = (1u << 2),
978-
/// A conditional or unconditional branch/jump that changed
979-
/// the control flow of the program.
980-
eTraceInstructionControlFlowTypeTakenBranch = (1u << 3),
981-
/// A call to a function.
982-
eTraceInstructionControlFlowTypeCall = (1u << 4),
983-
/// A return from a function.
984-
eTraceInstructionControlFlowTypeReturn = (1u << 5)};
985-
986-
LLDB_MARK_AS_BITMASK_ENUM(TraceInstructionControlFlowType)
973+
enum InstructionControlFlowKind {
974+
/// The instruction could not be classified.
975+
eInstructionControlFlowKindUnknown = 0,
976+
/// The instruction is something not listed below, i.e. it's a sequential
977+
/// instruction that doesn't affect the control flow of the program.
978+
eInstructionControlFlowKindOther,
979+
/// The instruction is a near (function) call.
980+
eInstructionControlFlowKindCall,
981+
/// The instruction is a near (function) return.
982+
eInstructionControlFlowKindReturn,
983+
/// The instruction is a near unconditional jump.
984+
eInstructionControlFlowKindJump,
985+
/// The instruction is a near conditional jump.
986+
eInstructionControlFlowKindCondJump,
987+
/// The instruction is a call-like far transfer.
988+
/// E.g. SYSCALL, SYSENTER, or FAR CALL.
989+
eInstructionControlFlowKindFarCall,
990+
/// The instruction is a return-like far transfer.
991+
/// E.g. SYSRET, SYSEXIT, IRET, or FAR RET.
992+
eInstructionControlFlowKindFarReturn,
993+
/// The instruction is a jump-like far transfer.
994+
/// E.g. FAR JMP.
995+
eInstructionControlFlowKindFarJump
996+
};
987997

988998
/// Watchpoint Kind.
989999
///

lldb/source/API/SBInstruction.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@ bool SBInstruction::GetDescription(lldb::SBStream &s) {
241241
// didn't have a stream already created, one will get created...
242242
FormatEntity::Entry format;
243243
FormatEntity::Parse("${addr}: ", format);
244-
inst_sp->Dump(&s.ref(), 0, true, false, nullptr, &sc, nullptr, &format, 0);
244+
inst_sp->Dump(&s.ref(), 0, true, false, /*show_control_flow_kind=*/false,
245+
nullptr, &sc, nullptr, &format, 0);
245246
return true;
246247
}
247248
return false;
@@ -275,8 +276,8 @@ void SBInstruction::Print(FileSP out_sp) {
275276
StreamFile out_stream(out_sp);
276277
FormatEntity::Entry format;
277278
FormatEntity::Parse("${addr}: ", format);
278-
inst_sp->Dump(&out_stream, 0, true, false, nullptr, &sc, nullptr, &format,
279-
0);
279+
inst_sp->Dump(&out_stream, 0, true, false, /*show_control_flow_kind=*/false,
280+
nullptr, &sc, nullptr, &format, 0);
280281
}
281282
}
282283

lldb/source/API/SBInstructionList.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,9 @@ bool SBInstructionList::GetDescription(Stream &sref) {
165165
addr, eSymbolContextEverything, sc);
166166
}
167167

168-
inst->Dump(&sref, max_opcode_byte_size, true, false, nullptr, &sc,
169-
&prev_sc, &format, 0);
168+
inst->Dump(&sref, max_opcode_byte_size, true, false,
169+
/*show_control_flow_kind=*/false, nullptr, &sc, &prev_sc,
170+
&format, 0);
170171
sref.EOL();
171172
}
172173
return true;

lldb/source/Commands/CommandObjectDisassemble.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ Status CommandObjectDisassemble::CommandOptions::SetOptionValue(
6565
show_bytes = true;
6666
break;
6767

68+
case 'k':
69+
show_control_flow_kind = true;
70+
break;
71+
6872
case 's': {
6973
start_addr = OptionArgParser::ToAddress(execution_context, option_arg,
7074
LLDB_INVALID_ADDRESS, &error);
@@ -154,6 +158,7 @@ void CommandObjectDisassemble::CommandOptions::OptionParsingStarting(
154158
ExecutionContext *execution_context) {
155159
show_mixed = false;
156160
show_bytes = false;
161+
show_control_flow_kind = false;
157162
num_lines_context = 0;
158163
num_instructions = 0;
159164
func_name.clear();
@@ -493,6 +498,9 @@ bool CommandObjectDisassemble::DoExecute(Args &command,
493498
if (m_options.show_bytes)
494499
options |= Disassembler::eOptionShowBytes;
495500

501+
if (m_options.show_control_flow_kind)
502+
options |= Disassembler::eOptionShowControlFlowKind;
503+
496504
if (m_options.raw)
497505
options |= Disassembler::eOptionRawOuput;
498506

lldb/source/Commands/CommandObjectDisassemble.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class CommandObjectDisassemble : public CommandObjectParsed {
4646

4747
bool show_mixed; // Show mixed source/assembly
4848
bool show_bytes;
49+
bool show_control_flow_kind;
4950
uint32_t num_lines_context = 0;
5051
uint32_t num_instructions = 0;
5152
bool raw;

lldb/source/Commands/CommandObjectThread.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2174,6 +2174,10 @@ class CommandObjectTraceDumpInstructions : public CommandObjectParsed {
21742174
m_dumper_options.forwards = true;
21752175
break;
21762176
}
2177+
case 'k': {
2178+
m_dumper_options.show_control_flow_kind = true;
2179+
break;
2180+
}
21772181
case 't': {
21782182
m_dumper_options.show_tsc = true;
21792183
break;

lldb/source/Commands/Options.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,11 @@ let Command = "breakpoint command delete" in {
300300
let Command = "disassemble" in {
301301
def disassemble_options_bytes : Option<"bytes", "b">,
302302
Desc<"Show opcode bytes when disassembling.">;
303+
def disassemble_options_kind : Option<"kind", "k">,
304+
Desc<"Show instruction control flow kind. Refer to the enum "
305+
"`InstructionControlFlowKind` for a list of control flow kind. "
306+
"As an important note, far jumps, far calls and far returns often indicate "
307+
"calls to and from kernel.">;
303308
def disassemble_options_context : Option<"context", "C">, Arg<"NumLines">,
304309
Desc<"Number of context lines of source to show.">;
305310
def disassemble_options_mixed : Option<"mixed", "m">,
@@ -1150,6 +1155,11 @@ let Command = "thread trace dump instructions" in {
11501155
def thread_trace_dump_instructions_pretty_print: Option<"pretty-json", "J">,
11511156
Group<1>,
11521157
Desc<"Dump in JSON format but pretty printing the output for easier readability.">;
1158+
def thread_trace_dump_instructions_show_kind : Option<"kind", "k">, Group<1>,
1159+
Desc<"Show instruction control flow kind. Refer to the enum "
1160+
"`InstructionControlFlowKind` for a list of control flow kind. "
1161+
"As an important note, far jumps, far calls and far returns often indicate "
1162+
"calls to and from kernel.">;
11531163
def thread_trace_dump_instructions_show_tsc : Option<"tsc", "t">, Group<1>,
11541164
Desc<"For each instruction, print the corresponding timestamp counter if "
11551165
"available.">;

0 commit comments

Comments
 (0)