added new command "process trace save -d <directory>". -it saves a JSON file as <directory>/trace.json, with the main properties of the trace session. -it saves binary Intel-pt trace as <directory>/thread_id.trace; each file saves each thread. -it saves modules to the directory <directory>/modules . -it only works for live process and it only support Intel-pt right now. Example: ``` b main run process trace start n process trace save -d /tmp/mytrace ``` A file named trace.json and xxx.trace should be generated in /tmp/mytrace. To load the trace that was just saved: ``` trace load /tmp/mytrace thread trace dump instructions ``` You should see the instructions of the trace got printed. To run a test: ``` cd ~/llvm-sand/build/Release/fbcode-x86_64/toolchain ninja lldb-dotest ./bin/lldb-dotest -p TestTraceSave ``` Reviewed By: wallace Differential Revision: https://reviews.llvm.org/D107669
70 lines
2.4 KiB
C++
70 lines
2.4 KiB
C++
//===-- TraceIntelPTSessionFileParser.cpp ---------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "TraceIntelPTSessionFileParser.h"
|
|
|
|
#include "../common/ThreadPostMortemTrace.h"
|
|
#include "TraceIntelPT.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
using namespace lldb_private::trace_intel_pt;
|
|
using namespace llvm;
|
|
|
|
StringRef TraceIntelPTSessionFileParser::GetSchema() {
|
|
static std::string schema;
|
|
if (schema.empty()) {
|
|
schema = TraceSessionFileParser::BuildSchema(R"({
|
|
"type": "intel-pt",
|
|
"cpuInfo": {
|
|
"vendor": "intel" | "unknown",
|
|
"family": integer,
|
|
"model": integer,
|
|
"stepping": integer
|
|
}
|
|
})");
|
|
}
|
|
return schema;
|
|
}
|
|
|
|
pt_cpu TraceIntelPTSessionFileParser::ParsePTCPU(
|
|
const JSONTraceIntelPTCPUInfo &cpu_info) {
|
|
return {cpu_info.vendor.compare("intel") == 0 ? pcv_intel : pcv_unknown,
|
|
static_cast<uint16_t>(cpu_info.family),
|
|
static_cast<uint8_t>(cpu_info.model),
|
|
static_cast<uint8_t>(cpu_info.stepping)};
|
|
}
|
|
|
|
TraceSP TraceIntelPTSessionFileParser::CreateTraceIntelPTInstance(
|
|
const pt_cpu &cpu_info, std::vector<ParsedProcess> &parsed_processes) {
|
|
std::vector<ThreadPostMortemTraceSP> threads;
|
|
for (const ParsedProcess &parsed_process : parsed_processes)
|
|
threads.insert(threads.end(), parsed_process.threads.begin(),
|
|
parsed_process.threads.end());
|
|
|
|
TraceSP trace_instance(new TraceIntelPT(cpu_info, threads));
|
|
for (const ParsedProcess &parsed_process : parsed_processes)
|
|
parsed_process.target_sp->SetTrace(trace_instance);
|
|
|
|
return trace_instance;
|
|
}
|
|
|
|
Expected<TraceSP> TraceIntelPTSessionFileParser::Parse() {
|
|
json::Path::Root root("traceSession");
|
|
JSONTraceSession<JSONTraceIntelPTSettings> session;
|
|
if (!json::fromJSON(m_trace_session_file, session, root))
|
|
return CreateJSONError(root, m_trace_session_file);
|
|
|
|
if (Expected<std::vector<ParsedProcess>> parsed_processes =
|
|
ParseCommonSessionFile(session))
|
|
return CreateTraceIntelPTInstance(ParsePTCPU(session.trace.cpuInfo),
|
|
*parsed_processes);
|
|
else
|
|
return parsed_processes.takeError();
|
|
}
|