174c93956SWalter Erquinigo //===-- CommandObjectTrace.cpp --------------------------------------------===// 274c93956SWalter Erquinigo // 374c93956SWalter Erquinigo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 474c93956SWalter Erquinigo // See https://llvm.org/LICENSE.txt for license information. 574c93956SWalter Erquinigo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 674c93956SWalter Erquinigo // 774c93956SWalter Erquinigo //===----------------------------------------------------------------------===// 874c93956SWalter Erquinigo 974c93956SWalter Erquinigo #include "CommandObjectTrace.h" 1074c93956SWalter Erquinigo 1174c93956SWalter Erquinigo #include "llvm/Support/JSON.h" 1274c93956SWalter Erquinigo #include "llvm/Support/MemoryBuffer.h" 1374c93956SWalter Erquinigo 1474c93956SWalter Erquinigo #include "lldb/Core/Debugger.h" 15ea1f4974SWalter Erquinigo #include "lldb/Core/PluginManager.h" 1674c93956SWalter Erquinigo #include "lldb/Host/OptionParser.h" 1774c93956SWalter Erquinigo #include "lldb/Interpreter/CommandInterpreter.h" 1874c93956SWalter Erquinigo #include "lldb/Interpreter/CommandObject.h" 1974c93956SWalter Erquinigo #include "lldb/Interpreter/CommandReturnObject.h" 2074c93956SWalter Erquinigo #include "lldb/Interpreter/OptionArgParser.h" 2174c93956SWalter Erquinigo #include "lldb/Interpreter/OptionGroupFormat.h" 2274c93956SWalter Erquinigo #include "lldb/Interpreter/OptionValueBoolean.h" 2374c93956SWalter Erquinigo #include "lldb/Interpreter/OptionValueLanguage.h" 2474c93956SWalter Erquinigo #include "lldb/Interpreter/OptionValueString.h" 2574c93956SWalter Erquinigo #include "lldb/Interpreter/Options.h" 2674c93956SWalter Erquinigo #include "lldb/Target/Trace.h" 2774c93956SWalter Erquinigo 2874c93956SWalter Erquinigo using namespace lldb; 2974c93956SWalter Erquinigo using namespace lldb_private; 3074c93956SWalter Erquinigo using namespace llvm; 3174c93956SWalter Erquinigo 3274c93956SWalter Erquinigo // CommandObjectTraceLoad 3374c93956SWalter Erquinigo #define LLDB_OPTIONS_trace_load 3474c93956SWalter Erquinigo #include "CommandOptions.inc" 3574c93956SWalter Erquinigo 3674c93956SWalter Erquinigo #pragma mark CommandObjectTraceLoad 3774c93956SWalter Erquinigo 3874c93956SWalter Erquinigo class CommandObjectTraceLoad : public CommandObjectParsed { 3974c93956SWalter Erquinigo public: 4074c93956SWalter Erquinigo class CommandOptions : public Options { 4174c93956SWalter Erquinigo public: 4274c93956SWalter Erquinigo CommandOptions() : Options() { OptionParsingStarting(nullptr); } 4374c93956SWalter Erquinigo 4474c93956SWalter Erquinigo ~CommandOptions() override = default; 4574c93956SWalter Erquinigo 4674c93956SWalter Erquinigo Status SetOptionValue(uint32_t option_idx, StringRef option_arg, 4774c93956SWalter Erquinigo ExecutionContext *execution_context) override { 4874c93956SWalter Erquinigo Status error; 4974c93956SWalter Erquinigo const int short_option = m_getopt_table[option_idx].val; 5074c93956SWalter Erquinigo 5174c93956SWalter Erquinigo switch (short_option) { 5274c93956SWalter Erquinigo case 'v': { 5374c93956SWalter Erquinigo m_verbose = true; 5474c93956SWalter Erquinigo break; 5574c93956SWalter Erquinigo } 5674c93956SWalter Erquinigo default: 5774c93956SWalter Erquinigo llvm_unreachable("Unimplemented option"); 5874c93956SWalter Erquinigo } 5974c93956SWalter Erquinigo return error; 6074c93956SWalter Erquinigo } 6174c93956SWalter Erquinigo 6274c93956SWalter Erquinigo void OptionParsingStarting(ExecutionContext *execution_context) override { 6374c93956SWalter Erquinigo m_verbose = false; 6474c93956SWalter Erquinigo } 6574c93956SWalter Erquinigo 6674c93956SWalter Erquinigo ArrayRef<OptionDefinition> GetDefinitions() override { 6774c93956SWalter Erquinigo return makeArrayRef(g_trace_load_options); 6874c93956SWalter Erquinigo } 6974c93956SWalter Erquinigo 7074c93956SWalter Erquinigo bool m_verbose; // Enable verbose logging for debugging purposes. 7174c93956SWalter Erquinigo }; 7274c93956SWalter Erquinigo 7374c93956SWalter Erquinigo CommandObjectTraceLoad(CommandInterpreter &interpreter) 7474c93956SWalter Erquinigo : CommandObjectParsed(interpreter, "trace load", 75ea1f4974SWalter Erquinigo "Load a processor trace session from a JSON file.", 7674c93956SWalter Erquinigo "trace load"), 7774c93956SWalter Erquinigo m_options() {} 7874c93956SWalter Erquinigo 7974c93956SWalter Erquinigo ~CommandObjectTraceLoad() override = default; 8074c93956SWalter Erquinigo 8174c93956SWalter Erquinigo Options *GetOptions() override { return &m_options; } 8274c93956SWalter Erquinigo 8374c93956SWalter Erquinigo protected: 8474c93956SWalter Erquinigo bool DoExecute(Args &command, CommandReturnObject &result) override { 8574c93956SWalter Erquinigo if (command.size() != 1) { 86ea1f4974SWalter Erquinigo result.AppendError( 87ea1f4974SWalter Erquinigo "a single path to a JSON file containing a trace session" 88ea1f4974SWalter Erquinigo "is required"); 8974c93956SWalter Erquinigo result.SetStatus(eReturnStatusFailed); 9074c93956SWalter Erquinigo return false; 9174c93956SWalter Erquinigo } 9274c93956SWalter Erquinigo 9374c93956SWalter Erquinigo auto end_with_failure = [&result](llvm::Error err) -> bool { 9474c93956SWalter Erquinigo result.AppendErrorWithFormat("%s\n", 9574c93956SWalter Erquinigo llvm::toString(std::move(err)).c_str()); 9674c93956SWalter Erquinigo result.SetStatus(eReturnStatusFailed); 9774c93956SWalter Erquinigo return false; 9874c93956SWalter Erquinigo }; 9974c93956SWalter Erquinigo 10074c93956SWalter Erquinigo FileSpec json_file(command[0].ref()); 10174c93956SWalter Erquinigo 10274c93956SWalter Erquinigo auto buffer_or_error = llvm::MemoryBuffer::getFile(json_file.GetPath()); 10374c93956SWalter Erquinigo if (!buffer_or_error) { 10474c93956SWalter Erquinigo return end_with_failure(llvm::createStringError( 10574c93956SWalter Erquinigo std::errc::invalid_argument, "could not open input file: %s - %s.", 10674c93956SWalter Erquinigo json_file.GetPath().c_str(), 10774c93956SWalter Erquinigo buffer_or_error.getError().message().c_str())); 10874c93956SWalter Erquinigo } 10974c93956SWalter Erquinigo 110ea1f4974SWalter Erquinigo llvm::Expected<json::Value> session_file = 11174c93956SWalter Erquinigo json::parse(buffer_or_error.get()->getBuffer().str()); 112ea1f4974SWalter Erquinigo if (!session_file) 113ea1f4974SWalter Erquinigo return end_with_failure(session_file.takeError()); 11474c93956SWalter Erquinigo 115ea1f4974SWalter Erquinigo if (Expected<lldb::TraceSP> traceOrErr = 116ea1f4974SWalter Erquinigo Trace::FindPlugin(GetDebugger(), *session_file, 117ea1f4974SWalter Erquinigo json_file.GetDirectory().AsCString())) { 11874c93956SWalter Erquinigo lldb::TraceSP trace_sp = traceOrErr.get(); 119*801067f4SStella Stamenova if (m_options.m_verbose && trace_sp) 12074c93956SWalter Erquinigo result.AppendMessageWithFormat("loading trace with plugin %s\n", 12174c93956SWalter Erquinigo trace_sp->GetPluginName().AsCString()); 12274c93956SWalter Erquinigo } else 12374c93956SWalter Erquinigo return end_with_failure(traceOrErr.takeError()); 12474c93956SWalter Erquinigo 12574c93956SWalter Erquinigo result.SetStatus(eReturnStatusSuccessFinishResult); 12674c93956SWalter Erquinigo return true; 12774c93956SWalter Erquinigo } 12874c93956SWalter Erquinigo 12974c93956SWalter Erquinigo CommandOptions m_options; 13074c93956SWalter Erquinigo }; 13174c93956SWalter Erquinigo 13274c93956SWalter Erquinigo // CommandObjectTraceDump 13374c93956SWalter Erquinigo #define LLDB_OPTIONS_trace_dump 13474c93956SWalter Erquinigo #include "CommandOptions.inc" 13574c93956SWalter Erquinigo 13674c93956SWalter Erquinigo #pragma mark CommandObjectTraceDump 13774c93956SWalter Erquinigo 13874c93956SWalter Erquinigo class CommandObjectTraceDump : public CommandObjectParsed { 13974c93956SWalter Erquinigo public: 14074c93956SWalter Erquinigo class CommandOptions : public Options { 14174c93956SWalter Erquinigo public: 14274c93956SWalter Erquinigo CommandOptions() : Options() { OptionParsingStarting(nullptr); } 14374c93956SWalter Erquinigo 14474c93956SWalter Erquinigo ~CommandOptions() override = default; 14574c93956SWalter Erquinigo 14674c93956SWalter Erquinigo Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 14774c93956SWalter Erquinigo ExecutionContext *execution_context) override { 14874c93956SWalter Erquinigo Status error; 14974c93956SWalter Erquinigo const int short_option = m_getopt_table[option_idx].val; 15074c93956SWalter Erquinigo 15174c93956SWalter Erquinigo switch (short_option) { 15274c93956SWalter Erquinigo case 'v': { 15374c93956SWalter Erquinigo m_verbose = true; 15474c93956SWalter Erquinigo break; 15574c93956SWalter Erquinigo } 15674c93956SWalter Erquinigo default: 15774c93956SWalter Erquinigo llvm_unreachable("Unimplemented option"); 15874c93956SWalter Erquinigo } 15974c93956SWalter Erquinigo return error; 16074c93956SWalter Erquinigo } 16174c93956SWalter Erquinigo 16274c93956SWalter Erquinigo void OptionParsingStarting(ExecutionContext *execution_context) override { 16374c93956SWalter Erquinigo m_verbose = false; 16474c93956SWalter Erquinigo } 16574c93956SWalter Erquinigo 16674c93956SWalter Erquinigo llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 16774c93956SWalter Erquinigo return llvm::makeArrayRef(g_trace_dump_options); 16874c93956SWalter Erquinigo } 16974c93956SWalter Erquinigo 17074c93956SWalter Erquinigo bool m_verbose; // Enable verbose logging for debugging purposes. 17174c93956SWalter Erquinigo }; 17274c93956SWalter Erquinigo 17374c93956SWalter Erquinigo CommandObjectTraceDump(CommandInterpreter &interpreter) 17474c93956SWalter Erquinigo : CommandObjectParsed(interpreter, "trace dump", 17574c93956SWalter Erquinigo "Dump the loaded processor trace data.", 17674c93956SWalter Erquinigo "trace dump"), 17774c93956SWalter Erquinigo m_options() {} 17874c93956SWalter Erquinigo 17974c93956SWalter Erquinigo ~CommandObjectTraceDump() override = default; 18074c93956SWalter Erquinigo 18174c93956SWalter Erquinigo Options *GetOptions() override { return &m_options; } 18274c93956SWalter Erquinigo 18374c93956SWalter Erquinigo protected: 18474c93956SWalter Erquinigo bool DoExecute(Args &command, CommandReturnObject &result) override { 18574c93956SWalter Erquinigo Status error; 18674c93956SWalter Erquinigo // TODO: fill in the dumping code here! 18774c93956SWalter Erquinigo if (error.Success()) { 18874c93956SWalter Erquinigo result.SetStatus(eReturnStatusSuccessFinishResult); 18974c93956SWalter Erquinigo } else { 19074c93956SWalter Erquinigo result.AppendErrorWithFormat("%s\n", error.AsCString()); 19174c93956SWalter Erquinigo result.SetStatus(eReturnStatusFailed); 19274c93956SWalter Erquinigo } 19374c93956SWalter Erquinigo return result.Succeeded(); 19474c93956SWalter Erquinigo } 19574c93956SWalter Erquinigo 19674c93956SWalter Erquinigo CommandOptions m_options; 19774c93956SWalter Erquinigo }; 19874c93956SWalter Erquinigo 19974c93956SWalter Erquinigo // CommandObjectTraceSchema 20074c93956SWalter Erquinigo #define LLDB_OPTIONS_trace_schema 20174c93956SWalter Erquinigo #include "CommandOptions.inc" 20274c93956SWalter Erquinigo 20374c93956SWalter Erquinigo #pragma mark CommandObjectTraceSchema 20474c93956SWalter Erquinigo 20574c93956SWalter Erquinigo class CommandObjectTraceSchema : public CommandObjectParsed { 20674c93956SWalter Erquinigo public: 20774c93956SWalter Erquinigo class CommandOptions : public Options { 20874c93956SWalter Erquinigo public: 20974c93956SWalter Erquinigo CommandOptions() : Options() { OptionParsingStarting(nullptr); } 21074c93956SWalter Erquinigo 21174c93956SWalter Erquinigo ~CommandOptions() override = default; 21274c93956SWalter Erquinigo 21374c93956SWalter Erquinigo Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 21474c93956SWalter Erquinigo ExecutionContext *execution_context) override { 21574c93956SWalter Erquinigo Status error; 21674c93956SWalter Erquinigo const int short_option = m_getopt_table[option_idx].val; 21774c93956SWalter Erquinigo 21874c93956SWalter Erquinigo switch (short_option) { 21974c93956SWalter Erquinigo case 'v': { 22074c93956SWalter Erquinigo m_verbose = true; 22174c93956SWalter Erquinigo break; 22274c93956SWalter Erquinigo } 22374c93956SWalter Erquinigo default: 22474c93956SWalter Erquinigo llvm_unreachable("Unimplemented option"); 22574c93956SWalter Erquinigo } 22674c93956SWalter Erquinigo return error; 22774c93956SWalter Erquinigo } 22874c93956SWalter Erquinigo 22974c93956SWalter Erquinigo void OptionParsingStarting(ExecutionContext *execution_context) override { 23074c93956SWalter Erquinigo m_verbose = false; 23174c93956SWalter Erquinigo } 23274c93956SWalter Erquinigo 23374c93956SWalter Erquinigo llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 23474c93956SWalter Erquinigo return llvm::makeArrayRef(g_trace_schema_options); 23574c93956SWalter Erquinigo } 23674c93956SWalter Erquinigo 23774c93956SWalter Erquinigo bool m_verbose; // Enable verbose logging for debugging purposes. 23874c93956SWalter Erquinigo }; 23974c93956SWalter Erquinigo 24074c93956SWalter Erquinigo CommandObjectTraceSchema(CommandInterpreter &interpreter) 24174c93956SWalter Erquinigo : CommandObjectParsed(interpreter, "trace schema", 24274c93956SWalter Erquinigo "Show the schema of the given trace plugin.", 243ea1f4974SWalter Erquinigo "trace schema <plug-in>. Use the plug-in name " 244ea1f4974SWalter Erquinigo "\"all\" to see all schemas.\n"), 24574c93956SWalter Erquinigo m_options() {} 24674c93956SWalter Erquinigo 24774c93956SWalter Erquinigo ~CommandObjectTraceSchema() override = default; 24874c93956SWalter Erquinigo 24974c93956SWalter Erquinigo Options *GetOptions() override { return &m_options; } 25074c93956SWalter Erquinigo 25174c93956SWalter Erquinigo protected: 25274c93956SWalter Erquinigo bool DoExecute(Args &command, CommandReturnObject &result) override { 25374c93956SWalter Erquinigo Status error; 25474c93956SWalter Erquinigo if (command.empty()) { 25574c93956SWalter Erquinigo result.SetError( 25674c93956SWalter Erquinigo "trace schema cannot be invoked without a plug-in as argument"); 25774c93956SWalter Erquinigo return false; 25874c93956SWalter Erquinigo } 25974c93956SWalter Erquinigo 26074c93956SWalter Erquinigo StringRef plugin_name(command[0].c_str()); 261ea1f4974SWalter Erquinigo if (plugin_name == "all") { 262ea1f4974SWalter Erquinigo size_t index = 0; 263ea1f4974SWalter Erquinigo while (true) { 264ea1f4974SWalter Erquinigo StringRef schema = PluginManager::GetTraceSchema(index++); 265ea1f4974SWalter Erquinigo if (schema.empty()) 266ea1f4974SWalter Erquinigo break; 26774c93956SWalter Erquinigo 268ea1f4974SWalter Erquinigo result.AppendMessage(schema); 269ea1f4974SWalter Erquinigo } 27074c93956SWalter Erquinigo } else { 271ea1f4974SWalter Erquinigo if (Expected<StringRef> schemaOrErr = 272ea1f4974SWalter Erquinigo Trace::FindPluginSchema(plugin_name)) 273ea1f4974SWalter Erquinigo result.AppendMessage(*schemaOrErr); 274ea1f4974SWalter Erquinigo else 275ea1f4974SWalter Erquinigo error = schemaOrErr.takeError(); 27674c93956SWalter Erquinigo } 27774c93956SWalter Erquinigo 27874c93956SWalter Erquinigo if (error.Success()) { 27974c93956SWalter Erquinigo result.SetStatus(eReturnStatusSuccessFinishResult); 28074c93956SWalter Erquinigo } else { 28174c93956SWalter Erquinigo result.AppendErrorWithFormat("%s\n", error.AsCString()); 28274c93956SWalter Erquinigo result.SetStatus(eReturnStatusFailed); 28374c93956SWalter Erquinigo } 28474c93956SWalter Erquinigo return result.Succeeded(); 28574c93956SWalter Erquinigo } 28674c93956SWalter Erquinigo 28774c93956SWalter Erquinigo CommandOptions m_options; 28874c93956SWalter Erquinigo }; 28974c93956SWalter Erquinigo 29074c93956SWalter Erquinigo // CommandObjectTrace 29174c93956SWalter Erquinigo 29274c93956SWalter Erquinigo CommandObjectTrace::CommandObjectTrace(CommandInterpreter &interpreter) 29374c93956SWalter Erquinigo : CommandObjectMultiword(interpreter, "trace", 29474c93956SWalter Erquinigo "Commands for loading and using processor " 29574c93956SWalter Erquinigo "trace information.", 29674c93956SWalter Erquinigo "trace [<sub-command-options>]") { 29774c93956SWalter Erquinigo LoadSubCommand("load", 29874c93956SWalter Erquinigo CommandObjectSP(new CommandObjectTraceLoad(interpreter))); 29974c93956SWalter Erquinigo LoadSubCommand("dump", 30074c93956SWalter Erquinigo CommandObjectSP(new CommandObjectTraceDump(interpreter))); 30174c93956SWalter Erquinigo LoadSubCommand("schema", 30274c93956SWalter Erquinigo CommandObjectSP(new CommandObjectTraceSchema(interpreter))); 30374c93956SWalter Erquinigo } 30474c93956SWalter Erquinigo 30574c93956SWalter Erquinigo CommandObjectTrace::~CommandObjectTrace() = default; 306