28#include "llvm/ADT/STLExtras.h"
29#include "llvm/Support/Error.h"
30#include "llvm/Support/FileSystem.h"
31#include "llvm/Support/FormatVariadic.h"
32#include "llvm/Support/JSON.h"
33#include "llvm/Support/raw_ostream.h"
46#define LLDB_PROPERTIES_diagnostics
47#include "CoreProperties.inc"
50#define LLDB_PROPERTIES_diagnostics
51#include "CorePropertiesEnum.inc"
57 m_collection_sp = std::make_shared<OptionValueProperties>(
"diagnostics");
62 const uint32_t idx = ePropertyCollectBinaries;
64 idx, g_diagnostics_properties[idx].default_uint_value != 0);
91 static std::optional<Diagnostics> g_diagnostics;
103 if (!diagnostics_dir) {
104 stream <<
"unable to create diagnostic dir: "
105 <<
toString(diagnostics_dir.takeError()) <<
'\n';
109 return Dump(stream, *diagnostics_dir);
113 stream <<
"LLDB diagnostics will be written to " << dir.
GetPath() <<
"\n";
114 stream <<
"Please include the directory content when filing a bug report\n";
125 SmallString<128> diagnostics_dir;
127 sys::fs::createUniqueDirectory(
"diagnostics", diagnostics_dir);
129 return errorCodeToError(ec);
130 return FileSpec(diagnostics_dir.str());
137 return Error::success();
143 llvm::raw_fd_ostream stream(log_file.
GetPath(), ec, llvm::sys::fs::OF_None);
145 return errorCodeToError(ec);
147 return Error::success();
173 llvm::StringRef content,
174 std::vector<std::string> &files) {
177 llvm::raw_fd_ostream os(file.
GetPath(), ec, llvm::sys::fs::OF_Text);
182 llvm::sys::fs::setPermissions(file.
GetPath(), llvm::sys::fs::owner_read |
183 llvm::sys::fs::owner_write);
184 files.push_back(name.str());
191 std::vector<std::string> &files) {
198 name = formatv(
"{0}.{1}", src.
GetFilename(), i).str();
204 llvm::sys::fs::setPermissions(dst.
GetPath(), llvm::sys::fs::owner_read |
205 llvm::sys::fs::owner_write);
206 files.push_back(std::move(name));
222struct TriageCommand {
223 llvm::StringRef command;
224 Requires requirement;
232 {
"target list", Requires::Always},
233 {
"image list", Requires::Target},
234 {
"process status", Requires::Process},
235 {
"thread list", Requires::Process},
236 {
"thread backtrace all", Requires::Process},
237 {
"image lookup -va $pc", Requires::Frame},
238 {
"register read", Requires::Frame},
239 {
"frame variable", Requires::Frame},
240 {
"scripting extension list --instances", Requires::Always},
244 switch (requirement) {
245 case Requires::Always:
247 case Requires::Target:
249 case Requires::Process:
251 case Requires::Frame:
254 llvm_unreachable(
"unhandled Requires");
257llvm::Expected<Diagnostics::Report>
262 llvm::sys::fs::setPermissions(dir.
GetPath(), llvm::sys::fs::owner_read |
263 llvm::sys::fs::owner_write |
264 llvm::sys::fs::owner_exe);
282 std::vector<std::string> &files) {
285 consumeError(std::move(
error));
287 files.push_back(
"diagnostics.log");
291 files.push_back(std::move(name));
297 std::vector<std::string> &files) {
302 raw_string_ostream os(str);
303 os << formatv(
"{0:2}", stats);
310 std::vector<std::string> &files) {
311 std::string snapshot;
315 snapshot += formatv(
"=== {0} ===\n", tc.command).str();
324 std::vector<std::string> &files) {
326 if (
Module *exe = target->GetExecutableModulePointer()) {
329 if (exe->GetSymbolFileFileSpec() != exe->GetFileSpec())
330 CopyBinary(exe->GetSymbolFileFileSpec(), dir, files);
335 CopyBinary(process->GetCoreFile(), dir, files);
339 std::vector<std::string> &files) {
342 std::vector<ArtifactProviderEntry> providers;
352 std::string os = HostInfo::GetTargetTriple().str();
360 os += formatv(
" platform={0}", platform_sp->GetName()).str();
361 VersionTuple version = platform_sp->GetOSVersion();
362 if (!version.empty())
363 os +=
" os=" + version.getAsString();
364 if (std::optional<std::string> build = platform_sp->GetOSBuildString())
365 os +=
" build=" + *build;
377 std::string invocation;
393 obj[
"attachments"] = json::Object{
static llvm::raw_ostream & error(Stream &strm)
static constexpr size_t g_num_log_messages
static constexpr TriageCommand g_triage_commands[]
static void CopyBinary(const FileSpec &src, const FileSpec &dir, std::vector< std::string > &files)
static bool Available(Requires requirement, const ExecutionContext &exe_ctx)
static std::string CaptureCommand(Debugger &debugger, llvm::StringRef command)
static void WriteArtifact(const FileSpec &dir, llvm::StringRef name, llvm::StringRef content, std::vector< std::string > &files)
A command line argument class.
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
const char * GetArgumentAtIndex(size_t idx) const
Gets the null-terminated C string argument pointer for the argument at index idx.
bool HandleCommand(const char *command_line, LazyBool add_to_history, const ExecutionContext &override_context, CommandReturnObject &result)
std::string GetErrorString(bool with_diagnostics=true) const
Return the errors as a string.
llvm::StringRef GetOutputString() const
static llvm::json::Value ReportStatistics(Debugger &debugger, Target *target, const lldb_private::StatisticsOptions &options)
Get metrics associated with one or all targets in a debugger in JSON format.
A class to manage flag bits.
CommandInterpreter & GetCommandInterpreter()
std::vector< std::string > CopyLogFilesToDirectory(const FileSpec &dir)
Copy this debugger's file-backed log files into the given directory, for inclusion in a diagnostics b...
The global diagnostics settings, exposed under diagnostics in the settings hierarchy.
bool SetCollectBinaries(bool collect)
bool GetCollectBinaries() const
std::mutex m_artifact_providers_mutex
RotatingLogHandler m_log_handler
std::vector< ArtifactProviderEntry > m_artifact_providers
bool Dump(llvm::raw_ostream &stream)
Write the diagnostic log into a directory and print a message to the given output stream.
static std::string GetInvocation()
static std::string GetHostDescription(const ExecutionContext &exe_ctx)
Scalars carried in the report rather than written as files.
static void CollectBinaries(const ExecutionContext &exe_ctx, const FileSpec &dir, std::vector< std::string > &files)
ArtifactProviderID AddArtifactProvider(std::string name, ArtifactProvider provider)
Register provider to contribute file name.
void CollectArtifactProviders(const FileSpec &dir, std::vector< std::string > &files)
llvm::Error DumpDiangosticsLog(const FileSpec &dir) const
void CollectLogs(Debugger &debugger, const FileSpec &dir, std::vector< std::string > &files)
Collect the individual parts of the bundle into dir, appending the name of each file to files as it i...
std::function< std::string()> ArtifactProvider
Supplies an artifact's contents on demand.
static DiagnosticsProperties & GetGlobalProperties()
void RemoveArtifactProvider(ArtifactProviderID id)
Unregister a provider. Thread-safe.
llvm::Error Create(const FileSpec &dir)
Write the in-memory diagnostic log into the given directory.
void Record(llvm::StringRef message)
Record a diagnostic message into the always-on, in-memory log.
static llvm::Expected< FileSpec > CreateUniqueDirectory()
Create a unique diagnostic directory.
static std::optional< Diagnostics > & InstanceImpl()
llvm::Expected< Report > Collect(Debugger &debugger, const ExecutionContext &exe_ctx, const FileSpec &dir)
Collect a full diagnostics bundle into dir and return its report.
ArtifactProviderID m_next_artifact_provider_id
Registered artifact providers, guarded by the mutex.
static void CollectCommands(Debugger &debugger, const ExecutionContext &exe_ctx, const FileSpec &dir, std::vector< std::string > &files)
uint64_t ArtifactProviderID
static Diagnostics & Instance()
static void CollectStatistics(Debugger &debugger, const ExecutionContext &exe_ctx, const FileSpec &dir, std::vector< std::string > &files)
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
StackFrame * GetFramePtr() const
Returns a pointer to the frame object.
Target * GetTargetPtr() const
Returns a pointer to the target object.
Process * GetProcessPtr() const
Returns a pointer to the process object.
FileSpec CopyByAppendingPathComponent(llvm::StringRef component) const
llvm::StringRef GetFilename() const
Filename string const get accessor.
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
bool Exists(const FileSpec &file_spec) const
Returns whether the given file exists.
static FileSystem & Instance()
static lldb::pid_t GetCurrentProcessID()
Get the process ID for the calling process.
static bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info)
A class that describes an executable image and its associated object and symbol files.
A plug-in interface definition class for debugging a process.
lldb::OptionValuePropertiesSP m_collection_sp
T GetPropertyAtIndexAs(uint32_t idx, T default_value, const ExecutionContext *exe_ctx=nullptr) const
bool SetPropertyAtIndex(uint32_t idx, T t, const ExecutionContext *exe_ctx=nullptr) const
lldb::PlatformSP GetPlatform()
A class that represents a running process on the host machine.
const char * GetVersion()
Retrieves a string representing the complete LLDB version, which includes the lldb version number,...
llvm::json::Value toJSON(const Diagnostics::Report &report)
Render a diagnostics report as JSON, for diagnostics dump's terminal output.
std::string toString(FormatterBytecode::OpCodes op)
std::shared_ptr< lldb_private::Platform > PlatformSP
std::vector< std::string > files
The state a triager needs to make sense of a bug report.