Skip to content

Commit 35e60f5

Browse files
author
Walter Erquinigo
committed
[NFC][trace] simplify the instruction dumper
TraceInstructionDumper::DumpInstructions was becoming too big, so I'm refactoring it into smaller functions. I also made some static methods proper instance methods to simplify calls. Other minor improvements are also done. Differential Revision: https://reviews.llvm.org/D124064
1 parent 9980148 commit 35e60f5

File tree

2 files changed

+140
-121
lines changed

2 files changed

+140
-121
lines changed

lldb/include/lldb/Target/TraceInstructionDumper.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,24 @@
88

99
#include "lldb/Target/TraceCursor.h"
1010

11+
#include "lldb/Symbol/SymbolContext.h"
12+
1113
#ifndef LLDB_TARGET_TRACE_INSTRUCTION_DUMPER_H
1214
#define LLDB_TARGET_TRACE_INSTRUCTION_DUMPER_H
1315

1416
namespace lldb_private {
1517

18+
/// Helper struct that holds symbol, disassembly and address information of an
19+
/// instruction.
20+
struct InstructionSymbolInfo {
21+
SymbolContext sc;
22+
Address address;
23+
lldb::addr_t load_address;
24+
lldb::DisassemblerSP disassembler;
25+
lldb::InstructionSP instruction;
26+
lldb_private::ExecutionContext exe_ctx;
27+
};
28+
1629
/// Class that holds the configuration used by \a TraceInstructionDumper for
1730
/// traversing and dumping instructions.
1831
struct TraceInstructionDumperOptions {
@@ -83,6 +96,28 @@ class TraceInstructionDumper {
8396

8497
void PrintEvents();
8598

99+
void PrintMissingInstructionsMessage();
100+
101+
void PrintInstructionHeader();
102+
103+
void DumpInstructionDisassembly(const InstructionSymbolInfo &insn);
104+
105+
/// Dump the symbol context of the given instruction address if it's different
106+
/// from the symbol context of the previous instruction in the trace.
107+
///
108+
/// \param[in] prev_sc
109+
/// The symbol context of the previous instruction in the trace.
110+
///
111+
/// \param[in] address
112+
/// The address whose symbol information will be dumped.
113+
///
114+
/// \return
115+
/// The symbol context of the current address, which might differ from the
116+
/// previous one.
117+
void DumpInstructionSymbolContext(
118+
const llvm::Optional<InstructionSymbolInfo> &prev_insn,
119+
const InstructionSymbolInfo &insn);
120+
86121
lldb::TraceCursorUP m_cursor_up;
87122
TraceInstructionDumperOptions m_options;
88123
Stream &m_s;

lldb/source/Target/TraceInstructionDumper.cpp

Lines changed: 105 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ TraceInstructionDumper::TraceInstructionDumper(
4747
}
4848
}
4949

50-
/// \return
51-
/// Return \b true if the cursor could move one step.
5250
bool TraceInstructionDumper::TryMoveOneStep() {
5351
if (!m_cursor_up->Next()) {
5452
SetNoMoreData();
@@ -57,17 +55,6 @@ bool TraceInstructionDumper::TryMoveOneStep() {
5755
return true;
5856
}
5957

60-
/// Helper struct that holds symbol, disassembly and address information of an
61-
/// instruction.
62-
struct InstructionSymbolInfo {
63-
SymbolContext sc;
64-
Address address;
65-
lldb::addr_t load_address;
66-
lldb::DisassemblerSP disassembler;
67-
lldb::InstructionSP instruction;
68-
lldb_private::ExecutionContext exe_ctx;
69-
};
70-
7158
// This custom LineEntry validator is neded because some line_entries have
7259
// 0 as line, which is meaningless. Notice that LineEntry::IsValid only
7360
// checks that line is not LLDB_INVALID_LINE_NUMBER, i.e. UINT32_MAX.
@@ -122,46 +109,35 @@ IsSameInstructionSymbolContext(const InstructionSymbolInfo &prev_insn,
122109
return curr_line_valid == prev_line_valid;
123110
}
124111

125-
/// Dump the symbol context of the given instruction address if it's different
126-
/// from the symbol context of the previous instruction in the trace.
127-
///
128-
/// \param[in] prev_sc
129-
/// The symbol context of the previous instruction in the trace.
130-
///
131-
/// \param[in] address
132-
/// The address whose symbol information will be dumped.
133-
///
134-
/// \return
135-
/// The symbol context of the current address, which might differ from the
136-
/// previous one.
137-
static void
138-
DumpInstructionSymbolContext(Stream &s,
139-
Optional<InstructionSymbolInfo> prev_insn,
140-
InstructionSymbolInfo &insn) {
112+
void TraceInstructionDumper::DumpInstructionSymbolContext(
113+
const Optional<InstructionSymbolInfo> &prev_insn,
114+
const InstructionSymbolInfo &insn) {
141115
if (prev_insn && IsSameInstructionSymbolContext(*prev_insn, insn))
142116
return;
143117

144-
s.Printf(" ");
118+
m_s << " ";
145119

146120
if (!insn.sc.module_sp)
147-
s.Printf("(none)");
121+
m_s << "(none)";
148122
else if (!insn.sc.function && !insn.sc.symbol)
149-
s.Printf("%s`(none)",
150-
insn.sc.module_sp->GetFileSpec().GetFilename().AsCString());
123+
m_s.Format("{0}`(none)",
124+
insn.sc.module_sp->GetFileSpec().GetFilename().AsCString());
151125
else
152-
insn.sc.DumpStopContext(&s, insn.exe_ctx.GetTargetPtr(), insn.address,
126+
insn.sc.DumpStopContext(&m_s, insn.exe_ctx.GetTargetPtr(), insn.address,
153127
/*show_fullpaths=*/false,
154128
/*show_module=*/true, /*show_inlined_frames=*/false,
155129
/*show_function_arguments=*/true,
156130
/*show_function_name=*/true);
157-
s.Printf("\n");
131+
m_s << "\n";
158132
}
159133

160-
static void DumpInstructionDisassembly(Stream &s, InstructionSymbolInfo &insn) {
134+
void TraceInstructionDumper::DumpInstructionDisassembly(
135+
const InstructionSymbolInfo &insn) {
161136
if (!insn.instruction)
162137
return;
163-
s.Printf(" ");
164-
insn.instruction->Dump(&s, /*max_opcode_byte_size=*/0, /*show_address=*/false,
138+
m_s << " ";
139+
insn.instruction->Dump(&m_s, /*max_opcode_byte_size=*/0,
140+
/*show_address=*/false,
165141
/*show_bytes=*/false, &insn.exe_ctx, &insn.sc,
166142
/*prev_sym_ctx=*/nullptr,
167143
/*disassembly_addr_format=*/nullptr,
@@ -172,6 +148,26 @@ void TraceInstructionDumper::SetNoMoreData() { m_no_more_data = true; }
172148

173149
bool TraceInstructionDumper::HasMoreData() { return !m_no_more_data; }
174150

151+
void TraceInstructionDumper::PrintMissingInstructionsMessage() {
152+
m_s << " ...missing instructions\n";
153+
}
154+
155+
void TraceInstructionDumper::PrintInstructionHeader() {
156+
m_s.Format(" {0}: ", m_cursor_up->GetId());
157+
158+
if (m_options.show_tsc) {
159+
m_s << "[tsc=";
160+
161+
if (Optional<uint64_t> timestamp =
162+
m_cursor_up->GetCounter(lldb::eTraceCounterTSC))
163+
m_s.Format("{0:x+16}", *timestamp);
164+
else
165+
m_s << "unavailable";
166+
167+
m_s << "] ";
168+
}
169+
}
170+
175171
void TraceInstructionDumper::PrintEvents() {
176172
if (!m_options.show_events)
177173
return;
@@ -182,90 +178,76 @@ void TraceInstructionDumper::PrintEvents() {
182178
});
183179
}
184180

185-
Optional<lldb::tid_t> TraceInstructionDumper::DumpInstructions(size_t count) {
181+
/// Find the symbol context for the given address reusing the previous
182+
/// instruction's symbol context when possible.
183+
static SymbolContext
184+
CalculateSymbolContext(const Address &address,
185+
const InstructionSymbolInfo &prev_insn_info) {
186+
AddressRange range;
187+
if (prev_insn_info.sc.GetAddressRange(eSymbolContextEverything, 0,
188+
/*inline_block_range*/ false, range) &&
189+
range.Contains(address))
190+
return prev_insn_info.sc;
191+
192+
SymbolContext sc;
193+
address.CalculateSymbolContext(&sc, eSymbolContextEverything);
194+
return sc;
195+
}
196+
197+
/// Find the disassembler for the given address reusing the previous
198+
/// instruction's disassembler when possible.
199+
static std::tuple<DisassemblerSP, InstructionSP>
200+
CalculateDisass(const InstructionSymbolInfo &insn_info,
201+
const InstructionSymbolInfo &prev_insn_info,
202+
const ExecutionContext &exe_ctx) {
203+
if (prev_insn_info.disassembler) {
204+
if (InstructionSP instruction =
205+
prev_insn_info.disassembler->GetInstructionList()
206+
.GetInstructionAtAddress(insn_info.address))
207+
return std::make_tuple(prev_insn_info.disassembler, instruction);
208+
}
209+
210+
if (insn_info.sc.function) {
211+
if (DisassemblerSP disassembler =
212+
insn_info.sc.function->GetInstructions(exe_ctx, nullptr)) {
213+
if (InstructionSP instruction =
214+
disassembler->GetInstructionList().GetInstructionAtAddress(
215+
insn_info.address))
216+
return std::make_tuple(disassembler, instruction);
217+
}
218+
}
219+
// We fallback to a single instruction disassembler
220+
Target &target = exe_ctx.GetTargetRef();
221+
const ArchSpec arch = target.GetArchitecture();
222+
AddressRange range(insn_info.address, arch.GetMaximumOpcodeByteSize());
223+
DisassemblerSP disassembler =
224+
Disassembler::DisassembleRange(arch, /*plugin_name*/ nullptr,
225+
/*flavor*/ nullptr, target, range);
226+
return std::make_tuple(
227+
disassembler,
228+
disassembler ? disassembler->GetInstructionList().GetInstructionAtAddress(
229+
insn_info.address)
230+
: InstructionSP());
231+
}
232+
233+
Optional<lldb::user_id_t>
234+
TraceInstructionDumper::DumpInstructions(size_t count) {
186235
ThreadSP thread_sp = m_cursor_up->GetExecutionContextRef().GetThreadSP();
187236
if (!thread_sp) {
188-
m_s.Printf("invalid thread");
237+
m_s << "invalid thread";
189238
return None;
190239
}
191240

192241
bool was_prev_instruction_an_error = false;
193-
194-
auto printMissingInstructionsMessage = [&]() {
195-
m_s.Printf(" ...missing instructions\n");
196-
};
197-
198-
auto printInstructionHeader = [&](uint64_t id) {
199-
m_s.Printf(" %" PRIu64 ": ", id);
200-
201-
if (m_options.show_tsc) {
202-
m_s.Printf("[tsc=");
203-
204-
if (Optional<uint64_t> timestamp = m_cursor_up->GetCounter(lldb::eTraceCounterTSC))
205-
m_s.Printf("0x%016" PRIx64, *timestamp);
206-
else
207-
m_s.Printf("unavailable");
208-
209-
m_s.Printf("] ");
210-
}
211-
};
212-
213242
InstructionSymbolInfo prev_insn_info;
243+
Optional<lldb::user_id_t> last_id;
214244

215-
Target &target = thread_sp->GetProcess()->GetTarget();
216245
ExecutionContext exe_ctx;
217-
target.CalculateExecutionContext(exe_ctx);
218-
const ArchSpec &arch = target.GetArchitecture();
219-
220-
// Find the symbol context for the given address reusing the previous
221-
// instruction's symbol context when possible.
222-
auto calculateSymbolContext = [&](const Address &address) {
223-
AddressRange range;
224-
if (prev_insn_info.sc.GetAddressRange(eSymbolContextEverything, 0,
225-
/*inline_block_range*/ false,
226-
range) &&
227-
range.Contains(address))
228-
return prev_insn_info.sc;
229-
230-
SymbolContext sc;
231-
address.CalculateSymbolContext(&sc, eSymbolContextEverything);
232-
return sc;
233-
};
234-
235-
// Find the disassembler for the given address reusing the previous
236-
// instruction's disassembler when possible.
237-
auto calculateDisass = [&](const Address &address, const SymbolContext &sc) {
238-
if (prev_insn_info.disassembler) {
239-
if (InstructionSP instruction =
240-
prev_insn_info.disassembler->GetInstructionList()
241-
.GetInstructionAtAddress(address))
242-
return std::make_tuple(prev_insn_info.disassembler, instruction);
243-
}
246+
thread_sp->GetProcess()->GetTarget().CalculateExecutionContext(exe_ctx);
244247

245-
if (sc.function) {
246-
if (DisassemblerSP disassembler =
247-
sc.function->GetInstructions(exe_ctx, nullptr)) {
248-
if (InstructionSP instruction =
249-
disassembler->GetInstructionList().GetInstructionAtAddress(
250-
address))
251-
return std::make_tuple(disassembler, instruction);
252-
}
253-
}
254-
// We fallback to a single instruction disassembler
255-
AddressRange range(address, arch.GetMaximumOpcodeByteSize());
256-
DisassemblerSP disassembler =
257-
Disassembler::DisassembleRange(arch, /*plugin_name*/ nullptr,
258-
/*flavor*/ nullptr, target, range);
259-
return std::make_tuple(disassembler,
260-
disassembler ? disassembler->GetInstructionList()
261-
.GetInstructionAtAddress(address)
262-
: InstructionSP());
263-
};
264-
265-
Optional<lldb::user_id_t> last_id;
266248
for (size_t i = 0; i < count; i++) {
267249
if (!HasMoreData()) {
268-
m_s.Printf(" no more data\n");
250+
m_s << " no more data\n";
269251
break;
270252
}
271253
last_id = m_cursor_up->GetId();
@@ -277,15 +259,15 @@ Optional<lldb::tid_t> TraceInstructionDumper::DumpInstructions(size_t count) {
277259

278260
if (const char *err = m_cursor_up->GetError()) {
279261
if (!m_cursor_up->IsForwards() && !was_prev_instruction_an_error)
280-
printMissingInstructionsMessage();
262+
PrintMissingInstructionsMessage();
281263

282264
was_prev_instruction_an_error = true;
283265

284-
printInstructionHeader(m_cursor_up->GetId());
266+
PrintInstructionHeader();
285267
m_s << err;
286268
} else {
287269
if (m_cursor_up->IsForwards() && was_prev_instruction_an_error)
288-
printMissingInstructionsMessage();
270+
PrintMissingInstructionsMessage();
289271

290272
was_prev_instruction_an_error = false;
291273

@@ -294,24 +276,26 @@ Optional<lldb::tid_t> TraceInstructionDumper::DumpInstructions(size_t count) {
294276
if (!m_options.raw) {
295277
insn_info.load_address = m_cursor_up->GetLoadAddress();
296278
insn_info.exe_ctx = exe_ctx;
297-
insn_info.address.SetLoadAddress(insn_info.load_address, &target);
298-
insn_info.sc = calculateSymbolContext(insn_info.address);
279+
insn_info.address.SetLoadAddress(insn_info.load_address,
280+
exe_ctx.GetTargetPtr());
281+
insn_info.sc =
282+
CalculateSymbolContext(insn_info.address, prev_insn_info);
299283
std::tie(insn_info.disassembler, insn_info.instruction) =
300-
calculateDisass(insn_info.address, insn_info.sc);
284+
CalculateDisass(insn_info, prev_insn_info, exe_ctx);
301285

302-
DumpInstructionSymbolContext(m_s, prev_insn_info, insn_info);
286+
DumpInstructionSymbolContext(prev_insn_info, insn_info);
303287
}
304288

305-
printInstructionHeader(m_cursor_up->GetId());
306-
m_s.Printf("0x%016" PRIx64, m_cursor_up->GetLoadAddress());
289+
PrintInstructionHeader();
290+
m_s.Format("{0:x+16}", m_cursor_up->GetLoadAddress());
307291

308292
if (!m_options.raw)
309-
DumpInstructionDisassembly(m_s, insn_info);
293+
DumpInstructionDisassembly(insn_info);
310294

311295
prev_insn_info = insn_info;
312296
}
313297

314-
m_s.Printf("\n");
298+
m_s << "\n";
315299

316300
if (!m_options.forwards) {
317301
// If we move backwards, we print the events after printing

0 commit comments

Comments
 (0)