@@ -2099,8 +2099,7 @@ class CommandObjectTraceStop : public CommandObjectMultipleThreads {
2099
2099
#define LLDB_OPTIONS_thread_trace_dump_instructions
2100
2100
#include " CommandOptions.inc"
2101
2101
2102
- class CommandObjectTraceDumpInstructions
2103
- : public CommandObjectIterateOverThreads {
2102
+ class CommandObjectTraceDumpInstructions : public CommandObjectParsed {
2104
2103
public:
2105
2104
class CommandOptions : public Options {
2106
2105
public:
@@ -2132,19 +2131,29 @@ class CommandObjectTraceDumpInstructions
2132
2131
" invalid integer value for option '%s'" ,
2133
2132
option_arg.str ().c_str ());
2134
2133
else
2135
- m_skip = skip;
2134
+ m_dumper_options.skip = skip;
2135
+ break ;
2136
+ }
2137
+ case ' i' : {
2138
+ uint64_t id;
2139
+ if (option_arg.empty () || option_arg.getAsInteger (0 , id))
2140
+ error.SetErrorStringWithFormat (
2141
+ " invalid integer value for option '%s'" ,
2142
+ option_arg.str ().c_str ());
2143
+ else
2144
+ m_dumper_options.id = id;
2136
2145
break ;
2137
2146
}
2138
2147
case ' r' : {
2139
- m_raw = true ;
2148
+ m_dumper_options. raw = true ;
2140
2149
break ;
2141
2150
}
2142
2151
case ' f' : {
2143
- m_forwards = true ;
2152
+ m_dumper_options. forwards = true ;
2144
2153
break ;
2145
2154
}
2146
2155
case ' t' : {
2147
- m_show_tsc = true ;
2156
+ m_dumper_options. show_tsc = true ;
2148
2157
break ;
2149
2158
}
2150
2159
case ' C' : {
@@ -2159,11 +2168,8 @@ class CommandObjectTraceDumpInstructions
2159
2168
2160
2169
void OptionParsingStarting (ExecutionContext *execution_context) override {
2161
2170
m_count = kDefaultCount ;
2162
- m_skip = 0 ;
2163
- m_raw = false ;
2164
- m_forwards = false ;
2165
- m_show_tsc = false ;
2166
2171
m_continue = false ;
2172
+ m_dumper_options = {};
2167
2173
}
2168
2174
2169
2175
llvm::ArrayRef<OptionDefinition> GetDefinitions () override {
@@ -2174,23 +2180,19 @@ class CommandObjectTraceDumpInstructions
2174
2180
2175
2181
// Instance variables to hold the values for command options.
2176
2182
size_t m_count;
2177
- size_t m_skip;
2178
- bool m_raw;
2179
- bool m_forwards;
2180
- bool m_show_tsc;
2181
- bool m_continue;
2183
+ size_t m_continue;
2184
+ TraceInstructionDumperOptions m_dumper_options;
2182
2185
};
2183
2186
2184
2187
CommandObjectTraceDumpInstructions (CommandInterpreter &interpreter)
2185
- : CommandObjectIterateOverThreads (
2188
+ : CommandObjectParsed (
2186
2189
interpreter, " thread trace dump instructions" ,
2187
- " Dump the traced instructions for one or more threads. If no "
2188
- " threads are specified, show the current thread. Use the "
2189
- " thread-index \" all\" to see all threads." ,
2190
+ " Dump the traced instructions for one thread. If no "
2191
+ " thread is specified, show the current thread." ,
2190
2192
nullptr ,
2191
- eCommandRequiresProcess | eCommandTryTargetAPILock |
2192
- eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
2193
- eCommandProcessMustBeTraced) {}
2193
+ eCommandRequiresProcess | eCommandRequiresThread |
2194
+ eCommandTryTargetAPILock | eCommandProcessMustBeLaunched |
2195
+ eCommandProcessMustBePaused | eCommandProcessMustBeTraced) {}
2194
2196
2195
2197
~CommandObjectTraceDumpInstructions () override = default ;
2196
2198
@@ -2200,57 +2202,63 @@ class CommandObjectTraceDumpInstructions
2200
2202
uint32_t index) override {
2201
2203
std::string cmd;
2202
2204
current_command_args.GetCommandString (cmd);
2203
- if (cmd.find (" --continue" ) == std::string::npos)
2205
+ if (cmd.find (" --continue" ) == std::string::npos)
2204
2206
cmd += " --continue" ;
2205
2207
return cmd;
2206
2208
}
2207
2209
2208
2210
protected:
2209
- bool DoExecute (Args &args, CommandReturnObject &result) override {
2210
- if (!m_options. m_continue )
2211
- m_dumpers. clear ();
2211
+ ThreadSP GetThread (Args &args, CommandReturnObject &result) {
2212
+ if (args. GetArgumentCount () == 0 )
2213
+ return m_exe_ctx. GetThreadSP ();
2212
2214
2213
- return CommandObjectIterateOverThreads::DoExecute (args, result);
2214
- }
2215
-
2216
- bool HandleOneThread (lldb::tid_t tid, CommandReturnObject &result) override {
2217
- Stream &s = result.GetOutputStream ();
2215
+ const char *arg = args.GetArgumentAtIndex (0 );
2216
+ uint32_t thread_idx;
2218
2217
2219
- const TraceSP &trace_sp = m_exe_ctx.GetTargetSP ()->GetTrace ();
2218
+ if (!llvm::to_integer (arg, thread_idx)) {
2219
+ result.AppendErrorWithFormat (" invalid thread specification: \" %s\"\n " ,
2220
+ arg);
2221
+ return nullptr ;
2222
+ }
2220
2223
ThreadSP thread_sp =
2221
- m_exe_ctx.GetProcessPtr ()->GetThreadList ().FindThreadByID (tid);
2222
-
2223
- if (!m_dumpers.count (thread_sp->GetID ())) {
2224
- lldb::TraceCursorUP cursor_up = trace_sp->GetCursor (*thread_sp);
2225
- // Set up the cursor and return the presentation index of the first
2226
- // instruction to dump after skipping instructions.
2227
- auto setUpCursor = [&]() {
2228
- cursor_up->SetForwards (m_options.m_forwards );
2229
- if (m_options.m_forwards )
2230
- return cursor_up->Seek (m_options.m_skip , TraceCursor::SeekType::Set);
2231
- return -cursor_up->Seek (-m_options.m_skip , TraceCursor::SeekType::End);
2232
- };
2233
-
2234
- int initial_index = setUpCursor ();
2224
+ m_exe_ctx.GetProcessRef ().GetThreadList ().FindThreadByIndexID (
2225
+ thread_idx);
2226
+ if (!thread_sp)
2227
+ result.AppendErrorWithFormat (" no thread with index: \" %s\"\n " , arg);
2228
+ return thread_sp;
2229
+ }
2235
2230
2236
- auto dumper = std::make_unique<TraceInstructionDumper>(
2237
- std::move (cursor_up), initial_index, m_options.m_raw ,
2238
- m_options.m_show_tsc );
2231
+ bool DoExecute (Args &args, CommandReturnObject &result) override {
2232
+ ThreadSP thread_sp = GetThread (args, result);
2233
+ if (!thread_sp)
2234
+ return false ;
2239
2235
2240
- // This happens when the seek value was more than the number of available
2241
- // instructions.
2242
- if (std::abs (initial_index) < (int )m_options.m_skip )
2243
- dumper->SetNoMoreData ();
2236
+ Stream &s = result.GetOutputStream ();
2237
+ s.Printf (" thread #%u: tid = %" PRIu64 " \n " , thread_sp->GetIndexID (),
2238
+ thread_sp->GetID ());
2244
2239
2245
- m_dumpers[thread_sp->GetID ()] = std::move (dumper);
2240
+ if (m_options.m_continue ) {
2241
+ if (!m_last_id) {
2242
+ result.AppendMessage (" no more data\n " );
2243
+ return true ;
2244
+ }
2245
+ // We set up the options to continue one instruction past where
2246
+ // the previous iteration stopped.
2247
+ m_options.m_dumper_options .skip = 1 ;
2248
+ m_options.m_dumper_options .id = m_last_id;
2246
2249
}
2247
2250
2248
- m_dumpers[thread_sp->GetID ()]->DumpInstructions (s, m_options.m_count );
2251
+ const TraceSP &trace_sp = m_exe_ctx.GetTargetSP ()->GetTrace ();
2252
+ TraceInstructionDumper dumper (trace_sp->GetCursor (*thread_sp), s,
2253
+ m_options.m_dumper_options );
2254
+ m_last_id = dumper.DumpInstructions (m_options.m_count );
2249
2255
return true ;
2250
2256
}
2251
2257
2252
2258
CommandOptions m_options;
2253
- std::map<lldb::tid_t , std::unique_ptr<TraceInstructionDumper>> m_dumpers;
2259
+ // Last traversed id used to continue a repeat command. None means
2260
+ // that all the trace has been consumed.
2261
+ llvm::Optional<lldb::user_id_t > m_last_id;
2254
2262
};
2255
2263
2256
2264
// CommandObjectTraceDumpInfo
0 commit comments