LLDB  mainline
TraceSessionFileParser.cpp
Go to the documentation of this file.
1 //===-- TraceSessionFileParser.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 
10 
11 #include <sstream>
12 
13 #include "lldb/Core/Debugger.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Target/Process.h"
16 #include "lldb/Target/Target.h"
18 
19 using namespace lldb;
20 using namespace lldb_private;
21 using namespace llvm;
22 
23 void TraceSessionFileParser::NormalizePath(lldb_private::FileSpec &file_spec) {
24  if (file_spec.IsRelative())
25  file_spec.PrependPathComponent(m_session_file_dir);
26 }
27 
28 Error TraceSessionFileParser::ParseModule(lldb::TargetSP &target_sp,
29  const JSONModule &module) {
30  FileSpec system_file_spec(module.system_path);
31  NormalizePath(system_file_spec);
32 
33  FileSpec local_file_spec(module.file.hasValue() ? *module.file
34  : module.system_path);
35  NormalizePath(local_file_spec);
36 
37  ModuleSpec module_spec;
38  module_spec.GetFileSpec() = local_file_spec;
39  module_spec.GetPlatformFileSpec() = system_file_spec;
40 
41  if (module.uuid.hasValue())
42  module_spec.GetUUID().SetFromStringRef(*module.uuid);
43 
44  Status error;
45  ModuleSP module_sp =
46  target_sp->GetOrCreateModule(module_spec, /*notify*/ false, &error);
47 
48  if (error.Fail())
49  return error.ToError();
50 
51  bool load_addr_changed = false;
52  module_sp->SetLoadAddress(*target_sp, module.load_address.value, false,
53  load_addr_changed);
54  return llvm::Error::success();
55 }
56 
57 Error TraceSessionFileParser::CreateJSONError(json::Path::Root &root,
58  const json::Value &value) {
59  std::string err;
60  raw_string_ostream os(err);
61  root.printErrorContext(value, os);
62  return createStringError(
63  std::errc::invalid_argument, "%s\n\nContext:\n%s\n\nSchema:\n%s",
64  toString(root.getError()).c_str(), os.str().c_str(), m_schema.data());
65 }
66 
67 std::string TraceSessionFileParser::BuildSchema(StringRef plugin_schema) {
68  std::ostringstream schema_builder;
69  schema_builder << "{\n \"trace\": ";
70  schema_builder << plugin_schema.data() << ",";
71  schema_builder << R"(
72  "processes": [
73  {
74  "pid": integer,
75  "triple": string, // llvm-triple
76  "threads": [
77  {
78  "tid": integer,
79  "traceFile": string
80  }
81  ],
82  "modules": [
83  {
84  "systemPath": string, // original path of the module at runtime
85  "file"?: string, // copy of the file if not available at "systemPath"
86  "loadAddress": string, // string address in hex or decimal form
87  "uuid"?: string,
88  }
89  ]
90  }
91  ]
92  // Notes:
93  // All paths are either absolute or relative to the session file.
94 }
95 )";
96  return schema_builder.str();
97 }
98 
99 ThreadPostMortemTraceSP
100 TraceSessionFileParser::ParseThread(ProcessSP &process_sp,
101  const JSONThread &thread) {
102  lldb::tid_t tid = static_cast<lldb::tid_t>(thread.tid);
103 
104  FileSpec trace_file(thread.trace_file);
105  NormalizePath(trace_file);
106 
107  ThreadPostMortemTraceSP thread_sp =
108  std::make_shared<ThreadPostMortemTrace>(*process_sp, tid, trace_file);
109  process_sp->GetThreadList().AddThread(thread_sp);
110  return thread_sp;
111 }
112 
113 Expected<TraceSessionFileParser::ParsedProcess>
114 TraceSessionFileParser::ParseProcess(const JSONProcess &process) {
115  TargetSP target_sp;
116  Status error = m_debugger.GetTargetList().CreateTarget(
117  m_debugger, /*user_exe_path*/ StringRef(), process.triple,
119  /*platform_options*/ nullptr, target_sp);
120 
121  if (!target_sp)
122  return error.ToError();
123 
124  ParsedProcess parsed_process;
125  parsed_process.target_sp = target_sp;
126 
127  ProcessSP process_sp = target_sp->CreateProcess(
128  /*listener*/ nullptr, "trace",
129  /*crash_file*/ nullptr,
130  /*can_connect*/ false);
131 
132  process_sp->SetID(static_cast<lldb::pid_t>(process.pid));
133 
134  for (const JSONThread &thread : process.threads)
135  parsed_process.threads.push_back(ParseThread(process_sp, thread));
136 
137  for (const JSONModule &module : process.modules)
138  if (Error err = ParseModule(target_sp, module))
139  return std::move(err);
140 
141  if (!process.threads.empty())
142  process_sp->GetThreadList().SetSelectedThreadByIndexID(0);
143 
144  // We invoke DidAttach to create a correct stopped state for the process and
145  // its threads.
146  ArchSpec process_arch;
147  process_sp->DidAttach(process_arch);
148 
149  return parsed_process;
150 }
151 
152 Expected<std::vector<TraceSessionFileParser::ParsedProcess>>
153 TraceSessionFileParser::ParseCommonSessionFile(
154  const JSONTraceSessionBase &session) {
155  std::vector<ParsedProcess> parsed_processes;
156 
157  auto onError = [&]() {
158  // Delete all targets that were created so far in case of failures
159  for (ParsedProcess &parsed_process : parsed_processes)
160  m_debugger.GetTargetList().DeleteTarget(parsed_process.target_sp);
161  };
162 
163  for (const JSONProcess &process : session.processes) {
164  if (Expected<ParsedProcess> parsed_process = ParseProcess(process))
165  parsed_processes.push_back(std::move(*parsed_process));
166  else {
167  onError();
168  return parsed_process.takeError();
169  }
170  }
171  return parsed_processes;
172 }
173 
174 namespace llvm {
175 namespace json {
176 
177 bool fromJSON(const Value &value, TraceSessionFileParser::JSONAddress &address,
178  Path path) {
179  Optional<StringRef> s = value.getAsString();
180  if (s.hasValue() && !s->getAsInteger(0, address.value))
181  return true;
182 
183  path.report("expected numeric string");
184  return false;
185 }
186 
187 bool fromJSON(const Value &value, TraceSessionFileParser::JSONModule &module,
188  Path path) {
189  ObjectMapper o(value, path);
190  return o && o.map("systemPath", module.system_path) &&
191  o.map("file", module.file) &&
192  o.map("loadAddress", module.load_address) &&
193  o.map("uuid", module.uuid);
194 }
195 
196 bool fromJSON(const Value &value, TraceSessionFileParser::JSONThread &thread,
197  Path path) {
198  ObjectMapper o(value, path);
199  return o && o.map("tid", thread.tid) && o.map("traceFile", thread.trace_file);
200 }
201 
202 bool fromJSON(const Value &value, TraceSessionFileParser::JSONProcess &process,
203  Path path) {
204  ObjectMapper o(value, path);
205  return o && o.map("pid", process.pid) && o.map("triple", process.triple) &&
206  o.map("threads", process.threads) && o.map("modules", process.modules);
207 }
208 
209 bool fromJSON(const Value &value,
211  Path path) {
212  ObjectMapper o(value, path);
213  return o && o.map("type", plugin_settings.type);
214 }
215 
216 bool fromJSON(const Value &value,
218  Path path) {
219  ObjectMapper o(value, path);
220  return o && o.map("processes", session.processes);
221 }
222 
223 } // namespace json
224 } // namespace llvm
llvm
Definition: Debugger.h:49
lldb_private::ArchSpec
Definition: ArchSpec.h:33
lldb_private::ModuleSpec::GetPlatformFileSpec
FileSpec & GetPlatformFileSpec()
Definition: ModuleSpec.h:71
lldb_private::TraceSessionFileParser::JSONProcess::pid
int64_t pid
Definition: TraceSessionFileParser.h:46
lldb_private::TraceSessionFileParser::JSONAddress
C++ structs representing the JSON trace session.
Definition: TraceSessionFileParser.h:29
lldb_private::Value
Definition: Value.h:38
llvm::json::fromJSON
bool fromJSON(const Value &value, TraceSessionFileParser::JSONTraceSessionBase &session, Path path)
Definition: TraceSessionFileParser.cpp:192
ThreadPostMortemTrace.h
Module.h
lldb_private::TraceSessionFileParser::JSONTraceSessionBase
Definition: TraceSessionFileParser.h:56
Debugger.h
lldb_private::FileSpec::PrependPathComponent
void PrependPathComponent(llvm::StringRef component)
Definition: FileSpec.cpp:421
Process.h
Target.h
lldb_private::ModuleSpec::GetUUID
UUID & GetUUID()
Definition: ModuleSpec.h:105
lldb_private::TraceSessionFileParser::JSONModule::load_address
JSONAddress load_address
Definition: TraceSessionFileParser.h:36
lldb_private::FileSpec
Definition: FileSpec.h:56
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::TraceSessionFileParser::JSONProcess::triple
std::string triple
Definition: TraceSessionFileParser.h:47
lldb_private::breakpad::toString
llvm::StringRef toString(Record::Kind K)
Definition: BreakpadRecords.cpp:483
lldb_private::eLoadDependentsNo
@ eLoadDependentsNo
Definition: Target.h:65
lldb_private::TraceSessionFileParser::JSONTraceSessionBase::processes
std::vector< JSONProcess > processes
Definition: TraceSessionFileParser.h:57
lldb_private::TraceSessionFileParser::JSONAddress::value
lldb::addr_t value
Definition: TraceSessionFileParser.h:30
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:38
lldb_private::TraceSessionFileParser::JSONProcess::modules
std::vector< JSONModule > modules
Definition: TraceSessionFileParser.h:49
lldb_private::TraceSessionFileParser::JSONProcess
Definition: TraceSessionFileParser.h:45
lldb_private::TraceSessionFileParser::JSONModule::system_path
std::string system_path
Definition: TraceSessionFileParser.h:34
lldb_private::TraceSessionFileParser::JSONThread::trace_file
std::string trace_file
Definition: TraceSessionFileParser.h:42
lldb_private::TraceSessionFileParser::JSONModule::file
llvm::Optional< std::string > file
Definition: TraceSessionFileParser.h:35
lldb_private::ModuleSpec::GetFileSpec
FileSpec & GetFileSpec()
Definition: ModuleSpec.h:59
lldb_private::ModuleSpec
Definition: ModuleSpec.h:26
lldb_private::Status
Definition: Status.h:44
lldb_private::FileSpec::IsRelative
bool IsRelative() const
Returns true if the filespec represents a relative path.
Definition: FileSpec.cpp:475
lldb::pid_t
uint64_t pid_t
Definition: lldb-types.h:85
lldb_private::UUID::SetFromStringRef
bool SetFromStringRef(llvm::StringRef str)
Definition: UUID.cpp:96
lldb_private::TraceSessionFileParser::JSONTracePluginSettings
Definition: TraceSessionFileParser.h:52
lldb_private::TraceSessionFileParser::JSONProcess::threads
std::vector< JSONThread > threads
Definition: TraceSessionFileParser.h:48
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::TraceSessionFileParser::JSONThread
Definition: TraceSessionFileParser.h:40
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:29
TraceSessionFileParser.h
lldb_private::TraceSessionFileParser::JSONModule
Definition: TraceSessionFileParser.h:33
lldb_private::TraceSessionFileParser::JSONThread::tid
int64_t tid
Definition: TraceSessionFileParser.h:41
lldb_private::TraceSessionFileParser::JSONTracePluginSettings::type
std::string type
Definition: TraceSessionFileParser.h:53
lldb_private::TraceSessionFileParser::JSONModule::uuid
llvm::Optional< std::string > uuid
Definition: TraceSessionFileParser.h:37
lldb
Definition: SBAddress.h:15
lldb::tid_t
uint64_t tid_t
Definition: lldb-types.h:86