1//===-- SBTrace.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 "lldb/Target/Process.h"
10#include "lldb/Utility/Instrumentation.h"
11
12#include "lldb/API/SBDebugger.h"
13#include "lldb/API/SBStructuredData.h"
14#include "lldb/API/SBThread.h"
15#include "lldb/API/SBTrace.h"
16
17#include "lldb/Core/StructuredDataImpl.h"
18
19#include <memory>
20
21using namespace lldb;
22using namespace lldb_private;
23using namespace llvm;
24
25SBTrace::SBTrace() { LLDB_INSTRUMENT_VA(this); }
26
27SBTrace::SBTrace(const lldb::TraceSP &trace_sp) : m_opaque_sp(trace_sp) {
28  LLDB_INSTRUMENT_VA(this, trace_sp);
29}
30
31SBTrace SBTrace::LoadTraceFromFile(SBError &error, SBDebugger &debugger,
32                                   const SBFileSpec &trace_description_file) {
33  LLDB_INSTRUMENT_VA(error, debugger, trace_description_file);
34
35  Expected<lldb::TraceSP> trace_or_err = Trace::LoadPostMortemTraceFromFile(
36      debugger.ref(), trace_description_file.ref());
37
38  if (!trace_or_err) {
39    error.SetErrorString(toString(trace_or_err.takeError()).c_str());
40    return SBTrace();
41  }
42
43  return SBTrace(trace_or_err.get());
44}
45
46SBTraceCursor SBTrace::CreateNewCursor(SBError &error, SBThread &thread) {
47  LLDB_INSTRUMENT_VA(this, error, thread);
48
49  if (!m_opaque_sp) {
50    error.SetErrorString("error: invalid trace");
51    return SBTraceCursor();
52  }
53  if (!thread.get()) {
54    error.SetErrorString("error: invalid thread");
55    return SBTraceCursor();
56  }
57
58  if (llvm::Expected<lldb::TraceCursorSP> trace_cursor_sp =
59          m_opaque_sp->CreateNewCursor(*thread.get())) {
60    return SBTraceCursor(std::move(*trace_cursor_sp));
61  } else {
62    error.SetErrorString(llvm::toString(trace_cursor_sp.takeError()).c_str());
63    return SBTraceCursor();
64  }
65}
66
67SBFileSpec SBTrace::SaveToDisk(SBError &error, const SBFileSpec &bundle_dir,
68                               bool compact) {
69  LLDB_INSTRUMENT_VA(this, error, bundle_dir, compact);
70
71  error.Clear();
72  SBFileSpec file_spec;
73
74  if (!m_opaque_sp)
75    error.SetErrorString("error: invalid trace");
76  else if (Expected<FileSpec> desc_file =
77               m_opaque_sp->SaveToDisk(bundle_dir.ref(), compact))
78    file_spec.SetFileSpec(*desc_file);
79  else
80    error.SetErrorString(llvm::toString(desc_file.takeError()).c_str());
81
82  return file_spec;
83}
84
85const char *SBTrace::GetStartConfigurationHelp() {
86  LLDB_INSTRUMENT_VA(this);
87  if (!m_opaque_sp)
88    return nullptr;
89
90  return ConstString(m_opaque_sp->GetStartConfigurationHelp()).GetCString();
91}
92
93SBError SBTrace::Start(const SBStructuredData &configuration) {
94  LLDB_INSTRUMENT_VA(this, configuration);
95  SBError error;
96  if (!m_opaque_sp)
97    error.SetErrorString("error: invalid trace");
98  else if (llvm::Error err =
99               m_opaque_sp->Start(configuration.m_impl_up->GetObjectSP()))
100    error.SetErrorString(llvm::toString(std::move(err)).c_str());
101  return error;
102}
103
104SBError SBTrace::Start(const SBThread &thread,
105                       const SBStructuredData &configuration) {
106  LLDB_INSTRUMENT_VA(this, thread, configuration);
107
108  SBError error;
109  if (!m_opaque_sp)
110    error.SetErrorString("error: invalid trace");
111  else {
112    if (llvm::Error err =
113            m_opaque_sp->Start(std::vector<lldb::tid_t>{thread.GetThreadID()},
114                               configuration.m_impl_up->GetObjectSP()))
115      error.SetErrorString(llvm::toString(std::move(err)).c_str());
116  }
117
118  return error;
119}
120
121SBError SBTrace::Stop() {
122  LLDB_INSTRUMENT_VA(this);
123  SBError error;
124  if (!m_opaque_sp)
125    error.SetErrorString("error: invalid trace");
126  else if (llvm::Error err = m_opaque_sp->Stop())
127    error.SetErrorString(llvm::toString(std::move(err)).c_str());
128  return error;
129}
130
131SBError SBTrace::Stop(const SBThread &thread) {
132  LLDB_INSTRUMENT_VA(this, thread);
133  SBError error;
134  if (!m_opaque_sp)
135    error.SetErrorString("error: invalid trace");
136  else if (llvm::Error err = m_opaque_sp->Stop({thread.GetThreadID()}))
137    error.SetErrorString(llvm::toString(std::move(err)).c_str());
138  return error;
139}
140
141bool SBTrace::IsValid() {
142  LLDB_INSTRUMENT_VA(this);
143  return this->operator bool();
144}
145
146SBTrace::operator bool() const {
147  LLDB_INSTRUMENT_VA(this);
148  return (bool)m_opaque_sp;
149}
150