LLDB  mainline
TraceSessionSaver.cpp
Go to the documentation of this file.
1 //===-- TraceSessionSaver.cpp ---------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "TraceSessionSaver.h"
10 
11 #include "lldb/Core/Module.h"
12 #include "lldb/Core/Value.h"
13 #include "lldb/Target/Process.h"
15 #include "lldb/Target/Target.h"
16 #include "lldb/lldb-types.h"
17 #include "llvm/Support/Error.h"
18 #include "llvm/Support/JSON.h"
19 
20 #include <fstream>
21 
22 using namespace lldb;
23 using namespace lldb_private;
24 using namespace llvm;
25 
26 llvm::Error TraceSessionSaver::WriteSessionToFile(
27  const llvm::json::Value &trace_session_description, FileSpec directory) {
28 
29  FileSpec trace_path = directory;
30  trace_path.AppendPathComponent("trace.json");
31  std::ofstream os(trace_path.GetPath());
32  os << std::string(formatv("{0:2}", trace_session_description));
33  os.close();
34  if (!os)
35  return createStringError(inconvertibleErrorCode(),
36  formatv("couldn't write to the file {0}",
37  trace_path.GetPath().c_str()));
38  return Error::success();
39 }
40 
41 llvm::Expected<JSONTraceSessionBase> TraceSessionSaver::BuildProcessesSection(
42  Process &live_process,
43  std::function<
44  llvm::Expected<llvm::Optional<std::vector<uint8_t>>>(lldb::tid_t tid)>
45  raw_trace_fetcher,
46  FileSpec directory) {
47 
48  JSONTraceSessionBase json_session_description;
49  Expected<std::vector<JSONThread>> json_threads =
50  BuildThreadsSection(live_process, raw_trace_fetcher, directory);
51  if (!json_threads)
52  return json_threads.takeError();
53 
54  Expected<std::vector<JSONModule>> json_modules =
55  BuildModulesSection(live_process, directory);
56  if (!json_modules)
57  return json_modules.takeError();
58 
59  json_session_description.processes.push_back(JSONProcess{
60  static_cast<int64_t>(live_process.GetID()),
61  live_process.GetTarget().GetArchitecture().GetTriple().getTriple(),
62  json_threads.get(), json_modules.get()});
63  return json_session_description;
64 }
65 
66 llvm::Expected<std::vector<JSONThread>> TraceSessionSaver::BuildThreadsSection(
67  Process &live_process,
68  std::function<
69  llvm::Expected<llvm::Optional<std::vector<uint8_t>>>(lldb::tid_t tid)>
70  raw_trace_fetcher,
71  FileSpec directory) {
72  std::vector<JSONThread> json_threads;
73  for (ThreadSP thread_sp : live_process.Threads()) {
74  // resolve the directory just in case
75  FileSystem::Instance().Resolve(directory);
76  FileSpec raw_trace_path = directory;
77  raw_trace_path.AppendPathComponent(std::to_string(thread_sp->GetID()) +
78  ".trace");
79  json_threads.push_back(JSONThread{static_cast<int64_t>(thread_sp->GetID()),
80  raw_trace_path.GetPath().c_str()});
81 
82  llvm::Expected<llvm::Optional<std::vector<uint8_t>>> raw_trace =
83  raw_trace_fetcher(thread_sp->GetID());
84 
85  if (!raw_trace)
86  return raw_trace.takeError();
87  if (!raw_trace.get())
88  continue;
89 
90  std::basic_fstream<char> raw_trace_fs = std::fstream(
91  raw_trace_path.GetPath().c_str(), std::ios::out | std::ios::binary);
92  raw_trace_fs.write(reinterpret_cast<const char *>(&raw_trace.get()->at(0)),
93  raw_trace.get()->size() * sizeof(uint8_t));
94  raw_trace_fs.close();
95  if (!raw_trace_fs) {
96  return createStringError(inconvertibleErrorCode(),
97  formatv("couldn't write to the file {0}",
98  raw_trace_path.GetPath().c_str()));
99  }
100  }
101  return json_threads;
102 }
103 
104 llvm::Expected<std::vector<JSONModule>>
105 TraceSessionSaver::BuildModulesSection(Process &live_process,
106  FileSpec directory) {
107  std::vector<JSONModule> json_modules;
108  ModuleList module_list = live_process.GetTarget().GetImages();
109  for (size_t i = 0; i < module_list.GetSize(); ++i) {
110  ModuleSP module_sp(module_list.GetModuleAtIndex(i));
111  if (!module_sp)
112  continue;
113  std::string system_path = module_sp->GetPlatformFileSpec().GetPath();
114  // TODO: support memory-only libraries like [vdso]
115  if (!module_sp->GetFileSpec().IsAbsolute())
116  continue;
117 
118  std::string file = module_sp->GetFileSpec().GetPath();
119  ObjectFile *objfile = module_sp->GetObjectFile();
120  if (objfile == nullptr)
121  continue;
122 
124  Address base_addr(objfile->GetBaseAddress());
125  if (base_addr.IsValid() &&
126  !live_process.GetTarget().GetSectionLoadList().IsEmpty())
127  load_addr = base_addr.GetLoadAddress(&live_process.GetTarget());
128 
129  if (load_addr == LLDB_INVALID_ADDRESS)
130  continue;
131 
132  FileSystem::Instance().Resolve(directory);
133  FileSpec path_to_copy_module = directory;
134  path_to_copy_module.AppendPathComponent("modules");
135  path_to_copy_module.AppendPathComponent(system_path);
136  sys::fs::create_directories(path_to_copy_module.GetDirectory().AsCString());
137 
138  if (std::error_code ec = llvm::sys::fs::copy_file(
139  system_path, path_to_copy_module.GetPath()))
140  return createStringError(
141  inconvertibleErrorCode(),
142  formatv("couldn't write to the file. {0}", ec.message()));
143 
144  json_modules.push_back(
145  JSONModule{system_path, path_to_copy_module.GetPath(),
146  JSONAddress{load_addr}, module_sp->GetUUID().GetAsString()});
147  }
148  return json_modules;
149 }
llvm
Definition: Debugger.h:49
lldb_private::Address::IsValid
bool IsValid() const
Check if the object state is valid.
Definition: Address.h:336
lldb_private::JSONThread
Definition: TraceJSONStructs.h:28
lldb_private::Process
Definition: Process.h:340
Module.h
lldb_private::Process::GetTarget
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1212
SectionLoadList.h
lldb_private::ConstString::AsCString
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:193
lldb_private::ArchSpec::GetTriple
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:444
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
lldb_private::Target::GetImages
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition: Target.h:924
Process.h
Target.h
lldb_private::FileSpec
Definition: FileSpec.h:56
lldb_private::ModuleList::GetSize
size_t GetSize() const
Gets the size of the module list.
Definition: ModuleList.cpp:594
lldb_private::Process::Threads
ThreadList::ThreadIterable Threads()
Definition: Process.h:2122
lldb_private::ModuleList
Definition: ModuleList.h:72
lldb_private::ObjectFile::GetBaseAddress
virtual lldb_private::Address GetBaseAddress()
Returns base address of this object file.
Definition: ObjectFile.h:481
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
lldb_private::JSONTraceSessionBase
Definition: TraceJSONStructs.h:44
lldb_private::JSONTraceSessionBase::processes
std::vector< JSONProcess > processes
Definition: TraceJSONStructs.h:45
lldb-types.h
lldb_private::JSONAddress
Definition: TraceJSONStructs.h:17
lldb_private::SectionLoadList::IsEmpty
bool IsEmpty() const
Definition: SectionLoadList.cpp:37
lldb_private::Target::GetArchitecture
const ArchSpec & GetArchitecture() const
Definition: Target.h:966
lldb_private::Address
Definition: Address.h:59
lldb_private::Address::GetLoadAddress
lldb::addr_t GetLoadAddress(Target *target) const
Get the load address.
Definition: Address.cpp:310
lldb_private::Target::GetSectionLoadList
SectionLoadList & GetSectionLoadList()
Definition: Target.h:1039
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:86
lldb_private::Process::GetID
lldb::pid_t GetID() const
Returns the pid of the process or LLDB_INVALID_PROCESS_ID if there is no known pid.
Definition: Process.h:540
lldb_private::FileSpec::AppendPathComponent
void AppendPathComponent(llvm::StringRef component)
Definition: FileSpec.cpp:435
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::JSONModule
Definition: TraceJSONStructs.h:21
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:29
lldb_private::ModuleList::GetModuleAtIndex
lldb::ModuleSP GetModuleAtIndex(size_t idx) const
Get the module shared pointer for the module at index idx.
Definition: ModuleList.cpp:353
lldb_private::FileSpec::GetDirectory
ConstString & GetDirectory()
Directory string get accessor.
Definition: FileSpec.cpp:335
TraceSessionSaver.h
lldb_private::FileSpec::GetPath
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:348
lldb
Definition: SBAddress.h:15
lldb_private::JSONProcess
Definition: TraceJSONStructs.h:33
Value.h
lldb_private::ObjectFile
Definition: ObjectFile.h:58
lldb::tid_t
uint64_t tid_t
Definition: lldb-types.h:86