21#include "llvm/Support/Error.h"
22#include "llvm/Support/JSON.h"
44 ArrayRef<uint8_t> data) {
45 std::basic_fstream<char> out_fs = std::fstream(
46 output_file.
GetPath().c_str(), std::ios::out | std::ios::binary);
48 out_fs.write(
reinterpret_cast<const char *
>(&data[0]), data.size());
52 return createStringError(inconvertibleErrorCode(),
53 formatv(
"couldn't write to the file {0}",
54 output_file.
GetPath().c_str()));
55 return Error::success();
70static Expected<FileSpec>
75 std::ofstream os(trace_path.
GetPath());
76 os << formatv(
"{0:2}", trace_bundle_description).str();
79 return createStringError(inconvertibleErrorCode(),
80 formatv(
"couldn't write to the file {0}",
97static llvm::Expected<std::vector<JSONThread>>
99 std::vector<JSONThread> json_threads;
104 sys::fs::create_directories(threads_dir.
GetPath().c_str());
108 if (!trace_sp->IsTraced(tid))
112 json_thread.
tid = tid;
114 if (trace_sp->GetTracedCpus().empty()) {
121 [&](llvm::ArrayRef<uint8_t> data) -> llvm::Error {
125 return std::move(err);
128 json_threads.push_back(std::move(json_thread));
137static Expected<std::optional<FileSpec>>
139 const FileSpec &cpus_dir,
bool compact) {
140 FileSpec output_context_switch_trace = cpus_dir;
142 ".perf_context_switch_trace");
144 bool should_skip =
false;
148 [&](llvm::ArrayRef<uint8_t> data) -> llvm::Error {
152 std::set<lldb::pid_t> pids;
154 pids.insert(process->GetID());
156 Expected<std::vector<uint8_t>> compact_context_switch_trace =
158 if (!compact_context_switch_trace)
159 return compact_context_switch_trace.takeError();
161 if (compact_context_switch_trace->empty()) {
163 return Error::success();
167 *compact_context_switch_trace);
170 return std::move(err);
174 return output_context_switch_trace;
185 [&](llvm::ArrayRef<uint8_t> data) -> llvm::Error {
189 return std::move(err);
193static llvm::Expected<std::optional<std::vector<JSONCpu>>>
198 std::vector<JSONCpu> json_cpus;
201 sys::fs::create_directories(cpus_dir.
GetPath().c_str());
205 json_cpu.
id = cpu_id;
206 Expected<std::optional<FileSpec>> context_switch_trace_path =
208 if (!context_switch_trace_path)
209 return context_switch_trace_path.takeError();
210 if (!*context_switch_trace_path)
215 if (Expected<FileSpec> ipt_trace_path =
219 return ipt_trace_path.takeError();
221 json_cpus.push_back(std::move(json_cpu));
246static llvm::Expected<std::vector<JSONModule>>
248 std::vector<JSONModule> json_modules;
250 for (
size_t i = 0; i < module_list.
GetSize(); ++i) {
254 std::string system_path = module_sp->GetPlatformFileSpec().GetPath();
256 if (!module_sp->GetFileSpec().IsAbsolute())
259 std::string file = module_sp->GetFileSpec().GetPath();
260 ObjectFile *objfile = module_sp->GetObjectFile();
261 if (objfile ==
nullptr)
273 FileSpec path_to_copy_module = directory;
278 if (std::error_code ec =
279 llvm::sys::fs::copy_file(file, path_to_copy_module.
GetPath()))
280 return createStringError(
281 inconvertibleErrorCode(),
282 formatv(
"couldn't write to the file. {0}", ec.message()));
284 json_modules.push_back(
286 JSONUINT64{load_addr}, module_sp->GetUUID().GetAsString()});
304static llvm::Expected<JSONProcess>
306 Expected<std::vector<JSONThread>> json_threads =
309 return json_threads.takeError();
311 Expected<std::vector<JSONModule>> json_modules =
314 return json_modules.takeError();
319 json_threads.get(), json_modules.get()};
323static llvm::Expected<std::vector<JSONProcess>>
325 std::vector<JSONProcess> processes;
327 if (llvm::Expected<JSONProcess> json_process =
329 processes.push_back(std::move(*json_process));
331 return json_process.takeError();
336static llvm::Expected<JSONKernel>
340 Process *kernel_process = processes[0];
342 assert(processes.size() == 1 &&
"User processeses exist in kernel mode");
344 "Kernel process not exist");
346 Expected<std::vector<JSONModule>> json_modules =
349 return json_modules.takeError();
351 JSONModule kernel_image = json_modules.get()[0];
358 if (std::error_code ec =
359 sys::fs::create_directories(directory.
GetPath().c_str()))
360 return llvm::errorCodeToError(ec);
362 Expected<pt_cpu> cpu_info = trace_ipt.
GetCPUInfo();
364 return cpu_info.takeError();
368 Expected<std::optional<std::vector<JSONCpu>>> json_cpus =
371 return json_cpus.takeError();
373 std::optional<std::vector<JSONProcess>> json_processes;
374 std::optional<JSONKernel> json_kernel;
377 Expected<std::optional<JSONKernel>> exp_json_kernel =
379 if (!exp_json_kernel)
380 return exp_json_kernel.takeError();
382 json_kernel = *exp_json_kernel;
384 Expected<std::optional<std::vector<JSONProcess>>> exp_json_processes =
386 if (!exp_json_processes)
387 return exp_json_processes.takeError();
389 json_processes = *exp_json_processes;
static llvm::Expected< JSONProcess > BuildProcessSection(Process &process, const FileSpec &directory)
Build the processes section of the trace bundle description object.
static llvm::Expected< std::optional< std::vector< JSONCpu > > > BuildCpusSection(TraceIntelPT &trace_ipt, FileSpec directory, bool compact)
static std::string GetRelativePath(const FileSpec &directory, const FileSpec &path)
Strip the directory component from the given path.
static llvm::Expected< std::vector< JSONModule > > BuildModulesSection(Process &process, FileSpec directory)
Build modules sub-section of the trace bundle.
static llvm::Expected< std::vector< JSONThread > > BuildThreadsSection(Process &process, FileSpec directory)
Build the threads sub-section of the trace bundle description file.
static Expected< std::optional< FileSpec > > WriteContextSwitchTrace(TraceIntelPT &trace_ipt, lldb::cpu_id_t cpu_id, const FileSpec &cpus_dir, bool compact)
static llvm::Error WriteBytesToDisk(FileSpec &output_file, ArrayRef< uint8_t > data)
Write a stream of bytes from data to the given output file.
static Expected< FileSpec > SaveTraceBundleDescription(const llvm::json::Value &trace_bundle_description, const FileSpec &directory)
Save the trace bundle description JSON object inside the given directory as a file named trace....
static Expected< FileSpec > WriteIntelPTTrace(TraceIntelPT &trace_ipt, lldb::cpu_id_t cpu_id, const FileSpec &cpus_dir)
static llvm::Expected< JSONKernel > BuildKernelSection(TraceIntelPT &trace_ipt, const FileSpec &directory)
static llvm::Expected< std::vector< JSONProcess > > BuildProcessesSection(TraceIntelPT &trace_ipt, const FileSpec &directory)
See BuildProcessSection()
A section + offset based address class.
lldb::addr_t GetLoadAddress(Target *target) const
Get the load address.
bool IsValid() const
Check if the object state is valid.
llvm::Triple & GetTriple()
Architecture triple accessor.
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
void AppendPathComponent(llvm::StringRef component)
const ConstString & GetDirectory() const
Directory string const get accessor.
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
void Resolve(llvm::SmallVectorImpl< char > &path)
Resolve path to make it canonical.
static FileSystem & Instance()
A collection class for Module objects.
lldb::ModuleSP GetModuleAtIndex(size_t idx) const
Get the module shared pointer for the module at index idx.
size_t GetSize() const
Gets the size of the module list.
A plug-in interface definition class for object file parsers.
virtual lldb_private::Address GetBaseAddress()
Returns base address of this object file.
A plug-in interface definition class for debugging a process.
lldb::pid_t GetID() const
Returns the pid of the process or LLDB_INVALID_PROCESS_ID if there is no known pid.
ThreadList::ThreadIterable Threads()
Target & GetTarget()
Get the target object pointer for this module.
lldb::TraceSP GetTrace()
Get the Trace object containing processor trace information of this target.
SectionLoadList & GetSectionLoadList()
const ModuleList & GetImages() const
Get accessor for the images for this process.
const ArchSpec & GetArchitecture() const
llvm::ArrayRef< lldb::cpu_id_t > GetTracedCpus()
std::vector< Process * > GetAllProcesses()
llvm::Error OnCpuBinaryDataRead(lldb::cpu_id_t cpu_id, llvm::StringRef kind, OnBinaryDataReadCallback callback)
Fetch binary data associated with a cpu, either live or postmortem, and pass it to the given callback...
llvm::Expected< FileSpec > SaveToDisk(TraceIntelPT &trace_ipt, FileSpec directory, bool compact)
Save the Intel PT trace of a live process to the specified directory, which will be created if needed...
llvm::Expected< pt_cpu > GetCPUInfo()
Get or fetch the cpu information from, for example, /proc/cpuinfo.
std::optional< LinuxPerfZeroTscConversion > GetPerfZeroTscConversion()
Get or fetch the values used to convert to and from TSCs and nanos.
#define LLDB_INVALID_ADDRESS
const lldb::pid_t kDefaultKernelProcessID
llvm::Expected< std::vector< uint8_t > > FilterProcessesFromContextSwitchTrace(llvm::ArrayRef< uint8_t > data, const std::set< lldb::pid_t > &pids)
json::Value toJSON(const JSONModule &module)
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::Trace > TraceSP
std::shared_ptr< lldb_private::Thread > ThreadSP
std::shared_ptr< lldb_private::Module > ModuleSP
static const char * kIptTrace
static const char * kPerfContextSwitchTrace
Helper structure to help parse long numbers that can't be easily represented by a JSON number that is...
std::string context_switch_trace
std::optional< std::string > ipt_trace