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