1 //===-- SBReproducer.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 "SBReproducerPrivate.h" 10 11 #include "SBReproducerPrivate.h" 12 #include "lldb/API/LLDB.h" 13 #include "lldb/API/SBAddress.h" 14 #include "lldb/API/SBAttachInfo.h" 15 #include "lldb/API/SBBlock.h" 16 #include "lldb/API/SBBreakpoint.h" 17 #include "lldb/API/SBCommandInterpreter.h" 18 #include "lldb/API/SBCommandInterpreterRunOptions.h" 19 #include "lldb/API/SBData.h" 20 #include "lldb/API/SBDebugger.h" 21 #include "lldb/API/SBDeclaration.h" 22 #include "lldb/API/SBError.h" 23 #include "lldb/API/SBFileSpec.h" 24 #include "lldb/API/SBHostOS.h" 25 #include "lldb/API/SBReproducer.h" 26 #include "lldb/Host/FileSystem.h" 27 #include "lldb/lldb-private.h" 28 29 using namespace lldb; 30 using namespace lldb_private; 31 using namespace lldb_private::repro; 32 33 SBReplayOptions::SBReplayOptions() 34 : m_opaque_up(std::make_unique<ReplayOptions>()){} 35 36 SBReplayOptions::SBReplayOptions(const SBReplayOptions &rhs) 37 : m_opaque_up(std::make_unique<ReplayOptions>(*rhs.m_opaque_up)) {} 38 39 SBReplayOptions::~SBReplayOptions() = default; 40 41 SBReplayOptions &SBReplayOptions::operator=(const SBReplayOptions &rhs) { 42 if (this == &rhs) 43 return *this; 44 *m_opaque_up = *rhs.m_opaque_up; 45 return *this; 46 } 47 48 void SBReplayOptions::SetVerify(bool verify) { m_opaque_up->verify = verify; } 49 50 bool SBReplayOptions::GetVerify() const { return m_opaque_up->verify; } 51 52 void SBReplayOptions::SetCheckVersion(bool check) { 53 m_opaque_up->check_version = check; 54 } 55 56 bool SBReplayOptions::GetCheckVersion() const { 57 return m_opaque_up->check_version; 58 } 59 60 SBRegistry::SBRegistry() { 61 Registry &R = *this; 62 63 RegisterMethods<SBAddress>(R); 64 RegisterMethods<SBAttachInfo>(R); 65 RegisterMethods<SBBlock>(R); 66 RegisterMethods<SBBreakpoint>(R); 67 RegisterMethods<SBBreakpointList>(R); 68 RegisterMethods<SBBreakpointLocation>(R); 69 RegisterMethods<SBBreakpointName>(R); 70 RegisterMethods<SBBroadcaster>(R); 71 RegisterMethods<SBCommandInterpreter>(R); 72 RegisterMethods<SBCommandInterpreterRunOptions>(R); 73 RegisterMethods<SBCommandReturnObject>(R); 74 RegisterMethods<SBCommunication>(R); 75 RegisterMethods<SBCompileUnit>(R); 76 RegisterMethods<SBData>(R); 77 RegisterMethods<SBDebugger>(R); 78 RegisterMethods<SBDeclaration>(R); 79 RegisterMethods<SBEnvironment>(R); 80 RegisterMethods<SBError>(R); 81 RegisterMethods<SBEvent>(R); 82 RegisterMethods<SBExecutionContext>(R); 83 RegisterMethods<SBExpressionOptions>(R); 84 RegisterMethods<SBFile>(R); 85 RegisterMethods<SBFileSpec>(R); 86 RegisterMethods<SBFileSpecList>(R); 87 RegisterMethods<SBFrame>(R); 88 RegisterMethods<SBFunction>(R); 89 RegisterMethods<SBHostOS>(R); 90 RegisterMethods<SBInputReader>(R); 91 RegisterMethods<SBInstruction>(R); 92 RegisterMethods<SBInstructionList>(R); 93 RegisterMethods<SBLanguageRuntime>(R); 94 RegisterMethods<SBLaunchInfo>(R); 95 RegisterMethods<SBLineEntry>(R); 96 RegisterMethods<SBListener>(R); 97 RegisterMethods<SBMemoryRegionInfo>(R); 98 RegisterMethods<SBMemoryRegionInfoList>(R); 99 RegisterMethods<SBModule>(R); 100 RegisterMethods<SBModuleSpec>(R); 101 RegisterMethods<SBPlatform>(R); 102 RegisterMethods<SBPlatformConnectOptions>(R); 103 RegisterMethods<SBPlatformShellCommand>(R); 104 RegisterMethods<SBProcess>(R); 105 RegisterMethods<SBProcessInfo>(R); 106 RegisterMethods<SBQueue>(R); 107 RegisterMethods<SBQueueItem>(R); 108 RegisterMethods<SBSection>(R); 109 RegisterMethods<SBSourceManager>(R); 110 RegisterMethods<SBStream>(R); 111 RegisterMethods<SBStringList>(R); 112 RegisterMethods<SBStructuredData>(R); 113 RegisterMethods<SBSymbol>(R); 114 RegisterMethods<SBSymbolContext>(R); 115 RegisterMethods<SBSymbolContextList>(R); 116 RegisterMethods<SBTarget>(R); 117 RegisterMethods<SBThread>(R); 118 RegisterMethods<SBThreadCollection>(R); 119 RegisterMethods<SBThreadPlan>(R); 120 RegisterMethods<SBTrace>(R); 121 RegisterMethods<SBTraceOptions>(R); 122 RegisterMethods<SBType>(R); 123 RegisterMethods<SBTypeCategory>(R); 124 RegisterMethods<SBTypeEnumMember>(R); 125 RegisterMethods<SBTypeFilter>(R); 126 RegisterMethods<SBTypeFormat>(R); 127 RegisterMethods<SBTypeNameSpecifier>(R); 128 RegisterMethods<SBTypeSummary>(R); 129 RegisterMethods<SBTypeSummaryOptions>(R); 130 RegisterMethods<SBTypeSynthetic>(R); 131 RegisterMethods<SBUnixSignals>(R); 132 RegisterMethods<SBValue>(R); 133 RegisterMethods<SBValueList>(R); 134 RegisterMethods<SBVariablesOptions>(R); 135 RegisterMethods<SBWatchpoint>(R); 136 } 137 138 const char *SBReproducer::Capture() { 139 static std::string error; 140 if (auto e = Reproducer::Initialize(ReproducerMode::Capture, llvm::None)) { 141 error = llvm::toString(std::move(e)); 142 return error.c_str(); 143 } 144 145 if (auto *g = lldb_private::repro::Reproducer::Instance().GetGenerator()) { 146 auto &p = g->GetOrCreate<SBProvider>(); 147 InstrumentationData::Initialize(p.GetSerializer(), p.GetRegistry()); 148 } 149 150 return nullptr; 151 } 152 153 const char *SBReproducer::Capture(const char *path) { 154 static std::string error; 155 if (auto e = 156 Reproducer::Initialize(ReproducerMode::Capture, FileSpec(path))) { 157 error = llvm::toString(std::move(e)); 158 return error.c_str(); 159 } 160 161 if (auto *g = lldb_private::repro::Reproducer::Instance().GetGenerator()) { 162 auto &p = g->GetOrCreate<SBProvider>(); 163 InstrumentationData::Initialize(p.GetSerializer(), p.GetRegistry()); 164 } 165 166 return nullptr; 167 } 168 169 const char *SBReproducer::PassiveReplay(const char *path) { 170 static std::string error; 171 if (auto e = Reproducer::Initialize(ReproducerMode::PassiveReplay, 172 FileSpec(path))) { 173 error = llvm::toString(std::move(e)); 174 return error.c_str(); 175 } 176 177 if (auto *l = lldb_private::repro::Reproducer::Instance().GetLoader()) { 178 FileSpec file = l->GetFile<SBProvider::Info>(); 179 auto error_or_file = llvm::MemoryBuffer::getFile(file.GetPath()); 180 if (!error_or_file) { 181 error = 182 "unable to read SB API data: " + error_or_file.getError().message(); 183 return error.c_str(); 184 } 185 static ReplayData r(std::move(*error_or_file)); 186 InstrumentationData::Initialize(r.GetDeserializer(), r.GetRegistry()); 187 } 188 189 return nullptr; 190 } 191 192 const char *SBReproducer::Replay(const char *path) { 193 SBReplayOptions options; 194 return SBReproducer::Replay(path, options); 195 } 196 197 const char *SBReproducer::Replay(const char *path, bool skip_version_check) { 198 SBReplayOptions options; 199 options.SetCheckVersion(!skip_version_check); 200 return SBReproducer::Replay(path, options); 201 } 202 203 const char *SBReproducer::Replay(const char *path, 204 const SBReplayOptions &options) { 205 static std::string error; 206 if (auto e = Reproducer::Initialize(ReproducerMode::Replay, FileSpec(path))) { 207 error = llvm::toString(std::move(e)); 208 return error.c_str(); 209 } 210 211 repro::Loader *loader = repro::Reproducer::Instance().GetLoader(); 212 if (!loader) { 213 error = "unable to get replay loader."; 214 return error.c_str(); 215 } 216 217 if (options.GetCheckVersion()) { 218 llvm::Expected<std::string> version = loader->LoadBuffer<VersionProvider>(); 219 if (!version) { 220 error = llvm::toString(version.takeError()); 221 return error.c_str(); 222 } 223 if (lldb_private::GetVersion() != llvm::StringRef(*version).rtrim()) { 224 error = "reproducer capture and replay version don't match:\n"; 225 error.append("reproducer captured with:\n"); 226 error.append(*version); 227 error.append("reproducer replayed with:\n"); 228 error.append(lldb_private::GetVersion()); 229 return error.c_str(); 230 } 231 } 232 233 if (options.GetVerify()) { 234 bool verification_failed = false; 235 llvm::raw_string_ostream os(error); 236 auto error_callback = [&](llvm::StringRef error) { 237 verification_failed = true; 238 os << "\nerror: " << error; 239 }; 240 241 auto warning_callback = [&](llvm::StringRef warning) { 242 verification_failed = true; 243 os << "\nwarning: " << warning; 244 }; 245 246 auto note_callback = [&](llvm::StringRef warning) {}; 247 248 Verifier verifier(loader); 249 verifier.Verify(error_callback, warning_callback, note_callback); 250 251 if (verification_failed) { 252 os.flush(); 253 return error.c_str(); 254 } 255 } 256 257 FileSpec file = loader->GetFile<SBProvider::Info>(); 258 if (!file) { 259 error = "unable to get replay data from reproducer."; 260 return error.c_str(); 261 } 262 263 SBRegistry registry; 264 registry.Replay(file); 265 266 return nullptr; 267 } 268 269 bool SBReproducer::Generate() { 270 auto &r = Reproducer::Instance(); 271 if (auto generator = r.GetGenerator()) { 272 generator->Keep(); 273 return true; 274 } 275 return false; 276 } 277 278 bool SBReproducer::SetAutoGenerate(bool b) { 279 auto &r = Reproducer::Instance(); 280 if (auto generator = r.GetGenerator()) { 281 generator->SetAutoGenerate(b); 282 return true; 283 } 284 return false; 285 } 286 287 const char *SBReproducer::GetPath() { 288 static std::string path; 289 auto &r = Reproducer::Instance(); 290 path = r.GetReproducerPath().GetCString(); 291 return path.c_str(); 292 } 293 294 void SBReproducer::SetWorkingDirectory(const char *path) { 295 if (auto *g = lldb_private::repro::Reproducer::Instance().GetGenerator()) { 296 auto &wp = g->GetOrCreate<repro::WorkingDirectoryProvider>(); 297 wp.SetDirectory(path); 298 auto &fp = g->GetOrCreate<repro::FileProvider>(); 299 fp.RecordInterestingDirectory(wp.GetDirectory()); 300 } 301 } 302 303 char lldb_private::repro::SBProvider::ID = 0; 304 const char *SBProvider::Info::name = "sbapi"; 305 const char *SBProvider::Info::file = "sbapi.bin"; 306