15ffd83dbSDimitry Andric //===-- SBReproducer.cpp --------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "SBReproducerPrivate.h"
100b57cec5SDimitry Andric
110b57cec5SDimitry Andric #include "lldb/API/LLDB.h"
120b57cec5SDimitry Andric #include "lldb/API/SBAddress.h"
130b57cec5SDimitry Andric #include "lldb/API/SBAttachInfo.h"
140b57cec5SDimitry Andric #include "lldb/API/SBBlock.h"
150b57cec5SDimitry Andric #include "lldb/API/SBBreakpoint.h"
160b57cec5SDimitry Andric #include "lldb/API/SBCommandInterpreter.h"
175ffd83dbSDimitry Andric #include "lldb/API/SBCommandInterpreterRunOptions.h"
180b57cec5SDimitry Andric #include "lldb/API/SBData.h"
190b57cec5SDimitry Andric #include "lldb/API/SBDebugger.h"
200b57cec5SDimitry Andric #include "lldb/API/SBDeclaration.h"
210b57cec5SDimitry Andric #include "lldb/API/SBError.h"
220b57cec5SDimitry Andric #include "lldb/API/SBFileSpec.h"
230b57cec5SDimitry Andric #include "lldb/API/SBHostOS.h"
240b57cec5SDimitry Andric #include "lldb/API/SBReproducer.h"
250b57cec5SDimitry Andric #include "lldb/Host/FileSystem.h"
26480093f4SDimitry Andric #include "lldb/lldb-private.h"
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric using namespace lldb;
290b57cec5SDimitry Andric using namespace lldb_private;
300b57cec5SDimitry Andric using namespace lldb_private::repro;
310b57cec5SDimitry Andric
SBReplayOptions()32*af732203SDimitry Andric SBReplayOptions::SBReplayOptions()
33*af732203SDimitry Andric : m_opaque_up(std::make_unique<ReplayOptions>()){}
34*af732203SDimitry Andric
SBReplayOptions(const SBReplayOptions & rhs)35*af732203SDimitry Andric SBReplayOptions::SBReplayOptions(const SBReplayOptions &rhs)
36*af732203SDimitry Andric : m_opaque_up(std::make_unique<ReplayOptions>(*rhs.m_opaque_up)) {}
37*af732203SDimitry Andric
38*af732203SDimitry Andric SBReplayOptions::~SBReplayOptions() = default;
39*af732203SDimitry Andric
operator =(const SBReplayOptions & rhs)40*af732203SDimitry Andric SBReplayOptions &SBReplayOptions::operator=(const SBReplayOptions &rhs) {
41*af732203SDimitry Andric if (this == &rhs)
42*af732203SDimitry Andric return *this;
43*af732203SDimitry Andric *m_opaque_up = *rhs.m_opaque_up;
44*af732203SDimitry Andric return *this;
45*af732203SDimitry Andric }
46*af732203SDimitry Andric
SetVerify(bool verify)47*af732203SDimitry Andric void SBReplayOptions::SetVerify(bool verify) { m_opaque_up->verify = verify; }
48*af732203SDimitry Andric
GetVerify() const49*af732203SDimitry Andric bool SBReplayOptions::GetVerify() const { return m_opaque_up->verify; }
50*af732203SDimitry Andric
SetCheckVersion(bool check)51*af732203SDimitry Andric void SBReplayOptions::SetCheckVersion(bool check) {
52*af732203SDimitry Andric m_opaque_up->check_version = check;
53*af732203SDimitry Andric }
54*af732203SDimitry Andric
GetCheckVersion() const55*af732203SDimitry Andric bool SBReplayOptions::GetCheckVersion() const {
56*af732203SDimitry Andric return m_opaque_up->check_version;
57*af732203SDimitry Andric }
58*af732203SDimitry Andric
SBRegistry()590b57cec5SDimitry Andric SBRegistry::SBRegistry() {
600b57cec5SDimitry Andric Registry &R = *this;
610b57cec5SDimitry Andric
620b57cec5SDimitry Andric RegisterMethods<SBAddress>(R);
630b57cec5SDimitry Andric RegisterMethods<SBAttachInfo>(R);
640b57cec5SDimitry Andric RegisterMethods<SBBlock>(R);
650b57cec5SDimitry Andric RegisterMethods<SBBreakpoint>(R);
660b57cec5SDimitry Andric RegisterMethods<SBBreakpointList>(R);
670b57cec5SDimitry Andric RegisterMethods<SBBreakpointLocation>(R);
680b57cec5SDimitry Andric RegisterMethods<SBBreakpointName>(R);
690b57cec5SDimitry Andric RegisterMethods<SBBroadcaster>(R);
705ffd83dbSDimitry Andric RegisterMethods<SBCommandInterpreter>(R);
710b57cec5SDimitry Andric RegisterMethods<SBCommandInterpreterRunOptions>(R);
720b57cec5SDimitry Andric RegisterMethods<SBCommandReturnObject>(R);
730b57cec5SDimitry Andric RegisterMethods<SBCommunication>(R);
740b57cec5SDimitry Andric RegisterMethods<SBCompileUnit>(R);
750b57cec5SDimitry Andric RegisterMethods<SBData>(R);
760b57cec5SDimitry Andric RegisterMethods<SBDebugger>(R);
770b57cec5SDimitry Andric RegisterMethods<SBDeclaration>(R);
785ffd83dbSDimitry Andric RegisterMethods<SBEnvironment>(R);
790b57cec5SDimitry Andric RegisterMethods<SBError>(R);
800b57cec5SDimitry Andric RegisterMethods<SBEvent>(R);
810b57cec5SDimitry Andric RegisterMethods<SBExecutionContext>(R);
820b57cec5SDimitry Andric RegisterMethods<SBExpressionOptions>(R);
839dba64beSDimitry Andric RegisterMethods<SBFile>(R);
840b57cec5SDimitry Andric RegisterMethods<SBFileSpec>(R);
850b57cec5SDimitry Andric RegisterMethods<SBFileSpecList>(R);
860b57cec5SDimitry Andric RegisterMethods<SBFrame>(R);
870b57cec5SDimitry Andric RegisterMethods<SBFunction>(R);
880b57cec5SDimitry Andric RegisterMethods<SBHostOS>(R);
895ffd83dbSDimitry Andric RegisterMethods<SBInputReader>(R);
900b57cec5SDimitry Andric RegisterMethods<SBInstruction>(R);
910b57cec5SDimitry Andric RegisterMethods<SBInstructionList>(R);
920b57cec5SDimitry Andric RegisterMethods<SBLanguageRuntime>(R);
930b57cec5SDimitry Andric RegisterMethods<SBLaunchInfo>(R);
940b57cec5SDimitry Andric RegisterMethods<SBLineEntry>(R);
950b57cec5SDimitry Andric RegisterMethods<SBListener>(R);
960b57cec5SDimitry Andric RegisterMethods<SBMemoryRegionInfo>(R);
970b57cec5SDimitry Andric RegisterMethods<SBMemoryRegionInfoList>(R);
980b57cec5SDimitry Andric RegisterMethods<SBModule>(R);
990b57cec5SDimitry Andric RegisterMethods<SBModuleSpec>(R);
1005ffd83dbSDimitry Andric RegisterMethods<SBPlatform>(R);
1010b57cec5SDimitry Andric RegisterMethods<SBPlatformConnectOptions>(R);
1020b57cec5SDimitry Andric RegisterMethods<SBPlatformShellCommand>(R);
1030b57cec5SDimitry Andric RegisterMethods<SBProcess>(R);
1040b57cec5SDimitry Andric RegisterMethods<SBProcessInfo>(R);
1050b57cec5SDimitry Andric RegisterMethods<SBQueue>(R);
1060b57cec5SDimitry Andric RegisterMethods<SBQueueItem>(R);
1070b57cec5SDimitry Andric RegisterMethods<SBSection>(R);
1080b57cec5SDimitry Andric RegisterMethods<SBSourceManager>(R);
1090b57cec5SDimitry Andric RegisterMethods<SBStream>(R);
1100b57cec5SDimitry Andric RegisterMethods<SBStringList>(R);
1110b57cec5SDimitry Andric RegisterMethods<SBStructuredData>(R);
1120b57cec5SDimitry Andric RegisterMethods<SBSymbol>(R);
1130b57cec5SDimitry Andric RegisterMethods<SBSymbolContext>(R);
1140b57cec5SDimitry Andric RegisterMethods<SBSymbolContextList>(R);
1150b57cec5SDimitry Andric RegisterMethods<SBTarget>(R);
1160b57cec5SDimitry Andric RegisterMethods<SBThread>(R);
1170b57cec5SDimitry Andric RegisterMethods<SBThreadCollection>(R);
1180b57cec5SDimitry Andric RegisterMethods<SBThreadPlan>(R);
1190b57cec5SDimitry Andric RegisterMethods<SBTrace>(R);
1200b57cec5SDimitry Andric RegisterMethods<SBType>(R);
1210b57cec5SDimitry Andric RegisterMethods<SBTypeCategory>(R);
1220b57cec5SDimitry Andric RegisterMethods<SBTypeEnumMember>(R);
1230b57cec5SDimitry Andric RegisterMethods<SBTypeFilter>(R);
1240b57cec5SDimitry Andric RegisterMethods<SBTypeFormat>(R);
1250b57cec5SDimitry Andric RegisterMethods<SBTypeNameSpecifier>(R);
1260b57cec5SDimitry Andric RegisterMethods<SBTypeSummary>(R);
1275ffd83dbSDimitry Andric RegisterMethods<SBTypeSummaryOptions>(R);
1280b57cec5SDimitry Andric RegisterMethods<SBTypeSynthetic>(R);
1290b57cec5SDimitry Andric RegisterMethods<SBUnixSignals>(R);
1300b57cec5SDimitry Andric RegisterMethods<SBValue>(R);
1310b57cec5SDimitry Andric RegisterMethods<SBValueList>(R);
1320b57cec5SDimitry Andric RegisterMethods<SBVariablesOptions>(R);
1330b57cec5SDimitry Andric RegisterMethods<SBWatchpoint>(R);
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric
Capture()1360b57cec5SDimitry Andric const char *SBReproducer::Capture() {
1370b57cec5SDimitry Andric static std::string error;
1380b57cec5SDimitry Andric if (auto e = Reproducer::Initialize(ReproducerMode::Capture, llvm::None)) {
1390b57cec5SDimitry Andric error = llvm::toString(std::move(e));
1400b57cec5SDimitry Andric return error.c_str();
1410b57cec5SDimitry Andric }
1425ffd83dbSDimitry Andric
1435ffd83dbSDimitry Andric if (auto *g = lldb_private::repro::Reproducer::Instance().GetGenerator()) {
1445ffd83dbSDimitry Andric auto &p = g->GetOrCreate<SBProvider>();
1455ffd83dbSDimitry Andric InstrumentationData::Initialize(p.GetSerializer(), p.GetRegistry());
1465ffd83dbSDimitry Andric }
1475ffd83dbSDimitry Andric
1480b57cec5SDimitry Andric return nullptr;
1490b57cec5SDimitry Andric }
1500b57cec5SDimitry Andric
Capture(const char * path)1510b57cec5SDimitry Andric const char *SBReproducer::Capture(const char *path) {
1520b57cec5SDimitry Andric static std::string error;
1530b57cec5SDimitry Andric if (auto e =
1540b57cec5SDimitry Andric Reproducer::Initialize(ReproducerMode::Capture, FileSpec(path))) {
1550b57cec5SDimitry Andric error = llvm::toString(std::move(e));
1560b57cec5SDimitry Andric return error.c_str();
1570b57cec5SDimitry Andric }
1585ffd83dbSDimitry Andric
1595ffd83dbSDimitry Andric if (auto *g = lldb_private::repro::Reproducer::Instance().GetGenerator()) {
1605ffd83dbSDimitry Andric auto &p = g->GetOrCreate<SBProvider>();
1615ffd83dbSDimitry Andric InstrumentationData::Initialize(p.GetSerializer(), p.GetRegistry());
1625ffd83dbSDimitry Andric }
1635ffd83dbSDimitry Andric
1645ffd83dbSDimitry Andric return nullptr;
1655ffd83dbSDimitry Andric }
1665ffd83dbSDimitry Andric
PassiveReplay(const char * path)1675ffd83dbSDimitry Andric const char *SBReproducer::PassiveReplay(const char *path) {
1685ffd83dbSDimitry Andric static std::string error;
1695ffd83dbSDimitry Andric if (auto e = Reproducer::Initialize(ReproducerMode::PassiveReplay,
1705ffd83dbSDimitry Andric FileSpec(path))) {
1715ffd83dbSDimitry Andric error = llvm::toString(std::move(e));
1725ffd83dbSDimitry Andric return error.c_str();
1735ffd83dbSDimitry Andric }
1745ffd83dbSDimitry Andric
1755ffd83dbSDimitry Andric if (auto *l = lldb_private::repro::Reproducer::Instance().GetLoader()) {
1765ffd83dbSDimitry Andric FileSpec file = l->GetFile<SBProvider::Info>();
1775ffd83dbSDimitry Andric auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath());
1785ffd83dbSDimitry Andric if (!error_or_file) {
1795ffd83dbSDimitry Andric error =
1805ffd83dbSDimitry Andric "unable to read SB API data: " + error_or_file.getError().message();
1815ffd83dbSDimitry Andric return error.c_str();
1825ffd83dbSDimitry Andric }
1835ffd83dbSDimitry Andric static ReplayData r(std::move(*error_or_file));
1845ffd83dbSDimitry Andric InstrumentationData::Initialize(r.GetDeserializer(), r.GetRegistry());
1855ffd83dbSDimitry Andric }
1865ffd83dbSDimitry Andric
1870b57cec5SDimitry Andric return nullptr;
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric
Replay(const char * path)1900b57cec5SDimitry Andric const char *SBReproducer::Replay(const char *path) {
191*af732203SDimitry Andric SBReplayOptions options;
192*af732203SDimitry Andric return SBReproducer::Replay(path, options);
193480093f4SDimitry Andric }
194480093f4SDimitry Andric
Replay(const char * path,bool skip_version_check)195480093f4SDimitry Andric const char *SBReproducer::Replay(const char *path, bool skip_version_check) {
196*af732203SDimitry Andric SBReplayOptions options;
197*af732203SDimitry Andric options.SetCheckVersion(!skip_version_check);
198*af732203SDimitry Andric return SBReproducer::Replay(path, options);
199*af732203SDimitry Andric }
200*af732203SDimitry Andric
Replay(const char * path,const SBReplayOptions & options)201*af732203SDimitry Andric const char *SBReproducer::Replay(const char *path,
202*af732203SDimitry Andric const SBReplayOptions &options) {
2030b57cec5SDimitry Andric static std::string error;
2040b57cec5SDimitry Andric if (auto e = Reproducer::Initialize(ReproducerMode::Replay, FileSpec(path))) {
2050b57cec5SDimitry Andric error = llvm::toString(std::move(e));
2060b57cec5SDimitry Andric return error.c_str();
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric
2090b57cec5SDimitry Andric repro::Loader *loader = repro::Reproducer::Instance().GetLoader();
2100b57cec5SDimitry Andric if (!loader) {
2110b57cec5SDimitry Andric error = "unable to get replay loader.";
2120b57cec5SDimitry Andric return error.c_str();
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric
215*af732203SDimitry Andric if (options.GetCheckVersion()) {
216480093f4SDimitry Andric llvm::Expected<std::string> version = loader->LoadBuffer<VersionProvider>();
217480093f4SDimitry Andric if (!version) {
218480093f4SDimitry Andric error = llvm::toString(version.takeError());
219480093f4SDimitry Andric return error.c_str();
220480093f4SDimitry Andric }
221480093f4SDimitry Andric if (lldb_private::GetVersion() != llvm::StringRef(*version).rtrim()) {
222480093f4SDimitry Andric error = "reproducer capture and replay version don't match:\n";
223480093f4SDimitry Andric error.append("reproducer captured with:\n");
224480093f4SDimitry Andric error.append(*version);
225480093f4SDimitry Andric error.append("reproducer replayed with:\n");
226480093f4SDimitry Andric error.append(lldb_private::GetVersion());
227480093f4SDimitry Andric return error.c_str();
228480093f4SDimitry Andric }
229480093f4SDimitry Andric }
230480093f4SDimitry Andric
231*af732203SDimitry Andric if (options.GetVerify()) {
232*af732203SDimitry Andric bool verification_failed = false;
233*af732203SDimitry Andric llvm::raw_string_ostream os(error);
234*af732203SDimitry Andric auto error_callback = [&](llvm::StringRef error) {
235*af732203SDimitry Andric verification_failed = true;
236*af732203SDimitry Andric os << "\nerror: " << error;
237*af732203SDimitry Andric };
238*af732203SDimitry Andric
239*af732203SDimitry Andric auto warning_callback = [&](llvm::StringRef warning) {
240*af732203SDimitry Andric verification_failed = true;
241*af732203SDimitry Andric os << "\nwarning: " << warning;
242*af732203SDimitry Andric };
243*af732203SDimitry Andric
244*af732203SDimitry Andric auto note_callback = [&](llvm::StringRef warning) {};
245*af732203SDimitry Andric
246*af732203SDimitry Andric Verifier verifier(loader);
247*af732203SDimitry Andric verifier.Verify(error_callback, warning_callback, note_callback);
248*af732203SDimitry Andric
249*af732203SDimitry Andric if (verification_failed) {
250*af732203SDimitry Andric os.flush();
251*af732203SDimitry Andric return error.c_str();
252*af732203SDimitry Andric }
253*af732203SDimitry Andric }
254*af732203SDimitry Andric
2550b57cec5SDimitry Andric FileSpec file = loader->GetFile<SBProvider::Info>();
2560b57cec5SDimitry Andric if (!file) {
2570b57cec5SDimitry Andric error = "unable to get replay data from reproducer.";
2580b57cec5SDimitry Andric return error.c_str();
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric
2610b57cec5SDimitry Andric SBRegistry registry;
2620b57cec5SDimitry Andric registry.Replay(file);
2630b57cec5SDimitry Andric
2640b57cec5SDimitry Andric return nullptr;
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric
Finalize(const char * path)267*af732203SDimitry Andric const char *SBReproducer::Finalize(const char *path) {
268*af732203SDimitry Andric static std::string error;
269*af732203SDimitry Andric if (auto e = Reproducer::Initialize(ReproducerMode::Replay, FileSpec(path))) {
270*af732203SDimitry Andric error = llvm::toString(std::move(e));
271*af732203SDimitry Andric return error.c_str();
272*af732203SDimitry Andric }
273*af732203SDimitry Andric
274*af732203SDimitry Andric repro::Loader *loader = repro::Reproducer::Instance().GetLoader();
275*af732203SDimitry Andric if (!loader) {
276*af732203SDimitry Andric error = "unable to get replay loader.";
277*af732203SDimitry Andric return error.c_str();
278*af732203SDimitry Andric }
279*af732203SDimitry Andric
280*af732203SDimitry Andric if (auto e = repro::Finalize(loader)) {
281*af732203SDimitry Andric error = llvm::toString(std::move(e));
282*af732203SDimitry Andric return error.c_str();
283*af732203SDimitry Andric }
284*af732203SDimitry Andric
285*af732203SDimitry Andric return nullptr;
286*af732203SDimitry Andric }
287*af732203SDimitry Andric
Generate()288480093f4SDimitry Andric bool SBReproducer::Generate() {
289480093f4SDimitry Andric auto &r = Reproducer::Instance();
290480093f4SDimitry Andric if (auto generator = r.GetGenerator()) {
291480093f4SDimitry Andric generator->Keep();
292480093f4SDimitry Andric return true;
293480093f4SDimitry Andric }
294480093f4SDimitry Andric return false;
295480093f4SDimitry Andric }
296480093f4SDimitry Andric
SetAutoGenerate(bool b)2975ffd83dbSDimitry Andric bool SBReproducer::SetAutoGenerate(bool b) {
2985ffd83dbSDimitry Andric auto &r = Reproducer::Instance();
2995ffd83dbSDimitry Andric if (auto generator = r.GetGenerator()) {
3005ffd83dbSDimitry Andric generator->SetAutoGenerate(b);
3015ffd83dbSDimitry Andric return true;
3025ffd83dbSDimitry Andric }
3035ffd83dbSDimitry Andric return false;
3045ffd83dbSDimitry Andric }
3055ffd83dbSDimitry Andric
GetPath()306480093f4SDimitry Andric const char *SBReproducer::GetPath() {
307*af732203SDimitry Andric ConstString path;
308480093f4SDimitry Andric auto &r = Reproducer::Instance();
309*af732203SDimitry Andric if (FileSpec reproducer_path = Reproducer::Instance().GetReproducerPath())
310*af732203SDimitry Andric path = ConstString(r.GetReproducerPath().GetCString());
311*af732203SDimitry Andric return path.GetCString();
312480093f4SDimitry Andric }
313480093f4SDimitry Andric
SetWorkingDirectory(const char * path)3145ffd83dbSDimitry Andric void SBReproducer::SetWorkingDirectory(const char *path) {
3155ffd83dbSDimitry Andric if (auto *g = lldb_private::repro::Reproducer::Instance().GetGenerator()) {
316*af732203SDimitry Andric auto &wp = g->GetOrCreate<repro::WorkingDirectoryProvider>();
317*af732203SDimitry Andric wp.SetDirectory(path);
318*af732203SDimitry Andric auto &fp = g->GetOrCreate<repro::FileProvider>();
319*af732203SDimitry Andric fp.RecordInterestingDirectory(wp.GetDirectory());
3205ffd83dbSDimitry Andric }
3215ffd83dbSDimitry Andric }
3225ffd83dbSDimitry Andric
3230b57cec5SDimitry Andric char lldb_private::repro::SBProvider::ID = 0;
3240b57cec5SDimitry Andric const char *SBProvider::Info::name = "sbapi";
3250b57cec5SDimitry Andric const char *SBProvider::Info::file = "sbapi.bin";
326